Skip to content

Commit

Permalink
chore: unhead v2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Feb 27, 2025
1 parent 6427ae5 commit fa80740
Show file tree
Hide file tree
Showing 9 changed files with 22 additions and 79 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"test:chrome": "HAS_CHROME=true vitest"
},
"peerDependencies": {
"unhead": "^1.0.0 || ^2.0.0",
"@unhead/vue": "^1.0.0 || ^2.0.0",
"unstorage": "^1.0.0"
},
"dependencies": {
Expand Down
6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/runtime/app/composables/defineOgImage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ActiveHeadEntry } from '@unhead/schema'
import type { ActiveHeadEntry } from '@unhead/vue'
import type { DefineOgImageInput, OgImageOptions } from '../../types'
import { defu } from 'defu'
import { appendHeader } from 'h3'
Expand Down
12 changes: 8 additions & 4 deletions src/runtime/app/utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import type { Head } from '@unhead/schema'
import type { Head } from '@unhead/vue'
import type { NuxtSSRContext } from 'nuxt/app'
import type { DefineOgImageInput, OgImageOptions, OgImagePrebuilt } from '../types'
import { componentNames } from '#build/nuxt-og-image/components.mjs'
import { resolveUnrefHeadInput, useServerHead } from '@unhead/vue'
import { useHead } from '#imports'
import { resolveUnrefHeadInput } from '@unhead/vue'
import { defu } from 'defu'
import { stringify } from 'devalue'
import { withQuery } from 'ufo'
import { unref } from 'vue'
import { generateMeta, separateProps } from '../shared'

export function createOgImageMeta(src: string | null, input: OgImageOptions | OgImagePrebuilt, resolvedOptions: OgImageOptions, ssrContext: NuxtSSRContext) {
if (import.meta.client) {
return
}
const _input = separateProps(defu(input, ssrContext._ogImagePayload))
let url = src || input.url || resolvedOptions.url
if (!url)
Expand Down Expand Up @@ -40,11 +44,11 @@ export function createOgImageMeta(src: string | null, input: OgImageOptions | Og
})
}

