Skip to content

Commit 98f4163

Browse files
authored
Merge pull request github#18766 from github/update-categories-json
Update categories.json used by support
2 parents c652d7f + b2ea29e commit 98f4163

File tree

5 files changed

+85
-79
lines changed

5 files changed

+85
-79
lines changed

includes/sidebar-specific-product.html

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
{% capture fullPathToCategory %}{{category[1].href}}{% endcapture %}
2020

2121
<li class="sidebar-category py-1 {% if breadcrumbs.category.href == category[1].href %}active {% if currentPath == fullPathToCategory %}is-current-page {% endif %}{% endif %}{% if category[1].standalone %}standalone-category{% endif %}">
22+
{% if category[1].shortTitle %}{% assign categoryTitle = category[1].shortTitle %}{% else %}{% assign categoryTitle = category[1].title %}{% endif %}
2223
{% if category[1].standalone %}
23-
<a href="{{fullPathToCategory}}" class="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3">{{ category[1].title }}</a>
24+
<a href="{{fullPathToCategory}}" class="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3">{{ categoryTitle }}</a>
2425
{% else %}
2526
<details class="dropdown-withArrow details details-reset" {% if breadcrumbs.category.href == category[1].href or forloop.index < 4 %}open{% endif %}>
2627
<summary>
2728
<div class="d-flex flex-justify-between">
28-
<a href="{{fullPathToCategory}}" class="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3">{{ category[1].title }}</a>
29+
<a href="{{fullPathToCategory}}" class="pl-4 pr-2 py-2 f6 text-uppercase d-block flex-auto mr-3">{{ categoryTitle }}</a>
2930
{% if breadcrumbs.category.href == category[1].href or forloop.index < 4 %}
3031
<svg xmlns="http://www.w3.org/2000/svg" class="octicon flex-shrink-0 arrow mr-3" style="margin-top:7px" viewBox="0 0 16 16" width="16" height="16"> <path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></svg>
3132
{% endif %}
@@ -39,16 +40,18 @@
3940
{% for maptopic in category[1].maptopics %}
4041
{% unless maptopic[1].hidden %}
4142
{% capture fullPathToMaptopic %}{{maptopic[1].href}}{% endcapture %}
43+
{% if maptopic[1].shortTitle %}{% assign maptopicTitle = maptopic[1].shortTitle %}{% else %}{% assign maptopicTitle = maptopic[1].title %}{% endif %}
4244

4345
<li class="sidebar-maptopic {% if breadcrumbs.maptopic.href == maptopic[1].href %}active {% if currentPath == fullPathToMaptopic %}is-current-page{% endif %}{% endif %}">
44-
<a href="{{fullPathToMaptopic}}" class="pl-4 pr-5 py-2">{{ maptopic[1].title }}</a>
46+
<a href="{{fullPathToMaptopic}}" class="pl-4 pr-5 py-2">{{ maptopicTitle }}</a>
4547
<ul class="sidebar-articles my-2">
4648
{% for article in maptopic[1].articles %}
4749
{% unless article[1].hidden %}
4850
{% capture fullPathToArticle %}{{article[1].href}}{% endcapture %}
51+
{% if article[1].shortTitle %}{% assign articleTitle = article[1].shortTitle %}{% else %}{% assign articleTitle = article[1].title %}{% endif %}
4952

5053
<li class="sidebar-article {% if breadcrumbs.article.href == article[1].href %}active {% if currentPath == fullPathToArticle %}is-current-page{% endif %}{% endif %}">
51-
<a href="{{fullPathToArticle}}" class="pl-6 pr-5 py-1{% if forloop.last %} pb-2{% endif %}">{{ article[1].title }}</a>
54+
<a href="{{fullPathToArticle}}" class="pl-6 pr-5 py-1{% if forloop.last %} pb-2{% endif %}">{{ articleTitle }}</a>
5255
</li>
5356
{% endunless %}
5457
{% endfor %}
@@ -63,8 +66,9 @@
6366
{% for article in category[1].articles %}
6467
{% unless article[1].hidden %}
6568
{% capture fullPathToArticle %}{{article[1].href}}{% endcapture %}
69+
{% if article[1].shortTitle %}{% assign articleTitle = article[1].shortTitle %}{% else %}{% assign articleTitle = article[1].title %}{% endif %}
6670
<li class="sidebar-article {% if breadcrumbs.article.href == article[1].href %}active {% if currentPath == fullPathToArticle %}is-current-page{% endif %}{% endif %}">
67-
<a href="{{fullPathToArticle}}" class="pl-4 pr-5 py-1{% if forloop.last %} pb-2{% endif %}">{{ article[1].title }}</a>
71+
<a href="{{fullPathToArticle}}" class="pl-4 pr-5 py-1{% if forloop.last %} pb-2{% endif %}">{{ articleTitle }}</a>
6872
</li>
6973
{% endunless %}
7074
{% endfor %}

