Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Auto-generate rule index #396

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions helpers/rule-index-template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Rules categories

{{#each categories}}
* [{{capitalize name}}](#{{name}})
{{/each}}

{{#each categories}}
## {{capitalize name}}

{{#each rules}}
* [`{{name}}`]({{link}})
{{/each}}

{{/each}}
103 changes: 91 additions & 12 deletions helpers/update-content.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,110 @@
/* global config cp exec ls mv rm */
const Handlebars = require('handlebars');
const _ = require('lodash');
const shell = require('shelljs/global'); // eslint-disable-line no-unused-vars
const fs = require('fs');

const CLONE_URL = 'https://github.com/sonarwhal/sonarwhal.git'; // eslint-disable-line no-process-env
const SOURCE_DIR = 'src/content';
const DEST_DIR = 'src/content';
const DEST_RULES_DIR = `${DEST_DIR}/docs/user-guide/rules`;
const TMP_DIR = require('./mktemp')();
// const TMP_DIR = 'C:/Users/Quing/AppData/Local/Temp/VpB2e';
const PACKAGES_TMP_DIR = `${TMP_DIR}/packages`;
const categories = {};

/**
* Process catogories to be suitable for Handlebars templating.
* Before: { performance: ['rule-amp-validator'] }
* After:
* [{
* name: 'performance',
* rules: [{
* link: 'rule-amp-validator/',
* name: 'amp-validator'
* }]
* }]
*/
const processCategories = (cats) => {
const processedCategories = _.reduce(cats, (allCategories, includedRules, category) => {
const rules = _.map(includedRules, (rule) => {
const processedRule = {
link: `${rule}/`,
name: rule.replace(/^rule-/, '')
};

return processedRule;
});

const processedCategory = {
name: category,
rules
};

allCategories.push(processedCategory);

return allCategories;
}, []);

return { categories: processedCategories };
};

/** Generate rule index markdown file. */
const getRuleIndexContent = (cats) => {
Handlebars.registerHelper('capitalize', (str) => {
const filtered = str.replace(/[^a-zA-Z0-9]/g, ' ');

return filtered.charAt(0).toUpperCase() + filtered.slice(1);
});

const templateContent = fs.readFileSync(`${__dirname}/rule-index-template.hbs`, 'utf8'); //eslint-disable-line no-sync
const template = Handlebars.compile(templateContent);
const ruleIndexContent = template(cats);

return ruleIndexContent;
};

config.fatal = true;

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

rm('-rf', `${SOURCE_DIR}/docs/contributor-guide`);
rm('-rf', `${SOURCE_DIR}/docs/user-guide`);
rm('-rf', `${SOURCE_DIR}/about`);
rm('-rf', `${DEST_DIR}/docs/contributor-guide`);
rm('-rf', `${DEST_DIR}/docs/user-guide`);
rm('-rf', `${DEST_DIR}/about`);

cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/contributor-guide`, `${SOURCE_DIR}/docs/contributor-guide`);
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/user-guide`, `${SOURCE_DIR}/docs/user-guide`);
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/about`, `${SOURCE_DIR}`);
cp(`${PACKAGES_TMP_DIR}/sonarwhal/CHANGELOG.md`, `${SOURCE_DIR}/about`);
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/contributor-guide`, `${DEST_DIR}/docs/contributor-guide`);
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/user-guide`, `${DEST_DIR}/docs/user-guide`);
cp('-R', `${PACKAGES_TMP_DIR}/sonarwhal/docs/about`, `${DEST_DIR}`);
cp(`${PACKAGES_TMP_DIR}/sonarwhal/CHANGELOG.md`, `${DEST_DIR}/about`);

const rules = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/README.md`);
const ruleDocs = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/README.md`);
const rules = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/src/rule.ts`);

// Get rule documentations.
ruleDocs.forEach((ruleDocPath) => {
const ruleName = ruleDocPath.split('/').reverse()[1];
const destRuleDocPath = `${DEST_RULES_DIR}/${ruleName}.md`;

mv(ruleDocPath, destRuleDocPath);
});

// Get category information of rules.
rules.forEach((rulePath) => {
const ruleName = rulePath.split('/').reverse()[1];
const destRulePath = `${SOURCE_DIR}/docs/user-guide/rules/${ruleName}.md`;
const ruleContent = fs.readFileSync(rulePath, 'utf8'); // eslint-disable-line no-sync
const ruleName = rulePath.split('/').reverse()[2];
const categoryRegex = /category:\s*Category\.([a-z]*)/;
const category = ruleContent.match(categoryRegex).pop();

mv(rulePath, destRulePath);
if (categories[category]) {
categories[category].push(ruleName);
} else {
categories[category] = [ruleName];
}
});

// Generate rule index markdown file.
const processedCategories = processCategories(categories);
const ruleIndexContent = getRuleIndexContent(processedCategories);

fs.writeFileSync(`${DEST_RULES_DIR}/index.md`, ruleIndexContent); //eslint-disable-line no-sync

rm('-rf', TMP_DIR);