Update MD040/fenced-code-language to add allowed_languages parameter (fixes #610).

This commit is contained in:
Sam Chen 2022-10-18 03:29:29 +08:00 committed by GitHub
parent c333976a44
commit 01ba757d3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 199 additions and 9 deletions

View file

@ -4152,16 +4152,25 @@ module.exports = {
"use strict"; "use strict";
// @ts-check // @ts-check
const { addErrorContext, filterTokens } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); const { addError, addErrorContext, filterTokens } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js");
module.exports = { module.exports = {
"names": ["MD040", "fenced-code-language"], "names": ["MD040", "fenced-code-language"],
"description": "Fenced code blocks should have a language specified", "description": "Fenced code blocks should have a language specified",
"tags": ["code", "language"], "tags": ["code", "language"],
"function": function MD040(params, onError) { "function": function MD040(params, onError) {
let allowed = params.config.allowed_languages;
allowed = Array.isArray(allowed) ?
allowed.map((lang) => lang.toLowerCase()) :
[];
filterTokens(params, "fence", function forToken(token) { filterTokens(params, "fence", function forToken(token) {
if (!token.info.trim()) { const lang = token.info.trim();
if (lang === "") {
addErrorContext(onError, token.lineNumber, token.line); addErrorContext(onError, token.lineNumber, token.line);
} }
else if (allowed.length > 0 &&
!allowed.includes(lang.toLowerCase())) {
addError(onError, token.lineNumber, `"${lang}" is not allowed`);
}
}); });
} }
}; };

View file

@ -1571,6 +1571,8 @@ Tags: code, language
Aliases: fenced-code-language Aliases: fenced-code-language
Parameters: allowed_languages (array of string; default [])
This rule is triggered when fenced code blocks are used, but a language isn't This rule is triggered when fenced code blocks are used, but a language isn't
specified: specified:
@ -1598,6 +1600,9 @@ Plain text in a code block
``` ```
```` ````
You can configure the `allowed_languages` parameter to specify a list of
languages code blocks could use. The default value is `[]` which means any language specifier is valid.
Rationale: Specifying a language improves content rendering by using the Rationale: Specifying a language improves content rendering by using the
correct syntax highlighting for code. More information: correct syntax highlighting for code. More information:
<https://cirosantilli.com/markdown-style-guide#option-code-fenced>. <https://cirosantilli.com/markdown-style-guide#option-code-fenced>.

View file

@ -2,16 +2,30 @@
"use strict"; "use strict";
const { addErrorContext, filterTokens } = require("../helpers"); const { addError, addErrorContext, filterTokens } = require("../helpers");
module.exports = { module.exports = {
"names": [ "MD040", "fenced-code-language" ], "names": [ "MD040", "fenced-code-language" ],
"description": "Fenced code blocks should have a language specified", "description": "Fenced code blocks should have a language specified",
"tags": [ "code", "language" ], "tags": [ "code", "language" ],
"function": function MD040(params, onError) { "function": function MD040(params, onError) {
let allowed = params.config.allowed_languages;
allowed = Array.isArray(allowed) ?
allowed.map((lang) => lang.toLowerCase()) :
[];
filterTokens(params, "fence", function forToken(token) { filterTokens(params, "fence", function forToken(token) {
if (!token.info.trim()) { const lang = token.info.trim();
if (lang === "") {
addErrorContext(onError, token.lineNumber, token.line); addErrorContext(onError, token.lineNumber, token.line);
} else if (
allowed.length > 0 &&
!allowed.includes(lang.toLowerCase())
) {
addError(
onError,
token.lineNumber,
`"${lang}" is not allowed`
);
} }
}); });
} }

View file

@ -207,7 +207,10 @@
"MD039": true, "MD039": true,
// MD040/fenced-code-language - Fenced code blocks should have a language specified // MD040/fenced-code-language - Fenced code blocks should have a language specified
"MD040": true, "MD040": {
// List of languages
"allowed_languages": []
},
// MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading // MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
"MD041": { "MD041": {

View file

@ -188,7 +188,9 @@ MD038: true
MD039: true MD039: true
# MD040/fenced-code-language - Fenced code blocks should have a language specified # MD040/fenced-code-language - Fenced code blocks should have a language specified
MD040: true MD040:
# List of languages
allowed_languages: []
# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading # MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
MD041: MD041:

View file

@ -347,6 +347,18 @@ for (const rule of rules) {
} }
}; };
break; break;
case "MD040":
scheme.properties = {
"allowed_languages": {
"description": "List of languages",
"type": "array",
"items": {
"type": "string"
},
"default": []
}
};
break;
case "MD025": case "MD025":
case "MD041": case "MD041":
scheme.properties = { scheme.properties = {

View file

@ -669,8 +669,22 @@
}, },
"MD040": { "MD040": {
"description": "MD040/fenced-code-language - Fenced code blocks should have a language specified", "description": "MD040/fenced-code-language - Fenced code blocks should have a language specified",
"type": "boolean", "type": [
"default": true "boolean",
"object"
],
"default": true,
"properties": {
"allowed_languages": {
"description": "List of languages",
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"additionalProperties": false
}, },
"fenced-code-language": { "fenced-code-language": {
"$ref": "#/properties/MD040" "$ref": "#/properties/MD040"

View file

@ -925,7 +925,7 @@ test("readme", (t) => new Promise((resolve) => {
})); }));
test("rules", (t) => new Promise((resolve) => { test("rules", (t) => new Promise((resolve) => {
t.plan(374); t.plan(375);
fs.readFile("doc/Rules.md", "utf8", fs.readFile("doc/Rules.md", "utf8",
(err, contents) => { (err, contents) => {
t.falsy(err); t.falsy(err);

View file

@ -0,0 +1,5 @@
{
"MD040": {
"allowed_languages": ["js", "scss", "md", "TS"]
}
}

View file

@ -0,0 +1,45 @@
# md040-allowed_languages.md
Code block with `html` not in allowed_languages:
```html
<h1>markdownlint</h1> {MD040:5}
```
Code block with `css` not in allowed_languages:
```css
body {} {MD040:11}
```
Code block with `js` in allowed_languages:
```js
console.log('markdownlint')
```
Code block with `scss` in allowed_languages:
```scss
body {
h1 {
color: red;
}
}
```
Code block with `md` in allowed_languages:
```MD
hello md
```
Code block with `TS` in allowed_languages:
```ts
body {
h1 {
color: red;
}
}
```

View file

@ -29318,6 +29318,87 @@ Generated by [AVA](https://avajs.dev).
`, `,
} }
## md040-allowed_languages.md
> Snapshot 1
{
errors: [
{
errorContext: null,
errorDetail: '"html" is not allowed',
errorRange: null,
fixInfo: null,
lineNumber: 5,
ruleDescription: 'Fenced code blocks should have a language specified',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md040',
ruleNames: [
'MD040',
'fenced-code-language',
],
},
{
errorContext: null,
errorDetail: '"css" is not allowed',
errorRange: null,
fixInfo: null,
lineNumber: 11,
ruleDescription: 'Fenced code blocks should have a language specified',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/Rules.md#md040',
ruleNames: [
'MD040',
'fenced-code-language',
],
},
],
fixed: `# md040-allowed_languages.md␊
Code block with \`html\` not in allowed_languages:␊
\`\`\`html␊
<h1>markdownlint</h1> {MD040:5}␊
\`\`\`␊
Code block with \`css\` not in allowed_languages:␊
\`\`\`css␊
body {} {MD040:11}␊
\`\`\`␊
Code block with \`js\` in allowed_languages:␊
\`\`\`js␊
console.log('markdownlint')␊
\`\`\`␊
Code block with \`scss\` in allowed_languages:␊
\`\`\`scss␊
body {␊
h1 {␊
color: red;␊
}␊
}␊
\`\`\`␊
Code block with \`md\` in allowed_languages:␊
\`\`\`MD␊
hello md␊
\`\`\`␊
Code block with \`TS\` in allowed_languages:␊
\`\`\`ts␊
body {␊
h1 {␊
color: red;␊
}␊
}␊
\`\`\`␊
`,
}
## md041-ignore-leading-comments-combined.md ## md041-ignore-leading-comments-combined.md
> Snapshot 1 > Snapshot 1