-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Expand file tree
/
Copy pathuseSiteNavigation.ts
More file actions
78 lines (66 loc) · 2.19 KB
/
useSiteNavigation.ts
File metadata and controls
78 lines (66 loc) · 2.19 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
import type { RichTranslationValues } from 'next-intl';
import { useTranslations } from 'next-intl';
import type { HTMLAttributeAnchorTarget } from 'react';
import { siteNavigation } from '#site/next.json.mjs';
import type {
FormattedMessage,
IntlMessageKeys,
NavigationEntry,
NavigationKeys,
} from '#site/types';
type Context = Record<string, RichTranslationValues>;
type Navigation = Record<string, NavigationEntry>;
type MappedNavigationEntry = {
items: Array<[string, MappedNavigationEntry]>;
label: FormattedMessage;
link: string;
target?: HTMLAttributeAnchorTarget | undefined;
};
// Provides Context replacement for variables within the Link. This is also something that is not going
// to happen in the future with `nodejs/nodejs.dev` codebase
const replaceLinkWithContext = (
link: string,
context?: RichTranslationValues
) =>
Object.entries(context || {}).reduce(
(finalLink, [find, replace]) =>
finalLink.replace(
`{${find}}`,
typeof replace === 'string' ? replace : ''
),
link
);
const useSiteNavigation = () => {
const t = useTranslations();
const mapNavigationEntries = (entries: Navigation, context: Context = {}) => {
const getFormattedMessage = (label: IntlMessageKeys, key: string) =>
t.rich(label, context[key] || {}) as FormattedMessage;
return Object.entries(entries).map(
([key, { label, link, items, target }]): [
string,
MappedNavigationEntry,
] => [
key,
{
target,
label: label ? getFormattedMessage(label, key) : '',
link: link ? replaceLinkWithContext(link, context[key]) : '',
items: items ? mapNavigationEntries(items, context) : [],
},
]
);
};
const getSideNavigation = (
keys: Array<NavigationKeys>,
context: Context = {}
) => {
const navigationEntries: Navigation = keys.reduce(
(acc, key) => ({ ...acc, [key]: siteNavigation.sideNavigation[key] }),
{}
);
return mapNavigationEntries(navigationEntries, context);
};
const navigationItems = mapNavigationEntries(siteNavigation.topNavigation);
return { getSideNavigation, navigationItems };
};
export default useSiteNavigation;