forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
breadcrumbs.js
90 lines (80 loc) · 2.69 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
export default function breadcrumbs(req, res, next) {
if (!req.context.page) return next()
const isEarlyAccess = req.context.page.relativePath.startsWith('early-access')
if (req.context.page.hidden && !isEarlyAccess) return next()
req.context.breadcrumbs = []
// Return an empty array on the landing page.
if (req.context.page.documentType === 'homepage') {
return next()
}
req.context.breadcrumbs = getBreadcrumbs(req, isEarlyAccess)
return next()
}
const earlyAccessExceptions = ['insights', 'enterprise-importer']
function getBreadcrumbs(req, isEarlyAccess) {
let cutoff = 0
// When in Early access docs consider the "root" be much higher.
// E.g. /en/early-access/github/migrating/understanding/about
// we only want it start at /migrating/understanding/about
// Essentially, we're skipping "/early-access" and its first
// top-level like "/github"
if (isEarlyAccess) {
const split = req.context.currentPath.split('/')
// There are a few exceptions to this rule for the
// /{version}/early-access/<product-name>/... URLs because they're a
// bit different.
// If there are more known exceptions, add them to the array above.
if (earlyAccessExceptions.some((product) => split.includes(product))) {
cutoff = 1
} else {
cutoff = 2
}
}
const breadcrumbs = traverseTreeTitles(
req.context.currentPath,
req.context.currentProductTreeTitles
)
;[...Array(cutoff)].forEach(() => breadcrumbs.shift())
return breadcrumbs
}
// Return an array as if you'd traverse down a tree. Imagine a tree like
//
// (root /)
// / \
// (/foo) (/bar)
// / \
// (/foo/bar) (/foo/buzz)
//
// If the "currentPath" is `/foo/buzz` what you want to return is:
//
// [
// {href: /, title: TITLE},
// {href: /foo, title: TITLE}
// {href: /foo/buzz, title: TITLE}
// ]
//
function traverseTreeTitles(currentPath, tree) {
const { href, title, shortTitle } = tree
const crumbs = [
{
href,
title: shortTitle || title,
},
]
const currentPathSplit = Array.isArray(currentPath) ? currentPath : currentPath.split('/')
for (const child of tree.childPages) {
if (isParentOrEqualArray(child.href.split('/'), currentPathSplit)) {
crumbs.push(...traverseTreeTitles(currentPathSplit, child))
// Only ever going down 1 of the children
break
}
}
return crumbs
}
// Return true if an array is part of another array or equal.
// Like `/foo/bar` is part of `/foo/bar/buzz`.
// But also include `/foo/bar/buzz`.
// Don't include `/foo/ba` if the final path is `/foo/baring`.
function isParentOrEqualArray(base, final) {
return base.every((part, i) => part === final[i])
}