mirror of
https://github.com/remarkjs/remark-lint.git
synced 2024-08-17 15:50:25 +03:00
Refactor more code, improve small things
This commit is contained in:
parent
547188ec6f
commit
627363b2a2
@ -136,6 +136,7 @@
|
|||||||
"remark-comment-config": "^8.0.0",
|
"remark-comment-config": "^8.0.0",
|
||||||
"remark-gfm": "^4.0.0",
|
"remark-gfm": "^4.0.0",
|
||||||
"remark-github": "^12.0.0",
|
"remark-github": "^12.0.0",
|
||||||
|
"remark-mdx": "^3.0.0",
|
||||||
"remark-toc": "^9.0.0",
|
"remark-toc": "^9.0.0",
|
||||||
"remark-validate-links": "^13.0.0",
|
"remark-validate-links": "^13.0.0",
|
||||||
"strip-indent": "^4.0.0",
|
"strip-indent": "^4.0.0",
|
||||||
|
@ -206,8 +206,8 @@ const remarkLintCheckboxCharacterStyle = lintRule(
|
|||||||
value.slice(point.offset - 2, point.offset + 1)
|
value.slice(point.offset - 2, point.offset + 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Failsafe to make sure we don‘t crash if there actually isn’t a checkbox.
|
/* c8 ignore next 2 -- failsafe so we don’t crash if there actually isn’t
|
||||||
/* c8 ignore next */
|
* a checkbox. */
|
||||||
if (!match) return
|
if (!match) return
|
||||||
|
|
||||||
const style = node.checked ? checked : unchecked
|
const style = node.checked ? checked : unchecked
|
||||||
|
@ -182,7 +182,8 @@ When configured with `{ checked: 'x' }`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
- [x] List item
|
- [x] List item
|
||||||
@ -199,7 +200,8 @@ When configured with `{ checked: 'X' }`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
- [X] List item
|
- [X] List item
|
||||||
@ -216,7 +218,8 @@ When configured with `{ unchecked: ' ' }`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
- [ ] List item
|
- [ ] List item
|
||||||
@ -235,7 +238,8 @@ When configured with `{ unchecked: '\t' }`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
- [␉] List item
|
- [␉] List item
|
||||||
@ -250,7 +254,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
- [x] List item
|
- [x] List item
|
||||||
|
@ -159,7 +159,8 @@ content after them with a single space between.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
- [ ] List item
|
- [ ] List item
|
||||||
@ -176,7 +177,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
- [ ] List item
|
- [ ] List item
|
||||||
|
@ -57,26 +57,44 @@
|
|||||||
* @example
|
* @example
|
||||||
* {"name": "not-ok.md", "label": "output"}
|
* {"name": "not-ok.md", "label": "output"}
|
||||||
*
|
*
|
||||||
* 3:1-3:47: Move definitions to the end of the file (after the node at line `5`)
|
* 3:1-3:47: Move definitions to the end of the file (after `5:19`)
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* {"name": "ok-comments.md"}
|
* {"name": "ok-html-comments.md"}
|
||||||
*
|
*
|
||||||
* Paragraph.
|
* Paragraph.
|
||||||
*
|
*
|
||||||
* [example-1]: http://example.com/one/
|
* [example-1]: http://example.com/one/
|
||||||
*
|
*
|
||||||
* <!-- Comments are fine between and after definitions -->
|
* <!-- Comments are fine between and after definitions. -->
|
||||||
|
*
|
||||||
|
* [example-2]: http://example.com/two/
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* {"name": "ok-mdx-comments.mdx", "mdx": true}
|
||||||
|
*
|
||||||
|
* Paragraph.
|
||||||
|
*
|
||||||
|
* [example-1]: http://example.com/one/
|
||||||
|
*
|
||||||
|
* {/* Comments are fine in MDX. *␀/}
|
||||||
*
|
*
|
||||||
* [example-2]: http://example.com/two/
|
* [example-2]: http://example.com/two/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef {import('mdast').Definition} Definition
|
||||||
|
* @typedef {import('mdast').FootnoteDefinition} FootnoteDefinition
|
||||||
* @typedef {import('mdast').Root} Root
|
* @typedef {import('mdast').Root} Root
|
||||||
|
*
|
||||||
|
* @typedef {import('unist').Point} Point
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// <reference types="mdast-util-mdx" />
|
||||||
|
|
||||||
import {lintRule} from 'unified-lint-rule'
|
import {lintRule} from 'unified-lint-rule'
|
||||||
import {pointStart} from 'unist-util-position'
|
import {pointEnd, pointStart} from 'unist-util-position'
|
||||||
|
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||||
import {visit} from 'unist-util-visit'
|
import {visit} from 'unist-util-visit'
|
||||||
|
|
||||||
const remarkLintFinalDefinition = lintRule(
|
const remarkLintFinalDefinition = lintRule(
|
||||||
@ -91,40 +109,47 @@ const remarkLintFinalDefinition = lintRule(
|
|||||||
* Nothing.
|
* Nothing.
|
||||||
*/
|
*/
|
||||||
function (tree, file) {
|
function (tree, file) {
|
||||||
let last = 0
|
/** @type {Array<Definition | FootnoteDefinition>} */
|
||||||
|
const definitions = []
|
||||||
|
/** @type {Point | undefined} */
|
||||||
|
let last
|
||||||
|
|
||||||
visit(
|
visit(tree, function (node) {
|
||||||
tree,
|
if (node.type === 'definition' || node.type === 'footnoteDefinition') {
|
||||||
function (node) {
|
definitions.push(node)
|
||||||
const start = pointStart(node)
|
} else if (
|
||||||
|
node.type === 'root' ||
|
||||||
|
node.type === 'blockquote' ||
|
||||||
|
node.type === 'listItem' ||
|
||||||
|
// Ignore HTML comments.
|
||||||
|
(node.type === 'html' && /^[\t ]*<!--/.test(node.value)) ||
|
||||||
|
// Ignore MDX comments.
|
||||||
|
((node.type === 'mdxFlowExpression' ||
|
||||||
|
node.type === 'mdxTextExpression') &&
|
||||||
|
/^\s*\/\*/.test(node.value))
|
||||||
|
) {
|
||||||
|
// Empty.
|
||||||
|
} else {
|
||||||
|
const place = pointEnd(node)
|
||||||
|
|
||||||
// To do: ignore MDX comments?
|
if (place) {
|
||||||
// Ignore generated and HTML comment nodes.
|
last = place
|
||||||
if (
|
|
||||||
!start ||
|
|
||||||
node.type === 'root' ||
|
|
||||||
(node.type === 'html' && /^\s*<!--/.test(node.value))
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const line = start.line
|
for (const node of definitions) {
|
||||||
|
const point = pointStart(node)
|
||||||
|
|
||||||
if (node.type === 'definition') {
|
if (point && last && point.line < last.line) {
|
||||||
if (last && last > line) {
|
file.message(
|
||||||
file.message(
|
'Move definitions to the end of the file (after `' +
|
||||||
'Move definitions to the end of the file (after the node at line `' +
|
stringifyPosition(last) +
|
||||||
last +
|
'`)',
|
||||||
'`)',
|
node
|
||||||
node
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
} else if (last === 0) {
|
|
||||||
last = line
|
|
||||||
}
|
|
||||||
},
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,8 +33,11 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
"@types/unist": "^3.0.0",
|
||||||
|
"mdast-util-mdx": "^3.0.0",
|
||||||
"unified-lint-rule": "^2.0.0",
|
"unified-lint-rule": "^2.0.0",
|
||||||
"unist-util-position": "^5.0.0",
|
"unist-util-position": "^5.0.0",
|
||||||
|
"unist-util-stringify-position": "^4.0.0",
|
||||||
"unist-util-visit": "^5.0.0"
|
"unist-util-visit": "^5.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
|
@ -171,10 +171,10 @@ Another paragraph.
|
|||||||
###### Out
|
###### Out
|
||||||
|
|
||||||
```text
|
```text
|
||||||
3:1-3:47: Move definitions to the end of the file (after the node at line `5`)
|
3:1-3:47: Move definitions to the end of the file (after `5:19`)
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `ok-comments.md`
|
##### `ok-html-comments.md`
|
||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
@ -183,7 +183,28 @@ Paragraph.
|
|||||||
|
|
||||||
[example-1]: http://example.com/one/
|
[example-1]: http://example.com/one/
|
||||||
|
|
||||||
<!-- Comments are fine between and after definitions -->
|
<!-- Comments are fine between and after definitions. -->
|
||||||
|
|
||||||
|
[example-2]: http://example.com/two/
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
|
##### `ok-mdx-comments.mdx`
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
> 👉 **Note**: this example uses
|
||||||
|
> MDX ([`remark-mdx`][github-remark-mdx]).
|
||||||
|
|
||||||
|
```mdx
|
||||||
|
Paragraph.
|
||||||
|
|
||||||
|
[example-1]: http://example.com/one/
|
||||||
|
|
||||||
|
{/* Comments are fine in MDX. */}
|
||||||
|
|
||||||
[example-2]: http://example.com/two/
|
[example-2]: http://example.com/two/
|
||||||
```
|
```
|
||||||
@ -263,6 +284,8 @@ abide by its terms.
|
|||||||
|
|
||||||
[github-remark-lint]: https://github.com/remarkjs/remark-lint
|
[github-remark-lint]: https://github.com/remarkjs/remark-lint
|
||||||
|
|
||||||
|
[github-remark-mdx]: https://mdxjs.com/packages/remark-mdx/
|
||||||
|
|
||||||
[github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
|
[github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
|
||||||
|
|
||||||
[npm-install]: https://docs.npmjs.com/cli/install
|
[npm-install]: https://docs.npmjs.com/cli/install
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {lintRule} from 'unified-lint-rule'
|
import {lintRule} from 'unified-lint-rule'
|
||||||
|
import {location} from 'vfile-location'
|
||||||
|
|
||||||
const remarkLintFinalNewline = lintRule(
|
const remarkLintFinalNewline = lintRule(
|
||||||
{
|
{
|
||||||
@ -95,11 +96,11 @@ const remarkLintFinalNewline = lintRule(
|
|||||||
*/
|
*/
|
||||||
function (_, file) {
|
function (_, file) {
|
||||||
const value = String(file)
|
const value = String(file)
|
||||||
|
const end = location(file).toPoint(value.length)
|
||||||
const last = value.length - 1
|
const last = value.length - 1
|
||||||
|
|
||||||
if (last > -1 && value.charAt(last) !== '\n') {
|
if (end && last > -1 && value.charAt(last) !== '\n') {
|
||||||
// To do: warn at last character.
|
file.message('Missing newline character at end of file', end)
|
||||||
file.message('Missing newline character at end of file')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
"unified-lint-rule": "^2.0.0"
|
"unified-lint-rule": "^2.0.0",
|
||||||
|
"vfile-location": "^5.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
"typeCoverage": {
|
"typeCoverage": {
|
||||||
|
@ -143,6 +143,13 @@
|
|||||||
* {"name": "not-ok-html.md", "config": 2, "label": "output"}
|
* {"name": "not-ok-html.md", "config": 2, "label": "output"}
|
||||||
*
|
*
|
||||||
* 1:1-1:14: First heading level should be `2`
|
* 1:1-1:14: First heading level should be `2`
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* {"name": "ok.mdx", "mdx": true}
|
||||||
|
*
|
||||||
|
* In <b>MDX</b>, JSX is supported.
|
||||||
|
*
|
||||||
|
* <h1>First heading</h1>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,11 +165,14 @@
|
|||||||
* Configuration.
|
* Configuration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// <reference types="mdast-util-mdx" />
|
||||||
|
|
||||||
import {lintRule} from 'unified-lint-rule'
|
import {lintRule} from 'unified-lint-rule'
|
||||||
import {position} from 'unist-util-position'
|
import {position} from 'unist-util-position'
|
||||||
import {EXIT, visit} from 'unist-util-visit'
|
import {EXIT, visit} from 'unist-util-visit'
|
||||||
|
|
||||||
const re = /<h([1-6])/
|
const htmlRe = /<h([1-6])/
|
||||||
|
const jsxNameRe = /h([1-6])/
|
||||||
|
|
||||||
const remarkLintFirstHeadingLevel = lintRule(
|
const remarkLintFirstHeadingLevel = lintRule(
|
||||||
{
|
{
|
||||||
@ -187,11 +197,17 @@ const remarkLintFirstHeadingLevel = lintRule(
|
|||||||
/** @type {Depth | undefined} */
|
/** @type {Depth | undefined} */
|
||||||
let rank
|
let rank
|
||||||
|
|
||||||
// To do: MDX?
|
|
||||||
if (node.type === 'heading') {
|
if (node.type === 'heading') {
|
||||||
rank = node.depth
|
rank = node.depth
|
||||||
} else if (node.type === 'html') {
|
} else if (node.type === 'html') {
|
||||||
const results = node.value.match(re)
|
const results = node.value.match(htmlRe)
|
||||||
|
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
|
||||||
|
} else if (
|
||||||
|
(node.type === 'mdxJsxFlowElement' ||
|
||||||
|
node.type === 'mdxJsxTextElement') &&
|
||||||
|
node.name
|
||||||
|
) {
|
||||||
|
const results = node.name.match(jsxNameRe)
|
||||||
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
|
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-mdx": "^3.0.0",
|
||||||
"unified-lint-rule": "^2.0.0",
|
"unified-lint-rule": "^2.0.0",
|
||||||
"unist-util-position": "^5.0.0",
|
"unist-util-position": "^5.0.0",
|
||||||
"unist-util-visit": "^5.0.0"
|
"unist-util-visit": "^5.0.0"
|
||||||
|
@ -305,6 +305,23 @@ Paragraph.
|
|||||||
1:1-1:14: First heading level should be `2`
|
1:1-1:14: First heading level should be `2`
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `ok.mdx`
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
> 👉 **Note**: this example uses
|
||||||
|
> MDX ([`remark-mdx`][github-remark-mdx]).
|
||||||
|
|
||||||
|
```mdx
|
||||||
|
In <b>MDX</b>, JSX is supported.
|
||||||
|
|
||||||
|
<h1>First heading</h1>
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
Projects maintained by the unified collective are compatible with maintained
|
Projects maintained by the unified collective are compatible with maintained
|
||||||
@ -380,6 +397,8 @@ abide by its terms.
|
|||||||
|
|
||||||
[github-remark-lint]: https://github.com/remarkjs/remark-lint
|
[github-remark-lint]: https://github.com/remarkjs/remark-lint
|
||||||
|
|
||||||
|
[github-remark-mdx]: https://mdxjs.com/packages/remark-mdx/
|
||||||
|
|
||||||
[github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
|
[github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
|
||||||
|
|
||||||
[npm-install]: https://docs.npmjs.com/cli/install
|
[npm-install]: https://docs.npmjs.com/cli/install
|
||||||
|
@ -126,8 +126,7 @@ const remarkLintListItemContentIndent = lintRule(
|
|||||||
|
|
||||||
file.message(
|
file.message(
|
||||||
'Don’t use mixed indentation for children, ' +
|
'Don’t use mixed indentation for children, ' +
|
||||||
// Hard to test, I couldn’t find it at least.
|
/* c8 ignore next -- hard to test, I couldn’t find it at least. */
|
||||||
/* c8 ignore next */
|
|
||||||
(diff > 0 ? 'add' : 'remove') +
|
(diff > 0 ? 'add' : 'remove') +
|
||||||
' ' +
|
' ' +
|
||||||
abs +
|
abs +
|
||||||
|
@ -151,7 +151,8 @@ Further children should align with it.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
1.␠[x] Alpha
|
1.␠[x] Alpha
|
||||||
@ -166,7 +167,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
1.␠[x] Charlie
|
1.␠[x] Charlie
|
||||||
|
@ -119,6 +119,8 @@
|
|||||||
* 4:12: Line must be at most 10 characters
|
* 4:12: Line must be at most 10 characters
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// <reference types="mdast-util-mdx" />
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('mdast').Root} Root
|
* @typedef {import('mdast').Root} Root
|
||||||
*/
|
*/
|
||||||
@ -146,26 +148,14 @@ const remarkLintMaximumLineLength = lintRule(
|
|||||||
const option = options || 80
|
const option = options || 80
|
||||||
|
|
||||||
visit(tree, function (node) {
|
visit(tree, function (node) {
|
||||||
// To do: add MDX types, etc.
|
|
||||||
// To do: remove MDX 1?
|
|
||||||
if (
|
if (
|
||||||
node.type === 'code' ||
|
node.type === 'code' ||
|
||||||
node.type === 'definition' ||
|
node.type === 'definition' ||
|
||||||
node.type === 'heading' ||
|
node.type === 'heading' ||
|
||||||
node.type === 'html' ||
|
node.type === 'html' ||
|
||||||
node.type === 'table' ||
|
|
||||||
// @ts-expect-error: These are from MDX@1 and MDX@2: <https://github.com/mdx-js/specification>.
|
|
||||||
node.type === 'jsx' ||
|
|
||||||
// @ts-expect-error: MDX
|
|
||||||
node.type === 'mdxFlowExpression' ||
|
|
||||||
// @ts-expect-error: MDX
|
|
||||||
node.type === 'mdxJsxFlowElement' ||
|
|
||||||
// @ts-expect-error: MDX
|
|
||||||
node.type === 'mdxJsxTextElement' ||
|
node.type === 'mdxJsxTextElement' ||
|
||||||
// @ts-expect-error: MDX
|
|
||||||
node.type === 'mdxTextExpression' ||
|
node.type === 'mdxTextExpression' ||
|
||||||
// @ts-expect-error: MDX
|
node.type === 'table' ||
|
||||||
node.type === 'mdxjsEsm' ||
|
|
||||||
// @ts-expect-error: TOML from frontmatter.
|
// @ts-expect-error: TOML from frontmatter.
|
||||||
node.type === 'toml' ||
|
node.type === 'toml' ||
|
||||||
node.type === 'yaml'
|
node.type === 'yaml'
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-mdx": "^3.0.0",
|
||||||
"unified-lint-rule": "^2.0.0",
|
"unified-lint-rule": "^2.0.0",
|
||||||
"unist-util-position": "^5.0.0",
|
"unist-util-position": "^5.0.0",
|
||||||
"unist-util-visit": "^5.0.0"
|
"unist-util-visit": "^5.0.0"
|
||||||
|
@ -151,7 +151,8 @@ Whether to wrap prose or not is a stylistic choice.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
This line is simply not toooooooooooooooooooooooooooooooooooooooooooo
|
This line is simply not toooooooooooooooooooooooooooooooooooooooooooo
|
||||||
|
@ -166,7 +166,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
http://foo.bar/baz
|
http://foo.bar/baz
|
||||||
|
@ -90,6 +90,7 @@
|
|||||||
* @typedef {import('mdast').Root} Root
|
* @typedef {import('mdast').Root} Root
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {collapseWhiteSpace} from 'collapse-white-space'
|
||||||
import {lintRule} from 'unified-lint-rule'
|
import {lintRule} from 'unified-lint-rule'
|
||||||
import {position} from 'unist-util-position'
|
import {position} from 'unist-util-position'
|
||||||
import {visit} from 'unist-util-visit'
|
import {visit} from 'unist-util-visit'
|
||||||
@ -140,23 +141,27 @@ const remarkLintNoShellDollars = lintRule(
|
|||||||
|
|
||||||
// Check known shell code.
|
// Check known shell code.
|
||||||
if (place && node.lang && flags.has(node.lang)) {
|
if (place && node.lang && flags.has(node.lang)) {
|
||||||
const lines = node.value.split('\n').filter(function (line) {
|
const lines = node.value.split('\n')
|
||||||
return line.trim().length > 0
|
|
||||||
})
|
|
||||||
let index = -1
|
let index = -1
|
||||||
|
|
||||||
if (lines.length === 0) {
|
let hasLines = false
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
while (++index < lines.length) {
|
while (++index < lines.length) {
|
||||||
const line = lines[index].trim()
|
const line = collapseWhiteSpace(lines[index], {style: 'html'})
|
||||||
|
|
||||||
|
if (!line) continue
|
||||||
|
|
||||||
|
hasLines = true
|
||||||
|
|
||||||
if (!/^\$/.test(line)) {
|
if (!/^\$/.test(line)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hasLines) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
file.message('Do not use dollar signs before shell commands', place)
|
file.message('Do not use dollar signs before shell commands', place)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
"collapse-white-space": "^2.0.0",
|
||||||
"unified-lint-rule": "^2.0.0",
|
"unified-lint-rule": "^2.0.0",
|
||||||
"unist-util-position": "^5.0.0",
|
"unist-util-position": "^5.0.0",
|
||||||
"unist-util-visit": "^5.0.0"
|
"unist-util-visit": "^5.0.0"
|
||||||
|
@ -138,8 +138,8 @@ const remarkLintNoTableIndentation = lintRule(
|
|||||||
const head = parent.children[0]
|
const head = parent.children[0]
|
||||||
column = pointStart(head)?.column
|
column = pointStart(head)?.column
|
||||||
|
|
||||||
// Skip past the first line if we’re the first child of a list item.
|
/* c8 ignore next 4 -- skip past the first line if we’re the first
|
||||||
/* c8 ignore next 3 */
|
* child of a list item. */
|
||||||
if (typeof line === 'number' && head === node) {
|
if (typeof line === 'number' && head === node) {
|
||||||
line++
|
line++
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,8 @@ So it’s recommended to not indent tables and to turn this rule on.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
Paragraph.
|
Paragraph.
|
||||||
@ -170,7 +171,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
Paragraph.
|
Paragraph.
|
||||||
@ -192,7 +194,8 @@ Paragraph.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
>␠␠| A |
|
>␠␠| A |
|
||||||
@ -209,7 +212,8 @@ Paragraph.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
-␠␠␠paragraph
|
-␠␠␠paragraph
|
||||||
|
@ -213,9 +213,9 @@ const remarkLintNoUndefinedReferences = lintRule(
|
|||||||
|
|
||||||
visit(tree, function (node) {
|
visit(tree, function (node) {
|
||||||
const place = position(node)
|
const place = position(node)
|
||||||
// CM specifiers that references only form when defined.
|
/* c8 ignore next 12 -- CM specifies that references only form when
|
||||||
// Still, they could be added by plugins, so let’s keep it.
|
* defined.
|
||||||
/* c8 ignore next 10 */
|
* Still, they could be added by plugins, so let’s keep it. */
|
||||||
if (
|
if (
|
||||||
(node.type === 'imageReference' ||
|
(node.type === 'imageReference' ||
|
||||||
node.type === 'linkReference' ||
|
node.type === 'linkReference' ||
|
||||||
|
@ -92,7 +92,7 @@ const remarkLintNoUnneededFullReferenceImage = lintRule(
|
|||||||
if (
|
if (
|
||||||
!place ||
|
!place ||
|
||||||
node.referenceType !== 'full' ||
|
node.referenceType !== 'full' ||
|
||||||
/* c8 ignore next */
|
/* c8 ignore next -- generated AST can omit `alt`. */
|
||||||
normalizeIdentifier(node.alt || '') !== node.identifier.toUpperCase()
|
normalizeIdentifier(node.alt || '') !== node.identifier.toUpperCase()
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
|
@ -62,11 +62,12 @@
|
|||||||
* @example
|
* @example
|
||||||
* {"name": "footnote.md", "gfm": true, "label": "output"}
|
* {"name": "footnote.md", "gfm": true, "label": "output"}
|
||||||
*
|
*
|
||||||
* 4:1-4:13: Found unused definition
|
* 4:1-4:13: Found unused footnote definition
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('mdast').DefinitionContent} DefinitionContent
|
* @typedef {import('mdast').Definition} Definition
|
||||||
|
* @typedef {import('mdast').FootnoteDefinition} FootnoteDefinition
|
||||||
* @typedef {import('mdast').Root} Root
|
* @typedef {import('mdast').Root} Root
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -86,13 +87,19 @@ const remarkLintNoUnusedDefinitions = lintRule(
|
|||||||
* Nothing.
|
* Nothing.
|
||||||
*/
|
*/
|
||||||
function (tree, file) {
|
function (tree, file) {
|
||||||
/** @type {Map<string, {node: DefinitionContent | undefined, used: boolean}>} */
|
/** @type {Map<string, {node: Definition | FootnoteDefinition | undefined, used: boolean}>} */
|
||||||
const map = new Map()
|
const footnoteDefinitions = new Map()
|
||||||
|
/** @type {Map<string, {node: Definition | FootnoteDefinition | undefined, used: boolean}>} */
|
||||||
|
const definitions = new Map()
|
||||||
|
|
||||||
// To do: separate maps for footnotes/definitions.
|
|
||||||
visit(tree, function (node) {
|
visit(tree, function (node) {
|
||||||
if ('identifier' in node) {
|
if ('identifier' in node) {
|
||||||
const id = node.identifier.toLowerCase()
|
const id = node.identifier.toLowerCase()
|
||||||
|
const map =
|
||||||
|
node.type === 'footnoteDefinition' ||
|
||||||
|
node.type === 'footnoteReference'
|
||||||
|
? footnoteDefinitions
|
||||||
|
: definitions
|
||||||
let entry = map.get(id)
|
let entry = map.get(id)
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
@ -112,7 +119,15 @@ const remarkLintNoUnusedDefinitions = lintRule(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
for (const entry of map.values()) {
|
for (const entry of footnoteDefinitions.values()) {
|
||||||
|
const place = position(entry.node)
|
||||||
|
|
||||||
|
if (place && !entry.used) {
|
||||||
|
file.message('Found unused footnote definition', place)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const entry of definitions.values()) {
|
||||||
const place = position(entry.node)
|
const place = position(entry.node)
|
||||||
|
|
||||||
if (place && !entry.used) {
|
if (place && !entry.used) {
|
||||||
|
@ -170,7 +170,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
a[^x].
|
a[^x].
|
||||||
@ -182,7 +183,7 @@ a[^x].
|
|||||||
###### Out
|
###### Out
|
||||||
|
|
||||||
```text
|
```text
|
||||||
4:1-4:13: Found unused definition
|
4:1-4:13: Found unused footnote definition
|
||||||
```
|
```
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
@ -177,7 +177,8 @@ When configured with `'~'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
~foo~
|
~foo~
|
||||||
@ -193,7 +194,8 @@ When configured with `'~'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
~~foo~~
|
~~foo~~
|
||||||
@ -211,7 +213,8 @@ When configured with `'~~'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
~~foo~~
|
~~foo~~
|
||||||
@ -227,7 +230,8 @@ When configured with `'~~'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
~foo~
|
~foo~
|
||||||
@ -243,7 +247,8 @@ When configured with `'~~'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
~~foo~~
|
~~foo~~
|
||||||
|
@ -271,7 +271,7 @@ const remarkLintTableCellPadding = lintRule(
|
|||||||
|
|
||||||
visit(tree, 'table', function (node) {
|
visit(tree, 'table', function (node) {
|
||||||
const rows = node.children
|
const rows = node.children
|
||||||
/* c8 ignore next -- to do: fix types to always have `align` defined. */
|
/* c8 ignore next -- generated AST can omit `align`. */
|
||||||
const align = node.align || []
|
const align = node.align || []
|
||||||
/** @type {Array<number>} */
|
/** @type {Array<number>} */
|
||||||
const sizes = []
|
const sizes = []
|
||||||
@ -414,7 +414,6 @@ export default remarkLintTableCellPadding
|
|||||||
function size(node) {
|
function size(node) {
|
||||||
const head = pointStart(node.children[0])?.offset
|
const head = pointStart(node.children[0])?.offset
|
||||||
const tail = pointEnd(node.children[node.children.length - 1])?.offset
|
const tail = pointEnd(node.children[node.children.length - 1])?.offset
|
||||||
// Only called when we’re sure offsets exist.
|
/* c8 ignore next -- Only called when we’re sure offsets exist. */
|
||||||
/* c8 ignore next */
|
|
||||||
return typeof head === 'number' && typeof tail === 'number' ? tail - head : 0
|
return typeof head === 'number' && typeof tail === 'number' ? tail - head : 0
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,8 @@ When configured with `'padded'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| A | B |
|
| A | B |
|
||||||
@ -204,7 +205,8 @@ When configured with `'padded'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| A | B |
|
| A | B |
|
||||||
@ -242,7 +244,8 @@ When configured with `'compact'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
|A |B |
|
|A |B |
|
||||||
@ -260,7 +263,8 @@ When configured with `'compact'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| A | B |
|
| A | B |
|
||||||
@ -284,7 +288,8 @@ When configured with `'compact'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
The default is `'consistent'`.
|
The default is `'consistent'`.
|
||||||
@ -308,7 +313,8 @@ When configured with `'consistent'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| A | B |
|
| A | B |
|
||||||
@ -332,7 +338,8 @@ When configured with `'consistent'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
|A |B |
|
|A |B |
|
||||||
@ -354,7 +361,8 @@ When configured with `'consistent'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
|A |B |
|
|A |B |
|
||||||
@ -388,7 +396,8 @@ When configured with `'padded'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
<!-- Empty cells are OK, but those surrounding them may not be. -->
|
<!-- Empty cells are OK, but those surrounding them may not be. -->
|
||||||
@ -412,7 +421,8 @@ When configured with `'padded'`.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
<!-- Missing cells are fine as well. -->
|
<!-- Missing cells are fine as well. -->
|
||||||
|
@ -160,7 +160,8 @@ in which case this rule must be turned off.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| A | B |
|
| A | B |
|
||||||
@ -176,7 +177,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| A | B |
|
| A | B |
|
||||||
@ -195,7 +197,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| | B | |
|
| | B | |
|
||||||
@ -211,7 +214,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| | | |
|
| | | |
|
||||||
|
@ -153,7 +153,8 @@ delimiters.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| A | B |
|
| A | B |
|
||||||
@ -169,7 +170,8 @@ No messages.
|
|||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][github-remark-gfm]).
|
> 👉 **Note**: this example uses
|
||||||
|
> GFM ([`remark-gfm`][github-remark-gfm]).
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
A | B
|
A | B
|
||||||
|
@ -56,8 +56,7 @@ export function lintRule(meta, rule) {
|
|||||||
const id = typeof meta === 'string' ? meta : meta.origin
|
const id = typeof meta === 'string' ? meta : meta.origin
|
||||||
const url = typeof meta === 'string' ? undefined : meta.url
|
const url = typeof meta === 'string' ? undefined : meta.url
|
||||||
const parts = id.split(':')
|
const parts = id.split(':')
|
||||||
// Possibly useful if externalised later.
|
/* c8 ignore next -- Possibly useful if externalised later. */
|
||||||
/* c8 ignore next */
|
|
||||||
const source = parts[1] ? parts[0] : undefined
|
const source = parts[1] ? parts[0] : undefined
|
||||||
const ruleId = parts[1]
|
const ruleId = parts[1]
|
||||||
|
|
||||||
@ -94,9 +93,9 @@ export function lintRule(meta, rule) {
|
|||||||
wrap(rule, function (error) {
|
wrap(rule, function (error) {
|
||||||
const messages = file.messages
|
const messages = file.messages
|
||||||
|
|
||||||
// Add the error, if not already properly added.
|
/* c8 ignore next 8 -- add the error,
|
||||||
// Only happens for incorrect plugins.
|
* if not already properly added.
|
||||||
/* c8 ignore next 6 */
|
* Only happens for incorrect plugins. */
|
||||||
// @ts-expect-error: errors could be `messages`.
|
// @ts-expect-error: errors could be `messages`.
|
||||||
if (error && !messages.includes(error)) {
|
if (error && !messages.includes(error)) {
|
||||||
try {
|
try {
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
* Whether to use GFM.
|
* Whether to use GFM.
|
||||||
* @property {string} input
|
* @property {string} input
|
||||||
* Input.
|
* Input.
|
||||||
|
* @property {boolean} mdx
|
||||||
|
* Whether to use MDX.
|
||||||
* @property {string} name
|
* @property {string} name
|
||||||
* Name.
|
* Name.
|
||||||
* @property {Array<string>} output
|
* @property {Array<string>} output
|
||||||
@ -27,6 +29,8 @@
|
|||||||
* Whether to use GFM (optional).
|
* Whether to use GFM (optional).
|
||||||
* @property {'input' | 'output'} [label]
|
* @property {'input' | 'output'} [label]
|
||||||
* Label (optional).
|
* Label (optional).
|
||||||
|
* @property {boolean} [mdx]
|
||||||
|
* Whether to use MDX (optional).
|
||||||
* @property {boolean} [positionless]
|
* @property {boolean} [positionless]
|
||||||
* Whether this check also applies without positions (optional).
|
* Whether this check also applies without positions (optional).
|
||||||
* @property {string} name
|
* @property {string} name
|
||||||
@ -168,7 +172,14 @@ async function addPlugin(name) {
|
|||||||
throw new Error('Could not parse example in `' + ruleId + '`', {cause})
|
throw new Error('Could not parse example in `' + ruleId + '`', {cause})
|
||||||
}
|
}
|
||||||
|
|
||||||
const exampleValue = strip(lines.join('\n').replace(/^\r?\n/g, ''))
|
const exampleValue = strip(
|
||||||
|
lines
|
||||||
|
.join('\n')
|
||||||
|
// Remove head.
|
||||||
|
.replace(/^\r?\n/g, '')
|
||||||
|
// Remove magic handling of `nul` control picture.
|
||||||
|
.replace(/␀/g, '')
|
||||||
|
)
|
||||||
const configuration = JSON.stringify({config: info.config || true})
|
const configuration = JSON.stringify({config: info.config || true})
|
||||||
const name = info.name
|
const name = info.name
|
||||||
|
|
||||||
@ -179,6 +190,7 @@ async function addPlugin(name) {
|
|||||||
positionless: info.positionless || false,
|
positionless: info.positionless || false,
|
||||||
gfm: info.gfm || false,
|
gfm: info.gfm || false,
|
||||||
input: exampleValue,
|
input: exampleValue,
|
||||||
|
mdx: info.mdx || false,
|
||||||
output: []
|
output: []
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -198,6 +210,7 @@ async function addPlugin(name) {
|
|||||||
positionless: info.positionless || false,
|
positionless: info.positionless || false,
|
||||||
gfm: info.gfm || false,
|
gfm: info.gfm || false,
|
||||||
input: '',
|
input: '',
|
||||||
|
mdx: info.mdx || false,
|
||||||
output: []
|
output: []
|
||||||
}
|
}
|
||||||
result.checks.push(found)
|
result.checks.push(found)
|
||||||
|
@ -1255,6 +1255,10 @@ function generateReadmeExample(state) {
|
|||||||
'github-remark-gfm',
|
'github-remark-gfm',
|
||||||
'https://github.com/remarkjs/remark-gfm'
|
'https://github.com/remarkjs/remark-gfm'
|
||||||
)
|
)
|
||||||
|
state.urls.set(
|
||||||
|
'github-remark-mdx',
|
||||||
|
'https://mdxjs.com/packages/remark-mdx/'
|
||||||
|
)
|
||||||
|
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
children.push({
|
children.push({
|
||||||
@ -1263,8 +1267,40 @@ function generateReadmeExample(state) {
|
|||||||
children: [{type: 'text', value: 'In'}]
|
children: [{type: 'text', value: 'In'}]
|
||||||
})
|
})
|
||||||
|
|
||||||
// To do: other plugins.
|
/** @type {Array<PhrasingContent>} */
|
||||||
|
const phrasing = []
|
||||||
|
|
||||||
if (check.gfm) {
|
if (check.gfm) {
|
||||||
|
phrasing.push(
|
||||||
|
{type: 'text', value: 'GFM ('},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'github-remark-gfm',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [{type: 'inlineCode', value: 'remark-gfm'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ')'}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check.mdx) {
|
||||||
|
if (phrasing.length > 0) {
|
||||||
|
phrasing.push({type: 'text', value: ',\n'})
|
||||||
|
}
|
||||||
|
|
||||||
|
phrasing.push(
|
||||||
|
{type: 'text', value: 'MDX ('},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'github-remark-mdx',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [{type: 'inlineCode', value: 'remark-mdx'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ')'}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phrasing.length > 0) {
|
||||||
children.push({
|
children.push({
|
||||||
type: 'blockquote',
|
type: 'blockquote',
|
||||||
children: [
|
children: [
|
||||||
@ -1276,14 +1312,9 @@ function generateReadmeExample(state) {
|
|||||||
type: 'strong',
|
type: 'strong',
|
||||||
children: [{type: 'text', value: 'Note'}]
|
children: [{type: 'text', value: 'Note'}]
|
||||||
},
|
},
|
||||||
{type: 'text', value: ': this example uses GFM ('},
|
{type: 'text', value: ': this example uses\n'},
|
||||||
{
|
...phrasing,
|
||||||
type: 'linkReference',
|
{type: 'text', value: '.'}
|
||||||
identifier: 'github-remark-gfm',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [{type: 'inlineCode', value: 'remark-gfm'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ').'}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1292,7 +1323,7 @@ function generateReadmeExample(state) {
|
|||||||
|
|
||||||
children.push({
|
children.push({
|
||||||
type: 'code',
|
type: 'code',
|
||||||
lang: 'markdown',
|
lang: check.mdx ? 'mdx' : 'markdown',
|
||||||
value: check.input
|
value: check.input
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
35
test.js
35
test.js
@ -16,6 +16,7 @@ import remarkLintFinalNewline from 'remark-lint-final-newline'
|
|||||||
import remarkLintNoHeadingPunctuation from 'remark-lint-no-heading-punctuation'
|
import remarkLintNoHeadingPunctuation from 'remark-lint-no-heading-punctuation'
|
||||||
import remarkLintNoMultipleToplevelHeadings from 'remark-lint-no-multiple-toplevel-headings'
|
import remarkLintNoMultipleToplevelHeadings from 'remark-lint-no-multiple-toplevel-headings'
|
||||||
import remarkLintNoUndefinedReferences from 'remark-lint-no-undefined-references'
|
import remarkLintNoUndefinedReferences from 'remark-lint-no-undefined-references'
|
||||||
|
import remarkMdx from 'remark-mdx'
|
||||||
import {lintRule} from 'unified-lint-rule'
|
import {lintRule} from 'unified-lint-rule'
|
||||||
import {removePosition} from 'unist-util-remove-position'
|
import {removePosition} from 'unist-util-remove-position'
|
||||||
import {VFile} from 'vfile'
|
import {VFile} from 'vfile'
|
||||||
@ -81,9 +82,12 @@ test('remark-lint', async function (t) {
|
|||||||
|
|
||||||
assert.deepEqual(file.messages.map(jsonClone), [
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
{
|
{
|
||||||
|
column: 2,
|
||||||
fatal: true,
|
fatal: true,
|
||||||
|
line: 1,
|
||||||
message: 'Missing newline character at end of file',
|
message: 'Missing newline character at end of file',
|
||||||
name: '1:1',
|
name: '1:2',
|
||||||
|
place: {column: 2, line: 1, offset: 1},
|
||||||
reason: 'Missing newline character at end of file',
|
reason: 'Missing newline character at end of file',
|
||||||
ruleId: 'final-newline',
|
ruleId: 'final-newline',
|
||||||
source: 'remark-lint',
|
source: 'remark-lint',
|
||||||
@ -96,7 +100,7 @@ test('remark-lint', async function (t) {
|
|||||||
const file = await remark().use(remarkLintFinalNewline, true).process('.')
|
const file = await remark().use(remarkLintFinalNewline, true).process('.')
|
||||||
|
|
||||||
assert.deepEqual(file.messages.map(String), [
|
assert.deepEqual(file.messages.map(String), [
|
||||||
'1:1: Missing newline character at end of file'
|
'1:2: Missing newline character at end of file'
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -114,7 +118,7 @@ test('remark-lint', async function (t) {
|
|||||||
.process('.')
|
.process('.')
|
||||||
|
|
||||||
assert.deepEqual(file.messages.map(String), [
|
assert.deepEqual(file.messages.map(String), [
|
||||||
'1:1: Missing newline character at end of file'
|
'1:2: Missing newline character at end of file'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -139,9 +143,12 @@ test('remark-lint', async function (t) {
|
|||||||
|
|
||||||
assert.deepEqual(file.messages.map(jsonClone), [
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
{
|
{
|
||||||
|
column: 2,
|
||||||
fatal: true,
|
fatal: true,
|
||||||
|
line: 1,
|
||||||
message: 'Missing newline character at end of file',
|
message: 'Missing newline character at end of file',
|
||||||
name: '1:1',
|
name: '1:2',
|
||||||
|
place: {column: 2, line: 1, offset: 1},
|
||||||
reason: 'Missing newline character at end of file',
|
reason: 'Missing newline character at end of file',
|
||||||
ruleId: 'final-newline',
|
ruleId: 'final-newline',
|
||||||
source: 'remark-lint',
|
source: 'remark-lint',
|
||||||
@ -160,9 +167,12 @@ test('remark-lint', async function (t) {
|
|||||||
|
|
||||||
assert.deepEqual(file.messages.map(jsonClone), [
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
{
|
{
|
||||||
|
column: 2,
|
||||||
fatal: false,
|
fatal: false,
|
||||||
|
line: 1,
|
||||||
message: 'Missing newline character at end of file',
|
message: 'Missing newline character at end of file',
|
||||||
name: '1:1',
|
name: '1:2',
|
||||||
|
place: {column: 2, line: 1, offset: 1},
|
||||||
reason: 'Missing newline character at end of file',
|
reason: 'Missing newline character at end of file',
|
||||||
ruleId: 'final-newline',
|
ruleId: 'final-newline',
|
||||||
source: 'remark-lint',
|
source: 'remark-lint',
|
||||||
@ -181,9 +191,12 @@ test('remark-lint', async function (t) {
|
|||||||
|
|
||||||
assert.deepEqual(file.messages.map(jsonClone), [
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
{
|
{
|
||||||
|
column: 2,
|
||||||
fatal: false,
|
fatal: false,
|
||||||
|
line: 1,
|
||||||
message: 'Missing newline character at end of file',
|
message: 'Missing newline character at end of file',
|
||||||
name: '1:1',
|
name: '1:2',
|
||||||
|
place: {column: 2, line: 1, offset: 1},
|
||||||
reason: 'Missing newline character at end of file',
|
reason: 'Missing newline character at end of file',
|
||||||
ruleId: 'final-newline',
|
ruleId: 'final-newline',
|
||||||
source: 'remark-lint',
|
source: 'remark-lint',
|
||||||
@ -302,9 +315,17 @@ async function assertCheck(plugin, info, check) {
|
|||||||
/** @type {{config: unknown}} */
|
/** @type {{config: unknown}} */
|
||||||
const {config} = JSON.parse(check.configuration)
|
const {config} = JSON.parse(check.configuration)
|
||||||
/** @type {PluggableList} */
|
/** @type {PluggableList} */
|
||||||
const extras = check.gfm ? [remarkGfm] : []
|
const extras = []
|
||||||
const value = controlPictures(check.input)
|
const value = controlPictures(check.input)
|
||||||
|
|
||||||
|
if (check.gfm) {
|
||||||
|
extras.push(remarkGfm)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check.mdx) {
|
||||||
|
extras.push(remarkMdx)
|
||||||
|
}
|
||||||
|
|
||||||
const file = await remark()
|
const file = await remark()
|
||||||
.use(plugin, config)
|
.use(plugin, config)
|
||||||
.use(extras)
|
.use(extras)
|
||||||
|
Loading…
Reference in New Issue
Block a user