Skip to content

Commit aee9c68

Browse files
author
Peter Bengtsson
authored
Fix reconcile-category-dirs-with-ids.js (github#40154)
1 parent 59e2eb0 commit aee9c68

File tree

1 file changed

+47
-96
lines changed

1 file changed

+47
-96
lines changed

script/reconcile-category-dirs-with-ids.js

Lines changed: 47 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -2,145 +2,96 @@
22

33
// [start-readme]
44
//
5-
// An automated test checks for discrepancies between category directory names and
6-
// slugified category titles as IDs.
7-
//
8-
// If the test fails, a human needs to run this script to update the directory
9-
// names and add appropriate redirects.
10-
//
11-
// **This script is not currently supported on Windows.**
5+
// This script will say which category pages needs to be renamed
6+
// so they match their respective titles (from the front matter)
127
//
138
// [end-readme]
149

1510
import fs from 'fs'
1611
import path from 'path'
17-
import frontmatter from '../lib/read-frontmatter.js'
12+
import assert from 'node:assert/strict'
13+
1814
import walk from 'walk-sync'
19-
import slash from 'slash'
15+
import chalk from 'chalk'
2016
import GithubSlugger from 'github-slugger'
2117
import { decode } from 'html-entities'
18+
19+
import frontmatter from '../lib/read-frontmatter.js'
2220
import { renderContent } from '#src/content-render/index.js'
21+
import { allVersions } from '../lib/all-versions.js'
22+
import { ROOT } from '../lib/constants.js'
2323

2424
const slugger = new GithubSlugger()
2525

26-
const contentDir = path.join(process.cwd(), 'content')
27-
28-
// TODO fix path separators in the redirect
29-
if (process.platform.startsWith('win')) {
30-
console.log('This script cannot be run on Windows at this time! Exiting...')
31-
process.exit()
32-
}
26+
const contentDir = path.join(ROOT, 'content')
3327

34-
// Execute!
3528
main()
3629

3730
async function main() {
3831
const englishCategoryIndices = getEnglishCategoryIndices()
3932

33+
const shouldRename = []
34+
4035
for (const categoryIndex of englishCategoryIndices) {
4136
const contents = fs.readFileSync(categoryIndex, 'utf8')
42-
const { data, content } = frontmatter(contents)
37+
const { data } = frontmatter(contents)
4338

44-
// Get the parent directory name
4539
const categoryDirPath = path.dirname(categoryIndex)
4640
const categoryDirName = path.basename(categoryDirPath)
4741

48-
const title = await renderContent(data.title, {}, { textOnly: true })
42+
const currentVersionObj = allVersions['free-pro-team@latest']
43+
assert(currentVersionObj, "No current version found for 'free-pro-team@latest'")
44+
const context = {
45+
currentLanguage: 'en',
46+
currentVersionObj,
47+
}
48+
const title = await renderContent(data.title, context, { textOnly: true })
4949
slugger.reset()
5050
const expectedSlug = slugger.slug(decode(title))
5151

5252
// If the directory name already matches the expected slug, bail out now
5353
if (categoryDirName === expectedSlug) continue
5454

55+
if (data.allowTitleToDifferFromFilename) {
56+
continue
57+
}
58+
5559
// Figure out the new path for the category
5660
const categoryDirParentDir = path.dirname(categoryDirPath)
5761
const newPath = path.join(categoryDirParentDir, expectedSlug)
5862

59-
// Figure out redirect path
60-
const relativeOldPath = path.relative(contentDir, categoryDirPath)
61-
const redirectPath = '/' + slash(relativeOldPath)
62-
63-
// Log it
64-
const relativeNewPath = path.relative(contentDir, newPath)
65-
console.log(`Renaming category directory:
66-
Old: "${relativeOldPath}"
67-
New: "${relativeNewPath}"
68-
Redirect: "${redirectPath}"
69-
`)
70-
71-
// Add a new redirect to the frontmatter
72-
if (!data.redirect_from) {
73-
data.redirect_from = []
74-
}
75-
data.redirect_from.push(redirectPath)
76-
77-
// Update the category index file on disk
78-
fs.writeFileSync(categoryIndex, frontmatter.stringify(content, data, { lineWidth: 10000 }))
79-
80-
// Update all of the category's articles on disk as well to add a new redirect to their frontmatter
81-
for (const articleFileName of fs.readdirSync(categoryDirPath)) {
82-
const articlePath = path.join(categoryDirPath, articleFileName)
83-
84-
// Figure out redirect path
85-
const articlePathMinusExtension = path.join(
86-
categoryDirPath,
87-
path.basename(articleFileName, '.md'),
88-
)
89-
const redirectArticlePath = '/' + slash(path.relative(contentDir, articlePathMinusExtension))
90-
91-
// Log it
92-
const relativeOldArticlePath = path.relative(contentDir, articlePath)
93-
const newArticlePath = path.join(categoryDirParentDir, expectedSlug, articleFileName)
94-
const relativeNewArticlePath = path.relative(contentDir, newArticlePath)
95-
console.log(`Adding redirect to article:
96-
Old: "${relativeOldArticlePath}"
97-
New: "${relativeNewArticlePath}"
98-
Redirect: "${redirectArticlePath}"
99-
`)
100-
101-
const articleContents = fs.readFileSync(articlePath, 'utf8')
102-
const { data: articleData, content: articleContent } = frontmatter(articleContents)
103-
104-
// Add a new redirect to the frontmatter
105-
if (!articleData.redirect_from) {
106-
articleData.redirect_from = []
107-
}
108-
articleData.redirect_from.push(redirectArticlePath)
109-
110-
// Update the article file on disk
111-
fs.writeFileSync(
112-
articlePath,
113-
frontmatter.stringify(articleContent, articleData, { lineWidth: 10000 }),
114-
)
115-
}
63+
const oldRelativePath = path.relative(ROOT, categoryDirPath)
64+
const newRelativePath = path.relative(ROOT, newPath)
65+
shouldRename.push({ oldRelativePath, newRelativePath })
66+
}
11667

117-
// Update the reference to this category in the product index file on disk
118-
//
119-
// NOTE: This approach may update the same product index multiple times per
120-
// script run but TBH I'm OK with that in a manually executed script
121-
const productIndexPath = path.join(categoryDirParentDir, 'index.md')
122-
const productIndexContents = fs.readFileSync(productIndexPath, 'utf8')
123-
const { data: productIndexData, content: productIndex } = frontmatter(productIndexContents)
124-
const revisedProductIndex = productIndex.replace(
125-
new RegExp(`(\\s+)(?:/${categoryDirName})(\\s+)`, 'g'),
126-
`$1/${expectedSlug}$2`,
127-
)
128-
fs.writeFileSync(
129-
productIndexPath,
130-
frontmatter.stringify(revisedProductIndex, productIndexData, { lineWidth: 10000 }),
68+
if (shouldRename.length > 0) {
69+
console.log(
70+
chalk.yellow(
71+
`${shouldRename.length} ${
72+
shouldRename.length === 1 ? 'category' : 'categories'
73+
} need to be renamed because their title doesn't match their directory name.`,
74+
),
13175
)
76+
console.log(chalk.dim('Run the following commands to rename them:'))
13277

133-
console.log(`*** Updated product index "${productIndexPath}" for ☝️\n`)
134-
135-
// Finally, rename the directory
136-
fs.renameSync(categoryDirPath, newPath)
78+
for (const { oldRelativePath, newRelativePath } of shouldRename) {
79+
console.log(`./script/move-content.js ${oldRelativePath} ${newRelativePath}`)
80+
}
81+
} else {
82+
console.log(chalk.green('No categories need to be renamed! 🎉'))
13783
}
13884
}
13985

14086
function getEnglishCategoryIndices() {
14187
const walkOptions = {
14288
globs: ['*/*/**/index.md'],
143-
ignore: ['{rest,graphql,developers}/**', 'enterprise/admin/index.md', '**/articles/**'],
89+
ignore: [
90+
'{rest,graphql,developers}/**',
91+
'enterprise/admin/index.md',
92+
'**/articles/**',
93+
'**/early-access/**',
94+
],
14495
directories: false,
14596
includeBasePath: true,
14697
}

0 commit comments

Comments
 (0)