-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
chore: check rule examples for syntax errors #17718
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
Changes from 1 commit
538e7e8
8d8a293
2c218fe
8822850
e9788b6
dba855e
3587faa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,28 @@ | ||||||
"use strict"; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add some comments in this file explaining how this works? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added some comments in b5b247a. |
||||||
|
||||||
module.exports = | ||||||
function markdownItRuleExample({ open, close }) { | ||||||
return { | ||||||
validate(info) { | ||||||
return /^\s*(?:in)?correct(?!\S)/u.test(info); | ||||||
}, | ||||||
render(tokens, index) { | ||||||
const tagToken = tokens[index]; | ||||||
|
||||||
if (tagToken.nesting < 0) { | ||||||
return close ? close() : void 0; | ||||||
} | ||||||
|
||||||
const { type, parserOptionsJSON } = /^\s*(?<type>\S+)(\s+(?<parserOptionsJSON>.+?))?\s*$/u.exec(tagToken.info).groups; | ||||||
|
const { type, parserOptionsJSON } = /^\s*(?<type>\S+)(\s+(?<parserOptionsJSON>.+?))?\s*$/u.exec(tagToken.info).groups; | |
const { type, parserOptionsJSON } = /^\s*(?<type>\S+)(\s+(?<parserOptionsJSON>\S.*?))?\s*$/u.exec(tagToken.info).groups; |
To avoid crashing on multiple trailing spaces.
const { type, parserOptionsJSON } = /^\s*(?<type>\S+)(\s+(?<parserOptionsJSON>.+?))?\s*$/u.exec("correct ").groups;
console.log({ type, parserOptionsJSON }); // { type: 'correct', parserOptionsJSON: ' ' }
parserOptionsJSON && JSON.parse(parserOptionsJSON); // SyntaxError: Unexpected end of JSON input
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Fixed in 512334f.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
"./use-at-your-own-risk": "./lib/unsupported-api.js" | ||
}, | ||
"scripts": { | ||
"build:docs:check-rule-examples": "node Makefile.js checkRuleExamples", | ||
|
||
"build:docs:update-links": "node tools/fetch-docs-links.js", | ||
"build:site": "node Makefile.js gensite", | ||
"build:webpack": "node Makefile.js webpack", | ||
|
@@ -42,6 +43,7 @@ | |
"git add packages/js/src/configs/eslint-all.js" | ||
], | ||
"docs/src/rules/*.md": [ | ||
"node tools/check-rule-examples.js", | ||
"node tools/fetch-docs-links.js", | ||
"git add docs/src/_data/further_reading_links.json" | ||
], | ||
|
@@ -132,6 +134,8 @@ | |
"gray-matter": "^4.0.3", | ||
"lint-staged": "^11.0.0", | ||
"load-perf": "^0.2.0", | ||
"markdown-it": "^12.2.0", | ||
"markdown-it-container": "^3.0.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two are the same versions as in |
||
"markdownlint": "^0.31.1", | ||
"markdownlint-cli": "^0.37.0", | ||
"marked": "^4.0.8", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
title: Lorem Ipsum | ||
--- | ||
|
||
This file contains rule example code with syntax errors. | ||
|
||
<!-- markdownlint-capture --> | ||
<!-- markdownlint-disable MD040 --> | ||
::: incorrect { "sourceType": "script" } | ||
|
||
``` | ||
export default "foo"; | ||
``` | ||
|
||
::: | ||
<!-- markdownlint-restore --> | ||
|
||
:::correct | ||
|
||
```ts | ||
const foo = "bar"; | ||
|
||
const foo = "baz"; | ||
``` | ||
|
||
::: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
This file contains rule example code without syntax errors. | ||
|
||
::: incorrect | ||
|
||
```js | ||
export default⏎ | ||
"foo"; | ||
``` | ||
|
||
::: | ||
|
||
::: correct { "ecmaFeatures": { "jsx": true } } | ||
|
||
```jsx | ||
const foo = <bar></bar>; | ||
``` | ||
|
||
::: | ||
|
||
The following code block is not a rule example, so it won't be checked: | ||
|
||
```js | ||
!@#$%^&*() | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Requirements | ||
//------------------------------------------------------------------------------ | ||
|
||
const assert = require("assert"); | ||
const { execFile } = require("child_process"); | ||
const { promisify } = require("util"); | ||
|
||
//------------------------------------------------------------------------------ | ||
// Helpers | ||
//------------------------------------------------------------------------------ | ||
|
||
/** | ||
* Runs check-rule-examples on the specified files. | ||
* @param {...string} filenames Files to be passed to check-rule-examples. | ||
* @returns {Promise<ChildProcess>} An object with properties `stdout` and `stderr` on success. | ||
* @throws An object with properties `code`, `stdout` and `stderr` on success. | ||
*/ | ||
async function runCheckRuleExamples(...filenames) { | ||
return await promisify(execFile)( | ||
process.execPath, | ||
["--no-deprecation", "tools/check-rule-examples.js", ...filenames] | ||
); | ||
} | ||
|
||
//------------------------------------------------------------------------------ | ||
// Tests | ||
//------------------------------------------------------------------------------ | ||
|
||
describe("check-rule-examples", () => { | ||
|
||
it("succeeds when not passed any files", async () => { | ||
const childProcess = await runCheckRuleExamples(); | ||
|
||
assert.strictEqual(childProcess.stdout, ""); | ||
assert.strictEqual(childProcess.stderr, ""); | ||
}); | ||
|
||
it("succeeds when passed a syntax error free file", async () => { | ||
const childProcess = await runCheckRuleExamples("tests/fixtures/good-examples.md"); | ||
|
||
assert.strictEqual(childProcess.stdout, ""); | ||
assert.strictEqual(childProcess.stderr, ""); | ||
}); | ||
|
||
it("fails when passed a file with a syntax error", async () => { | ||
const promise = runCheckRuleExamples("tests/fixtures/good-examples.md", "tests/fixtures/bad-examples.md"); | ||
|
||
await assert.rejects( | ||
promise, | ||
{ | ||
code: 1, | ||
stdout: "", | ||
stderr: | ||
"\n" + | ||
"tests/fixtures/bad-examples.md\n" + | ||
" 11:4 error Missing language tag: use one of 'javascript', 'js' or 'jsx'\n" + | ||
" 12:1 error Syntax error: 'import' and 'export' may appear only with 'sourceType: module'\n" + | ||
" 20:4 error Nonstandard language tag 'ts': use one of 'javascript', 'js' or 'jsx'\n" + | ||
" 23:7 error Syntax error: Identifier 'foo' has already been declared\n" + | ||
"\n" + | ||
"✖ 4 problems (4 errors, 0 warnings)\n" + | ||
"\n" | ||
} | ||
); | ||
}); | ||
|
||
it("fails when a file cannot be processed", async () => { | ||
const promise = runCheckRuleExamples("tests/fixtures/non-existing-examples.md"); | ||
|
||
await assert.rejects( | ||
promise, | ||
{ | ||
code: 1, | ||
stdout: "", | ||
stderr: | ||
"\n" + | ||
"tests/fixtures/non-existing-examples.md\n" + | ||
" 0:0 error Error checking file: ENOENT: no such file or directory, open 'tests/fixtures/non-existing-examples.md'\n" + | ||
"\n" + | ||
"✖ 1 problem (1 error, 0 warnings)\n" + | ||
"\n" | ||
} | ||
); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to work on Windows, probably because
exec()
runs commands throughcmd.exe
which doesn't expand*.md
.Perhaps we could pass no arguments and in that case find all rule docs files in the tool? Something like
fetch-docs-links
is doing:eslint/tools/fetch-docs-links.js
Lines 43 to 48 in 21ebf8a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this on GithHub Actions with windows-latest and it seemed to be working, so it's possible that I did a mistake, or maybe the containers have a special configuration that would let the task run. Now I'm testing on a real Windows machine, and I can reproduce the error above.
But I noticed that there is also another glitch: when shelljs'
exec
is used to run the command, color and underlining are not rendered in the terminal.This is how it looks like when I run the script directly with node:
And this is what I'm getting when I run it with
exec
in the Makefile:Probably because
stout
is not a TTY stream in the second example. It would be nice to fix that as well. I'll see what I can do.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed the problem by using glob to expand the patterns passed on the command line into file names, and I stopped using
exec
because its behavior depends on the system shell and is not the consistent on Windows and Unix. I'm using now Node's built-inexecFileSync
which correctly renders colors and underlining in th 10BC0 e terminal and does not automatically expand glob patterns.I've also updated the unit tests to ensure that the sequences for colors and underlining are inserted in the output (only for
check-rule-example.js
, because there are no tests for the Makefile). We could also revert this change if it makes the output in the tests difficult to read.Commit: 0f64bf9