forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
breadcrumbs.js
103 lines (90 loc) · 3.52 KB
/
breadcrumbs.js
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
export default async function breadcrumbs(req, res, next) {
if (!req.context.page) return next()
if (req.context.page.hidden) return next()
req.context.breadcrumbs = []
// Return an empty array on the landing page.
if (req.context.page.documentType === 'homepage') {
return next()
}
const currentSiteTree =
req.context.siteTree[req.context.currentLanguage][req.context.currentVersion]
const fallbackSiteTree = req.context.siteTree.en[req.context.currentVersion]
req.context.breadcrumbs = await getBreadcrumbs(
// Array of child pages on the root, i.e., the product level.
currentSiteTree.childPages,
fallbackSiteTree.childPages,
req.context.currentPath.slice(3),
req.context.currentLanguage
)
return next()
}
async function getBreadcrumbs(
pageArray,
fallbackPageArray,
currentPathWithoutLanguage,
intendedLanguage
) {
// Find the page that starts with the requested path
let childPage = findPageWithPath(currentPathWithoutLanguage, pageArray)
// Find the page in the fallback page array (likely the English sub-tree)
const fallbackChildPage =
findPageWithPath(currentPathWithoutLanguage, fallbackPageArray || []) || childPage
// No matches, we bail
if (!childPage && !fallbackChildPage) {
return []
}
// Didn't find the intended page, but found the fallback
if (!childPage) {
childPage = fallbackChildPage
}
const breadcrumb = {
documentType: childPage.page.documentType,
// give the breadcrumb the intendedLanguage, so nav through breadcrumbs doesn't inadvertantly change the user's selected language
href: `/${intendedLanguage}/${childPage.href.slice(4)}`,
title: childPage.renderedShortTitle || childPage.renderedFullTitle,
}
// Recursively loop through the childPages and create each breadcrumb, until we reach the
// point where the current siteTree page is the same as the requested page. Then stop.
if (childPage.childPages && currentPathWithoutLanguage !== childPage.href.slice(3)) {
return [
breadcrumb,
...(await getBreadcrumbs(
childPage.childPages,
fallbackChildPage.childPages,
currentPathWithoutLanguage,
intendedLanguage
)),
]
} else {
return [breadcrumb]
}
}
// Finds the page that starts with or equals the requested path in the array of
// pages e.g. if the current page is /actions/learn-github-actions/understanding-github-actions,
// depending on the pages in the pageArray agrument, would find:
//
// * /actions
// * /actions/learn-github-actions
// * /actions/learn-github-actions/understanding-github-actions
function findPageWithPath(pageToFind, pageArray) {
return pageArray.find((page) => {
const pageWithoutLanguage = page.href.slice(3)
const numPathSegments = pageWithoutLanguage.split('/').length
const pageToFindNumPathSegments = pageToFind.split('/').length
if (pageToFindNumPathSegments > numPathSegments) {
// if the current page to find has more path segments, add a trailing
// slash to the page comparison to avoid an overlap like:
//
// * /github-cli/github-cli/about-github-cli with /github
return pageToFind.startsWith(`${pageWithoutLanguage}/`)
} else if (pageToFindNumPathSegments === numPathSegments) {
// if the current page has the same number of path segments, only match
// if the paths are the same to avoid an overlap like:
//
// * /get-started/using-github with /get-started/using-git
return pageToFind === pageWithoutLanguage
} else {
return false
}
})
}