Skip to content

Commit

Permalink
feat: hook into resolved tags hookTagsResolved (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Oct 3, 2022
1 parent 675f526 commit 46f9848
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 6 deletions.
17 changes: 15 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { resolveHeadInput, sortTags, tagDedupeKey } from './utils'
import type {
HeadAttrs,
HeadObjectPlain, HeadTag,
HookBeforeDomUpdate, TagKeys,
HookBeforeDomUpdate, HookTagsResolved, TagKeys,
UseHeadInput,
} from './types'
import { setAttrs, updateElements } from './dom'
Expand All @@ -40,6 +40,10 @@ export interface HeadClient {
* You are able to modify the payload of hook using this.
*/
hookBeforeDomUpdate: HookBeforeDomUpdate
/**
* Array of user provided functions to hook into after the tags have been resolved (deduped and sorted).
*/
hookTagsResolved: HookTagsResolved
}

/**
Expand Down Expand Up @@ -134,6 +138,7 @@ export const createHead = (initHeadObject?: UseHeadInput) => {
const previousTags = new Set<string>()

const hookBeforeDomUpdate: HookBeforeDomUpdate = []
const hookTagsResolved: HookTagsResolved = []

if (initHeadObject)
allHeadObjs.push(initHeadObject)
Expand All @@ -145,6 +150,7 @@ export const createHead = (initHeadObject?: UseHeadInput) => {
},

hookBeforeDomUpdate,
hookTagsResolved,

/**
* Get deduped tags
Expand Down Expand Up @@ -186,7 +192,14 @@ export const createHead = (initHeadObject?: UseHeadInput) => {
// add the entries we were deduping
deduped.push(...Object.values(deduping))
// ensure their original positions are kept
return deduped.sort((a, b) => a._position! - b._position!)
const tags = deduped.sort((a, b) => a._position! - b._position!)

if (head.hookTagsResolved) {
for (const k in head.hookTagsResolved)
head.hookTagsResolved[k](tags)
}

return tags
},

addHeadObjs(objs) {
Expand Down
6 changes: 2 additions & 4 deletions src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import type { Ref } from 'vue'
import type { HandlesDuplicates, HasRenderPriority, RendersInnerContent, RendersToBody, TagKeys } from './schema'

export * from './schema'

export type MaybeRef<T> = T | Ref<T>

export interface HeadAttrs { [k: string]: any }

export type HookBeforeDomUpdate = ((tags: Record<string, HeadTag[]>) => void | boolean | Record<string, HeadTag[]>)[]
export type HookBeforeDomUpdate = ((tags: Record<string, HeadTag[]>) => void | boolean)[]
export type HookTagsResolved = ((tags: HeadTag[]) => void)[]

export interface HeadTag {
tag: TagKeys
Expand Down
76 changes: 76 additions & 0 deletions tests/hook-tags-resolved.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { computed } from 'vue'
import { JSDOM } from 'jsdom'
import { createHead } from '../src'

describe('hook tags resolved', () => {
test('read tags', async () => {
const head = createHead()

const hookTags = new Promise((resolve) => {
head.hookTagsResolved.push((tags) => {
resolve(tags)
})
})

head.addHeadObjs(
computed(() => ({
title: 'test',
})),
)
const dom = new JSDOM(
'<!DOCTYPE html><html><head></head><body></body></html>',
)
head.updateDOM(dom.window.document)

const tags = await hookTags
expect(tags[0].tag).toEqual('title')
expect(tags[0].props.children).toEqual('test')
expect(tags).toMatchInlineSnapshot(`
[
{
"_position": 0,
"props": {
"children": "test",
},
"tag": "title",
},
]
`)
})

test('write tags', async () => {
const head = createHead()

const hookTags = new Promise((resolve) => {
head.hookTagsResolved.push((tags) => {
for (const k in tags)
tags[k].props.extra = true

resolve(tags)
})
})

head.addHeadObjs(
computed(() => ({
title: 'test',
})),
)
const dom = new JSDOM(
'<!DOCTYPE html><html><head></head><body></body></html>',
)
head.updateDOM(dom.window.document)

const hooks = await hookTags
expect(hooks[0].props.extra).toBeTruthy()
expect(hooks[0]).toMatchInlineSnapshot(`
{
"_position": 0,
"props": {
"children": "test",
"extra": true,
},
"tag": "title",
}
`)
})
})

0 comments on commit 46f9848

Please sign in to comment.