/
index.ts
68 lines (61 loc) · 1.76 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import type { MaybeRef, MaybeRefOrGetter, ReadonlyRefOrGetter } from '@vueuse/shared'
import { toRef } from '@vueuse/shared'
import type { ComputedRef, Ref } from 'vue-demi'
import { watch } from 'vue-demi'
import type { ConfigurableDocument } from '../_configurable'
import { defaultDocument } from '../_configurable'
export interface UseFaviconOptions extends ConfigurableDocument {
baseUrl?: string
rel?: string
}
/**
* Reactive favicon.
*
* @see https://vueuse.org/useFavicon
* @param newIcon
* @param options
*/
export function useFavicon(
newIcon: ReadonlyRefOrGetter<string | null | undefined>,
options?: UseFaviconOptions
): ComputedRef<string | null | undefined>
export function useFavicon(
newIcon?: MaybeRef<string | null | undefined>,
options?: UseFaviconOptions
): Ref<string | null | undefined>
export function useFavicon(
newIcon: MaybeRefOrGetter<string | null | undefined> = null,
options: UseFaviconOptions = {},
) {
const {
baseUrl = '',
rel = 'icon',
document = defaultDocument,
} = options
const favicon = toRef(newIcon)
const applyIcon = (icon: string) => {
const elements = document?.head
.querySelectorAll<HTMLLinkElement>(`link[rel*="${rel}"]`)
if (!elements || elements.length === 0) {
const link = document?.createElement('link')
if (link) {
link.rel = rel
link.href = `${baseUrl}${icon}`
link.type = `image/${icon.split('.').pop()}`
document?.head.append(link)
}
return
}
elements?.forEach(el => el.href = `${baseUrl}${icon}`)
}
watch(
favicon,
(i, o) => {
if (typeof i === 'string' && i !== o)
applyIcon(i)
},
{ immediate: true },
)
return favicon
}
export type UseFaviconReturn = ReturnType<typeof useFavicon>