angular-cn/aio/tools/transforms/angular-api-package/content-rules/noMarkdownHeadings.js

50 lines
1.7 KiB
JavaScript

/**
* A factory for creating a rule for the `checkContentRules` processor, which disallows markdown
* headings in a content property.
*
* @param {...number|string} disallowedHeadings
* Each parameter identifies heading levels that are not allowed. They can be in the form of:
*
* - a number (e.g. 1), which implies that the specified heading is not allowed
* - a range (e.g. '2,3'), which implies the range of headings that are not allowed
*
* (A range can be open ended on the upper bound by not specifying a value after the comma.)
*
* @example
* To create a rule that will only allow level 3 headings:
*
* ```
* const rule = createNoMarkdownHeadingRule(1, 2, '4,');
* ```
*
*/
module.exports = function createrNoMarkdownHeadingRule() {
const args = Array.prototype.slice.apply(arguments);
const disallowedHeadings = args.map(arg => `#{${arg}}`);
if (!disallowedHeadings.length) {
disallowedHeadings.push('#{1,}');
}
const regex = new RegExp(`^ {0,3}(${disallowedHeadings.join('|')}) +.*$`, 'mg');
return (doc, prop, value) => {
let match, matches = [];
while(match = regex.exec(value)) { // eslint-disable-line no-cond-assign
matches.push(match[0]);
}
if (matches.length) {
const list = listify(matches.map(match => `"${match}"`));
return `Invalid headings found in "${prop}" property: ${list}.`;
}
};
};
/**
* Convert an array of strings in to a human list - e.g separated by commas and the word `and`.
* @param {string[]} values The strings to convert to a list
*/
function listify(values) {
if (values.length <= 1) return values;
const last = values[values.length - 1];
const rest = values.slice(0, values.length - 1);
return [rest.join(', '), last].join(' and ');
}