lib/site-tree-titles.js

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@ const flat = require('flat')
22
const renderContent = require('./render-content')
33
const delimiter = '#'
44

5-
// render localized and product-version-aware page title
6-
// note this only supports titles with liquid, not short titles
5+
// render localized and product-version-aware page title or shortTitle
76

87
module.exports = async function siteTreeTitles (siteTree, siteData) {
98
// use a non-period delimiter because versions contain periods (like 2.19)
109
const flatTree = flat(siteTree, { delimiter: delimiter })
1110

1211
const titlesWithLiquid = Object.entries(flatTree)
13-
.filter(([path, title]) => path.endsWith('title') && title.includes('{'))
12+
.filter(([path, shortOrLongTitle]) => path.endsWith('itle') && shortOrLongTitle && shortOrLongTitle.includes('{'))
1413

15-
await Promise.all(titlesWithLiquid.map(async ([path, title]) => {
16-
path = path.replace(`${delimiter}title`, '') // ignore the `title` path part for now
14+
await Promise.all(titlesWithLiquid.map(async ([path, shortOrLongTitle]) => {
15+
const isShortTitle = /shortTitle$/.test(path)
16+
17+
path = path.replace(`${delimiter}(shortT|t)itle`, '') // ignore the `title` path part for now
1718

1819
// derive values from path parts
1920
const [
@@ -31,29 +32,39 @@ module.exports = async function siteTreeTitles (siteTree, siteData) {
3132

3233
// create context object for rendering of dynamic liquid data in page titles
3334
const ctx = {
34-
page: { version },
35+
currentVersion: version,
3536
site: siteData[languageCode].site
3637
}
3738

38-
const renderedTitle = await renderContent(title, ctx, { textOnly: true })
39+
const renderedShortOrLongTitle = await renderContent(shortOrLongTitle, ctx, { textOnly: true })
3940

4041
// no product titles have liquid because we get them from lib/all-products.js
4142
// so we can assume all titles processed here will be either a category, maptopic, or article
4243
// we can also assume a category value will exist for any of these
4344
const currentCategory = siteTree[languageCode][version][products][product][categories][category]
4445

45-
if (!maptopic) currentCategory.title = renderedTitle
46+
if (!maptopic) {
47+
isShortTitle
48+
? currentCategory.shortTitle = renderedShortOrLongTitle
49+
: currentCategory.title = renderedShortOrLongTitle
50+
}
4651

4752
let currentMaptopic
4853
if (maptopic) {
4954
currentMaptopic = currentCategory[maptopics][maptopic]
50-
if (!article) currentMaptopic.title = renderedTitle
55+
if (!article) {
56+
isShortTitle
57+
? currentMaptopic.shortTitle = renderedShortOrLongTitle
58+
: currentMaptopic.title = renderedShortOrLongTitle
59+
}
5160
}
5261

5362
let currentArticle
5463
if (article) {
5564
currentArticle = currentMaptopic[articles][article]
56-
currentArticle.title = renderedTitle
65+
isShortTitle
66+
? currentArticle.shortTitle = renderedShortOrLongTitle
67+
: currentArticle.title = renderedShortOrLongTitle
5768
}
5869
}))
5970
}

lib/site-tree.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ function buildCategoriesTree (tocItems, versionedProductHref, pageMap, redirects
7878
if (!page) return
7979
if (!getApplicableVersions(page.versions).includes(version)) return
8080

81-
category.title = page.shortTitle || page.title
81+
category.title = page.title
82+
category.shortTitle = page.shortTitle
8283

8384
// support standalone pages at the category level, like actions/quickstart.md
8485
if (!page.tocItems) {
@@ -157,7 +158,8 @@ function buildArticlesTree (tocItems, versionedCategoryHref, pageMap, redirects,
157158
if (!page) return
158159
if (!getApplicableVersions(page.versions).includes(version)) return
159160

160-
article.title = page.shortTitle || page.title
161+
article.title = page.title
162+
article.shortTitle = page.shortTitle
161163
article.hidden = page.hidden
162164

163165
articleTree[article.href] = article
Lines changed: 50 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,54 @@
1-
// This middleware serves a file that's used by the GitHub support team
2-
// to quickly search for Help articles by title and insert the link to
3-
// the article into a reply to a customer.
41
const path = require('path')
5-
const matter = require('gray-matter')
6-
const readFileAsync = require('../lib/readfile-async')
7-
const dotcomDir = path.join(__dirname, '../content/github')
8-
const dotcomIndex = path.join(dotcomDir, 'index.md')
9-
const linkRegex = /{% (?:topic_)?link_in_list ?\/(.*?) ?%}/g
102

113
module.exports = async function categoriesForSupportTeam (req, res, next) {
12-
if (req.path !== '/categories.json') return next()
13-
const categories = await generateCategories()
14-
return res.json(categories)
15-
}
16-
17-
async function generateCategories () {
18-
// get links included in dotcom index page.
19-
// each link corresponds to a dotcom subdirectory
20-
// example: getting-started-with-github
21-
const links = getLinks(await readFileAsync(dotcomIndex, 'utf8'))
22-
23-
// get links included in each subdir's index page
24-
// these are links to articles
25-
const categories = await Promise.all(links.map(async link => {
26-
const category = {}
27-
const indexPath = getPath(link, 'index')
28-
const indexContents = await readFileAsync(indexPath, 'utf8')
29-
const { data, content } = matter(indexContents)
30-
31-
// get name from title frontmatter
32-
category.name = data.title
33-
34-
// get child article links
35-
const articleLinks = getLinks(content)
36-
37-
category.published_articles = (await Promise.all(articleLinks.map(async articleLink => {
38-
// get title from frontmatter
39-
const articlePath = getPath(link, articleLink)
40-
const articleContents = await readFileAsync(articlePath, 'utf8')
41-
const { data } = matter(articleContents)
42-
43-
// do not include map topics in list of published articles
44-
if (data.mapTopic) return
45-
46-
return {
47-
title: data.title,
48-
slug: articleLink
49-
}
50-
}))).filter(Boolean)
51-
52-
return category
53-
}))
54-
55-
return categories
56-
}
57-
58-
function getLinks (contents) {
59-
return contents.match(linkRegex)
60-
.map(link => link.match(linkRegex.source)[1])
61-
}
62-
63-
function getPath (link, filename) {
64-
return path.join(dotcomDir, link, `${filename}.md`)
4+
const englishSiteTree = req.context.siteTree.en
5+
6+
const allCategories = []
7+
8+
Object.keys(englishSiteTree).forEach(version => {
9+
const versionedProductsTree = englishSiteTree[version].products
10+
11+
Object.values(versionedProductsTree).forEach(productObj => {
12+
if (productObj.id === 'early-access') return
13+
if (productObj.external) return
14+
15+
Object.values(productObj.categories).forEach(categoryObj => {
16+
const articlesArry = []
17+
18+
if (categoryObj.maptopics) {
19+
Object.values(categoryObj.maptopics).forEach(maptopicObj => {
20+
Object.values(maptopicObj.articles).forEach(articleObj => {
21+
articlesArry.push({
22+
title: articleObj.title,
23+
slug: path.basename(articleObj.href)
24+
})
25+
})
26+
})
27+
}
28+
29+
if (categoryObj.standalone) {
30+
articlesArry.push({
31+
title: categoryObj.title,
32+
slug: path.basename(categoryObj.href)
33+
})
34+
}
35+
36+
if (categoryObj.articles) {
37+
Object.values(categoryObj.articles).forEach(articleObj => {
38+
articlesArry.push({
39+
title: articleObj.title,
40+
slug: path.basename(articleObj.href)
41+
})
42+
})
43+
}
44+
45+
allCategories.push({
46+
name: categoryObj.title,
47+
published_articles: articlesArry
48+
})
49+
})
50+
})
51+
})
52+
53+
return res.json(allCategories)
6554
}

middleware/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ module.exports = function (app) {
9797
app.use(asyncMiddleware(instrument('./archived-enterprise-versions')))
9898
app.use(instrument('./robots'))
9999
app.use(/(\/.*)?\/early-access$/, instrument('./contextualizers/early-access-links'))
100-
app.use(asyncMiddleware(instrument('./categories-for-support-team')))
100+
app.use('/categories.json', asyncMiddleware(instrument('./categories-for-support-team')))
101101
app.use(instrument('./loaderio-verification'))
102102
app.get('/_500', asyncMiddleware(instrument('./trigger-error')))
103103

0 commit comments

Comments
 (0)