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
|
/* eslint-disable max-statements */
import { useIntl } from 'react-intl';
import type { BreadcrumbList } from 'schema-dts';
import type { BreadcrumbsItem } from '../../components';
import { CONFIG } from '../config';
import { ROUTES } from '../constants';
import { slugify } from '../helpers';
const isArticle = (url: string) => url.startsWith(`${ROUTES.ARTICLE}/`);
const isHome = (url: string) => url === '/';
const isPageNumber = (url: string) => url.includes('/page/');
const isProject = (url: string) => url.startsWith(`${ROUTES.PROJECTS}/`);
const isSearch = (url: string) => url.startsWith(ROUTES.SEARCH);
const isThematic = (url: string) => url.startsWith(`${ROUTES.THEMATICS}/`);
const isTopic = (url: string) => url.startsWith(`${ROUTES.TOPICS}/`);
const hasBlogAsParent = (url: string) =>
isArticle(url) ||
isPageNumber(url) ||
isSearch(url) ||
isThematic(url) ||
isTopic(url);
export type useBreadcrumbProps = {
/**
* The current page title.
*/
title: string;
/**
* The current page url.
*/
url: string;
};
export type useBreadcrumbReturn = {
/**
* The breadcrumb items.
*/
items: BreadcrumbsItem[];
/**
* The breadcrumb JSON schema.
*/
schema: BreadcrumbList['itemListElement'][];
};
/**
* Retrieve the breadcrumb items.
*
* @param {useBreadcrumbProps} props - An object (the current page title & url).
* @returns {useBreadcrumbReturn} The breadcrumb items and its JSON schema.
*/
export const useBreadcrumb = ({
title,
url,
}: useBreadcrumbProps): useBreadcrumbReturn => {
const intl = useIntl();
const labels = {
home: intl.formatMessage({
defaultMessage: 'Home',
description: 'Breadcrumb: home label',
id: 'j5k9Fe',
}),
blog: intl.formatMessage({
defaultMessage: 'Blog',
description: 'Breadcrumb: blog label',
id: 'Es52wh',
}),
projects: intl.formatMessage({
defaultMessage: 'Projects',
description: 'Breadcrumb: projects label',
id: '28GZdv',
}),
};
const items: BreadcrumbsItem[] = [
{ id: 'home', name: labels.home, url: '/' },
];
const schema: BreadcrumbList['itemListElement'][] = [
{
'@type': 'ListItem',
position: 1,
name: labels.home,
item: CONFIG.url,
},
];
if (isHome(url)) return { items, schema };
if (hasBlogAsParent(url)) {
items.push({ id: 'blog', name: labels.blog, url: ROUTES.BLOG });
schema.push({
'@type': 'ListItem',
position: 2,
name: labels.blog,
item: `${CONFIG.url}${ROUTES.BLOG}`,
});
}
if (isProject(url)) {
items.push({ id: 'projects', name: labels.projects, url: ROUTES.PROJECTS });
schema.push({
'@type': 'ListItem',
position: 2,
name: labels.projects,
item: `${CONFIG.url}${ROUTES.PROJECTS}`,
});
}
items.push({ id: slugify(title), name: title, url });
schema.push({
'@type': 'ListItem',
position: schema.length + 1,
name: title,
item: `${CONFIG.url}${url}`,
});
return { items, schema };
};
|