Skip to content

Commit

Permalink
fix(schema-org): duplicate tag generated in some instances
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Nov 25, 2024
1 parent cb8526b commit 0cf6214
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
23 changes: 22 additions & 1 deletion packages/schema-org/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { SchemaOrgGraph } from '.'
import type { MetaInput, ResolvedMeta } from './types'
import { defineHeadPlugin, processTemplateParams } from '@unhead/shared'
import { defu } from 'defu'
import {
createSchemaOrgGraph,
resolveMeta,
Expand Down Expand Up @@ -38,6 +39,7 @@ export function SchemaOrgUnheadPlugin(config: MetaInput, meta: () => Partial<Met
},
'tag:normalise': async ({ tag }) => {
if (tag.tag === 'script' && tag.props.type === 'application/ld+json' && tag.props.nodes) {
console.log('tag', tag)
// this is a bit expensive, load in seperate chunk
const { loadResolver } = await import('./resolver')
const nodes = await tag.props.nodes
Expand Down Expand Up @@ -85,6 +87,7 @@ export function SchemaOrgUnheadPlugin(config: MetaInput, meta: () => Partial<Met
for (const k in ctx.tags) {
const tag = ctx.tags[k]
if (tag.tag === 'script' && tag.props.type === 'application/ld+json' && tag.props.nodes) {
delete tag.props.nodes
const resolvedGraph = graph.resolveGraph({ ...(await meta?.() || {}), ...config, ...resolvedMeta })
if (!resolvedGraph.length) {
// removes the tag
Expand All @@ -101,11 +104,29 @@ export function SchemaOrgUnheadPlugin(config: MetaInput, meta: () => Partial<Met
return processTemplateParams(value, head._templateParams!, head._separator!)
return value
}, minify ? 0 : 2)
delete tag.props.nodes
return
}
}
},
'tags:afterResolve': (ctx) => {
let firstNodeKey: number | undefined
for (const k in ctx.tags) {
const tag = ctx.tags[k]
if ((tag.props.type === 'application/ld+json' && tag.props.nodes) || tag.key === 'schema-org-graph') {
if (typeof firstNodeKey === 'undefined') {
firstNodeKey = k as any
continue
}
// merge props on to first node and delete
ctx.tags[firstNodeKey].props = defu(ctx.tags[firstNodeKey].props, tag.props)
delete ctx.tags[firstNodeKey].props.nodes
// @ts-expect-error untyped
ctx.tags[k] = false
}
}
// there many be multiple script nodes within the same entry
ctx.tags = ctx.tags.filter(Boolean)
},
},
}))
}
54 changes: 54 additions & 0 deletions test/schema.org/ssr/dupes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { defineWebSite, UnheadSchemaOrg } from '@unhead/schema-org'
import { renderSSRHead } from '@unhead/ssr'
import { createHead, useHead } from 'unhead'
import { describe, expect, it } from 'vitest'

describe('schema.org dupes', () => {
it('basic websites', async () => {
const ssrHead = createHead()

ssrHead.use(UnheadSchemaOrg())

useHead({
script: [
{
type: 'application/ld+json',
key: 'schema-org-graph',
nodes: [
defineWebSite({
url: '/',
inLanguage: 'en',
name: 'hello',
}),
],
},
{
type: 'application/ld+json',
key: 'schema-org-graph',
id: 'schema-org-graph-2',
nodes: [
defineWebSite({
'@type': 'AboutPage',
}),
],
},
],
})

const data = await renderSSRHead(ssrHead)
expect(data.bodyTags).toMatchInlineSnapshot(`
"<script type="application/ld+json" id="schema-org-graph-2" data-hid="3437552">{
"@context": "https://schema.org",
"@graph": [
{
"@id": "#website",
"@type": "AboutPage",
"inLanguage": "en",
"name": "hello",
"url": "/"
}
]
}</script>"
`)
})
})

0 comments on commit 0cf6214

Please sign in to comment.