-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathuseSiteOverrides.ts
More file actions
126 lines (109 loc) · 3.42 KB
/
useSiteOverrides.ts
File metadata and controls
126 lines (109 loc) · 3.42 KB
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { isProduction, withBase } from '@rspress/core/runtime'
import virtual from 'doom-@global-virtual'
import { merge } from 'es-toolkit/compat'
import { useEffect, useMemo, useState } from 'react'
import { parse } from 'yaml'
import { isUnversioned, type Language } from '../../shared/index.js'
import type { DoomSite } from '../../shared/types.js'
import { namedTerms, type NamedTerms, type TermName } from '../../terms.js'
import { useLang } from './useTranslation.js'
export type SiteOverridesTerms = Record<TermName, string>
export interface SiteOverridesItem {
title?: string
logoText?: string
terms?: SiteOverridesTerms
}
export type SiteOverrides = {
[K in Exclude<keyof SiteOverridesItem, 'terms'>]?: Partial<
Record<Language, SiteOverridesItem[K]>
>
} & {
terms?: NamedTerms
}
export type NormalizedSiteOverrides = Record<Language, SiteOverridesItem>
const normalizeOverrides = <K extends string, T>(
origin: Partial<Record<K, Partial<Record<Language, T>>>>,
) =>
Object.keys(origin).reduce(
(acc, key_) => {
const key = key_ as K
const term = origin[key]
if (!term) {
return acc
}
const en = (acc.en[key] = term.en!)
acc.zh[key] = term.zh || en
acc.ru[key] = term.ru || en
return acc
},
{ en: {}, zh: {}, ru: {} } as Record<Language, Record<K, T>>,
)
let normalizedSiteOverrides: NormalizedSiteOverrides | undefined
let promise: Promise<NormalizedSiteOverrides> | undefined
const fetchSiteOverrides = async (
version?: string,
acpSite?: DoomSite,
): Promise<NormalizedSiteOverrides> => {
if (promise) {
return promise
}
const acpSiteOverridesUrl =
acpSite && isProduction()
? `${(virtual.prefix || '') + acpSite.base}${isUnversioned(version) ? '' : acpSite.version + '/'}overrides.yaml`
: null
const siteOverridesUrl = withBase('overrides.yaml')
const urls = [acpSiteOverridesUrl]
if (acpSiteOverridesUrl !== siteOverridesUrl) {
urls.push(siteOverridesUrl)
}
return (promise = Promise.all(
urls.map(async (url) => {
if (!url) {
return
}
const res = await fetch(url)
if (!res.ok) {
return
}
try {
return parse(await res.text()) as SiteOverrides
} catch {
//
}
}),
)
.then(([acpSiteOverrides, siteOverrides]) => ({
...(urls.length === 1 ? acpSiteOverrides : siteOverrides),
terms: merge(
{},
namedTerms,
acpSiteOverrides?.terms,
siteOverrides?.terms,
),
}))
.catch(() => ({ terms: namedTerms }))
.then(({ terms, ...siteOverrides }) => {
const normalizedSiteOverrides = normalizeOverrides(siteOverrides)
const normalizedTerms = normalizeOverrides(terms)
return {
en: { ...normalizedSiteOverrides.en, terms: normalizedTerms.en },
zh: { ...normalizedSiteOverrides.zh, terms: normalizedTerms.zh },
ru: { ...normalizedSiteOverrides.ru, terms: normalizedTerms.ru },
}
}))
}
export const useSiteOverrides = (): SiteOverridesItem => {
const [siteOverrides, setSiteOverrides] = useState(normalizedSiteOverrides)
const lang = useLang()
const acpSite = useMemo(
() => virtual.sites?.find((s) => s.name === 'acp'),
[],
)
useEffect(() => {
if (normalizedSiteOverrides) {
return
}
void fetchSiteOverrides(virtual.version, acpSite).then(setSiteOverrides)
}, [acpSite])
return siteOverrides?.[lang] || {}
}