const baseMetas: Meta[] = [
{ name: 'keyword', content: null },
{ name: 'description', content: null },
{ property: 'og:url', content: null },
{ property: 'og:type', content: null },
{ property: 'og:description', content: null },
{ property: 'og:title', content: null },
{ property: 'og:site_name', content: null },
{ property: 'og:image', content: null }
]
const mergeMetas = (metas: Meta[]) =>
metas.reduce((memo, meta) => {
let overrided = false
const metas = memo.map(base => {
if (
(base.name && base.name === meta.name) ||
(base.property && base.property === meta.property)
) {
overrided = true
return meta
}
return base
})
if (overrided) return metas
return [...memo, meta]
}, baseMetas)
export const setHeadTags = (headTags: HeadTags) => {
if (!document) return
const head = document.querySelector('head')
if (!head) return
// title
const title = document.querySelector('title')
if (title) {
document.title = headTags.title + titleSuffix
} else {
const title = document.createElement(HeadTag.title)
title.text = headTags.title + titleSuffix
head.appendChild(title)
}
// link
headTags.links.forEach(setting => {
const link = head.querySelector(`[rel="${setting.rel}"]`)
if (link) {
setting.href !== null
? link.setAttribute('href', setting.href)
: head.removeChild(link)
return
}
if (setting.href) {
const link = document.createElement(HeadTag.link)
link.setAttribute('rel', setting.rel)
link.setAttribute('href', setting.href)
setting.href && head.appendChild(link)
}
})
// meta
mergeMetas(headTags.metas).forEach(setting => {
const meta =
head.querySelector(`[name="${setting.name}"]`) ||
head.querySelector(`[property="${setting.property}"]`)
if (meta) {
setting.content !== null
? meta.setAttribute('content', setting.content)
: head.removeChild(meta)
return
}
if (setting.content) {
const meta = document.createElement(HeadTag.meta)
if (setting.name) meta.setAttribute('name', setting.name)
if (setting.property) meta.setAttribute('property', setting.property)
meta.setAttribute('content', setting.content)
setting.content && head.appendChild(meta)
}
})
}
enum HeadTag {
title = 'title',
link = 'link',
meta = 'meta'
}
type HeadTags = {
title: string
links: Link[]
metas: Meta[]
}
type Link = {
rel: string
href: string | null
}
type Meta = {
name?: string
property?: string
content: string | null
}