Skip to content

Commit 39a27b4

Browse files
committed
New: Update rule landing page
* Enable automatic generation of `categories.json` to store the category-rule data. * Update rule landing page and category landing page with data. * Some fixes to adapt to the changes.
1 parent 319899f commit 39a27b4

File tree

12 files changed

+251
-168
lines changed

12 files changed

+251
-168
lines changed

helpers/update-content.js

+96-12
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,115 @@
11
/* global config cp exec ls mv rm */
2+
const _ = require('lodash');
3+
const getDirname = require('path').dirname;
4+
const mkdirp = require('mkdirp');
5+
const os = require('os');
26
const shell = require('shelljs/global'); // eslint-disable-line no-unused-vars
7+
const fs = require('fs');
38

49
const CLONE_URL = 'https://github.com/sonarwhal/sonarwhal.git'; // eslint-disable-line no-process-env
5-
const SOURCE_DIR = 'src/content';
10+
const DEST_DIR = 'src/content';
11+
const DEST_RULES_DIR = `${DEST_DIR}/docs/user-guide/rules`;
12+
const DATA_DIR = `${DEST_DIR}/_data`;
613
const TMP_DIR = require('./mktemp')();
714
const PACKAGES_TMP_DIR = `${TMP_DIR}/packages`;
15+
const categories = {};
16+
17+
/**
18+
* Process catogories to be suitable for Handlebars templating.
19+
* Before: { performance: ['rule-amp-validator'] }
20+
* After:
21+
* [{
22+
* name: 'performance',
23+
* rules: [{
24+
* link: 'rule-amp-validator/',
25+
* name: 'amp-validator'
26+
* }]
27+
* }]
28+
*/
29+
const processCategories = (cats) => {
30+
const processedCategories = _.reduce(cats, (allCategories, includedRules, category) => {
31+
const rules = _.map(includedRules, (rule) => {
32+
const processedRule = {
33+
link: `/docs/user-guide/rules/${rule}/`,
34+
name: rule.replace(/^rule-/, '')
35+
};
36+
37+
return processedRule;
38+
});
39+
40+
const processedCategory = {
41+
link: `/docs/user-guide/rules/${category}/`,
42+
name: category,
43+
rules
44+
};
45+
46+
allCategories.push(processedCategory);
47+
48+
return allCategories;
49+
}, []);
50+
51+
return { categories: processedCategories };
52+
};
853

954
config.fatal = true;
1055

1156
exec(`git clone ${CLONE_URL} "${TMP_DIR}"`);
1257

13-
rm('-rf', `${SOURCE_DIR}/docs/contributor-guide`);
14-
rm('-rf', `${SOURCE_DIR}/docs/user-guide`);
15-
rm('-rf', `${SOURCE_DIR}/about`);
58+
rm('-rf', `${DEST_DIR}/docs/contributor-guide`);
59+
rm('-rf', `${DEST_DIR}/docs/user-guide`);
60+
rm('-rf', `${DEST_DIR}/about`);
61+
62+
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/contributor-guide`, `${DEST_DIR}/docs/contributor-guide`);
63+
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/user-guide`, `${DEST_DIR}/docs/user-guide`);
64+
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/about`, `${DEST_DIR}`);
65+
cp(`${PACKAGES_TMP_DIR}/sonarwhal/CHANGELOG.md`, `${DEST_DIR}/about`);
66+
67+
const ruleDocs = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/README.md`);
68+
const rules = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/src/rule.ts`);
1669

17-
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/contributor-guide`, `${SOURCE_DIR}/docs/contributor-guide`);
18-
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/user-guide`, `${SOURCE_DIR}/docs/user-guide`);
19-
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/about`, `${SOURCE_DIR}`);
20-
cp(`${PACKAGES_TMP_DIR}/sonarwhal/CHANGELOG.md`, `${SOURCE_DIR}/about`);
70+
// Create folder if not exist before writing file.
71+
// Reference: https://stackoverflow.com/a/16317628
72+
const safeWriteFile = (dir, content) => {
73+
const folderPath = getDirname(dir);
2174

22-
const rules = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/README.md`);
75+
return mkdirp(folderPath, (err) => {
76+
if (err) {
77+
console.error(`Error creating path ${folderPath}: ${err.message}.`);
78+
}
2379

80+
fs.writeFile(dir, content);
81+
});
82+
};
83+
84+
// Get rule documentations.
85+
ruleDocs.forEach((ruleDocPath) => {
86+
const ruleName = ruleDocPath.split('/').reverse()[1];
87+
const destRuleDocPath = `${DEST_RULES_DIR}/${ruleName}.md`;
88+
89+
mv(ruleDocPath, destRuleDocPath);
90+
});
91+
92+
// Get category information of rules.
2493
rules.forEach((rulePath) => {
25-
const ruleName = rulePath.split('/').reverse()[1];
26-
const destRulePath = `${SOURCE_DIR}/docs/user-guide/rules/${ruleName}.md`;
94+
const ruleContent = fs.readFileSync(rulePath, 'utf8'); // eslint-disable-line no-sync
95+
const ruleName = rulePath.split('/').reverse()[2];
96+
const categoryRegex = /category:\s*Category\.([a-z]*)/;
97+
const category = ruleContent.match(categoryRegex).pop();
98+
99+
if (categories[category]) {
100+
categories[category].push(ruleName);
101+
} else {
102+
categories[category] = [ruleName];
103+
}
104+
});
105+
106+
// Generate JSON file that contains the category-rule information.
107+
const processedCategories = processCategories(categories);
108+
109+
fs.writeFileSync(`${DATA_DIR}/categories.json`, JSON.stringify(processedCategories), 'utf8'); //eslint-disable-line no-sync
27110

28-
mv(rulePath, destRulePath);
111+
processedCategories.categories.forEach((category) => {
112+
safeWriteFile(`${DEST_RULES_DIR}/${category.name}/index.md`, `# ${category.name}${os.EOL}`);
29113
});
30114

31115
rm('-rf', TMP_DIR);

helpers/updater.js

+6
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ const generateFrontMatterInfo = (filePath, title, description, currentFrontMatte
136136
tocTitle: tocTitle ? tocTitle.replace(/-/g, ' ') : tocTitle
137137
};
138138

139+
if (originalFile.endsWith('index.md')) {
140+
newFrontMatter.contentType = 'index';
141+
} else {
142+
newFrontMatter.contentType = 'details';
143+
}
144+
139145
const finalFrontMatterData = _.assign(newFrontMatter, existingFrontMatter);
140146
// Override frontmatter if there are existing frontmatter values.
141147

0 commit comments

Comments
 (0)