diff --git a/docs/content/1.usage/2.guides/2.positions.md b/docs/content/1.usage/2.guides/2.positions.md index 1e422864..a11e83a6 100644 --- a/docs/content/1.usage/2.guides/2.positions.md +++ b/docs/content/1.usage/2.guides/2.positions.md @@ -17,7 +17,6 @@ Possible values: - `bodyClose` - Render at the end of the `` Note: -- Providing `body: true` is the same as `tagPosition: 'bodyClose'`. - Sorting may not be stricly honoured when moving outside the head ## Examples diff --git a/docs/content/1.usage/2.guides/6.handling-duplicates.md b/docs/content/1.usage/2.guides/6.handling-duplicates.md index 8066c98b..8a4c77c5 100644 --- a/docs/content/1.usage/2.guides/6.handling-duplicates.md +++ b/docs/content/1.usage/2.guides/6.handling-duplicates.md @@ -18,7 +18,7 @@ There is different logic used to determine what tags are duplicates: - Any of the following tags: `base`, `title`, `titleTemplate`, `bodyAttrs`, `htmlAttrs`. - `` - `` -- Custom provided `key` attribute (`hid` and `vmid` is also supported) +- Custom provided `key` attribute - Meta `content`, `property` and `http-equiv` attributes Example of a dedupe using the meta `content`. @@ -114,8 +114,6 @@ useHead({ }) ``` -Note: this shares the same behaviour with `hid` and `vmid` from vue-meta. - ## `tagDuplicateStrategy` The default behaviour when a duplicate is found, is to `replace` it. diff --git a/packages/schema/src/tags.ts b/packages/schema/src/tags.ts index f14122a4..bee868a1 100644 --- a/packages/schema/src/tags.ts +++ b/packages/schema/src/tags.ts @@ -17,14 +17,6 @@ export interface ResolvesDuplicates { * @default 'replace' (some tags will default to 'merge', such as htmlAttr) */ tagDuplicateStrategy?: 'replace' | 'merge' - /** - * @deprecated Use `key` instead - */ - hid?: string - /** - * @deprecated Use `key` instead - */ - vmid?: string } export type ValidTagPositions = 'head' | 'bodyClose' | 'bodyOpen' @@ -51,12 +43,6 @@ export interface InnerContent { * Sets the textContent of an element. Safer for XSS. */ textContent?: InnerContentVal - /** - * Sets the textContent of an element. - * - * @deprecated Use `textContent` or `innerHTML`. - */ - children?: InnerContentVal } export interface TagPriority { diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts index 61e142cf..7657c8f9 100644 --- a/packages/shared/src/constants.ts +++ b/packages/shared/src/constants.ts @@ -24,7 +24,7 @@ export const ValidHeadTags = new Set([ export const UniqueTags = new Set(['base', 'title', 'titleTemplate', 'bodyAttrs', 'htmlAttrs', 'templateParams']) -export const TagConfigKeys = new Set(['tagPosition', 'tagPriority', 'tagDuplicateStrategy', 'children', 'innerHTML', 'textContent', 'processTemplateParams']) +export const TagConfigKeys = new Set(['tagPosition', 'tagPriority', 'tagDuplicateStrategy', 'innerHTML', 'textContent', 'processTemplateParams']) export const IsBrowser = typeof window !== 'undefined' diff --git a/packages/shared/src/normalise.ts b/packages/shared/src/normalise.ts index 9a8f1f98..cecf16c6 100644 --- a/packages/shared/src/normalise.ts +++ b/packages/shared/src/normalise.ts @@ -19,21 +19,14 @@ export function normaliseTag(tagName: T['tag'], input: HeadTa // @ts-expect-error untyped const val = tag.props[k] !== undefined ? tag.props[k] : e[k] if (val !== undefined) { - // strip innerHTML and textContent for tags which don't support it= - if (!(k === 'innerHTML' || k === 'textContent' || k === 'children') || TagsWithInnerContent.has(tag.tag)) { + // strip innerHTML and textContent for tags which don't support it + if (!(k === 'innerHTML' || k === 'textContent') || TagsWithInnerContent.has(tag.tag)) { // @ts-expect-error untyped - tag[k === 'children' ? 'innerHTML' : k] = val + tag[k] = val } delete tag.props[k] } } - // TODO remove v2 - if (tag.props.body) { - // inserting dangerous javascript potentially - tag.tagPosition = 'bodyClose' - // clean up - delete tag.props.body - } // shorthand for objects if (tag.tag === 'script') { if (typeof tag.innerHTML === 'object') { diff --git a/packages/unhead/src/optionalPlugins/deprecations.ts b/packages/unhead/src/optionalPlugins/deprecations.ts new file mode 100644 index 00000000..93d5eb68 --- /dev/null +++ b/packages/unhead/src/optionalPlugins/deprecations.ts @@ -0,0 +1,24 @@ +import { defineHeadPlugin } from '@unhead/shared' + +export const DeprecationsPlugin = defineHeadPlugin({ + hooks: { + 'tag:normalise': ({ tag }) => { + if (tag.props.children) { + tag.innerHTML = tag.props.children + delete tag.props.children + } + if (tag.props.hid) { + tag.key = tag.props.hid + delete tag.props.hid + } + if (tag.props.vmid) { + tag.key = tag.props.vmid + delete tag.props.vmid + } + if (tag.props.body) { + tag.tagPosition = 'bodyClose' + delete tag.props.body + } + }, + }, +}) diff --git a/packages/unhead/src/optionalPlugins/index.ts b/packages/unhead/src/optionalPlugins/index.ts index 392681d0..5934a8c7 100644 --- a/packages/unhead/src/optionalPlugins/index.ts +++ b/packages/unhead/src/optionalPlugins/index.ts @@ -1 +1,2 @@ +export * from './deprecations' export * from './promises' diff --git a/packages/unhead/src/plugins/dedupe.ts b/packages/unhead/src/plugins/dedupe.ts index ceae9463..71f5df54 100644 --- a/packages/unhead/src/plugins/dedupe.ts +++ b/packages/unhead/src/plugins/dedupe.ts @@ -6,15 +6,6 @@ const UsesMergeStrategy = new Set(['templateParams', 'htmlAttrs', 'bodyAttrs']) export default defineHeadPlugin(head => ({ hooks: { 'tag:normalise': ({ tag }) => { - // support for third-party dedupe keys - if (tag.props.hid) { - tag.key = tag.props.hid - delete tag.props.hid - } - if (tag.props.vmid) { - tag.key = tag.props.vmid - delete tag.props.vmid - } if (tag.props.key) { tag.key = tag.props.key delete tag.props.key diff --git a/packages/unhead/src/plugins/templateParams.ts b/packages/unhead/src/plugins/templateParams.ts index 58a53e14..a0b5486f 100644 --- a/packages/unhead/src/plugins/templateParams.ts +++ b/packages/unhead/src/plugins/templateParams.ts @@ -62,7 +62,6 @@ export default defineHeadPlugin(head => ({ }, 'tags:afterResolve': ({ tags }) => { // we need to re-process in case then user had a function as the titleTemplate - // TODO drop support for function in v2 let title: HeadTag | undefined for (let i = 0; i < tags.length; i += 1) { const tag = tags[i] diff --git a/packages/vue/test/dom/innerContent.test.ts b/packages/vue/test/dom/innerContent.test.ts index dc841c97..d56be700 100644 --- a/packages/vue/test/dom/innerContent.test.ts +++ b/packages/vue/test/dom/innerContent.test.ts @@ -12,7 +12,7 @@ describe('vue dom innerContent', () => { const entry = head.push({ script: [ { - children: 'console.log(\'hello\')', + innerHTML: 'console.log(\'hello\')', }, ], }) @@ -38,7 +38,7 @@ describe('vue dom innerContent', () => { entry.patch({ script: [ { - children: 'console.log(\'hello world\')', + innerHTML: 'console.log(\'hello world\')', }, ], }) diff --git a/packages/vue/test/dom/lifecycle.test.ts b/packages/vue/test/dom/lifecycle.test.ts index cc0289c5..3470838e 100644 --- a/packages/vue/test/dom/lifecycle.test.ts +++ b/packages/vue/test/dom/lifecycle.test.ts @@ -139,7 +139,7 @@ describe('vue dom', () => { }, script: [ { - children: 'console.log(\'hello\')', + innerHTML: 'console.log(\'hello\')', tagPosition: 'bodyClose', }, ], diff --git a/packages/vue/test/promises.test.ts b/packages/vue/test/promises.test.ts index 211e44dc..8d0584f7 100644 --- a/packages/vue/test/promises.test.ts +++ b/packages/vue/test/promises.test.ts @@ -11,7 +11,7 @@ describe('vue promises', () => { script: [ { src: new Promise(resolve => resolve('https://example.com/script.js')) }, { - children: new Promise(resolve => setTimeout(() => resolve('test'), 250)), + innerHTML: new Promise(resolve => setTimeout(() => resolve('test'), 250)), }, ], }) diff --git a/packages/vue/test/ssr/innerContent.test.ts b/packages/vue/test/ssr/innerContent.test.ts index 050bc588..e63d25ab 100644 --- a/packages/vue/test/ssr/innerContent.test.ts +++ b/packages/vue/test/ssr/innerContent.test.ts @@ -2,8 +2,8 @@ import { useHead } from '@unhead/vue' import { describe } from 'vitest' import { ssrRenderHeadToString } from '../util' -describe('vue ssr innerContent', () => { - it('children', async () => { +describe('vue ssr innerHTML', () => { + it('innerHTML', async () => { const headResult = await ssrRenderHeadToString(() => { useHead({ script: [ diff --git a/test/unhead/dom/innerHTML.test.ts b/test/unhead/dom/innerHTML.test.ts index 6fee56fd..a44ffca7 100644 --- a/test/unhead/dom/innerHTML.test.ts +++ b/test/unhead/dom/innerHTML.test.ts @@ -53,7 +53,7 @@ describe('dom innerHTML', () => { useHead({ noscript: [ { - children: ``, }, ], diff --git a/test/unhead/e2e/json.test.ts b/test/unhead/e2e/json.test.ts index b5044310..f01cce1b 100644 --- a/test/unhead/e2e/json.test.ts +++ b/test/unhead/e2e/json.test.ts @@ -15,7 +15,7 @@ describe('unhead e2e json', () => { script: [ { type: 'application/json', - children: { + innerHTML: { foo: 'bar', }, }, @@ -41,7 +41,7 @@ describe('unhead e2e json', () => { script: [ { type: 'application/json', - children: { + innerHTML: { foo: 'bar', }, }, diff --git a/test/unhead/promises.test.ts b/test/unhead/promises.test.ts index 0220f10e..89b67061 100644 --- a/test/unhead/promises.test.ts +++ b/test/unhead/promises.test.ts @@ -12,7 +12,7 @@ describe('promises', () => { script: [ { src: new Promise(resolve => resolve('https://example.com/script.js')) }, { - children: new Promise(resolve => setTimeout(() => resolve('test'), 250)), + innerHTML: new Promise(resolve => setTimeout(() => resolve('test'), 250)), }, ], }) diff --git a/test/unhead/ssr/deduping.test.ts b/test/unhead/ssr/deduping.test.ts index 196df283..d1f7d4e5 100644 --- a/test/unhead/ssr/deduping.test.ts +++ b/test/unhead/ssr/deduping.test.ts @@ -1,5 +1,6 @@ import { renderSSRHead } from '@unhead/ssr' import { useHead } from 'unhead' +import { DeprecationsPlugin } from 'unhead/optionalPlugins' import { describe, it } from 'vitest' import { createHeadWithContext } from '../../util' @@ -215,7 +216,9 @@ describe('dedupe', () => { }) it('dedupes legacy', async () => { - const head = createHeadWithContext() + const head = createHeadWithContext({ + plugins: [DeprecationsPlugin], + }) head.push({ meta: [ { diff --git a/test/unhead/ssr/innerHTML.test.ts b/test/unhead/ssr/innerHTML.test.ts index 0338708d..4692b0ed 100644 --- a/test/unhead/ssr/innerHTML.test.ts +++ b/test/unhead/ssr/innerHTML.test.ts @@ -58,7 +58,7 @@ describe('ssr innerHTML', () => { head.push({ noscript: [ { - children: ``, }, ], @@ -126,14 +126,5 @@ describe('ssr innerHTML', () => { ], }) expect(await head.resolveTags()).toMatchInlineSnapshot('[]') - - head.push({ - script: [ - { - children: '', - }, - ], - }) - expect(await head.resolveTags()).toMatchInlineSnapshot('[]') }) }) diff --git a/test/unhead/ssr/tagPosition.test.ts b/test/unhead/ssr/tagPosition.test.ts index 2532a1dd..e4a20275 100644 --- a/test/unhead/ssr/tagPosition.test.ts +++ b/test/unhead/ssr/tagPosition.test.ts @@ -1,4 +1,5 @@ import { renderSSRHead } from '@unhead/ssr' +import { DeprecationsPlugin } from 'unhead/optionalPlugins' import { createHeadWithContext } from '../../util' describe('tagPosition', () => { @@ -24,7 +25,9 @@ describe('tagPosition', () => { `) }) it('body: true', async () => { - const head = createHeadWithContext() + const head = createHeadWithContext({ + plugins: [DeprecationsPlugin], + }) head.push({ script: [ {