const instance = useServerHead({
const instance = useHead({
script,
meta,
}, {
tagPriority: 35,
tagPriority: 'high',
})
ssrContext._ogImagePayload = _input
ssrContext._ogImageInstances.push(instance)
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/app/utils/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ActiveHeadEntry, HeadPlugin } from '@unhead/schema'
import type { ActiveHeadEntry } from '@unhead/vue'
import type { NitroRouteRules } from 'nitropack'
import type { NuxtApp } from 'nuxt/app'
import type { OgImageOptions } from '../../types'
Expand All @@ -22,7 +22,7 @@ export function ogImageCanonicalUrls(nuxtApp: NuxtApp) {
return

// unhead plugin to correct missing site URL, this is to fix the Nuxt Content integration not being able to resolve the correct URL
ssrContext?.head.use(<HeadPlugin>{
ssrContext?.head.use({
key: 'nuxt-og-image:overrides-and-canonical-urls',
hooks: {
'tags:resolve': async (ctx) => {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/server/og-image/templates/html.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { FontConfig, OgImageRenderEventContext } from '../../../types'
import { theme } from '#og-image-virtual/unocss-config.mjs'
import { renderSSRHead } from '@unhead/ssr'
import { createHeadCore } from '@unhead/vue'
import { createError } from 'h3'
import { createHeadCore } from 'unhead'
import { normaliseFontInput, useOgImageRuntimeConfig } from '../../../shared'
import { fetchIsland } from '../../util/kit'
import { applyEmojis } from '../satori/transforms/emojis'
Expand Down
6 changes: 3 additions & 3 deletions src/runtime/server/util/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ParsedContent } from '@nuxt/content'
import type { Head } from '@unhead/vue'
import type { NitroApp } from 'nitropack/runtime/app'
import type { UseHeadInput } from 'unhead'
import { defu } from 'defu'
import { stringify } from 'devalue'
import { withQuery } from 'ufo'
Expand Down Expand Up @@ -33,7 +33,7 @@ export function nuxtContentPlugin(nitroApp: NitroApp) {
const meta = generateMeta(src, optionsWithDefault)
// user has provided a prebuilt og image
if (optionsWithDefault.url) {
content.head = defu(<UseHeadInput<any>> { meta }, content.head)
content.head = defu(<Head> { meta }, content.head)
return content
}

Expand All @@ -48,7 +48,7 @@ export function nuxtContentPlugin(nitroApp: NitroApp) {
payload[key.replace(/-([a-z])/g, g => g[1].toUpperCase())] = val
})

content.head = defu(<UseHeadInput<any>> {
content.head = defu(<Head> {
script: [
{
id: 'nuxt-og-image-overrides',
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/shared.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Head } from '@unhead/schema'
import type { Head } from '@unhead/vue'
import type { OgImageOptions, OgImageRuntimeConfig } from './types'
import { useRuntimeConfig } from '#imports'
import { defu } from 'defu'
Expand All @@ -9,7 +9,7 @@ import { getExtension } from './pure'

export * from './pure'

export function generateMeta(url: string, resolvedOptions: OgImageOptions) {
export function generateMeta(url: string, resolvedOptions: OgImageOptions): Head['meta'] {
let urlExtension = getExtension(url) || resolvedOptions.extension
if (urlExtension === 'jpg')
urlExtension = 'jpeg'
Expand Down
63 changes: 1 addition & 62 deletions test/integration/dev-debugging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,68 +247,7 @@ describe('dev', () => {

it('html', async () => {
const font = await $fetch('/__og-image__/image/satori/og.html')
expect(font).toMatchInlineSnapshot(`
"<!DOCTYPE html>
<html >
<head><meta charset="utf-8">
<style>body { font-family: 'Inter', sans-serif; }</style>
<style>body {
transform: scale(1);
transform-origin: top left;
max-height: 100vh;
position: relative;
width: 1200px;
height: 600px;
overflow: hidden;
background-color: #fff;
}
div {
display: flex;
}
div:has(div, p, ul, ol, li, blockquote, pre, hr, table, dl) {
display: flex;
flex-direction: column;
}
div:not(:has(div, p, ul, ol, li, blockquote, pre, hr, table, dl)) {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
svg[data-emoji] {
display: inline-block;
}
</style>
<style>
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
src: url('/__og-image__/font/nuxt-og-image:fonts:Inter-normal-400.ttf.base64') format('truetype');
}
</style>
<style>
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
src: url('/__og-image__/font/nuxt-og-image:fonts:Inter-normal-700.ttf.base64') format('truetype');
}
</style>
<script src="https://cdn.jsdelivr.net/npm/@unocss/runtime/preset-wind.global.js"></script>
<script>
window.__unocss = {
theme: {},
presets: [
() => window.__unocss_runtime.presets.presetWind(),
],
}
</script>
<script src="https://cdn.jsdelivr.net/npm/@unocss/runtime/core.global.js"></script>
<link href="https://cdn.jsdelivr.net/npm/gardevoir" rel="stylesheet"></head>
<body ><div data-v-inspector-ignore="true" style="position: relative; display: flex; margin: 0 auto; width: 1200px; height: 600px; overflow: hidden;"><div class="w-full h-full flex justify-between relative p-[60px] bg-white text-gray-900" data-island-uid><div class="flex absolute top-0 right-[-100%]" style="width:200%;height:200%;background-image:radial-gradient(circle, rgba(0, 220, 130, 0.5) 0%, rgba(255, 255, 255, 0.7) 50%, rgba(255, 255, 255, 0) 70%);"></div><div class="h-full w-full justify-between relative"><div class="flex flex-row justify-between items-start"><div class="flex flex-col w-full max-w-[65%]"><h1 class="m-0 font-bold mb-[30px] text-[75px]">Hello World</h1><!----></div><!----></div><div class="flex flex-row justify-center items-center text-left w-full"><!--[--><svg height="50" width="50" class="mr-3" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><path fill="#00dc82" d="M62.3,-53.9C74.4,-34.5,73.5,-9,67.1,13.8C60.6,36.5,48.7,56.5,30.7,66.1C12.7,75.7,-11.4,74.8,-31.6,65.2C-51.8,55.7,-67.9,37.4,-73.8,15.7C-79.6,-6,-75.1,-31.2,-61.1,-51C-47.1,-70.9,-23.6,-85.4,0.8,-86C25.1,-86.7,50.2,-73.4,62.3,-53.9Z" transform="translate(100 100)"></path></svg><p style="font-size:25px;" class="font-bold">nuxt-og-image</p><!--]--></div></div></div></div></body>
</html>"
`)
expect(font).toContain('<!DOCTYPE html>')
}, 60000)
it('debug.json', async () => {
const debug = await $fetch('/__og-image__/debug.json')
Expand Down

0 comments on commit fa80740

Please sign in to comment.