Skip to content

rules-index.hbs #406

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

Merged
merged 10 commits into from
Apr 9, 2018
Merged
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
19 changes: 19 additions & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,22 @@ descriptions:
"contributor-guide/development-environment": What you need to do to start developing for sonar
"contributor-guide/index.md": Learn about the different pieces that build sonarwhal and what each one of them does

categories:
accessibility:
description: Is your site usable via the keyboard? Does your content have enough contrast to be read without issues? Everyone should enjoy your content. Let us help you!
name: Accessibility
development:
description: "Web developers use a wide variety of tools: bundlers, transpilers, optimizers... But sometimes there can be problems when using them together or the configuration might not be the most optimal. Let us take care of this for you!"
name: Development
interoperability:
description: The web has been around for decades and it can be accessed from many different devices and form factors, old and new. These rules help you make your sites more interoperable so your users can have a better experience no matter how they visit you.
name: Interoperability
pwa:
description: Progressive Web Apps allow your users to have a more immersive experience within your site. Make sure your PWA looks the best no matter the platform of your users.
name: PWA
performance:
description: No one likes to wait while a website loads. Validate that you are using the right compression, cache strategy and more to make your site (re)load faster.
name: Performance
security:
description: Browsers are one of the main vectors for attacks. The web platform has many features that allow you to mitigate the risks. Are you doing everything you can to keep your users safe?
name: Security
170 changes: 158 additions & 12 deletions helpers/update-content.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,177 @@
/* global config cp exec ls mv rm */
const _ = require('lodash');
const getDirname = require('path').dirname;
const mkdirp = require('mkdirp');
const os = require('os');
const shell = require('shelljs/global'); // eslint-disable-line no-unused-vars
const fs = require('fs');
const path = require('path');
const yamlLoader = require('js-yaml');

const configDir = path.resolve(__dirname, '..', '_config.yml');
const hexoConfig = yamlLoader.safeLoad(fs.readFileSync(configDir, 'utf8')); // eslint-disable-line no-sync

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 DATA_DIR = `${DEST_DIR}/_data`;
const TMP_DIR = require('./mktemp')();
const PACKAGES_TMP_DIR = `${TMP_DIR}/packages`;
const categories = {};

const processRule = (rule, isSummary) => {
const processedRule = {
/*
* For packages with multiple rules we have a summary
* file with how to install and links to all the rules.
* This property is used to not take into account in
* the rule index page total.
*/
isSummary: isSummary === true,
link: `/docs/user-guide/rules/${rule}/`,
name: rule.replace(/^rule-/, '')
};

return processedRule;
};

/**
* 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, category) => {
const includedRules = category.rules;

const singleRules = includedRules.filter((ruleName) => {
return !ruleName.includes('/');
});

/*
* Rules with id: package-name/rule-name will be
* considered part of a package with multiple rules
*/
const multiRules = includedRules.filter((ruleName) => {
return ruleName.includes('/');
});

/*
* Group rules by package name.
*/
const packagesName = _.groupBy(multiRules, (ruleName) => {
return ruleName.split('/')[0];
});

const rules = _.map(singleRules, processRule);

const multiRulesProcessed = _.reduce(packagesName, (multi, values, key) => {
// Add an item with the link to the package with multiple rules itself.
const partial = processRule(key, true);

multi.push(partial);

// Add an item for each individual rule for a package with multiple rules.
return multi.concat(_.map(values, processRule));
}, []);

const processedCategory = {
description: category.description,
link: `/docs/user-guide/rules/${category.name}/`,
name: category.name,
rules: rules.concat(multiRulesProcessed)
};

allCategories.push(processedCategory);

return allCategories;
}, []);

return { categories: processedCategories };
};

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`, `${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 ruleDocs = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/{README.md,/docs/*.md}`);
const rules = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/src/!(index).ts`);

// Create folder if not exist before writing file.
// Reference: https://stackoverflow.com/a/16317628
const safeWriteFile = (dir, content) => {
const folderPath = getDirname(dir);

mkdirp.sync(folderPath);
fs.writeFileSync(dir, content); // eslint-disable-line no-sync
};

// Get rule documentations.
ruleDocs.forEach((ruleDocPath) => {
const ruleDocPathSplitted = ruleDocPath.split('/').reverse();
let ruleName;

if (ruleDocPathSplitted[1] === 'docs') {
ruleName = `${ruleDocPathSplitted[2]}/${ruleDocPathSplitted[0].replace('.md', '')}`;

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`);
mkdirp.sync(path.join(process.cwd(), DEST_RULES_DIR, path.dirname(ruleName)));
} else {
ruleName = ruleDocPathSplitted[1];
}

const rules = ls('-R', `${PACKAGES_TMP_DIR}/rule-*/README.md`);
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 ruleNameRegex = /id:\s*'([^']*)'/;
const ruleNameMatch = ruleContent.match(ruleNameRegex);
const categoryRegex = /category:\s*Category\.([a-z]*)/;
const categoryMatch = ruleContent.match(categoryRegex);

// If we don't find the category or the name, we will assume that it is not a rule.
if (categoryMatch && ruleNameMatch) {
const category = categoryMatch.pop();
const ruleName = `rule-${ruleNameMatch.pop()}`;

if (categories[category]) {
categories[category].rules.push(ruleName);
} else {
categories[category] = {
description: hexoConfig.categories[category].description,
name: hexoConfig.categories[category].name,
rules: [ruleName]
};
}
}
});

// Generate JSON file that contains the category-rule information.
const processedCategories = processCategories(categories);

fs.writeFileSync(`${DATA_DIR}/categories.json`, JSON.stringify(processedCategories), 'utf8'); //eslint-disable-line no-sync

mv(rulePath, destRulePath);
processedCategories.categories.forEach((category) => {
safeWriteFile(`${DEST_RULES_DIR}/${category.name}/index.md`, `# ${category.name}${os.EOL}`);
});

rm('-rf', TMP_DIR);
6 changes: 6 additions & 0 deletions helpers/updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ const generateFrontMatterInfo = (filePath, title, description, currentFrontMatte
tocTitle: tocTitle ? tocTitle.replace(/-/g, ' ') : tocTitle
};

if (originalFile.endsWith('index.md')) {
newFrontMatter.contentType = 'index';
} else {
newFrontMatter.contentType = 'details';
}

const finalFrontMatterData = _.assign(newFrontMatter, existingFrontMatter);
// Override frontmatter if there are existing frontmatter values.

Expand Down
Loading