|
1 | 1 | /* 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'); |
2 | 6 | const shell = require('shelljs/global'); // eslint-disable-line no-unused-vars
|
| 7 | +const fs = require('fs'); |
3 | 8 |
|
4 | 9 | 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`; |
6 | 13 | const TMP_DIR = require('./mktemp')();
|
7 | 14 | 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 | +}; |
8 | 53 |
|
9 | 54 | config.fatal = true;
|
10 | 55 |
|
11 | 56 | exec(`git clone ${CLONE_URL} "${TMP_DIR}"`);
|
12 | 57 |
|
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`); |
16 | 69 |
|
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); |
21 | 74 |
|
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 | + } |
23 | 79 |
|
| 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. |
24 | 93 | 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 |
27 | 110 |
|
28 |
| - mv(rulePath, destRulePath); |
| 111 | +processedCategories.categories.forEach((category) => { |
| 112 | + safeWriteFile(`${DEST_RULES_DIR}/${category.name}/index.md`, `# ${category.name}${os.EOL}`); |
29 | 113 | });
|
30 | 114 |
|
31 | 115 | rm('-rf', TMP_DIR);
|
0 commit comments