forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsite-tree.js
189 lines (139 loc) · 6.02 KB
/
site-tree.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
const path = require('path')
const findPageInVersion = require('./find-page-in-version')
const products = Object.values(require('../lib/all-products'))
const { getVersionedPathWithoutLanguage } = require('./path-utils')
const languageCodes = Object.keys(require('./languages'))
const addTitlesToTree = require('./site-tree-titles')
const allVersions = Object.keys(require('./all-versions'))
// This module builds a localized tree of every page on the site
// It includes single-source pages that have different variants
// for different product versions, e.g. dotcom vs GHES
//
// siteTree[languageCode][version].products[productHref].categories[categoryHref].maptopics[maptopicHref].articles
// or if a category has direct child articles:
// siteTree[languageCode][version].products[productHref].categories[categoryHref].articles
module.exports = async function buildSiteTree (pageMap, site, redirects) {
const siteTree = {}
languageCodes.forEach(languageCode => {
siteTree[languageCode] = {}
allVersions.forEach(version => {
siteTree[languageCode][version] = {}
const productTree = {}
products.forEach(item => {
const product = { title: item.name }
// return early if the product has external docs, like Atom
if (item.external) {
product.href = item.href
product.external = true
productTree[item.id] = product
return
}
product.href = item.href
// find the product TOC page and get TOC items
const page = findPageInVersion(item.href, pageMap, redirects, languageCode, version)
// skip if page can't be found in this version
if (!page) return
product.categories = buildCategoriesTree(page.tocItems, item.href, pageMap, redirects, version, languageCode)
productTree[item.id] = product
return null
})
siteTree[languageCode][version].products = productTree
})
})
await addTitlesToTree(siteTree, site)
return siteTree
}
function buildCategoriesTree (tocItems, productHref, pageMap, redirects, version, languageCode) {
const categoryTree = {}
// for every category in a product TOC...
tocItems.forEach(item => {
const category = {}
const categoryHref = path.join(productHref, item.href)
const versionedCategoryHref = getVersionedPathWithoutLanguage(categoryHref, version)
category.href = versionedCategoryHref
// find the category TOC page and get its TOC items
const page = findPageInVersion(categoryHref, pageMap, redirects, languageCode, version)
// skip if page can't be found in this version
if (!page) return
category.title = page.shortTitle || page.title
// support standalone pages at the category level, like actions/quickstart.md
if (!page.tocItems) {
category.standalone = true
}
// TOC items can be maptopics and/or articles
if (page.tocItems) {
const hasMaptopics = page.tocItems.some(item => item.type === 'maptopic')
// if TOC contains maptopics, build a maptopics tree
// otherwise build an articles tree
if (hasMaptopics) {
category.maptopics = buildMaptopicsTree(page.tocItems, categoryHref, pageMap, redirects, version, languageCode)
} else {
category.articles = buildArticlesTree(page.tocItems, categoryHref, pageMap, redirects, version, languageCode)
}
}
categoryTree[versionedCategoryHref] = category
})
return categoryTree
}
function buildMaptopicsTree (tocItems, categoryHref, pageMap, redirects, version, languageCode) {
const maptopicTree = {}
// for every maptopic in a category TOC...
tocItems
.filter(item => item.type === 'maptopic')
.forEach(item => {
const maptopic = {}
const maptopicHref = path.join(categoryHref, item.href)
const versionedMaptopicHref = getVersionedPathWithoutLanguage(maptopicHref, version)
maptopic.href = versionedMaptopicHref
// we already have access to the child articles via the category TOC items
// but we still need the page to get the available versions
const page = findPageInVersion(maptopicHref, pageMap, redirects, languageCode, version)
// skip if page can't be found in this version
if (!page) return
// if this is not a maptopic, return early
if (!page.mapTopic) return
const childArticles = getChildArticles(tocItems, item.href)
maptopic.title = page.title
maptopic.shortTitle = page.shortTitle
maptopic.hidden = page.hidden
// make the child articles accessible to the page object for maptopic rendering
if (!page.childArticles) page.childArticles = childArticles
maptopic.articles = buildArticlesTree(childArticles, categoryHref, pageMap, redirects, version, languageCode)
maptopicTree[versionedMaptopicHref] = maptopic
})
return maptopicTree
}
function buildArticlesTree (tocItems, categoryHref, pageMap, redirects, version, languageCode) {
const articleTree = {}
// REST categories may not have TOC items
if (!tocItems) return articleTree
// for every article in a maptopic (or category) TOC...
tocItems.forEach(item => {
const article = {}
const articleHref = path.join(categoryHref, item.href)
const versionedArticleHref = getVersionedPathWithoutLanguage(articleHref, version)
article.href = versionedArticleHref
const page = findPageInVersion(articleHref, pageMap, redirects, languageCode, version)
// skip if page can't be found in this version
if (!page) return
article.title = page.shortTitle || page.title
articleTree[versionedArticleHref] = article
})
return articleTree
}
// in a category TOC, get the {% link_in_list %} items under the current {% topic_link_in_list %}
function getChildArticles (tocItems, maptopicPath) {
let withinMaptopic = false
return tocItems.filter(item => {
if (item.type === 'maptopic') {
if (item.href === maptopicPath) {
withinMaptopic = true
} else {
withinMaptopic = false
}
} else {
if (withinMaptopic) return item.href
}
return false
})
}