mirror of
https://github.com/remarkjs/remark-lint.git
synced 2024-09-11 19:57:15 +03:00
Refactor code style in scripts
This commit is contained in:
parent
db4810d891
commit
0e79b65cc7
@ -58,9 +58,14 @@ touch .remarkrc.js
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// .remarkrc.js
|
// .remarkrc.js
|
||||||
module.exports = {
|
/**
|
||||||
plugins: []
|
* @typedef {import('unified').Preset} Preset
|
||||||
}
|
*/
|
||||||
|
|
||||||
|
/** @type {Preset} */
|
||||||
|
const preset = {plugins: []}
|
||||||
|
|
||||||
|
export default preset
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, in our `package.json`, add the following script to process all the
|
Then, in our `package.json`, add the following script to process all the
|
||||||
@ -142,7 +147,7 @@ import {lintRule} from 'unified-lint-rule'
|
|||||||
|
|
||||||
const remarkLintNoGifAllowed = lintRule(
|
const remarkLintNoGifAllowed = lintRule(
|
||||||
'remark-lint:no-gif-allowed',
|
'remark-lint:no-gif-allowed',
|
||||||
(tree, file, options) => {
|
function (tree, file, options) {
|
||||||
// Rule implementation
|
// Rule implementation
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -155,9 +160,16 @@ namespace.
|
|||||||
If your project was named `my-project`, then you can export your rule as:
|
If your project was named `my-project`, then you can export your rule as:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const remarkLintNoGifAllowed = lintRule('my-project-name:no-gif-allowed', () => {})
|
const remarkLintNoGifAllowed = lintRule(
|
||||||
|
'my-project-name:no-gif-allowed',
|
||||||
|
function () {}
|
||||||
|
)
|
||||||
|
|
||||||
// Or:
|
// Or:
|
||||||
const remarkLintNoGifAllowed = lintRule('my-npm-published-package:no-gif-allowed', () => {})
|
const remarkLintNoGifAllowed = lintRule(
|
||||||
|
'my-npm-published-package:no-gif-allowed',
|
||||||
|
function () {}
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
This can help you when wanting to create a group of rules under the same
|
This can help you when wanting to create a group of rules under the same
|
||||||
@ -168,7 +180,7 @@ This can help you when wanting to create a group of rules under the same
|
|||||||
Your rule function will receive three arguments:
|
Your rule function will receive three arguments:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
(tree, file, options) => {}
|
function rule(tree, file, options) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
* `tree` (*required*): [mdast][]
|
* `tree` (*required*): [mdast][]
|
||||||
@ -187,38 +199,36 @@ recursively inspect all the image nodes, and
|
|||||||
nodes that we have generated ourselves and do not belong to the `doc.md`.
|
nodes that we have generated ourselves and do not belong to the `doc.md`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {lintRule} from 'unified-lint-rule'
|
/**
|
||||||
import {visit} from 'unist-visit-util'
|
* @typedef {import('mdast').Root} Root
|
||||||
import {generated} from 'unist-util-generated'
|
*/
|
||||||
|
|
||||||
function isValidNode(node) {
|
import {lintRule} from 'unified-lint-rule'
|
||||||
// Here we check whether the given node violates our rule.
|
import {visit} from 'unist-util-visit'
|
||||||
// Implementation details are not relevant to the scope of this example.
|
|
||||||
// This is an overly simplified solution for demonstration purposes
|
|
||||||
if (node.url && typeof node.url === 'string') {
|
|
||||||
return !node.url.endsWith('.gif')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const remarkLintNoGifAllowed = lintRule(
|
const remarkLintNoGifAllowed = lintRule(
|
||||||
'remark-lint:no-gif-allowed',
|
'remark-lint:no-gif-allowed',
|
||||||
(tree, file, options) => {
|
/**
|
||||||
visit(tree, 'image', (node) => {
|
* @param {Root} tree
|
||||||
if (!generated(node)) {
|
* Tree.
|
||||||
// This is an extremely simplified example of how to structure
|
* @returns {undefined}
|
||||||
// the logic to check whether a node violates your rule.
|
* Nothing.
|
||||||
// You have complete freedom over how to visit/inspect the tree,
|
*/
|
||||||
// and on how to implement the validation logic for your node.
|
function (tree, file, options) {
|
||||||
const isValid = isValidNode(node)
|
visit(tree, 'image', function (node) {
|
||||||
|
// This is an extremely simplified example of how to structure
|
||||||
|
// the logic to check whether a node violates your rule.
|
||||||
|
// You have complete freedom over how to visit/inspect the tree,
|
||||||
|
// and on how to implement the validation logic for your node.
|
||||||
|
const isValid = !node.url.endsWith('.gif')
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
// Remember to provide the node as second argument to the message,
|
// Remember to provide the node as second argument to the message,
|
||||||
// in order to obtain the position and column where the violation occurred.
|
// in order to obtain the position and column where the violation occurred.
|
||||||
file.message(
|
file.message(
|
||||||
'Invalid image file extensions. Please do not use gifs',
|
'Invalid image file extensions. Please do not use gifs',
|
||||||
node
|
node
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -236,13 +246,14 @@ You can do that by importing your rule and adding it in `plugins` array:
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// .remarkrc.js
|
// .remarkrc.js
|
||||||
|
/**
|
||||||
|
* @typedef {import('unified').Preset} Preset
|
||||||
|
*/
|
||||||
|
|
||||||
import remarkLintNoGifAllowed from './rules/no-gif-allowed.js'
|
import remarkLintNoGifAllowed from './rules/no-gif-allowed.js'
|
||||||
|
|
||||||
const plugins = {
|
/** @type {Preset} */
|
||||||
plugins: [remarkLintNoGifAllowed]
|
const preset = {plugins: [remarkLintNoGifAllowed]}
|
||||||
}
|
|
||||||
|
|
||||||
const preset = {plugins}
|
|
||||||
|
|
||||||
export default preset
|
export default preset
|
||||||
```
|
```
|
||||||
|
15
package.json
15
package.json
@ -116,7 +116,11 @@
|
|||||||
"c8": "^8.0.0",
|
"c8": "^8.0.0",
|
||||||
"comment-parser": "^1.0.0",
|
"comment-parser": "^1.0.0",
|
||||||
"github-slugger": "^2.0.0",
|
"github-slugger": "^2.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-gfm": "^3.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.0.0",
|
||||||
"mdast-zone": "^6.0.0",
|
"mdast-zone": "^6.0.0",
|
||||||
|
"micromark-extension-gfm": "^3.0.0",
|
||||||
"parse-author": "^2.0.0",
|
"parse-author": "^2.0.0",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"remark": "^15.0.0",
|
"remark": "^15.0.0",
|
||||||
@ -127,16 +131,16 @@
|
|||||||
"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",
|
||||||
"to-vfile": "^8.0.0",
|
|
||||||
"type-coverage": "^2.0.0",
|
"type-coverage": "^2.0.0",
|
||||||
"type-fest": "^4.0.0",
|
"type-fest": "^4.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"unist-builder": "^4.0.0",
|
"unist-builder": "^4.0.0",
|
||||||
"unist-util-remove-position": "^5.0.0",
|
"unist-util-remove-position": "^5.0.0",
|
||||||
|
"vfile": "^6.0.0",
|
||||||
"xo": "^0.56.0"
|
"xo": "^0.56.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"generate": "node --conditions development script/build-presets.js && node --conditions development script/build-rules.js",
|
"generate": "node --conditions development script/build-plugins.js && node --conditions development script/build-presets.js",
|
||||||
"build": "tsc --build --clean && tsc --build && type-coverage",
|
"build": "tsc --build --clean && tsc --build && type-coverage",
|
||||||
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix",
|
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix",
|
||||||
"test": "npm run build && npm run generate && npm run format && npm run test-coverage",
|
"test": "npm run build && npm run generate && npm run format && npm run test-coverage",
|
||||||
@ -174,8 +178,8 @@
|
|||||||
"remark-lint-list-item-indent",
|
"remark-lint-list-item-indent",
|
||||||
"space"
|
"space"
|
||||||
],
|
],
|
||||||
"./script/plugin/list-of-presets.js",
|
"./script/plugin/list-of-plugins.js",
|
||||||
"./script/plugin/list-of-rules.js"
|
"./script/plugin/list-of-presets.js"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"typeCoverage": {
|
"typeCoverage": {
|
||||||
@ -193,7 +197,8 @@
|
|||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"max-depth": "off",
|
"max-depth": "off",
|
||||||
"no-await-in-loop": "off"
|
"no-await-in-loop": "off",
|
||||||
|
"unicorn/no-array-callback-reference": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -77,22 +77,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintBlockquoteIndentation from 'remark-lint-blockquote-indentation'
|
import remarkLintBlockquoteIndentation from 'remark-lint-blockquote-indentation'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintBlockquoteIndentation)
|
||||||
.use(remarkLintBlockquoteIndentation)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintCheckboxCharacterStyle from 'remark-lint-checkbox-character-style'
|
import remarkLintCheckboxCharacterStyle from 'remark-lint-checkbox-character-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintCheckboxCharacterStyle)
|
||||||
.use(remarkLintCheckboxCharacterStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -72,22 +72,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintCheckboxContentIndent from 'remark-lint-checkbox-content-indent'
|
import remarkLintCheckboxContentIndent from 'remark-lint-checkbox-content-indent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintCheckboxContentIndent)
|
||||||
.use(remarkLintCheckboxContentIndent)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintCodeBlockStyle from 'remark-lint-code-block-style'
|
import remarkLintCodeBlockStyle from 'remark-lint-code-block-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintCodeBlockStyle)
|
||||||
.use(remarkLintCodeBlockStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintDefinitionCase from 'remark-lint-definition-case'
|
import remarkLintDefinitionCase from 'remark-lint-definition-case'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintDefinitionCase)
|
||||||
.use(remarkLintDefinitionCase)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintDefinitionSpacing from 'remark-lint-definition-spacing'
|
import remarkLintDefinitionSpacing from 'remark-lint-definition-spacing'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintDefinitionSpacing)
|
||||||
.use(remarkLintDefinitionSpacing)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintEmphasisMarker from 'remark-lint-emphasis-marker'
|
import remarkLintEmphasisMarker from 'remark-lint-emphasis-marker'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintEmphasisMarker)
|
||||||
.use(remarkLintEmphasisMarker)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintFencedCodeFlag from 'remark-lint-fenced-code-flag'
|
import remarkLintFencedCodeFlag from 'remark-lint-fenced-code-flag'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintFencedCodeFlag)
|
||||||
.use(remarkLintFencedCodeFlag)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintFencedCodeMarker from 'remark-lint-fenced-code-marker'
|
import remarkLintFencedCodeMarker from 'remark-lint-fenced-code-marker'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintFencedCodeMarker)
|
||||||
.use(remarkLintFencedCodeMarker)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -162,46 +160,6 @@ Indented code blocks are not affected by this rule:
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
##### `not-ok-consistent-tick.md`
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
````markdown
|
|
||||||
```alpha
|
|
||||||
bravo()
|
|
||||||
```
|
|
||||||
|
|
||||||
~~~
|
|
||||||
charlie()
|
|
||||||
~~~
|
|
||||||
````
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
5:1-7:4: Fenced code should use `` ` `` as a marker
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `not-ok-consistent-tilde.md`
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
````markdown
|
|
||||||
~~~alpha
|
|
||||||
bravo()
|
|
||||||
~~~
|
|
||||||
|
|
||||||
```
|
|
||||||
charlie()
|
|
||||||
```
|
|
||||||
````
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
5:1-7:4: Fenced code should use `~` as a marker
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `ok.md`
|
##### `ok.md`
|
||||||
|
|
||||||
When configured with ``'`'``.
|
When configured with ``'`'``.
|
||||||
@ -242,6 +200,46 @@ charlie()
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
|
##### `not-ok-consistent-tick.md`
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```alpha
|
||||||
|
bravo()
|
||||||
|
```
|
||||||
|
|
||||||
|
~~~
|
||||||
|
charlie()
|
||||||
|
~~~
|
||||||
|
````
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
5:1-7:4: Fenced code should use `` ` `` as a marker
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `not-ok-consistent-tilde.md`
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
~~~alpha
|
||||||
|
bravo()
|
||||||
|
~~~
|
||||||
|
|
||||||
|
```
|
||||||
|
charlie()
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
5:1-7:4: Fenced code should use `~` as a marker
|
||||||
|
```
|
||||||
|
|
||||||
##### `not-ok-incorrect.md`
|
##### `not-ok-incorrect.md`
|
||||||
|
|
||||||
When configured with `'💩'`.
|
When configured with `'💩'`.
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintFileExtension from 'remark-lint-file-extension'
|
import remarkLintFileExtension from 'remark-lint-file-extension'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintFileExtension)
|
||||||
.use(remarkLintFileExtension)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintFinalDefinition from 'remark-lint-final-definition'
|
import remarkLintFinalDefinition from 'remark-lint-final-definition'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintFinalDefinition)
|
||||||
.use(remarkLintFinalDefinition)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintFinalNewline from 'remark-lint-final-newline'
|
import remarkLintFinalNewline from 'remark-lint-final-newline'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintFinalNewline)
|
||||||
.use(remarkLintFinalNewline)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -69,22 +69,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintFirstHeadingLevel from 'remark-lint-first-heading-level'
|
import remarkLintFirstHeadingLevel from 'remark-lint-first-heading-level'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintFirstHeadingLevel)
|
||||||
.use(remarkLintFirstHeadingLevel)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintHardBreakSpaces from 'remark-lint-hard-break-spaces'
|
import remarkLintHardBreakSpaces from 'remark-lint-hard-break-spaces'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintHardBreakSpaces)
|
||||||
.use(remarkLintHardBreakSpaces)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintHeadingIncrement from 'remark-lint-heading-increment'
|
import remarkLintHeadingIncrement from 'remark-lint-heading-increment'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintHeadingIncrement)
|
||||||
.use(remarkLintHeadingIncrement)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintHeadingStyle from 'remark-lint-heading-style'
|
import remarkLintHeadingStyle from 'remark-lint-heading-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintHeadingStyle)
|
||||||
.use(remarkLintHeadingStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -70,22 +70,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintLinebreakStyle from 'remark-lint-linebreak-style'
|
import remarkLintLinebreakStyle from 'remark-lint-linebreak-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintLinebreakStyle)
|
||||||
.use(remarkLintLinebreakStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintLinkTitleStyle from 'remark-lint-link-title-style'
|
import remarkLintLinkTitleStyle from 'remark-lint-link-title-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintLinkTitleStyle)
|
||||||
.use(remarkLintLinkTitleStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintListItemBulletIndent from 'remark-lint-list-item-bullet-indent'
|
import remarkLintListItemBulletIndent from 'remark-lint-list-item-bullet-indent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintListItemBulletIndent)
|
||||||
.use(remarkLintListItemBulletIndent)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintListItemContentIndent from 'remark-lint-list-item-content-indent'
|
import remarkLintListItemContentIndent from 'remark-lint-list-item-content-indent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintListItemContentIndent)
|
||||||
.use(remarkLintListItemContentIndent)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -77,22 +77,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintListItemIndent from 'remark-lint-list-item-indent'
|
import remarkLintListItemIndent from 'remark-lint-list-item-indent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintListItemIndent)
|
||||||
.use(remarkLintListItemIndent)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -230,24 +228,6 @@ Paragraph.
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
##### `not-ok.md`
|
|
||||||
|
|
||||||
When configured with `'mixed'`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
> 👉 **Note**: `·` represents a space.
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
*···List item.
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
1:5: Incorrect list-item indent: remove 2 spaces
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `ok.md`
|
##### `ok.md`
|
||||||
|
|
||||||
When configured with `'space'`.
|
When configured with `'space'`.
|
||||||
@ -316,6 +296,24 @@ When configured with `'tab-size'`.
|
|||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
|
When configured with `'mixed'`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
> 👉 **Note**: `·` represents a space.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
*···List item.
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
1:5: Incorrect list-item indent: remove 2 spaces
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `not-ok.md`
|
||||||
|
|
||||||
When configured with `'💩'`.
|
When configured with `'💩'`.
|
||||||
|
|
||||||
###### Out
|
###### Out
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintListItemSpacing from 'remark-lint-list-item-spacing'
|
import remarkLintListItemSpacing from 'remark-lint-list-item-spacing'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintListItemSpacing)
|
||||||
.use(remarkLintListItemSpacing)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintMaximumHeadingLength from 'remark-lint-maximum-heading-length'
|
import remarkLintMaximumHeadingLength from 'remark-lint-maximum-heading-length'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintMaximumHeadingLength)
|
||||||
.use(remarkLintMaximumHeadingLength)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length'
|
import remarkLintMaximumLineLength from 'remark-lint-maximum-line-length'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintMaximumLineLength)
|
||||||
.use(remarkLintMaximumLineLength)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoBlockquoteWithoutMarker from 'remark-lint-no-blockquote-without-marker'
|
import remarkLintNoBlockquoteWithoutMarker from 'remark-lint-no-blockquote-without-marker'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoBlockquoteWithoutMarker)
|
||||||
.use(remarkLintNoBlockquoteWithoutMarker)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoConsecutiveBlankLines from 'remark-lint-no-consecutive-blank-lines'
|
import remarkLintNoConsecutiveBlankLines from 'remark-lint-no-consecutive-blank-lines'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoConsecutiveBlankLines)
|
||||||
.use(remarkLintNoConsecutiveBlankLines)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -69,22 +69,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoDuplicateDefinedUrls from 'remark-lint-no-duplicate-defined-urls'
|
import remarkLintNoDuplicateDefinedUrls from 'remark-lint-no-duplicate-defined-urls'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoDuplicateDefinedUrls)
|
||||||
.use(remarkLintNoDuplicateDefinedUrls)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoDuplicateDefinitions from 'remark-lint-no-duplicate-definitions'
|
import remarkLintNoDuplicateDefinitions from 'remark-lint-no-duplicate-definitions'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoDuplicateDefinitions)
|
||||||
.use(remarkLintNoDuplicateDefinitions)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -71,22 +71,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoDuplicateHeadingsInSection from 'remark-lint-no-duplicate-headings-in-section'
|
import remarkLintNoDuplicateHeadingsInSection from 'remark-lint-no-duplicate-headings-in-section'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoDuplicateHeadingsInSection)
|
||||||
.use(remarkLintNoDuplicateHeadingsInSection)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoDuplicateHeadings from 'remark-lint-no-duplicate-headings'
|
import remarkLintNoDuplicateHeadings from 'remark-lint-no-duplicate-headings'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoDuplicateHeadings)
|
||||||
.use(remarkLintNoDuplicateHeadings)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoEmphasisAsHeading from 'remark-lint-no-emphasis-as-heading'
|
import remarkLintNoEmphasisAsHeading from 'remark-lint-no-emphasis-as-heading'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoEmphasisAsHeading)
|
||||||
.use(remarkLintNoEmphasisAsHeading)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -69,22 +69,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoEmptyUrl from 'remark-lint-no-empty-url'
|
import remarkLintNoEmptyUrl from 'remark-lint-no-empty-url'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoEmptyUrl)
|
||||||
.use(remarkLintNoEmptyUrl)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoFileNameArticles from 'remark-lint-no-file-name-articles'
|
import remarkLintNoFileNameArticles from 'remark-lint-no-file-name-articles'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoFileNameArticles)
|
||||||
.use(remarkLintNoFileNameArticles)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoFileNameConsecutiveDashes from 'remark-lint-no-file-name-consecutive-dashes'
|
import remarkLintNoFileNameConsecutiveDashes from 'remark-lint-no-file-name-consecutive-dashes'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoFileNameConsecutiveDashes)
|
||||||
.use(remarkLintNoFileNameConsecutiveDashes)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -72,22 +72,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoFileNameIrregularCharacters from 'remark-lint-no-file-name-irregular-characters'
|
import remarkLintNoFileNameIrregularCharacters from 'remark-lint-no-file-name-irregular-characters'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoFileNameIrregularCharacters)
|
||||||
.use(remarkLintNoFileNameIrregularCharacters)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -151,14 +149,6 @@ No messages.
|
|||||||
1:1: Do not use `_` in a file name
|
1:1: Do not use `_` in a file name
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `plug ins.md`
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
1:1: Do not use ` ` in a file name
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `README.md`
|
##### `README.md`
|
||||||
|
|
||||||
When configured with `'\\.a-z0-9'`.
|
When configured with `'\\.a-z0-9'`.
|
||||||
@ -169,6 +159,14 @@ When configured with `'\\.a-z0-9'`.
|
|||||||
1:1: Do not use `R` in a file name
|
1:1: Do not use `R` in a file name
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `plug ins.md`
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
1:1: Do not use ` ` in a file name
|
||||||
|
```
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
Projects maintained by the unified collective are compatible with all maintained
|
Projects maintained by the unified collective are compatible with all maintained
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoFileNameMixedCase from 'remark-lint-no-file-name-mixed-case'
|
import remarkLintNoFileNameMixedCase from 'remark-lint-no-file-name-mixed-case'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoFileNameMixedCase)
|
||||||
.use(remarkLintNoFileNameMixedCase)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoFileNameOuterDashes from 'remark-lint-no-file-name-outer-dashes'
|
import remarkLintNoFileNameOuterDashes from 'remark-lint-no-file-name-outer-dashes'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoFileNameOuterDashes)
|
||||||
.use(remarkLintNoFileNameOuterDashes)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoHeadingContentIndent from 'remark-lint-no-heading-content-indent'
|
import remarkLintNoHeadingContentIndent from 'remark-lint-no-heading-content-indent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoHeadingContentIndent)
|
||||||
.use(remarkLintNoHeadingContentIndent)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -70,22 +70,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoHeadingIndent from 'remark-lint-no-heading-indent'
|
import remarkLintNoHeadingIndent from 'remark-lint-no-heading-indent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoHeadingIndent)
|
||||||
.use(remarkLintNoHeadingIndent)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -70,22 +70,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoHeadingLikeParagraph from 'remark-lint-no-heading-like-paragraph'
|
import remarkLintNoHeadingLikeParagraph from 'remark-lint-no-heading-like-paragraph'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoHeadingLikeParagraph)
|
||||||
.use(remarkLintNoHeadingLikeParagraph)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -72,22 +72,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoHeadingPunctuation from 'remark-lint-no-heading-punctuation'
|
import remarkLintNoHeadingPunctuation from 'remark-lint-no-heading-punctuation'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoHeadingPunctuation)
|
||||||
.use(remarkLintNoHeadingPunctuation)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -143,6 +141,20 @@ The following options (default: `'\\.,;:!?'`) are accepted:
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
|
##### `ok.md`
|
||||||
|
|
||||||
|
When configured with `',;:!?'`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Hello…
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
###### In
|
###### In
|
||||||
@ -169,20 +181,6 @@ No messages.
|
|||||||
9:1-9:9: Don’t add a trailing `;` to headings
|
9:1-9:9: Don’t add a trailing `;` to headings
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `ok.md`
|
|
||||||
|
|
||||||
When configured with `',;:!?'`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Hello…
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
No messages.
|
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
Projects maintained by the unified collective are compatible with all maintained
|
Projects maintained by the unified collective are compatible with all maintained
|
||||||
|
@ -68,22 +68,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoHtml from 'remark-lint-no-html'
|
import remarkLintNoHtml from 'remark-lint-no-html'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoHtml)
|
||||||
.use(remarkLintNoHtml)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoInlinePadding from 'remark-lint-no-inline-padding'
|
import remarkLintNoInlinePadding from 'remark-lint-no-inline-padding'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoInlinePadding)
|
||||||
.use(remarkLintNoInlinePadding)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoLiteralUrls from 'remark-lint-no-literal-urls'
|
import remarkLintNoLiteralUrls from 'remark-lint-no-literal-urls'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoLiteralUrls)
|
||||||
.use(remarkLintNoLiteralUrls)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -70,22 +70,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoMissingBlankLines from 'remark-lint-no-missing-blank-lines'
|
import remarkLintNoMissingBlankLines from 'remark-lint-no-missing-blank-lines'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoMissingBlankLines)
|
||||||
.use(remarkLintNoMissingBlankLines)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoMultipleToplevelHeadings from 'remark-lint-no-multiple-toplevel-headings'
|
import remarkLintNoMultipleToplevelHeadings from 'remark-lint-no-multiple-toplevel-headings'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoMultipleToplevelHeadings)
|
||||||
.use(remarkLintNoMultipleToplevelHeadings)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -106,7 +106,6 @@ const remarkLintNoParagraphContentIndent = lintRule(
|
|||||||
const value = String(file)
|
const value = String(file)
|
||||||
const loc = location(value)
|
const loc = location(value)
|
||||||
|
|
||||||
// eslint-disable-next-line complexity
|
|
||||||
visit(tree, 'paragraph', (node, _, parent) => {
|
visit(tree, 'paragraph', (node, _, parent) => {
|
||||||
const end = pointEnd(node)?.line
|
const end = pointEnd(node)?.line
|
||||||
let line = pointStart(node)?.line
|
let line = pointStart(node)?.line
|
||||||
|
@ -53,7 +53,8 @@
|
|||||||
"xo": {
|
"xo": {
|
||||||
"prettier": true,
|
"prettier": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"capitalized-comments": "off"
|
"capitalized-comments": "off",
|
||||||
|
"complexity": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,22 +70,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoParagraphContentIndent from 'remark-lint-no-paragraph-content-indent'
|
import remarkLintNoParagraphContentIndent from 'remark-lint-no-paragraph-content-indent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoParagraphContentIndent)
|
||||||
.use(remarkLintNoParagraphContentIndent)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -70,22 +70,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoReferenceLikeUrl from 'remark-lint-no-reference-like-url'
|
import remarkLintNoReferenceLikeUrl from 'remark-lint-no-reference-like-url'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoReferenceLikeUrl)
|
||||||
.use(remarkLintNoReferenceLikeUrl)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoShellDollars from 'remark-lint-no-shell-dollars'
|
import remarkLintNoShellDollars from 'remark-lint-no-shell-dollars'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoShellDollars)
|
||||||
.use(remarkLintNoShellDollars)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoShortcutReferenceImage from 'remark-lint-no-shortcut-reference-image'
|
import remarkLintNoShortcutReferenceImage from 'remark-lint-no-shortcut-reference-image'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoShortcutReferenceImage)
|
||||||
.use(remarkLintNoShortcutReferenceImage)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoShortcutReferenceLink from 'remark-lint-no-shortcut-reference-link'
|
import remarkLintNoShortcutReferenceLink from 'remark-lint-no-shortcut-reference-link'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoShortcutReferenceLink)
|
||||||
.use(remarkLintNoShortcutReferenceLink)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoTableIndentation from 'remark-lint-no-table-indentation'
|
import remarkLintNoTableIndentation from 'remark-lint-no-table-indentation'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoTableIndentation)
|
||||||
.use(remarkLintNoTableIndentation)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -70,22 +70,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoTabs from 'remark-lint-no-tabs'
|
import remarkLintNoTabs from 'remark-lint-no-tabs'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoTabs)
|
||||||
.use(remarkLintNoTabs)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -213,7 +213,6 @@ const remarkLintNoUndefinedReferences = lintRule(
|
|||||||
/** @type {Array<Range>} */
|
/** @type {Array<Range>} */
|
||||||
let ranges = []
|
let ranges = []
|
||||||
|
|
||||||
// eslint-disable-next-line complexity
|
|
||||||
visit(node, (child) => {
|
visit(node, (child) => {
|
||||||
// Ignore the node itself.
|
// Ignore the node itself.
|
||||||
if (child === node) return
|
if (child === node) return
|
||||||
@ -292,12 +291,10 @@ const remarkLintNoUndefinedReferences = lintRule(
|
|||||||
let range = ranges.pop()
|
let range = ranges.pop()
|
||||||
|
|
||||||
// Range should always exist.
|
// Range should always exist.
|
||||||
// eslint-disable-next-line max-depth
|
|
||||||
if (range) {
|
if (range) {
|
||||||
range.push(lines[lineIndex][0] + index)
|
range.push(lines[lineIndex][0] + index)
|
||||||
|
|
||||||
// This is the end of a reference already.
|
// This is the end of a reference already.
|
||||||
// eslint-disable-next-line max-depth
|
|
||||||
if (range.length === 4) {
|
if (range.length === 4) {
|
||||||
handleRange(range)
|
handleRange(range)
|
||||||
range = []
|
range = []
|
||||||
@ -314,7 +311,6 @@ const remarkLintNoUndefinedReferences = lintRule(
|
|||||||
const range = ranges.pop()
|
const range = ranges.pop()
|
||||||
|
|
||||||
// Range should always exist.
|
// Range should always exist.
|
||||||
// eslint-disable-next-line max-depth
|
|
||||||
if (range) {
|
if (range) {
|
||||||
range.push(lines[lineIndex][0] + index)
|
range.push(lines[lineIndex][0] + index)
|
||||||
handleRange(range)
|
handleRange(range)
|
||||||
|
@ -55,6 +55,8 @@
|
|||||||
"prettier": true,
|
"prettier": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"capitalized-comments": "off",
|
"capitalized-comments": "off",
|
||||||
|
"complexity": "off",
|
||||||
|
"max-depth": "off",
|
||||||
"unicorn/prefer-at": "off",
|
"unicorn/prefer-at": "off",
|
||||||
"unicorn/prefer-code-point": "off",
|
"unicorn/prefer-code-point": "off",
|
||||||
"unicorn/prefer-string-replace-all": "off",
|
"unicorn/prefer-string-replace-all": "off",
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoUndefinedReferences from 'remark-lint-no-undefined-references'
|
import remarkLintNoUndefinedReferences from 'remark-lint-no-undefined-references'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoUndefinedReferences)
|
||||||
.use(remarkLintNoUndefinedReferences)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -178,6 +176,38 @@ Just two braces can’t link: [].
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
|
##### `ok-allow.md`
|
||||||
|
|
||||||
|
When configured with `{ allow: [ '...', '…' ] }`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> Eliding a portion of a quoted passage […] is acceptable.
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
|
##### `ok-allow.md`
|
||||||
|
|
||||||
|
When configured with `{ allow: [ 'a', { source: '^b\\.' } ] }`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
[foo][b.c]
|
||||||
|
|
||||||
|
[bar][a]
|
||||||
|
|
||||||
|
Matching is case-insensitive: [bar][B.C]
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
###### In
|
###### In
|
||||||
@ -216,38 +246,6 @@ Multiple pairs: [a][b][c].
|
|||||||
17:23-17:26: Found reference to undefined definition
|
17:23-17:26: Found reference to undefined definition
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `ok-allow.md`
|
|
||||||
|
|
||||||
When configured with `{ allow: [ '...', '…' ] }`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
> Eliding a portion of a quoted passage […] is acceptable.
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
No messages.
|
|
||||||
|
|
||||||
##### `ok-allow.md`
|
|
||||||
|
|
||||||
When configured with `{ allow: [ 'a', { source: '^b\\.' } ] }`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
[foo][b.c]
|
|
||||||
|
|
||||||
[bar][a]
|
|
||||||
|
|
||||||
Matching is case-insensitive: [bar][B.C]
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
No messages.
|
|
||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
When configured with `{ allow: [ 'a', { source: '^b\\.' } ] }`.
|
When configured with `{ allow: [ 'a', { source: '^b\\.' } ] }`.
|
||||||
|
@ -71,22 +71,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoUnneededFullReferenceImage from 'remark-lint-no-unneeded-full-reference-image'
|
import remarkLintNoUnneededFullReferenceImage from 'remark-lint-no-unneeded-full-reference-image'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoUnneededFullReferenceImage)
|
||||||
.use(remarkLintNoUnneededFullReferenceImage)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -71,22 +71,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoUnneededFullReferenceLink from 'remark-lint-no-unneeded-full-reference-link'
|
import remarkLintNoUnneededFullReferenceLink from 'remark-lint-no-unneeded-full-reference-link'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoUnneededFullReferenceLink)
|
||||||
.use(remarkLintNoUnneededFullReferenceLink)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -73,22 +73,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintNoUnusedDefinitions from 'remark-lint-no-unused-definitions'
|
import remarkLintNoUnusedDefinitions from 'remark-lint-no-unused-definitions'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintNoUnusedDefinitions)
|
||||||
.use(remarkLintNoUnusedDefinitions)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintOrderedListMarkerStyle from 'remark-lint-ordered-list-marker-style'
|
import remarkLintOrderedListMarkerStyle from 'remark-lint-ordered-list-marker-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintOrderedListMarkerStyle)
|
||||||
.use(remarkLintOrderedListMarkerStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -170,22 +168,6 @@ Unordered lists are not affected by this rule.
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
##### `not-ok.md`
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
1. Foo
|
|
||||||
|
|
||||||
2) Bar
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
3:1-3:8: Marker style should be `.`
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `ok.md`
|
##### `ok.md`
|
||||||
|
|
||||||
When configured with `'.'`.
|
When configured with `'.'`.
|
||||||
@ -220,6 +202,22 @@ No messages.
|
|||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
1. Foo
|
||||||
|
|
||||||
|
2) Bar
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
3:1-3:8: Marker style should be `.`
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `not-ok.md`
|
||||||
|
|
||||||
When configured with `'💩'`.
|
When configured with `'💩'`.
|
||||||
|
|
||||||
###### Out
|
###### Out
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintOrderedListMarkerValue from 'remark-lint-ordered-list-marker-value'
|
import remarkLintOrderedListMarkerValue from 'remark-lint-ordered-list-marker-value'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintOrderedListMarkerValue)
|
||||||
.use(remarkLintOrderedListMarkerValue)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -202,40 +200,6 @@ Paragraph.
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
##### `not-ok.md`
|
|
||||||
|
|
||||||
When configured with `'one'`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
1. Foo
|
|
||||||
2. Bar
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
2:1-2:8: Marker should be `1`, was `2`
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `also-not-ok.md`
|
|
||||||
|
|
||||||
When configured with `'one'`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
2. Foo
|
|
||||||
1. Bar
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
1:1-1:8: Marker should be `1`, was `2`
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `ok.md`
|
##### `ok.md`
|
||||||
|
|
||||||
When configured with `'single'`.
|
When configured with `'single'`.
|
||||||
@ -294,6 +258,40 @@ No messages.
|
|||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
|
When configured with `'one'`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
1. Foo
|
||||||
|
2. Bar
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
2:1-2:8: Marker should be `1`, was `2`
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `also-not-ok.md`
|
||||||
|
|
||||||
|
When configured with `'one'`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
2. Foo
|
||||||
|
1. Bar
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
1:1-1:8: Marker should be `1`, was `2`
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `not-ok.md`
|
||||||
|
|
||||||
When configured with `'ordered'`.
|
When configured with `'ordered'`.
|
||||||
|
|
||||||
###### In
|
###### In
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintRuleStyle from 'remark-lint-rule-style'
|
import remarkLintRuleStyle from 'remark-lint-rule-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintRuleStyle)
|
||||||
.use(remarkLintRuleStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -74,22 +74,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintStrikethroughMarker from 'remark-lint-strikethrough-marker'
|
import remarkLintStrikethroughMarker from 'remark-lint-strikethrough-marker'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintStrikethroughMarker)
|
||||||
.use(remarkLintStrikethroughMarker)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintStrongMarker from 'remark-lint-strong-marker'
|
import remarkLintStrongMarker from 'remark-lint-strong-marker'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintStrongMarker)
|
||||||
.use(remarkLintStrongMarker)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -178,20 +176,6 @@ __foo__ and __bar__.
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
##### `not-ok.md`
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
**foo** and __bar__.
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
1:13-1:20: Strong should use `*` as a marker
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `ok.md`
|
##### `ok.md`
|
||||||
|
|
||||||
When configured with `'*'`.
|
When configured with `'*'`.
|
||||||
@ -222,6 +206,20 @@ No messages.
|
|||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
**foo** and __bar__.
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
1:13-1:20: Strong should use `*` as a marker
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `not-ok.md`
|
||||||
|
|
||||||
When configured with `'💩'`.
|
When configured with `'💩'`.
|
||||||
|
|
||||||
###### Out
|
###### Out
|
||||||
|
@ -77,22 +77,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintTableCellPadding from 'remark-lint-table-cell-padding'
|
import remarkLintTableCellPadding from 'remark-lint-table-cell-padding'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintTableCellPadding)
|
||||||
.use(remarkLintTableCellPadding)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -206,51 +204,6 @@ Too much padding isn’t good either:
|
|||||||
13:32: Cell should be padded with 1 space, not 2
|
13:32: Cell should be padded with 1 space, not 2
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `empty.md`
|
|
||||||
|
|
||||||
When configured with `'padded'`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][gfm]).
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
<!-- Empty cells are OK, but those surrounding them may not be. -->
|
|
||||||
|
|
||||||
| | Alpha | Bravo|
|
|
||||||
| ------ | ----- | ---: |
|
|
||||||
| Charlie| | Echo|
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
3:25: Cell should be padded
|
|
||||||
5:10: Cell should be padded
|
|
||||||
5:25: Cell should be padded
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `missing-body.md`
|
|
||||||
|
|
||||||
When configured with `'padded'`.
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
> 👉 **Note**: this example uses GFM ([`remark-gfm`][gfm]).
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
<!-- Missing cells are fine as well. -->
|
|
||||||
|
|
||||||
| Alpha | Bravo | Charlie |
|
|
||||||
| ----- | ------- | ------- |
|
|
||||||
| Delta |
|
|
||||||
| Echo | Foxtrot |
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
No messages.
|
|
||||||
|
|
||||||
##### `ok.md`
|
##### `ok.md`
|
||||||
|
|
||||||
When configured with `'compact'`.
|
When configured with `'compact'`.
|
||||||
@ -397,6 +350,51 @@ When configured with `'💩'`.
|
|||||||
1:1: Incorrect table cell padding style `💩`, expected `'padded'`, `'compact'`, or `'consistent'`
|
1:1: Incorrect table cell padding style `💩`, expected `'padded'`, `'compact'`, or `'consistent'`
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `empty.md`
|
||||||
|
|
||||||
|
When configured with `'padded'`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
> 👉 **Note**: this example uses GFM ([`remark-gfm`][gfm]).
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
<!-- Empty cells are OK, but those surrounding them may not be. -->
|
||||||
|
|
||||||
|
| | Alpha | Bravo|
|
||||||
|
| ------ | ----- | ---: |
|
||||||
|
| Charlie| | Echo|
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
3:25: Cell should be padded
|
||||||
|
5:10: Cell should be padded
|
||||||
|
5:25: Cell should be padded
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `missing-body.md`
|
||||||
|
|
||||||
|
When configured with `'padded'`.
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
> 👉 **Note**: this example uses GFM ([`remark-gfm`][gfm]).
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
<!-- Missing cells are fine as well. -->
|
||||||
|
|
||||||
|
| Alpha | Bravo | Charlie |
|
||||||
|
| ----- | ------- | ------- |
|
||||||
|
| Delta |
|
||||||
|
| Echo | Foxtrot |
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
Projects maintained by the unified collective are compatible with all maintained
|
Projects maintained by the unified collective are compatible with all maintained
|
||||||
|
@ -76,22 +76,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintTablePipeAlignment from 'remark-lint-table-pipe-alignment'
|
import remarkLintTablePipeAlignment from 'remark-lint-table-pipe-alignment'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintTablePipeAlignment)
|
||||||
.use(remarkLintTablePipeAlignment)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -78,22 +78,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintTablePipes from 'remark-lint-table-pipes'
|
import remarkLintTablePipes from 'remark-lint-table-pipes'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintTablePipes)
|
||||||
.use(remarkLintTablePipes)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -75,22 +75,20 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLint from 'remark-lint'
|
import remarkLint from 'remark-lint'
|
||||||
import remarkLintUnorderedListMarkerStyle from 'remark-lint-unordered-list-marker-style'
|
import remarkLintUnorderedListMarkerStyle from 'remark-lint-unordered-list-marker-style'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkLint)
|
||||||
.use(remarkLint)
|
.use(remarkLintUnorderedListMarkerStyle)
|
||||||
.use(remarkLintUnorderedListMarkerStyle)
|
.process(file)
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
@ -174,23 +172,6 @@ Ordered lists are not affected.
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
##### `not-ok.md`
|
|
||||||
|
|
||||||
###### In
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
* Foo
|
|
||||||
- Bar
|
|
||||||
+ Baz
|
|
||||||
```
|
|
||||||
|
|
||||||
###### Out
|
|
||||||
|
|
||||||
```text
|
|
||||||
2:1-2:6: Marker style should be `*`
|
|
||||||
3:1-3:6: Marker style should be `*`
|
|
||||||
```
|
|
||||||
|
|
||||||
##### `ok.md`
|
##### `ok.md`
|
||||||
|
|
||||||
When configured with `'*'`.
|
When configured with `'*'`.
|
||||||
@ -235,6 +216,23 @@ No messages.
|
|||||||
|
|
||||||
##### `not-ok.md`
|
##### `not-ok.md`
|
||||||
|
|
||||||
|
###### In
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
* Foo
|
||||||
|
- Bar
|
||||||
|
+ Baz
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
2:1-2:6: Marker style should be `*`
|
||||||
|
3:1-3:6: Marker style should be `*`
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `not-ok.md`
|
||||||
|
|
||||||
When configured with `'💩'`.
|
When configured with `'💩'`.
|
||||||
|
|
||||||
###### Out
|
###### Out
|
||||||
|
@ -82,20 +82,18 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
|
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkPresetLintConsistent)
|
||||||
.use(remarkPresetLintConsistent)
|
.process(await read('example.md'))
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -203,20 +203,18 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkPresetLintMarkdownStyleGuide from 'remark-preset-lint-markdown-style-guide'
|
import remarkPresetLintMarkdownStyleGuide from 'remark-preset-lint-markdown-style-guide'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkPresetLintMarkdownStyleGuide)
|
||||||
.use(remarkPresetLintMarkdownStyleGuide)
|
.process(await read('example.md'))
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
@ -84,20 +84,18 @@ In browsers with [`esm.sh`][esmsh]:
|
|||||||
On the API:
|
On the API:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {read} from 'to-vfile'
|
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
|
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
|
||||||
|
import {read} from 'to-vfile'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await read('example.md')
|
||||||
|
|
||||||
async function main() {
|
await remark()
|
||||||
const file = await remark()
|
.use(remarkPresetLintRecommended)
|
||||||
.use(remarkPresetLintRecommended)
|
.process(await read('example.md'))
|
||||||
.process(await read('example.md'))
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
console.error(reporter(file))
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
On the CLI:
|
On the CLI:
|
||||||
|
54
readme.md
54
readme.md
@ -369,28 +369,24 @@ npm install vfile-reporter remark remark-preset-lint-consistent remark-preset-li
|
|||||||
Then create a module `example.js` that contains:
|
Then create a module `example.js` that contains:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
|
import remarkLintListItemIndent from 'remark-lint-list-item-indent'
|
||||||
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
|
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
|
||||||
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
|
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
|
||||||
import remarkLintListItemIndent from 'remark-lint-list-item-indent'
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await remark()
|
||||||
|
// Check that markdown is consistent.
|
||||||
|
.use(remarkPresetLintConsistent)
|
||||||
|
// Few recommended rules.
|
||||||
|
.use(remarkPresetLintRecommended)
|
||||||
|
// `remark-lint-list-item-indent` is configured with `tab-size` in the
|
||||||
|
// recommended preset, but if we’d prefer something else, it can be
|
||||||
|
// reconfigured:
|
||||||
|
.use(remarkLintListItemIndent, 'space')
|
||||||
|
.process('1) Hello, _Jupiter_ and *Neptune*!')
|
||||||
|
|
||||||
async function main() {
|
console.error(reporter(file))
|
||||||
const file = await remark()
|
|
||||||
// Check that markdown is consistent.
|
|
||||||
.use(remarkPresetLintConsistent)
|
|
||||||
// Few recommended rules.
|
|
||||||
.use(remarkPresetLintRecommended)
|
|
||||||
// `remark-lint-list-item-indent` is configured with `tab-size` in the
|
|
||||||
// recommended preset, but if we’d prefer something else, it can be
|
|
||||||
// reconfigured:
|
|
||||||
.use(remarkLintListItemIndent, 'space')
|
|
||||||
.process('1) Hello, _Jupiter_ and *Neptune*!')
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Running that with `node example.js` yields:
|
Running that with `node example.js` yields:
|
||||||
@ -411,25 +407,21 @@ When you configure lint rules and use remark to format markdown, you must
|
|||||||
manually synchronize their configuration:
|
manually synchronize their configuration:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import {reporter} from 'vfile-reporter'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkLintEmphasisMarker from 'remark-lint-emphasis-marker'
|
import remarkLintEmphasisMarker from 'remark-lint-emphasis-marker'
|
||||||
import remarkLintStrongMarker from 'remark-lint-strong-marker'
|
import remarkLintStrongMarker from 'remark-lint-strong-marker'
|
||||||
|
import {reporter} from 'vfile-reporter'
|
||||||
|
|
||||||
main()
|
const file = await remark()
|
||||||
|
.use(remarkLintEmphasisMarker, '*')
|
||||||
|
.use(remarkLintStrongMarker, '*')
|
||||||
|
.use({
|
||||||
|
settings: {emphasis: '*', strong: '*'} // `remark-stringify` settings.
|
||||||
|
})
|
||||||
|
.process('_Hello_, __world__!')
|
||||||
|
|
||||||
async function main() {
|
console.error(reporter(file))
|
||||||
const file = await remark()
|
console.log(String(file))
|
||||||
.use(remarkLintEmphasisMarker, '*')
|
|
||||||
.use(remarkLintStrongMarker, '*')
|
|
||||||
.use({
|
|
||||||
settings: {emphasis: '*', strong: '*'} // `remark-stringify` settings.
|
|
||||||
})
|
|
||||||
.process('_Hello_, __world__!')
|
|
||||||
|
|
||||||
console.error(reporter(file))
|
|
||||||
console.log(String(file))
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Yields:
|
Yields:
|
||||||
|
919
script/build-plugins.js
Normal file
919
script/build-plugins.js
Normal file
@ -0,0 +1,919 @@
|
|||||||
|
/**
|
||||||
|
* @typedef {import('mdast').TableContent} TableContent
|
||||||
|
* @typedef {import('mdast').TopLevelContent} TopLevelContent
|
||||||
|
*
|
||||||
|
* @typedef {import('type-fest').PackageJson} PackageJson
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import fs from 'node:fs/promises'
|
||||||
|
import {inspect} from 'node:util'
|
||||||
|
import {slug as githubSlug} from 'github-slugger'
|
||||||
|
import {findAndReplace} from 'mdast-util-find-and-replace'
|
||||||
|
import {fromMarkdown} from 'mdast-util-from-markdown'
|
||||||
|
import {gfmToMarkdown} from 'mdast-util-gfm'
|
||||||
|
import {toMarkdown} from 'mdast-util-to-markdown'
|
||||||
|
import {toString} from 'mdast-util-to-string'
|
||||||
|
import parseAuthor from 'parse-author'
|
||||||
|
import {packagesUrl, plugins, presets} from './info.js'
|
||||||
|
import {characters} from './characters.js'
|
||||||
|
|
||||||
|
/** @type {PackageJson} */
|
||||||
|
const pack = JSON.parse(await fs.readFile('package.json', 'utf8'))
|
||||||
|
assert(pack.repository && typeof pack.repository === 'object')
|
||||||
|
const remote = pack.repository.url
|
||||||
|
|
||||||
|
let index = -1
|
||||||
|
|
||||||
|
while (++index < plugins.length) {
|
||||||
|
const info = plugins[index]
|
||||||
|
const packageUrl = new URL(info.name + '/', packagesUrl)
|
||||||
|
/** @type {PackageJson} */
|
||||||
|
const pack = JSON.parse(
|
||||||
|
await fs.readFile(new URL('package.json', packageUrl), 'utf8')
|
||||||
|
)
|
||||||
|
const version = (pack.version || '0').split('.')[0]
|
||||||
|
const author =
|
||||||
|
typeof pack.author === 'string' ? parseAuthor(pack.author) : pack.author
|
||||||
|
const camelcased = info.name.replace(
|
||||||
|
/-(\w)/g,
|
||||||
|
function (_, /** @type {string} */ $1) {
|
||||||
|
return $1.toUpperCase()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const org = remote.split('/').slice(0, -1).join('/')
|
||||||
|
const main = remote + '/blob/main'
|
||||||
|
const health = org + '/.github'
|
||||||
|
const hMain = health + '/blob/main'
|
||||||
|
const slug = remote.split('/').slice(-2).join('/')
|
||||||
|
let hasGfm = false
|
||||||
|
const descriptionTree = fromMarkdown(info.description)
|
||||||
|
const summaryTree = fromMarkdown(info.summary || '')
|
||||||
|
|
||||||
|
// Autolink `remark-lint`
|
||||||
|
findAndReplace(summaryTree, [
|
||||||
|
/remark-lint/g,
|
||||||
|
function () {
|
||||||
|
return {
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'mono',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [{type: 'inlineCode', value: 'remark-lint'}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const descriptionContent = /** @type {Array<TopLevelContent>} */ (
|
||||||
|
descriptionTree.children
|
||||||
|
)
|
||||||
|
const summaryContent = /** @type {Array<TopLevelContent>} */ (
|
||||||
|
summaryTree.children
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(info.name, pack.name, 'expected correct package name')
|
||||||
|
|
||||||
|
/** @type {Record<string, Array<TopLevelContent>>} */
|
||||||
|
const categories = {}
|
||||||
|
let category = 'Intro'
|
||||||
|
let contentIndex = -1
|
||||||
|
|
||||||
|
while (++contentIndex < descriptionContent.length) {
|
||||||
|
const node = descriptionContent[contentIndex]
|
||||||
|
|
||||||
|
if (node.type === 'heading' && node.depth === 2) {
|
||||||
|
category = githubSlug(toString(node))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(category in categories)) {
|
||||||
|
categories[category] = []
|
||||||
|
}
|
||||||
|
|
||||||
|
categories[category].push(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
const includes = presets.filter(function (preset) {
|
||||||
|
return preset.plugins.find(function (d) {
|
||||||
|
return d[0] === info.name
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/** @type {Array<TopLevelContent>} */
|
||||||
|
const children = [
|
||||||
|
{type: 'html', value: '<!--This file is generated-->'},
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 1,
|
||||||
|
children: [{type: 'text', value: info.name}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if (info.deprecated) {
|
||||||
|
children.push(...descriptionContent)
|
||||||
|
} else {
|
||||||
|
children.push(
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'build',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'imageReference',
|
||||||
|
identifier: 'build-badge',
|
||||||
|
referenceType: 'full',
|
||||||
|
alt: 'Build'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'text', value: '\n'},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'coverage',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'imageReference',
|
||||||
|
identifier: 'coverage-badge',
|
||||||
|
referenceType: 'full',
|
||||||
|
alt: 'Coverage'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'text', value: '\n'},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'downloads',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'imageReference',
|
||||||
|
identifier: 'downloads-badge',
|
||||||
|
referenceType: 'full',
|
||||||
|
alt: 'Downloads'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'text', value: '\n'},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'size',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'imageReference',
|
||||||
|
identifier: 'size-badge',
|
||||||
|
referenceType: 'full',
|
||||||
|
alt: 'Size'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'text', value: '\n'},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'collective',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'imageReference',
|
||||||
|
identifier: 'sponsors-badge',
|
||||||
|
referenceType: 'full',
|
||||||
|
alt: 'Sponsors'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'text', value: '\n'},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'collective',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'imageReference',
|
||||||
|
identifier: 'backers-badge',
|
||||||
|
referenceType: 'full',
|
||||||
|
alt: 'Backers'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'text', value: '\n'},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'chat',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'imageReference',
|
||||||
|
identifier: 'chat-badge',
|
||||||
|
referenceType: 'full',
|
||||||
|
alt: 'Chat'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...summaryContent,
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'Contents'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'What is this?'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: 'This package is a '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'unified',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
children: [{type: 'text', value: 'unified'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ' ('},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'remark',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
children: [{type: 'text', value: 'remark'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: ') plugin, specifically a '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inlineCode',
|
||||||
|
value: 'remark-lint'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: '\nrule.\nLint rules check markdown code style.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...(categories['when-should-i-use-this'] || []),
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'Presets'}]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (includes.length === 0) {
|
||||||
|
children.push({
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: 'This rule is not included in a preset maintained here.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
children.push(
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: 'This rule is included in the following presets:'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'table',
|
||||||
|
align: [],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'tableRow',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'tableCell',
|
||||||
|
children: [{type: 'text', value: 'Preset'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'tableCell',
|
||||||
|
children: [{type: 'text', value: 'Setting'}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...includes.map(function (preset) {
|
||||||
|
const tuple = preset.plugins.find(function (d) {
|
||||||
|
return d[0] === info.name
|
||||||
|
})
|
||||||
|
assert(tuple)
|
||||||
|
const option = tuple[1]
|
||||||
|
|
||||||
|
/** @type {TableContent} */
|
||||||
|
const row = {
|
||||||
|
type: 'tableRow',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'tableCell',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'link',
|
||||||
|
url: remote + '/tree/main/packages/' + preset.name,
|
||||||
|
children: [{type: 'inlineCode', value: preset.name}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'tableCell',
|
||||||
|
children: option
|
||||||
|
? [{type: 'inlineCode', value: inspect(option)}]
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return row
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'Install'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: 'This package is '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'esm',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [{type: 'text', value: 'ESM only'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value:
|
||||||
|
'.\nIn Node.js (version 12.20+, 14.14+, or 16.0+), ' +
|
||||||
|
'install with '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'npm',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
children: [{type: 'text', value: 'npm'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ':'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'code', lang: 'sh', value: 'npm install ' + info.name},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: 'In Deno with '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'esmsh',
|
||||||
|
label: 'esmsh',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [{type: 'inlineCode', value: 'esm.sh'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ':'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'code',
|
||||||
|
lang: 'js',
|
||||||
|
value:
|
||||||
|
'import ' +
|
||||||
|
camelcased +
|
||||||
|
" from 'https://esm.sh/" +
|
||||||
|
info.name +
|
||||||
|
'@' +
|
||||||
|
version +
|
||||||
|
"'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: 'In browsers with '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'esmsh',
|
||||||
|
label: 'esmsh',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [{type: 'inlineCode', value: 'esm.sh'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ':'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'code',
|
||||||
|
lang: 'html',
|
||||||
|
value:
|
||||||
|
'<script type="module">\n import ' +
|
||||||
|
camelcased +
|
||||||
|
" from 'https://esm.sh/" +
|
||||||
|
info.name +
|
||||||
|
'@' +
|
||||||
|
version +
|
||||||
|
"?bundle'\n</script>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'Use'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [{type: 'text', value: 'On the API:'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'code',
|
||||||
|
lang: 'js',
|
||||||
|
value: [
|
||||||
|
"import {remark} from 'remark'",
|
||||||
|
"import remarkLint from 'remark-lint'",
|
||||||
|
'import ' + camelcased + " from '" + info.name + "'",
|
||||||
|
"import {read} from 'to-vfile'",
|
||||||
|
"import {reporter} from 'vfile-reporter'",
|
||||||
|
'',
|
||||||
|
"const file = await read('example.md')",
|
||||||
|
'',
|
||||||
|
'await remark()',
|
||||||
|
' .use(remarkLint)',
|
||||||
|
' .use(' + camelcased + ')',
|
||||||
|
' .process(file)',
|
||||||
|
'',
|
||||||
|
'console.error(reporter(file))'
|
||||||
|
].join('\n')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [{type: 'text', value: 'On the CLI:'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'code',
|
||||||
|
lang: 'sh',
|
||||||
|
value: 'remark --use remark-lint --use ' + info.name + ' example.md'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: 'On the CLI in a config file (here a '
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inlineCode',
|
||||||
|
value: 'package.json'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: '):'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'code',
|
||||||
|
lang: 'diff',
|
||||||
|
value: [
|
||||||
|
' …',
|
||||||
|
' "remarkConfig": {',
|
||||||
|
' "plugins": [',
|
||||||
|
' …',
|
||||||
|
' "remark-lint",',
|
||||||
|
'+ "' + info.name + '",',
|
||||||
|
' …',
|
||||||
|
' ]',
|
||||||
|
' }',
|
||||||
|
' …'
|
||||||
|
].join('\n')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if ('api' in categories) {
|
||||||
|
const [apiHeading, ...apiBody] = categories.api
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
apiHeading,
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value:
|
||||||
|
'This package exports no identifiers.\nThe default export is '
|
||||||
|
},
|
||||||
|
{type: 'inlineCode', value: camelcased},
|
||||||
|
{type: 'text', value: '.'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 3,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'inlineCode',
|
||||||
|
value: 'unified().use(' + camelcased + '[, config])'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value:
|
||||||
|
'This rule supports standard configuration that all remark lint rules accept\n(such as '
|
||||||
|
},
|
||||||
|
{type: 'inlineCode', value: 'false'},
|
||||||
|
{type: 'text', value: ' to turn it off or '},
|
||||||
|
{type: 'inlineCode', value: '[1, options]'},
|
||||||
|
{type: 'text', value: ' to configure it).'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...apiBody
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
...(categories.recommendation || []),
|
||||||
|
...(categories.fix || []),
|
||||||
|
...(categories.example || [])
|
||||||
|
)
|
||||||
|
|
||||||
|
let first = true
|
||||||
|
|
||||||
|
for (const check of info.checks) {
|
||||||
|
if (first) {
|
||||||
|
children.push({
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'Examples'}]
|
||||||
|
})
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {{config: unknown}} */
|
||||||
|
const {config} = JSON.parse(check.configuration)
|
||||||
|
let clean = check.input
|
||||||
|
|
||||||
|
children.push({
|
||||||
|
type: 'heading',
|
||||||
|
depth: 5,
|
||||||
|
children: [{type: 'inlineCode', value: check.name}]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (config !== true) {
|
||||||
|
children.push({
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: 'When configured with '},
|
||||||
|
{type: 'inlineCode', value: inspect(config)},
|
||||||
|
{type: 'text', value: '.'}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check.input.trim() !== '') {
|
||||||
|
children.push({
|
||||||
|
type: 'heading',
|
||||||
|
depth: 6,
|
||||||
|
children: [{type: 'text', value: 'In'}]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (check.gfm) {
|
||||||
|
hasGfm = true
|
||||||
|
children.push({
|
||||||
|
type: 'blockquote',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: '👉 '},
|
||||||
|
{
|
||||||
|
type: 'strong',
|
||||||
|
children: [{type: 'text', value: 'Note'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ': this example uses GFM ('},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
identifier: 'gfm',
|
||||||
|
referenceType: 'full',
|
||||||
|
children: [{type: 'inlineCode', value: 'remark-gfm'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ').'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = -1
|
||||||
|
while (++index < characters.length) {
|
||||||
|
const char = characters[index]
|
||||||
|
const next = clean.replace(char.in, char.out)
|
||||||
|
|
||||||
|
if (clean !== next) {
|
||||||
|
children.push({
|
||||||
|
type: 'blockquote',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: '👉 '},
|
||||||
|
{
|
||||||
|
type: 'strong',
|
||||||
|
children: [{type: 'text', value: 'Note'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ': '},
|
||||||
|
{type: 'inlineCode', value: char.char},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: ' represents ' + char.name + '.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
clean = next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push({
|
||||||
|
type: 'code',
|
||||||
|
lang: 'markdown',
|
||||||
|
value: check.input
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push({
|
||||||
|
type: 'heading',
|
||||||
|
depth: 6,
|
||||||
|
children: [{type: 'text', value: 'Out'}]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (check.output.length === 0) {
|
||||||
|
children.push({
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [{type: 'text', value: 'No messages.'}]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
children.push({
|
||||||
|
type: 'code',
|
||||||
|
lang: 'text',
|
||||||
|
value: check.output.join('\n')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'Compatibility'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value:
|
||||||
|
'Projects maintained by the unified collective are compatible with all maintained\nversions of Node.js.\nAs of now, that is Node.js 12.20+, 14.14+, and 16.0+.\nOur projects sometimes work with older versions, but this is not guaranteed.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'heading',
|
||||||
|
depth: 2,
|
||||||
|
children: [{type: 'text', value: 'Contribute'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: 'See '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
identifier: 'contributing',
|
||||||
|
children: [{type: 'inlineCode', value: 'contributing.md'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ' in '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
identifier: 'health',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'inlineCode',
|
||||||
|
value: health.split('/').slice(-2).join('/')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ' for ways\nto get started.\nSee '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
identifier: 'support',
|
||||||
|
children: [{type: 'inlineCode', value: 'support.md'}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ' for ways to get help.'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: 'This project has a '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
identifier: 'coc',
|
||||||
|
children: [{type: 'text', value: 'code of conduct'}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value:
|
||||||
|
'.\nBy interacting with this repository, organization, or community you agree to\nabide by its terms.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
{type: 'heading', depth: 2, children: [{type: 'text', value: 'License'}]},
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
identifier: 'license',
|
||||||
|
children: [{type: 'text', value: String(pack.license || '')}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ' © '},
|
||||||
|
{
|
||||||
|
type: 'linkReference',
|
||||||
|
referenceType: 'collapsed',
|
||||||
|
identifier: 'author',
|
||||||
|
children: [
|
||||||
|
{type: 'text', value: String((author && author.name) || '')}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!info.deprecated) {
|
||||||
|
children.push(
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'build-badge',
|
||||||
|
url: 'https://github.com/' + slug + '/workflows/main/badge.svg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'build',
|
||||||
|
url: 'https://github.com/' + slug + '/actions'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'coverage-badge',
|
||||||
|
url: 'https://img.shields.io/codecov/c/github/' + slug + '.svg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'coverage',
|
||||||
|
url: 'https://codecov.io/github/' + slug
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'downloads-badge',
|
||||||
|
url: 'https://img.shields.io/npm/dm/' + info.name + '.svg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'downloads',
|
||||||
|
url: 'https://www.npmjs.com/package/' + info.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'size-badge',
|
||||||
|
url: 'https://img.shields.io/bundlephobia/minzip/' + info.name + '.svg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'size',
|
||||||
|
url: 'https://bundlephobia.com/result?p=' + info.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'sponsors-badge',
|
||||||
|
url: 'https://opencollective.com/unified/sponsors/badge.svg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'backers-badge',
|
||||||
|
url: 'https://opencollective.com/unified/backers/badge.svg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'collective',
|
||||||
|
url: 'https://opencollective.com/unified'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'chat-badge',
|
||||||
|
url: 'https://img.shields.io/badge/chat-discussions-success.svg'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'chat',
|
||||||
|
url: 'https://github.com/remarkjs/remark/discussions'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'unified',
|
||||||
|
url: 'https://github.com/unifiedjs/unified'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'remark',
|
||||||
|
url: 'https://github.com/remarkjs/remark'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'mono',
|
||||||
|
url: 'https://github.com/' + slug
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'esm',
|
||||||
|
url: 'https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'esmsh',
|
||||||
|
url: 'https://esm.sh'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'npm',
|
||||||
|
url: 'https://docs.npmjs.com/cli/install'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'health',
|
||||||
|
url: health
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'contributing',
|
||||||
|
url: hMain + '/contributing.md'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'support',
|
||||||
|
url: hMain + '/support.md'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'coc',
|
||||||
|
url: hMain + '/code-of-conduct.md'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'license',
|
||||||
|
url: main + '/license'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'author',
|
||||||
|
url: String((author && author.url) || '')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (hasGfm) {
|
||||||
|
children.push({
|
||||||
|
type: 'definition',
|
||||||
|
identifier: 'gfm',
|
||||||
|
url: 'https://github.com/remarkjs/remark-gfm'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
new URL('readme.md', packageUrl),
|
||||||
|
toMarkdown({type: 'root', children}, {extensions: [gfmToMarkdown()]})
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log('✓ wrote `readme.md` in `' + info.name + '`')
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,967 +0,0 @@
|
|||||||
/**
|
|
||||||
* @typedef {import('mdast').BlockContent} BlockContent
|
|
||||||
* @typedef {import('mdast').DefinitionContent} DefinitionContent
|
|
||||||
* @typedef {import('mdast').TableContent} TableContent
|
|
||||||
* @typedef {import('type-fest').PackageJson} PackageJson
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {BlockContent | DefinitionContent} BlockAndDefinitionContent
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fs from 'node:fs'
|
|
||||||
import path from 'node:path'
|
|
||||||
import process from 'node:process'
|
|
||||||
import {inspect} from 'node:util'
|
|
||||||
import {unified} from 'unified'
|
|
||||||
import {remark} from 'remark'
|
|
||||||
import remarkParse from 'remark-parse'
|
|
||||||
import remarkGfm from 'remark-gfm'
|
|
||||||
import {findAndReplace} from 'mdast-util-find-and-replace'
|
|
||||||
import {toString} from 'mdast-util-to-string'
|
|
||||||
import {slug as githubSlug} from 'github-slugger'
|
|
||||||
import parseAuthor from 'parse-author'
|
|
||||||
import {rules} from './util/rules.js'
|
|
||||||
import {rule} from './util/rule.js'
|
|
||||||
import {presets} from './util/presets.js'
|
|
||||||
import {repoUrl} from './util/repo-url.js'
|
|
||||||
import {characters} from './characters.js'
|
|
||||||
|
|
||||||
const own = {}.hasOwnProperty
|
|
||||||
|
|
||||||
const remote = repoUrl('package.json')
|
|
||||||
|
|
||||||
const root = path.join(process.cwd(), 'packages')
|
|
||||||
|
|
||||||
// eslint-disable-next-line complexity, unicorn/prefer-top-level-await
|
|
||||||
presets(root).then((presetObjects) => {
|
|
||||||
const allRules = rules(root)
|
|
||||||
let index = -1
|
|
||||||
|
|
||||||
while (++index < allRules.length) {
|
|
||||||
const basename = allRules[index]
|
|
||||||
const base = path.resolve(root, basename)
|
|
||||||
/** @type {PackageJson} */
|
|
||||||
const pack = JSON.parse(
|
|
||||||
String(fs.readFileSync(path.join(base, 'package.json')))
|
|
||||||
)
|
|
||||||
const version = (pack.version || '0').split('.')[0]
|
|
||||||
const info = rule(base)
|
|
||||||
const tests = info.tests
|
|
||||||
const author =
|
|
||||||
typeof pack.author === 'string' ? parseAuthor(pack.author) : pack.author
|
|
||||||
const camelcased = basename.replace(
|
|
||||||
/-(\w)/g,
|
|
||||||
(_, /** @type {string} */ $1) => $1.toUpperCase()
|
|
||||||
)
|
|
||||||
const org = remote.split('/').slice(0, -1).join('/')
|
|
||||||
const main = remote + '/blob/main'
|
|
||||||
const health = org + '/.github'
|
|
||||||
const hMain = health + '/blob/main'
|
|
||||||
const slug = remote.split('/').slice(-2).join('/')
|
|
||||||
let hasGfm = false
|
|
||||||
|
|
||||||
const descriptionTree = unified().use(remarkParse).parse(info.description)
|
|
||||||
const summaryTree = unified()
|
|
||||||
.use(remarkParse)
|
|
||||||
.parse(info.summary || '')
|
|
||||||
|
|
||||||
// Autolink `remark-lint`
|
|
||||||
unified()
|
|
||||||
.use(
|
|
||||||
/** @type {import('unified').Plugin<Array<void>, import('mdast').Root>} */
|
|
||||||
() => (tree) => {
|
|
||||||
findAndReplace(tree, [
|
|
||||||
/remark-lint/g,
|
|
||||||
() => {
|
|
||||||
return {
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'mono',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [{type: 'inlineCode', value: 'remark-lint'}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.runSync(summaryTree)
|
|
||||||
|
|
||||||
const descriptionContent = /** @type {Array<BlockAndDefinitionContent>} */ (
|
|
||||||
descriptionTree.children
|
|
||||||
)
|
|
||||||
const summaryContent = /** @type {Array<BlockAndDefinitionContent>} */ (
|
|
||||||
summaryTree.children
|
|
||||||
)
|
|
||||||
|
|
||||||
if (basename !== pack.name) {
|
|
||||||
throw new Error(
|
|
||||||
'Expected package name (`' +
|
|
||||||
pack.name +
|
|
||||||
'`) to be the same as directory name (`' +
|
|
||||||
basename +
|
|
||||||
'`)'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {Record<string, Array<BlockAndDefinitionContent>>} */
|
|
||||||
const categories = {}
|
|
||||||
let category = 'Intro'
|
|
||||||
let contentIndex = -1
|
|
||||||
|
|
||||||
while (++contentIndex < descriptionContent.length) {
|
|
||||||
const node = descriptionContent[contentIndex]
|
|
||||||
if (node.type === 'heading' && node.depth === 2) {
|
|
||||||
category = githubSlug(toString(node))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(category in categories)) {
|
|
||||||
categories[category] = []
|
|
||||||
}
|
|
||||||
|
|
||||||
categories[category].push(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
const includes = presetObjects.filter(
|
|
||||||
(preset) => basename in preset.packages
|
|
||||||
)
|
|
||||||
|
|
||||||
/** @type {Array<BlockAndDefinitionContent>} */
|
|
||||||
const children = [
|
|
||||||
{type: 'html', value: '<!--This file is generated-->'},
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 1,
|
|
||||||
children: [{type: 'text', value: basename}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
if (info.deprecated) {
|
|
||||||
children.push(...descriptionContent)
|
|
||||||
} else {
|
|
||||||
children.push(
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'build',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'imageReference',
|
|
||||||
identifier: 'build-badge',
|
|
||||||
referenceType: 'full',
|
|
||||||
alt: 'Build'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: '\n'},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'coverage',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'imageReference',
|
|
||||||
identifier: 'coverage-badge',
|
|
||||||
referenceType: 'full',
|
|
||||||
alt: 'Coverage'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: '\n'},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'downloads',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'imageReference',
|
|
||||||
identifier: 'downloads-badge',
|
|
||||||
referenceType: 'full',
|
|
||||||
alt: 'Downloads'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: '\n'},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'size',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'imageReference',
|
|
||||||
identifier: 'size-badge',
|
|
||||||
referenceType: 'full',
|
|
||||||
alt: 'Size'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: '\n'},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'collective',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'imageReference',
|
|
||||||
identifier: 'sponsors-badge',
|
|
||||||
referenceType: 'full',
|
|
||||||
alt: 'Sponsors'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: '\n'},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'collective',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'imageReference',
|
|
||||||
identifier: 'backers-badge',
|
|
||||||
referenceType: 'full',
|
|
||||||
alt: 'Backers'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: '\n'},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'chat',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'imageReference',
|
|
||||||
identifier: 'chat-badge',
|
|
||||||
referenceType: 'full',
|
|
||||||
alt: 'Chat'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...summaryContent,
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'Contents'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'What is this?'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: 'This package is a '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'unified',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
children: [{type: 'text', value: 'unified'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ' ('},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'remark',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
children: [{type: 'text', value: 'remark'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value: ') plugin, specifically a '
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'inlineCode',
|
|
||||||
value: 'remark-lint'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value: '\nrule.\nLint rules check markdown code style.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...(categories['when-should-i-use-this'] || []),
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'Presets'}]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (includes.length === 0) {
|
|
||||||
children.push({
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value: 'This rule is not included in a preset maintained here.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
children.push(
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value: 'This rule is included in the following presets:'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'table',
|
|
||||||
align: [],
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'tableRow',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'tableCell',
|
|
||||||
children: [{type: 'text', value: 'Preset'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'tableCell',
|
|
||||||
children: [{type: 'text', value: 'Setting'}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...includes.map((preset) => {
|
|
||||||
const option = preset.packages[basename]
|
|
||||||
|
|
||||||
/** @type {TableContent} */
|
|
||||||
const row = {
|
|
||||||
type: 'tableRow',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'tableCell',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'link',
|
|
||||||
url: remote + '/tree/main/packages/' + preset.name,
|
|
||||||
title: null,
|
|
||||||
children: [{type: 'inlineCode', value: preset.name}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'tableCell',
|
|
||||||
children: option
|
|
||||||
? [{type: 'inlineCode', value: inspect(option)}]
|
|
||||||
: []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
return row
|
|
||||||
})
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push(
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'Install'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: 'This package is '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'esm',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [{type: 'text', value: 'ESM only'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value:
|
|
||||||
'.\nIn Node.js (version 12.20+, 14.14+, or 16.0+), ' +
|
|
||||||
'install with '
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'npm',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
children: [{type: 'text', value: 'npm'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ':'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'code', lang: 'sh', value: 'npm install ' + basename},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: 'In Deno with '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'esmsh',
|
|
||||||
label: 'esmsh',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [{type: 'inlineCode', value: 'esm.sh'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ':'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'code',
|
|
||||||
lang: 'js',
|
|
||||||
value:
|
|
||||||
'import ' +
|
|
||||||
camelcased +
|
|
||||||
" from 'https://esm.sh/" +
|
|
||||||
basename +
|
|
||||||
'@' +
|
|
||||||
version +
|
|
||||||
"'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: 'In browsers with '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'esmsh',
|
|
||||||
label: 'esmsh',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [{type: 'inlineCode', value: 'esm.sh'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ':'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'code',
|
|
||||||
lang: 'html',
|
|
||||||
value:
|
|
||||||
'<script type="module">\n import ' +
|
|
||||||
camelcased +
|
|
||||||
" from 'https://esm.sh/" +
|
|
||||||
basename +
|
|
||||||
'@' +
|
|
||||||
version +
|
|
||||||
"?bundle'\n</script>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'Use'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [{type: 'text', value: 'On the API:'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'code',
|
|
||||||
lang: 'js',
|
|
||||||
value: [
|
|
||||||
"import {read} from 'to-vfile'",
|
|
||||||
"import {reporter} from 'vfile-reporter'",
|
|
||||||
"import {remark} from 'remark'",
|
|
||||||
"import remarkLint from 'remark-lint'",
|
|
||||||
'import ' + camelcased + " from '" + basename + "'",
|
|
||||||
'',
|
|
||||||
'main()',
|
|
||||||
'',
|
|
||||||
'async function main() {',
|
|
||||||
' const file = await remark()',
|
|
||||||
' .use(remarkLint)',
|
|
||||||
' .use(' + camelcased + ')',
|
|
||||||
" .process(await read('example.md'))",
|
|
||||||
'',
|
|
||||||
' console.error(reporter(file))',
|
|
||||||
'}'
|
|
||||||
].join('\n')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [{type: 'text', value: 'On the CLI:'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'code',
|
|
||||||
lang: 'sh',
|
|
||||||
value: 'remark --use remark-lint --use ' + basename + ' example.md'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value: 'On the CLI in a config file (here a '
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'inlineCode',
|
|
||||||
value: 'package.json'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value: '):'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'code',
|
|
||||||
lang: 'diff',
|
|
||||||
value: [
|
|
||||||
' …',
|
|
||||||
' "remarkConfig": {',
|
|
||||||
' "plugins": [',
|
|
||||||
' …',
|
|
||||||
' "remark-lint",',
|
|
||||||
'+ "' + basename + '",',
|
|
||||||
' …',
|
|
||||||
' ]',
|
|
||||||
' }',
|
|
||||||
' …'
|
|
||||||
].join('\n')
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if ('api' in categories) {
|
|
||||||
const [apiHeading, ...apiBody] = categories.api
|
|
||||||
|
|
||||||
children.push(
|
|
||||||
apiHeading,
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value:
|
|
||||||
'This package exports no identifiers.\nThe default export is '
|
|
||||||
},
|
|
||||||
{type: 'inlineCode', value: camelcased},
|
|
||||||
{type: 'text', value: '.'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 3,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'inlineCode',
|
|
||||||
value: 'unified().use(' + camelcased + '[, config])'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value:
|
|
||||||
'This rule supports standard configuration that all remark lint rules accept\n(such as '
|
|
||||||
},
|
|
||||||
{type: 'inlineCode', value: 'false'},
|
|
||||||
{type: 'text', value: ' to turn it off or '},
|
|
||||||
{type: 'inlineCode', value: '[1, options]'},
|
|
||||||
{type: 'text', value: ' to configure it).'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...apiBody
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push(
|
|
||||||
...(categories.recommendation || []),
|
|
||||||
...(categories.fix || []),
|
|
||||||
...(categories.example || [])
|
|
||||||
)
|
|
||||||
|
|
||||||
let first = true
|
|
||||||
/** @type {string} */
|
|
||||||
let configuration
|
|
||||||
|
|
||||||
for (configuration in tests) {
|
|
||||||
if (own.call(tests, configuration)) {
|
|
||||||
const fixtures = tests[configuration]
|
|
||||||
|
|
||||||
if (first) {
|
|
||||||
children.push({
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'Examples'}]
|
|
||||||
})
|
|
||||||
first = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {string} */
|
|
||||||
let fileName
|
|
||||||
|
|
||||||
for (fileName in fixtures) {
|
|
||||||
if (own.call(fixtures, fileName)) {
|
|
||||||
const fixture = fixtures[fileName]
|
|
||||||
/** @type {{config: unknown}} */
|
|
||||||
const {config} = JSON.parse(configuration)
|
|
||||||
let clean = fixture.input
|
|
||||||
|
|
||||||
children.push({
|
|
||||||
type: 'heading',
|
|
||||||
depth: 5,
|
|
||||||
children: [{type: 'inlineCode', value: fileName}]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (config !== true) {
|
|
||||||
children.push({
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: 'When configured with '},
|
|
||||||
{type: 'inlineCode', value: inspect(config)},
|
|
||||||
{type: 'text', value: '.'}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
fixture.input !== null &&
|
|
||||||
fixture.input !== undefined &&
|
|
||||||
fixture.input.trim() !== ''
|
|
||||||
) {
|
|
||||||
children.push({
|
|
||||||
type: 'heading',
|
|
||||||
depth: 6,
|
|
||||||
children: [{type: 'text', value: 'In'}]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (fixture.gfm) {
|
|
||||||
hasGfm = true
|
|
||||||
children.push({
|
|
||||||
type: 'blockquote',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: '👉 '},
|
|
||||||
{
|
|
||||||
type: 'strong',
|
|
||||||
children: [{type: 'text', value: 'Note'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ': this example uses GFM ('},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
identifier: 'gfm',
|
|
||||||
referenceType: 'full',
|
|
||||||
children: [
|
|
||||||
{type: 'inlineCode', value: 'remark-gfm'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ').'}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = -1
|
|
||||||
while (++index < characters.length) {
|
|
||||||
const char = characters[index]
|
|
||||||
const next = clean.replace(char.in, char.out)
|
|
||||||
|
|
||||||
if (clean !== next) {
|
|
||||||
children.push({
|
|
||||||
type: 'blockquote',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: '👉 '},
|
|
||||||
{
|
|
||||||
type: 'strong',
|
|
||||||
children: [{type: 'text', value: 'Note'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ': '},
|
|
||||||
{type: 'inlineCode', value: char.char},
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value: ' represents ' + char.name + '.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
clean = next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push({
|
|
||||||
type: 'code',
|
|
||||||
lang: 'markdown',
|
|
||||||
value: fixture.input
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push({
|
|
||||||
type: 'heading',
|
|
||||||
depth: 6,
|
|
||||||
children: [{type: 'text', value: 'Out'}]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (fixture.output.length === 0) {
|
|
||||||
children.push({
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [{type: 'text', value: 'No messages.'}]
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
children.push({
|
|
||||||
type: 'code',
|
|
||||||
lang: 'text',
|
|
||||||
value: fixture.output.join('\n')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push(
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'Compatibility'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value:
|
|
||||||
'Projects maintained by the unified collective are compatible with all maintained\nversions of Node.js.\nAs of now, that is Node.js 12.20+, 14.14+, and 16.0+.\nOur projects sometimes work with older versions, but this is not guaranteed.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'heading',
|
|
||||||
depth: 2,
|
|
||||||
children: [{type: 'text', value: 'Contribute'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: 'See '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
identifier: 'contributing',
|
|
||||||
children: [{type: 'inlineCode', value: 'contributing.md'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ' in '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
identifier: 'health',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'inlineCode',
|
|
||||||
value: health.split('/').slice(-2).join('/')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ' for ways\nto get started.\nSee '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
identifier: 'support',
|
|
||||||
children: [{type: 'inlineCode', value: 'support.md'}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ' for ways to get help.'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: 'This project has a '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
identifier: 'coc',
|
|
||||||
children: [{type: 'text', value: 'code of conduct'}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
value:
|
|
||||||
'.\nBy interacting with this repository, organization, or community you agree to\nabide by its terms.'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push(
|
|
||||||
{type: 'heading', depth: 2, children: [{type: 'text', value: 'License'}]},
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
identifier: 'license',
|
|
||||||
children: [{type: 'text', value: String(pack.license || '')}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ' © '},
|
|
||||||
{
|
|
||||||
type: 'linkReference',
|
|
||||||
referenceType: 'collapsed',
|
|
||||||
identifier: 'author',
|
|
||||||
children: [
|
|
||||||
{type: 'text', value: String((author && author.name) || '')}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!info.deprecated) {
|
|
||||||
children.push(
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'build-badge',
|
|
||||||
url: 'https://github.com/' + slug + '/workflows/main/badge.svg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'build',
|
|
||||||
url: 'https://github.com/' + slug + '/actions'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'coverage-badge',
|
|
||||||
url: 'https://img.shields.io/codecov/c/github/' + slug + '.svg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'coverage',
|
|
||||||
url: 'https://codecov.io/github/' + slug
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'downloads-badge',
|
|
||||||
url: 'https://img.shields.io/npm/dm/' + basename + '.svg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'downloads',
|
|
||||||
url: 'https://www.npmjs.com/package/' + basename
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'size-badge',
|
|
||||||
url: 'https://img.shields.io/bundlephobia/minzip/' + basename + '.svg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'size',
|
|
||||||
url: 'https://bundlephobia.com/result?p=' + basename
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'sponsors-badge',
|
|
||||||
url: 'https://opencollective.com/unified/sponsors/badge.svg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'backers-badge',
|
|
||||||
url: 'https://opencollective.com/unified/backers/badge.svg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'collective',
|
|
||||||
url: 'https://opencollective.com/unified'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'chat-badge',
|
|
||||||
url: 'https://img.shields.io/badge/chat-discussions-success.svg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'chat',
|
|
||||||
url: 'https://github.com/remarkjs/remark/discussions'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'unified',
|
|
||||||
url: 'https://github.com/unifiedjs/unified'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'remark',
|
|
||||||
url: 'https://github.com/remarkjs/remark'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'mono',
|
|
||||||
url: 'https://github.com/' + slug
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'esm',
|
|
||||||
url: 'https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'esmsh',
|
|
||||||
url: 'https://esm.sh'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'npm',
|
|
||||||
url: 'https://docs.npmjs.com/cli/install'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'health',
|
|
||||||
url: health
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'contributing',
|
|
||||||
url: hMain + '/contributing.md'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'support',
|
|
||||||
url: hMain + '/support.md'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'coc',
|
|
||||||
url: hMain + '/code-of-conduct.md'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
children.push(
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'license',
|
|
||||||
url: main + '/license'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'author',
|
|
||||||
url: String((author && author.url) || '')
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (hasGfm) {
|
|
||||||
children.push({
|
|
||||||
type: 'definition',
|
|
||||||
identifier: 'gfm',
|
|
||||||
url: 'https://github.com/remarkjs/remark-gfm'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(base, 'readme.md'),
|
|
||||||
remark().use(remarkGfm).stringify({type: 'root', children})
|
|
||||||
)
|
|
||||||
|
|
||||||
console.log('✓ wrote `readme.md` in `' + basename + '`')
|
|
||||||
}
|
|
||||||
})
|
|
253
script/info.js
Normal file
253
script/info.js
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/**
|
||||||
|
* @typedef {import('unified').Preset} Preset
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Check
|
||||||
|
* Check.
|
||||||
|
* @property {string} configuration
|
||||||
|
* Configuration.
|
||||||
|
* @property {boolean} gfm
|
||||||
|
* Whether to use GFM.
|
||||||
|
* @property {string} input
|
||||||
|
* Input.
|
||||||
|
* @property {string} name
|
||||||
|
* Name.
|
||||||
|
* @property {Array<string>} output
|
||||||
|
* Output.
|
||||||
|
* @property {boolean} positionless
|
||||||
|
* Whether this check also applies without positions.
|
||||||
|
*
|
||||||
|
* @typedef ExampleInfo
|
||||||
|
* Example.
|
||||||
|
* @property {unknown} [config]
|
||||||
|
* Configuration.
|
||||||
|
* @property {boolean} [gfm]
|
||||||
|
* Whether to use GFM.
|
||||||
|
* @property {'input' | 'output'} [label]
|
||||||
|
* Label.
|
||||||
|
* @property {boolean} [positionless]
|
||||||
|
* Whether this check also applies without positions.
|
||||||
|
* @property {string} name
|
||||||
|
* Name.
|
||||||
|
*
|
||||||
|
* @typedef PluginInfo
|
||||||
|
* Plugin.
|
||||||
|
* @property {boolean} deprecated
|
||||||
|
* Whether the plugin is deprecated.
|
||||||
|
* @property {string} description
|
||||||
|
* Description.
|
||||||
|
* @property {string} name
|
||||||
|
* Name.
|
||||||
|
* @property {string} ruleId
|
||||||
|
* Rule ID.
|
||||||
|
* @property {string | undefined} summary
|
||||||
|
* Summary.
|
||||||
|
* @property {Array<Check>} checks
|
||||||
|
* Checks.
|
||||||
|
*
|
||||||
|
* @typedef PresetInfo
|
||||||
|
* Preset.
|
||||||
|
* @property {string} name
|
||||||
|
* Name.
|
||||||
|
* @property {Array<[string, unknown]>} plugins
|
||||||
|
* Plugins and their configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import fs from 'node:fs/promises'
|
||||||
|
import {parse} from 'comment-parser'
|
||||||
|
import strip from 'strip-indent'
|
||||||
|
|
||||||
|
export const packagesUrl = new URL('../packages/', import.meta.url)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Array<PluginInfo>}
|
||||||
|
* Plugins.
|
||||||
|
*/
|
||||||
|
export const plugins = []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Array<PresetInfo>}
|
||||||
|
* Presets.
|
||||||
|
*/
|
||||||
|
export const presets = []
|
||||||
|
|
||||||
|
const names = await fs.readdir(packagesUrl)
|
||||||
|
|
||||||
|
for (const name of names) {
|
||||||
|
if (name.startsWith('remark-lint-')) {
|
||||||
|
await addPlugin(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.startsWith('remark-preset-lint-')) {
|
||||||
|
await addPreset(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
* Plugin name.
|
||||||
|
* @returns {Promise<undefined>}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
async function addPlugin(name) {
|
||||||
|
const ruleId = name.slice('remark-lint-'.length)
|
||||||
|
const code = await fs.readFile(
|
||||||
|
new URL(name + '/index.js', packagesUrl),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
const fileInfo = parse(code, {spacing: 'preserve'})[0]
|
||||||
|
const tags = fileInfo.tags
|
||||||
|
const deprecatedTag = tags.find(function (d) {
|
||||||
|
return d.tag === 'deprecated'
|
||||||
|
})
|
||||||
|
const moduleTag = tags.find(function (d) {
|
||||||
|
return d.tag === 'module'
|
||||||
|
})
|
||||||
|
const summaryTag = tags.find(function (d) {
|
||||||
|
return d.tag === 'summary'
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(moduleTag, 'expected `@module` in JSDoc')
|
||||||
|
|
||||||
|
assert.equal(moduleTag.name, ruleId, 'expected correct `@module`')
|
||||||
|
|
||||||
|
let description = deprecatedTag
|
||||||
|
? deprecatedTag.description
|
||||||
|
: fileInfo.description
|
||||||
|
|
||||||
|
assert(description, 'expected description (or `@deprecated`)')
|
||||||
|
|
||||||
|
description = strip(description)
|
||||||
|
|
||||||
|
/** @type {PluginInfo} */
|
||||||
|
const result = {
|
||||||
|
deprecated: Boolean(deprecatedTag),
|
||||||
|
description: description.trim(),
|
||||||
|
name,
|
||||||
|
ruleId,
|
||||||
|
summary: summaryTag ? strip(summaryTag.description).trim() : undefined,
|
||||||
|
checks: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const examples = tags
|
||||||
|
.filter(function (d) {
|
||||||
|
return d.tag === 'example'
|
||||||
|
})
|
||||||
|
.map(function (d) {
|
||||||
|
return d.description.replace(/^\r?\n|\r?\n$/g, '')
|
||||||
|
})
|
||||||
|
|
||||||
|
let index = -1
|
||||||
|
|
||||||
|
while (++index < examples.length) {
|
||||||
|
const lines = examples[index].split('\n')
|
||||||
|
/** @type {ExampleInfo} */
|
||||||
|
let info
|
||||||
|
|
||||||
|
try {
|
||||||
|
info = JSON.parse(lines[0])
|
||||||
|
lines.splice(0, 1)
|
||||||
|
/* c8 ignore next 4 */
|
||||||
|
} catch (error) {
|
||||||
|
const cause = /** @type {Error} */ (error)
|
||||||
|
throw new Error('Could not parse example in `' + ruleId + '`', {cause})
|
||||||
|
}
|
||||||
|
|
||||||
|
const exampleValue = strip(lines.join('\n').replace(/^\r?\n/g, ''))
|
||||||
|
const configuration = JSON.stringify({config: info.config || true})
|
||||||
|
const name = info.name
|
||||||
|
|
||||||
|
if (!info.label) {
|
||||||
|
result.checks.push({
|
||||||
|
configuration,
|
||||||
|
name,
|
||||||
|
positionless: info.positionless || false,
|
||||||
|
gfm: info.gfm || false,
|
||||||
|
input: exampleValue,
|
||||||
|
output: []
|
||||||
|
})
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(info.label === 'input' || info.label === 'output')
|
||||||
|
|
||||||
|
let found = result.checks.find(function (d) {
|
||||||
|
return d.configuration === configuration && d.name === name
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
found = {
|
||||||
|
configuration,
|
||||||
|
name,
|
||||||
|
positionless: info.positionless || false,
|
||||||
|
gfm: info.gfm || false,
|
||||||
|
input: '',
|
||||||
|
output: []
|
||||||
|
}
|
||||||
|
result.checks.push(found)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.label === 'input') {
|
||||||
|
found.input = exampleValue
|
||||||
|
} else {
|
||||||
|
found.output = exampleValue.split('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.push(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
* Preset name.
|
||||||
|
* @returns {Promise<undefined>}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
async function addPreset(name) {
|
||||||
|
/** @type {{default: Preset}} */
|
||||||
|
const mod = await import(new URL(name + '/index.js', packagesUrl).href)
|
||||||
|
const plugins = mod.default.plugins
|
||||||
|
assert(plugins, 'expected plugins in preset')
|
||||||
|
/** @type {PresetInfo} */
|
||||||
|
const presetInfo = {name, plugins: []}
|
||||||
|
|
||||||
|
let index = -1
|
||||||
|
|
||||||
|
while (++index < plugins.length) {
|
||||||
|
const plugin = plugins[index]
|
||||||
|
/** @type {import('unified').Plugin<[unknown]>} */
|
||||||
|
let fn
|
||||||
|
/** @type {unknown} */
|
||||||
|
let option
|
||||||
|
|
||||||
|
if (Array.isArray(plugin)) {
|
||||||
|
;[fn, option] = /** @type {import('unified').PluginTuple<[unknown]>} */ (
|
||||||
|
plugin
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
assert(typeof plugin === 'function')
|
||||||
|
fn = plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error: `displayName`s are fine.
|
||||||
|
const name = /** @type {string} */ (fn.displayName || fn.name)
|
||||||
|
|
||||||
|
const pluginName = name
|
||||||
|
.replace(
|
||||||
|
/[:-](\w)/g,
|
||||||
|
function (/** @type {string} */ _, /** @type {string} */ $1) {
|
||||||
|
return $1.toUpperCase()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.replace(/[A-Z]/g, function (/** @type {string} */ $0) {
|
||||||
|
return '-' + $0.toLowerCase()
|
||||||
|
})
|
||||||
|
|
||||||
|
presetInfo.plugins.push([pluginName, option])
|
||||||
|
}
|
||||||
|
|
||||||
|
presets.push(presetInfo)
|
||||||
|
}
|
85
script/plugin/list-of-plugins.js
Normal file
85
script/plugin/list-of-plugins.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* @typedef {import('mdast').List} List
|
||||||
|
* @typedef {import('mdast').ListItem} ListItem
|
||||||
|
* @typedef {import('mdast').Root} Root
|
||||||
|
*
|
||||||
|
* @typedef {import('type-fest').PackageJson} PackageJson
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import fs from 'node:fs/promises'
|
||||||
|
import {zone} from 'mdast-zone'
|
||||||
|
import {packagesUrl, plugins} from '../info.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Array<ListItem | undefined>}
|
||||||
|
* List items.
|
||||||
|
*/
|
||||||
|
const items = await Promise.all(
|
||||||
|
plugins.map(async function (info) {
|
||||||
|
const packageUrl = new URL(info.name + '/', packagesUrl)
|
||||||
|
/** @type {PackageJson} */
|
||||||
|
const pack = JSON.parse(
|
||||||
|
String(await fs.readFile(new URL('package.json', packageUrl)))
|
||||||
|
)
|
||||||
|
const description = String(pack.description || '').replace(
|
||||||
|
/^remark-lint rule to ?/i,
|
||||||
|
''
|
||||||
|
)
|
||||||
|
|
||||||
|
if (/^deprecated/i.test(description)) return
|
||||||
|
|
||||||
|
assert(pack.repository && typeof pack.repository === 'object')
|
||||||
|
assert(pack.repository.directory)
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'listItem',
|
||||||
|
spread: false,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'link',
|
||||||
|
url:
|
||||||
|
pack.repository.url + '/tree/main/' + pack.repository.directory,
|
||||||
|
children: [{type: 'inlineCode', value: info.name}]
|
||||||
|
},
|
||||||
|
{type: 'text', value: ' — ' + description}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
/** @type {List} */
|
||||||
|
const list = {
|
||||||
|
type: 'list',
|
||||||
|
ordered: false,
|
||||||
|
spread: false,
|
||||||
|
// @ts-expect-error: filter is correct.
|
||||||
|
children: items.filter(Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List rules.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* Transform.
|
||||||
|
*/
|
||||||
|
export default function remarkListOfRules() {
|
||||||
|
/**
|
||||||
|
* Transform.
|
||||||
|
*
|
||||||
|
* @param {Root} tree
|
||||||
|
* Tree.
|
||||||
|
* @returns {undefined}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
return function (tree) {
|
||||||
|
zone(tree, 'rules', function (start, _, end) {
|
||||||
|
return [start, structuredClone(list), end]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -2,65 +2,77 @@
|
|||||||
* @typedef {import('mdast').List} List
|
* @typedef {import('mdast').List} List
|
||||||
* @typedef {import('mdast').ListItem} ListItem
|
* @typedef {import('mdast').ListItem} ListItem
|
||||||
* @typedef {import('mdast').Root} Root
|
* @typedef {import('mdast').Root} Root
|
||||||
|
*
|
||||||
* @typedef {import('type-fest').PackageJson} PackageJson
|
* @typedef {import('type-fest').PackageJson} PackageJson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'node:fs'
|
import assert from 'node:assert/strict'
|
||||||
import path from 'node:path'
|
import fs from 'node:fs/promises'
|
||||||
import process from 'node:process'
|
|
||||||
import {zone} from 'mdast-zone'
|
import {zone} from 'mdast-zone'
|
||||||
import {presets} from '../util/presets.js'
|
import {packagesUrl, presets} from '../info.js'
|
||||||
import {repoUrl} from '../util/repo-url.js'
|
|
||||||
|
|
||||||
const root = path.join(process.cwd(), 'packages')
|
/**
|
||||||
|
* @type {Array<ListItem>}
|
||||||
|
* List items.
|
||||||
|
*/
|
||||||
|
const items = await Promise.all(
|
||||||
|
presets.map(async function (info) {
|
||||||
|
const packageUrl = new URL(info.name + '/', packagesUrl)
|
||||||
|
/** @type {PackageJson} */
|
||||||
|
const pack = JSON.parse(
|
||||||
|
await fs.readFile(new URL('package.json', packageUrl), 'utf8')
|
||||||
|
)
|
||||||
|
|
||||||
/** @type {import('unified').Plugin<Array<void>, Root>} */
|
const description = String(pack.description || '').replace(
|
||||||
export default function listOfPresets() {
|
/^remark preset to configure remark-lint with ?/i,
|
||||||
const presetPromise = presets(root)
|
''
|
||||||
|
)
|
||||||
|
|
||||||
return async (tree) => {
|
assert(pack.repository && typeof pack.repository === 'object')
|
||||||
const presetObjects = await presetPromise
|
assert(pack.repository.directory)
|
||||||
|
|
||||||
zone(tree, 'presets', (start, _, end) => {
|
return {
|
||||||
/** @type {List} */
|
type: 'listItem',
|
||||||
const list = {
|
spread: false,
|
||||||
type: 'list',
|
children: [
|
||||||
ordered: false,
|
{
|
||||||
spread: false,
|
type: 'paragraph',
|
||||||
children: presetObjects.map(({name}) => {
|
children: [
|
||||||
/** @type {PackageJson} */
|
{
|
||||||
const pack = JSON.parse(
|
type: 'link',
|
||||||
String(fs.readFileSync(path.join(root, name, 'package.json')))
|
url:
|
||||||
)
|
pack.repository.url + '/tree/main/' + pack.repository.directory,
|
||||||
const description = String(pack.description || '').replace(
|
children: [{type: 'inlineCode', value: info.name}]
|
||||||
/^remark preset to configure remark-lint with ?/i,
|
},
|
||||||
''
|
{type: 'text', value: ' — ' + description}
|
||||||
)
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
/** @type {ListItem} */
|
/** @type {List} */
|
||||||
const item = {
|
const list = {type: 'list', ordered: false, spread: false, children: items}
|
||||||
type: 'listItem',
|
|
||||||
spread: false,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'link',
|
|
||||||
url: repoUrl(pack),
|
|
||||||
children: [{type: 'inlineCode', value: name}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ' — ' + description}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
return item
|
/**
|
||||||
})
|
* List presets.
|
||||||
}
|
*
|
||||||
|
* @returns
|
||||||
return [start, list, end]
|
* Transform.
|
||||||
|
*/
|
||||||
|
export default function remarkListOfPresets() {
|
||||||
|
/**
|
||||||
|
* Transform.
|
||||||
|
*
|
||||||
|
* @param {Root} tree
|
||||||
|
* Tree.
|
||||||
|
* @returns {undefined}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
return function (tree) {
|
||||||
|
zone(tree, 'presets', function (start, _, end) {
|
||||||
|
return [start, structuredClone(list), end]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
/**
|
|
||||||
* @typedef {import('type-fest').PackageJson} PackageJson
|
|
||||||
* @typedef {import('mdast').ListItem} ListItem
|
|
||||||
* @typedef {import('mdast').List} List
|
|
||||||
* @typedef {import('mdast').Root} Root
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fs from 'node:fs'
|
|
||||||
import path from 'node:path'
|
|
||||||
import process from 'node:process'
|
|
||||||
import {zone} from 'mdast-zone'
|
|
||||||
import {rules} from '../util/rules.js'
|
|
||||||
import {repoUrl} from '../util/repo-url.js'
|
|
||||||
|
|
||||||
const root = path.join(process.cwd(), 'packages')
|
|
||||||
|
|
||||||
/** @type {import('unified').Plugin<Array<void>, Root>} */
|
|
||||||
export default function listOfRules() {
|
|
||||||
return (tree) => {
|
|
||||||
zone(tree, 'rules', (start, _, end) => {
|
|
||||||
/** @type {List} */
|
|
||||||
const list = {
|
|
||||||
type: 'list',
|
|
||||||
ordered: false,
|
|
||||||
spread: false,
|
|
||||||
children: rules(root)
|
|
||||||
.map((basename) => {
|
|
||||||
/** @type {PackageJson} */
|
|
||||||
const pack = JSON.parse(
|
|
||||||
String(fs.readFileSync(path.join(root, basename, 'package.json')))
|
|
||||||
)
|
|
||||||
const description = String(pack.description || '').replace(
|
|
||||||
/^remark-lint rule to ?/i,
|
|
||||||
''
|
|
||||||
)
|
|
||||||
const deprecated = /^deprecated/i.test(description)
|
|
||||||
|
|
||||||
/** @type {ListItem} */
|
|
||||||
const item = {
|
|
||||||
type: 'listItem',
|
|
||||||
spread: false,
|
|
||||||
children: deprecated
|
|
||||||
? []
|
|
||||||
: [
|
|
||||||
{
|
|
||||||
type: 'paragraph',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
type: 'link',
|
|
||||||
url: repoUrl(pack),
|
|
||||||
children: [{type: 'inlineCode', value: basename}]
|
|
||||||
},
|
|
||||||
{type: 'text', value: ' — ' + description}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
return item
|
|
||||||
})
|
|
||||||
.filter((d) => d.children.length > 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [start, list, end]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
/**
|
|
||||||
* @typedef {import('unified').Plugin} Plugin
|
|
||||||
* @typedef {import('unified').Preset} Preset
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {promises as fs} from 'node:fs'
|
|
||||||
import path from 'node:path'
|
|
||||||
import url from 'node:url'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} base
|
|
||||||
* @returns {Promise<Array<{name: string, packages: Record<string, unknown>}>>}
|
|
||||||
*/
|
|
||||||
export async function presets(base) {
|
|
||||||
const allFiles = await fs.readdir(base)
|
|
||||||
const files = allFiles.filter((basename) =>
|
|
||||||
/remark-preset-lint/.test(basename)
|
|
||||||
)
|
|
||||||
|
|
||||||
return Promise.all(
|
|
||||||
files.map(async (name) => {
|
|
||||||
const href = url.pathToFileURL(path.join(base, name, 'index.js')).href
|
|
||||||
// type-coverage:ignore-next-line
|
|
||||||
const presetMod = await import(href)
|
|
||||||
/** @type {Preset} */
|
|
||||||
// type-coverage:ignore-next-line
|
|
||||||
const preset = presetMod.default
|
|
||||||
const plugins = preset.plugins || []
|
|
||||||
/** @type {Record<string, unknown>} */
|
|
||||||
const packages = {}
|
|
||||||
|
|
||||||
let index = -1
|
|
||||||
while (++index < plugins.length) {
|
|
||||||
const plugin = plugins[index]
|
|
||||||
/** @type {Plugin} */
|
|
||||||
let fn
|
|
||||||
/** @type {unknown} */
|
|
||||||
let option
|
|
||||||
|
|
||||||
if (typeof plugin === 'function') {
|
|
||||||
fn = plugin
|
|
||||||
} else if (Array.isArray(plugin)) {
|
|
||||||
// Fine:
|
|
||||||
// type-coverage:ignore-next-line
|
|
||||||
fn = plugin[0]
|
|
||||||
// Fine:
|
|
||||||
// type-coverage:ignore-next-line
|
|
||||||
option = plugin[1]
|
|
||||||
} else {
|
|
||||||
throw new TypeError(
|
|
||||||
'Expected plugin, plugin tuple, not `' + plugin + '`'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @type {string} */
|
|
||||||
// @ts-expect-error: `displayName`s are fine.
|
|
||||||
const name = fn.displayName || fn.name
|
|
||||||
|
|
||||||
packages[
|
|
||||||
name
|
|
||||||
.replace(
|
|
||||||
/[:-](\w)/g,
|
|
||||||
(/** @type {string} */ _, /** @type {string} */ $1) =>
|
|
||||||
$1.toUpperCase()
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
/[A-Z]/g,
|
|
||||||
(/** @type {string} */ $0) => '-' + $0.toLowerCase()
|
|
||||||
)
|
|
||||||
] = option
|
|
||||||
}
|
|
||||||
|
|
||||||
return {name, packages}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
import fs from 'node:fs'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import('type-fest').PackageJson} PackageJson
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string | PackageJson} pathOrJson
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function repoUrl(pathOrJson) {
|
|
||||||
const pkg =
|
|
||||||
typeof pathOrJson === 'string' ? readPackageJson(pathOrJson) : pathOrJson
|
|
||||||
|
|
||||||
if (
|
|
||||||
pkg.repository === undefined ||
|
|
||||||
typeof pkg.repository !== 'object' ||
|
|
||||||
typeof pkg.repository.url !== 'string'
|
|
||||||
) {
|
|
||||||
throw new TypeError(
|
|
||||||
`Expected \`string\` for \`repository.url\` in \`${pathOrJson}\``
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pkg.repository.directory) {
|
|
||||||
return pkg.repository.url + `/tree/main/${pkg.repository.directory}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkg.repository.url
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} filePath
|
|
||||||
* @returns {PackageJson}
|
|
||||||
*/
|
|
||||||
function readPackageJson(filePath) {
|
|
||||||
return JSON.parse(String(fs.readFileSync(filePath)))
|
|
||||||
}
|
|
@ -1,140 +0,0 @@
|
|||||||
/**
|
|
||||||
* @typedef Rule
|
|
||||||
* @property {string} ruleId
|
|
||||||
* @property {string} description
|
|
||||||
* @property {string | undefined} summary
|
|
||||||
* @property {boolean} deprecated
|
|
||||||
* @property {Record<string, Checks>} tests
|
|
||||||
* @property {string} filePath
|
|
||||||
*
|
|
||||||
* @typedef {Record<string, Check>} Checks
|
|
||||||
*
|
|
||||||
* @typedef Check
|
|
||||||
* @property {string} input
|
|
||||||
* @property {Array<string>} output
|
|
||||||
* @property {boolean} gfm
|
|
||||||
* @property {boolean} positionless
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fs from 'node:fs'
|
|
||||||
import path from 'node:path'
|
|
||||||
import {parse} from 'comment-parser'
|
|
||||||
import strip from 'strip-indent'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get information for a rule at `filePath`.
|
|
||||||
*
|
|
||||||
* @param {string} filePath
|
|
||||||
* @returns {Rule}
|
|
||||||
*/
|
|
||||||
export function rule(filePath) {
|
|
||||||
const ruleId = path.basename(filePath).slice('remark-lint-'.length)
|
|
||||||
/** @type {Record<string, Checks>} */
|
|
||||||
const tests = {}
|
|
||||||
const code = fs.readFileSync(path.join(filePath, 'index.js'), 'utf8')
|
|
||||||
// Note: To do: `comment-parser` types are wrong.
|
|
||||||
/** @type {import('comment-parser/primitives').Block} */
|
|
||||||
const fileInfo = parse(code, {spacing: 'preserve'})[0]
|
|
||||||
const tags = fileInfo.tags
|
|
||||||
const moduleTag = tags.find((d) => d.tag === 'module')
|
|
||||||
const summaryTag = tags.find((d) => d.tag === 'summary')
|
|
||||||
const deprecatedTag = tags.find((d) => d.tag === 'deprecated')
|
|
||||||
|
|
||||||
/* c8 ignore next 3 */
|
|
||||||
if (!moduleTag) {
|
|
||||||
throw new Error('Expected `@module` in JSDoc')
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = moduleTag.name
|
|
||||||
let description =
|
|
||||||
(deprecatedTag && deprecatedTag.description) || fileInfo.description
|
|
||||||
|
|
||||||
/* c8 ignore next 3 */
|
|
||||||
if (name !== ruleId) {
|
|
||||||
throw new Error(ruleId + ' has an incorrect `@module`: ' + name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* c8 ignore next 3 */
|
|
||||||
if (!description) {
|
|
||||||
throw new Error(ruleId + ' is missing a description or `@deprecated`')
|
|
||||||
}
|
|
||||||
|
|
||||||
description = strip(description)
|
|
||||||
|
|
||||||
/** @type {Rule} */
|
|
||||||
const result = {
|
|
||||||
ruleId,
|
|
||||||
description: description.trim(),
|
|
||||||
summary: summaryTag ? strip(summaryTag.description).trim() : undefined,
|
|
||||||
deprecated: Boolean(deprecatedTag),
|
|
||||||
tests,
|
|
||||||
filePath
|
|
||||||
}
|
|
||||||
|
|
||||||
const examples = tags
|
|
||||||
.filter((d) => d.tag === 'example')
|
|
||||||
.map((d) => d.description.replace(/^\r?\n|\r?\n$/g, ''))
|
|
||||||
let index = -1
|
|
||||||
|
|
||||||
while (++index < examples.length) {
|
|
||||||
const lines = examples[index].split('\n')
|
|
||||||
/** @type {{name: string, label?: 'input' | 'output', config?: unknown, positionless?: boolean, gfm?: boolean}} */
|
|
||||||
let info
|
|
||||||
|
|
||||||
try {
|
|
||||||
info = JSON.parse(lines[0])
|
|
||||||
lines.splice(0, 1)
|
|
||||||
/* c8 ignore next 6 */
|
|
||||||
} catch (error) {
|
|
||||||
const exception = /** @type Error */ (error)
|
|
||||||
throw new Error(
|
|
||||||
'Could not parse example in ' + ruleId + ':\n' + exception.stack
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const exampleValue = strip(lines.join('\n').replace(/^\r?\n/g, ''))
|
|
||||||
const configuration = JSON.stringify({config: info.config || true})
|
|
||||||
const name = info.name
|
|
||||||
const context =
|
|
||||||
configuration in tests
|
|
||||||
? tests[configuration]
|
|
||||||
: (tests[configuration] = {})
|
|
||||||
|
|
||||||
if (!info.label) {
|
|
||||||
context[name] = {
|
|
||||||
positionless: info.positionless || false,
|
|
||||||
gfm: info.gfm || false,
|
|
||||||
input: exampleValue,
|
|
||||||
output: []
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
/* c8 ignore next 9 */
|
|
||||||
if (info.label !== 'input' && info.label !== 'output') {
|
|
||||||
throw new Error(
|
|
||||||
'Expected `input` or `ouput` for `label` in ' +
|
|
||||||
ruleId +
|
|
||||||
', not `' +
|
|
||||||
info.label +
|
|
||||||
'`'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context[name]) {
|
|
||||||
context[name] = {
|
|
||||||
positionless: info.positionless || false,
|
|
||||||
gfm: info.gfm || false,
|
|
||||||
input: '',
|
|
||||||
output: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-expect-error: fine: array for output, string for rest.
|
|
||||||
context[name][info.label] =
|
|
||||||
info.label === 'output' ? exampleValue.split('\n') : exampleValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import fs from 'node:fs'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} filePath
|
|
||||||
* @returns {Array<string>}
|
|
||||||
*/
|
|
||||||
export function rules(filePath) {
|
|
||||||
return fs
|
|
||||||
.readdirSync(filePath)
|
|
||||||
.filter(
|
|
||||||
(basename) => /remark-lint/.test(basename) && basename !== 'remark-lint'
|
|
||||||
)
|
|
||||||
}
|
|
590
test.js
590
test.js
@ -1,32 +1,33 @@
|
|||||||
/**
|
/**
|
||||||
* @typedef {import('unified').Plugin} Plugin
|
* @typedef {import('unified').PluggableList} PluggableList
|
||||||
* @typedef {import('vfile-message').VFileMessage} VFileMessage
|
* @typedef {import('unified').Plugin<[unknown]>} Plugin
|
||||||
* @typedef {import('./script/util/rule.js').Check} Check
|
*
|
||||||
* @typedef {import('./script/util/rule.js').Rule} Rule
|
* @typedef {import('./script/info.js').Check} Check
|
||||||
|
* @typedef {import('./script/info.js').PluginInfo} PluginInfo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import assert from 'node:assert/strict'
|
import assert from 'node:assert/strict'
|
||||||
import path from 'node:path'
|
|
||||||
import process from 'node:process'
|
|
||||||
import test from 'node:test'
|
import test from 'node:test'
|
||||||
import url from 'node:url'
|
|
||||||
import {toVFile} from 'to-vfile'
|
|
||||||
import {removePosition} from 'unist-util-remove-position'
|
|
||||||
import {remark} from 'remark'
|
import {remark} from 'remark'
|
||||||
import remarkGfm from 'remark-gfm'
|
import remarkGfm from 'remark-gfm'
|
||||||
|
import remarkLint from 'remark-lint'
|
||||||
|
import remarkLintFinalNewline from 'remark-lint-final-newline'
|
||||||
|
import remarkLintNoHeadingPunctuation from 'remark-lint-no-heading-punctuation'
|
||||||
|
import remarkLintNoMultipleToplevelHeadings from 'remark-lint-no-multiple-toplevel-headings'
|
||||||
|
import remarkLintNoUndefinedReferences from 'remark-lint-no-undefined-references'
|
||||||
import {lintRule} from 'unified-lint-rule'
|
import {lintRule} from 'unified-lint-rule'
|
||||||
import {rules} from './script/util/rules.js'
|
import {removePosition} from 'unist-util-remove-position'
|
||||||
import {rule} from './script/util/rule.js'
|
import {VFile} from 'vfile'
|
||||||
import {characters} from './script/characters.js'
|
import {characters} from './script/characters.js'
|
||||||
import lint from './packages/remark-lint/index.js'
|
import {plugins} from './script/info.js'
|
||||||
import noHeadingPunctuation from './packages/remark-lint-no-heading-punctuation/index.js'
|
|
||||||
import noMultipleToplevelHeadings from './packages/remark-lint-no-multiple-toplevel-headings/index.js'
|
|
||||||
import noUndefinedReferences from './packages/remark-lint-no-undefined-references/index.js'
|
|
||||||
import finalNewline from './packages/remark-lint-final-newline/index.js'
|
|
||||||
|
|
||||||
const own = {}.hasOwnProperty
|
test('remark-lint', async function (t) {
|
||||||
|
await t.test('should expose the public api', async function () {
|
||||||
|
assert.deepEqual(Object.keys(await import('remark-lint')).sort(), [
|
||||||
|
'default'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
test('core', async () => {
|
|
||||||
const doc = [
|
const doc = [
|
||||||
'# A heading',
|
'# A heading',
|
||||||
'',
|
'',
|
||||||
@ -37,53 +38,48 @@ test('core', async () => {
|
|||||||
'# Another main heading.'
|
'# Another main heading.'
|
||||||
].join('\n')
|
].join('\n')
|
||||||
|
|
||||||
let file = await remark()
|
await t.test('should support `remark-lint` last', async function () {
|
||||||
.use(noHeadingPunctuation)
|
const file = await remark()
|
||||||
.use(noMultipleToplevelHeadings)
|
.use(remarkLintNoHeadingPunctuation)
|
||||||
.use(lint)
|
.use(remarkLintNoMultipleToplevelHeadings)
|
||||||
.process(toVFile({path: 'virtual.md', value: doc}))
|
.use(remarkLint)
|
||||||
|
.process({path: 'virtual.md', value: doc})
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages.map(String), [
|
||||||
asStrings(file.messages),
|
|
||||||
[
|
|
||||||
'virtual.md:3:1-3:24: Don’t add a trailing `.` to headings',
|
'virtual.md:3:1-3:24: Don’t add a trailing `.` to headings',
|
||||||
'virtual.md:3:1-3:24: Don’t use multiple top level headings (1:1)'
|
'virtual.md:3:1-3:24: Don’t use multiple top level headings (1:1)'
|
||||||
],
|
])
|
||||||
'should support `remark-lint` last'
|
})
|
||||||
)
|
|
||||||
|
|
||||||
file = await remark()
|
await t.test('should support `remark-lint` first', async function () {
|
||||||
.use(lint)
|
const file = await remark()
|
||||||
.use(noHeadingPunctuation)
|
.use(remarkLint)
|
||||||
.use(noMultipleToplevelHeadings)
|
.use(remarkLintNoHeadingPunctuation)
|
||||||
.process(toVFile({path: 'virtual.md', value: doc}))
|
.use(remarkLintNoMultipleToplevelHeadings)
|
||||||
|
.process({path: 'virtual.md', value: doc})
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages.map(String), [
|
||||||
asStrings(file.messages),
|
|
||||||
[
|
|
||||||
'virtual.md:3:1-3:24: Don’t add a trailing `.` to headings',
|
'virtual.md:3:1-3:24: Don’t add a trailing `.` to headings',
|
||||||
'virtual.md:3:1-3:24: Don’t use multiple top level headings (1:1)'
|
'virtual.md:3:1-3:24: Don’t use multiple top level headings (1:1)'
|
||||||
],
|
])
|
||||||
'should support `remark-lint` first'
|
})
|
||||||
)
|
|
||||||
|
|
||||||
file = await remark().use(lint).process('.')
|
await t.test('should support no rules', async function () {
|
||||||
|
const file = await remark().use(remarkLint).process('.')
|
||||||
|
|
||||||
assert.deepEqual(asStrings(file.messages), [], 'should support no rules')
|
assert.deepEqual(file.messages, [])
|
||||||
|
})
|
||||||
|
|
||||||
file = await remark().use(finalNewline).process('')
|
await t.test('should support successful rules', async function () {
|
||||||
|
const file = await remark().use(remarkLintFinalNewline).process('')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages, [])
|
||||||
asStrings(file.messages),
|
})
|
||||||
[],
|
|
||||||
'should support successful rules'
|
|
||||||
)
|
|
||||||
|
|
||||||
file = await remark().use(finalNewline, [2]).process('.')
|
await t.test('should support a list with a severity', async function () {
|
||||||
|
const file = await remark().use(remarkLintFinalNewline, [2]).process('.')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
file.messages.map((d) => JSON.parse(JSON.stringify(d))),
|
|
||||||
[
|
|
||||||
{
|
{
|
||||||
fatal: true,
|
fatal: true,
|
||||||
message: 'Missing newline character at end of file',
|
message: 'Missing newline character at end of file',
|
||||||
@ -93,315 +89,269 @@ test('core', async () => {
|
|||||||
source: 'remark-lint',
|
source: 'remark-lint',
|
||||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
||||||
}
|
}
|
||||||
],
|
])
|
||||||
'should support a list with a severity'
|
})
|
||||||
|
|
||||||
|
await t.test('should support a boolean (`true`)', async function () {
|
||||||
|
const file = await remark().use(remarkLintFinalNewline, true).process('.')
|
||||||
|
|
||||||
|
assert.deepEqual(file.messages.map(String), [
|
||||||
|
'1:1: Missing newline character at end of file'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
await t.test('should support a boolean (`false`)', async function () {
|
||||||
|
const file = await remark().use(remarkLintFinalNewline, false).process('.')
|
||||||
|
|
||||||
|
assert.deepEqual(file.messages, [])
|
||||||
|
})
|
||||||
|
|
||||||
|
await t.test(
|
||||||
|
'should support a list with a boolean severity (true, for on)',
|
||||||
|
async function () {
|
||||||
|
const file = await remark()
|
||||||
|
.use(remarkLintFinalNewline, [true])
|
||||||
|
.process('.')
|
||||||
|
|
||||||
|
assert.deepEqual(file.messages.map(String), [
|
||||||
|
'1:1: Missing newline character at end of file'
|
||||||
|
])
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, true).process('.')
|
await t.test(
|
||||||
|
'should support a list with boolean severity (false, for off)',
|
||||||
|
async function () {
|
||||||
|
const file = await remark()
|
||||||
|
.use(remarkLintFinalNewline, [false])
|
||||||
|
.process('.')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages, [])
|
||||||
asStrings(file.messages),
|
}
|
||||||
['1:1: Missing newline character at end of file'],
|
|
||||||
'should support a boolean (`true`)'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, false).process('.')
|
await t.test(
|
||||||
|
'should support a list with string severity (`error`)',
|
||||||
|
async function () {
|
||||||
|
const file = await remark()
|
||||||
|
.use(remarkLintFinalNewline, ['error'])
|
||||||
|
.process('.')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
asStrings(file.messages),
|
{
|
||||||
[],
|
fatal: true,
|
||||||
'should support a boolean (`false`)'
|
message: 'Missing newline character at end of file',
|
||||||
|
name: '1:1',
|
||||||
|
reason: 'Missing newline character at end of file',
|
||||||
|
ruleId: 'final-newline',
|
||||||
|
source: 'remark-lint',
|
||||||
|
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, [true]).process('.')
|
await t.test(
|
||||||
|
'should support a list with string severity (`on`)',
|
||||||
|
async function () {
|
||||||
|
const file = await remark()
|
||||||
|
.use(remarkLintFinalNewline, ['on'])
|
||||||
|
.process('.')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
asStrings(file.messages),
|
{
|
||||||
['1:1: Missing newline character at end of file'],
|
fatal: false,
|
||||||
'should support a list with a boolean severity (true, for on)'
|
message: 'Missing newline character at end of file',
|
||||||
|
name: '1:1',
|
||||||
|
reason: 'Missing newline character at end of file',
|
||||||
|
ruleId: 'final-newline',
|
||||||
|
source: 'remark-lint',
|
||||||
|
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, [false]).process('.')
|
await t.test(
|
||||||
|
'should support a list with string severity (`warn`)',
|
||||||
|
async function () {
|
||||||
|
const file = await remark()
|
||||||
|
.use(remarkLintFinalNewline, ['warn'])
|
||||||
|
.process('.')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
asStrings(file.messages),
|
{
|
||||||
[],
|
fatal: false,
|
||||||
'should support a list with boolean severity (false, for off)'
|
message: 'Missing newline character at end of file',
|
||||||
|
name: '1:1',
|
||||||
|
reason: 'Missing newline character at end of file',
|
||||||
|
ruleId: 'final-newline',
|
||||||
|
source: 'remark-lint',
|
||||||
|
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, ['error']).process('.')
|
await t.test(
|
||||||
|
'should support a list with string severity (`off`)',
|
||||||
|
async function () {
|
||||||
|
const file = await remark()
|
||||||
|
.use(remarkLintFinalNewline, ['off'])
|
||||||
|
.process('.')
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages, [])
|
||||||
file.messages.map((d) => JSON.parse(JSON.stringify(d))),
|
}
|
||||||
[
|
|
||||||
{
|
|
||||||
fatal: true,
|
|
||||||
message: 'Missing newline character at end of file',
|
|
||||||
name: '1:1',
|
|
||||||
reason: 'Missing newline character at end of file',
|
|
||||||
ruleId: 'final-newline',
|
|
||||||
source: 'remark-lint',
|
|
||||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'should support a list with string severity (`error`)'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, ['on']).process('.')
|
await t.test(
|
||||||
|
'should fail on incorrect severities (too high)',
|
||||||
assert.deepEqual(
|
async function () {
|
||||||
file.messages.map((d) => JSON.parse(JSON.stringify(d))),
|
assert.throws(function () {
|
||||||
[
|
remark().use(remarkLintFinalNewline, [3]).freeze()
|
||||||
{
|
}, /^Error: Incorrect severity `3` for `final-newline`, expected 0, 1, or 2$/)
|
||||||
fatal: false,
|
}
|
||||||
message: 'Missing newline character at end of file',
|
|
||||||
name: '1:1',
|
|
||||||
reason: 'Missing newline character at end of file',
|
|
||||||
ruleId: 'final-newline',
|
|
||||||
source: 'remark-lint',
|
|
||||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'should support a list with string severity (`on`)'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, ['warn']).process('.')
|
await t.test(
|
||||||
|
'should fail on incorrect severities (too low)',
|
||||||
assert.deepEqual(
|
async function () {
|
||||||
file.messages.map((d) => JSON.parse(JSON.stringify(d))),
|
assert.throws(function () {
|
||||||
[
|
remark().use(remarkLintFinalNewline, [-1]).freeze()
|
||||||
{
|
}, /^Error: Incorrect severity `-1` for `final-newline`, expected 0, 1, or 2$/)
|
||||||
fatal: false,
|
}
|
||||||
message: 'Missing newline character at end of file',
|
|
||||||
name: '1:1',
|
|
||||||
reason: 'Missing newline character at end of file',
|
|
||||||
ruleId: 'final-newline',
|
|
||||||
source: 'remark-lint',
|
|
||||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'should support a list with string severity (`warn`)'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
file = await remark().use(finalNewline, ['off']).process('.')
|
await t.test(
|
||||||
|
'should support regex as options (remark-lint-no-undefined-references)',
|
||||||
|
async function () {
|
||||||
|
const file = await remark()
|
||||||
|
.use(remarkLintNoUndefinedReferences, {allow: [/^b\./i]})
|
||||||
|
.process({
|
||||||
|
path: 'virtual.md',
|
||||||
|
value: ['[foo][b.c]', '', '[bar][b]'].join('\n')
|
||||||
|
})
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(file.messages.map(String), [
|
||||||
asStrings(file.messages),
|
'virtual.md:3:1-3:9: Found reference to undefined definition'
|
||||||
[],
|
])
|
||||||
'should support a list with string severity (`off`)'
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.throws(
|
await t.test(
|
||||||
() => {
|
'should support meta as a string (unified-lint-rule)',
|
||||||
remark().use(finalNewline, [3]).freeze()
|
async function () {
|
||||||
},
|
const file = await remark()
|
||||||
/^Error: Incorrect severity `3` for `final-newline`, expected 0, 1, or 2$/,
|
.use(
|
||||||
'should fail on incorrect severities (too high)'
|
lintRule('test:rule', function (_, file) {
|
||||||
)
|
file.message('Test message')
|
||||||
|
}),
|
||||||
|
['warn']
|
||||||
|
)
|
||||||
|
.process('.')
|
||||||
|
|
||||||
assert.throws(
|
assert.deepEqual(file.messages.map(jsonClone), [
|
||||||
() => {
|
{
|
||||||
remark().use(finalNewline, [-1]).freeze()
|
fatal: false,
|
||||||
},
|
message: 'Test message',
|
||||||
/^Error: Incorrect severity `-1` for `final-newline`, expected 0, 1, or 2$/,
|
name: '1:1',
|
||||||
'should fail on incorrect severities (too low)'
|
reason: 'Test message',
|
||||||
)
|
ruleId: 'rule',
|
||||||
|
source: 'test'
|
||||||
file = await remark()
|
}
|
||||||
.use(noUndefinedReferences, {allow: [/^b\./i]})
|
])
|
||||||
.process(
|
}
|
||||||
toVFile({
|
|
||||||
path: 'virtual.md',
|
|
||||||
value: ['[foo][b.c]', '', '[bar][b]'].join('\n')
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.deepEqual(
|
|
||||||
asStrings(file.messages),
|
|
||||||
['virtual.md:3:1-3:9: Found reference to undefined definition'],
|
|
||||||
'no-undefined-references allow option should work with native regex'
|
|
||||||
)
|
|
||||||
|
|
||||||
file = await remark()
|
|
||||||
.use(
|
|
||||||
lintRule('test:rule', (tree, file) => {
|
|
||||||
file.message('Test message')
|
|
||||||
}),
|
|
||||||
['warn']
|
|
||||||
)
|
|
||||||
.process('.')
|
|
||||||
|
|
||||||
assert.deepEqual(
|
|
||||||
file.messages.map((d) => JSON.parse(JSON.stringify(d))),
|
|
||||||
[
|
|
||||||
{
|
|
||||||
fatal: false,
|
|
||||||
message: 'Test message',
|
|
||||||
name: '1:1',
|
|
||||||
reason: 'Test message',
|
|
||||||
ruleId: 'rule',
|
|
||||||
source: 'test'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'should support string meta'
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('rules', async (t) => {
|
test('plugins', async function (t) {
|
||||||
const root = path.join(process.cwd(), 'packages')
|
for (const plugin of plugins) {
|
||||||
const all = rules(root)
|
await t.test(plugin.name, async function () {
|
||||||
let index = -1
|
await assertPlugin(plugin)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
while (++index < all.length) {
|
/**
|
||||||
const basename = all[index]
|
* @param {PluginInfo} info
|
||||||
const base = path.resolve(root, basename)
|
* Info.
|
||||||
const info = rule(base)
|
* @returns {Promise<undefined>}
|
||||||
const href = url.pathToFileURL(base).href + '/index.js'
|
* Nothing.
|
||||||
|
*/
|
||||||
|
async function assertPlugin(info) {
|
||||||
|
/** @type {{default: Plugin}} */
|
||||||
|
const pluginMod = await import(info.name)
|
||||||
|
const plugin = pluginMod.default
|
||||||
|
|
||||||
/** @type {{default: Plugin}} */
|
for (const check of info.checks) {
|
||||||
const pluginMod = await import(href)
|
await assertCheck(plugin, info, check)
|
||||||
const fn = pluginMod.default
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Object.keys(info.tests).length === 0) {
|
/**
|
||||||
assert.ok(true, info.ruleId + ': no tests')
|
* @param {Plugin} plugin
|
||||||
} else {
|
* Plugin.
|
||||||
await t.test(info.ruleId, async () => {
|
* @param {PluginInfo} info
|
||||||
const tests = info.tests
|
* info.
|
||||||
/** @type {string} */
|
* @param {Check} check
|
||||||
let configuration
|
* Check.
|
||||||
|
* @returns {Promise<undefined>}
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
async function assertCheck(plugin, info, check) {
|
||||||
|
/** @type {{config: unknown}} */
|
||||||
|
const {config} = JSON.parse(check.configuration)
|
||||||
|
/** @type {PluggableList} */
|
||||||
|
const extras = check.gfm ? [remarkGfm] : []
|
||||||
|
let value = check.input
|
||||||
|
|
||||||
for (configuration in tests) {
|
for (const character of characters) {
|
||||||
if (own.call(tests, configuration)) {
|
value = value.replace(character.in, character.out)
|
||||||
const checks = tests[configuration]
|
}
|
||||||
/** @type {{config: unknown}} */
|
|
||||||
const {config} = JSON.parse(configuration)
|
|
||||||
|
|
||||||
/** @type {string} */
|
const file = await remark()
|
||||||
let name
|
.use(plugin, config)
|
||||||
|
.use(extras)
|
||||||
|
.process(new VFile({path: check.name, value}))
|
||||||
|
|
||||||
for (name in checks) {
|
for (const message of file.messages) {
|
||||||
if (own.call(checks, name)) {
|
assert.equal(message.ruleId, info.ruleId)
|
||||||
const basename = name
|
assert.equal(
|
||||||
const check = checks[name]
|
message.url,
|
||||||
|
'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-' +
|
||||||
|
info.ruleId +
|
||||||
|
'#readme'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await assertFixture(fn, info, check, basename, config)
|
assert.deepEqual(
|
||||||
}
|
file.messages.map(String).map(function (value) {
|
||||||
}
|
return value.slice(value.indexOf(':') + 1)
|
||||||
}
|
}),
|
||||||
|
check.output
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!check.positionless) {
|
||||||
|
const file = await remark()
|
||||||
|
.use(function () {
|
||||||
|
return function (tree) {
|
||||||
|
removePosition(tree)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
.use(plugin, config)
|
||||||
}
|
.use(extras)
|
||||||
})
|
.process(new VFile({path: check.name, value}))
|
||||||
|
|
||||||
/**
|
assert.deepEqual(file.messages, [])
|
||||||
* @param {Plugin} rule
|
|
||||||
* @param {Rule} info
|
|
||||||
* @param {Check} fixture
|
|
||||||
* @param {string} basename
|
|
||||||
* @param {unknown} config
|
|
||||||
*/
|
|
||||||
/* eslint-disable-next-line max-params */
|
|
||||||
function assertFixture(rule, info, fixture, basename, config) {
|
|
||||||
const ruleId = info.ruleId
|
|
||||||
const file = toVFile(basename)
|
|
||||||
const expected = fixture.output
|
|
||||||
const positionless = fixture.positionless
|
|
||||||
// @ts-expect-error: to do: fix types.
|
|
||||||
let proc = remark().use(rule, config)
|
|
||||||
|
|
||||||
if (fixture.gfm) proc.use(remarkGfm)
|
|
||||||
|
|
||||||
file.value = preprocess(fixture.input || '')
|
|
||||||
|
|
||||||
try {
|
|
||||||
proc.runSync(proc.parse(file), file)
|
|
||||||
} catch (error) {
|
|
||||||
const exception = /** @type VFileMessage */ (error)
|
|
||||||
if (exception && exception.source !== 'remark-lint') {
|
|
||||||
throw exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = -1
|
|
||||||
while (++index < file.messages.length) {
|
|
||||||
const message = file.messages[index]
|
|
||||||
if (message.ruleId !== ruleId) {
|
|
||||||
throw new Error(
|
|
||||||
'Expected `' +
|
|
||||||
ruleId +
|
|
||||||
'`, not `' +
|
|
||||||
message.ruleId +
|
|
||||||
'` as `ruleId` for ' +
|
|
||||||
message
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const expectedUrl =
|
|
||||||
'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-' +
|
|
||||||
ruleId +
|
|
||||||
'#readme'
|
|
||||||
if (message.url !== expectedUrl) {
|
|
||||||
throw new Error(
|
|
||||||
'Expected `' +
|
|
||||||
expectedUrl +
|
|
||||||
'`, not `' +
|
|
||||||
message.url +
|
|
||||||
'` as `ruleId` for ' +
|
|
||||||
message
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.deepEqual(
|
|
||||||
normalize(file.messages),
|
|
||||||
expected,
|
|
||||||
'should equal with position'
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!positionless) {
|
|
||||||
file.messages = []
|
|
||||||
proc = remark()
|
|
||||||
.use(() => (tree) => removePosition(tree))
|
|
||||||
// @ts-expect-error: to do: fix types.
|
|
||||||
.use(rule, config)
|
|
||||||
if (fixture.gfm) proc.use(remarkGfm)
|
|
||||||
proc.processSync(file)
|
|
||||||
|
|
||||||
assert.deepEqual(
|
|
||||||
normalize(file.messages),
|
|
||||||
[],
|
|
||||||
'should equal without position'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<VFileMessage>} messages
|
* @param {unknown} d
|
||||||
* @returns {Array<string>}
|
* Value.
|
||||||
|
* @returns {unknown}
|
||||||
|
* Cloned value.
|
||||||
*/
|
*/
|
||||||
function normalize(messages) {
|
function jsonClone(d) {
|
||||||
return asStrings(messages).map((value) => value.slice(value.indexOf(':') + 1))
|
return JSON.parse(JSON.stringify(d))
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Array<VFileMessage>} messages
|
|
||||||
* @returns {Array<string>}
|
|
||||||
*/
|
|
||||||
function asStrings(messages) {
|
|
||||||
return messages.map(String)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} value
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function preprocess(value) {
|
|
||||||
let index = -1
|
|
||||||
|
|
||||||
while (++index < characters.length) {
|
|
||||||
value = value.replace(characters[index].in, characters[index].out)
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
"emitDeclarationOnly": true,
|
"emitDeclarationOnly": true,
|
||||||
"exactOptionalPropertyTypes": true,
|
"exactOptionalPropertyTypes": true,
|
||||||
"lib": ["es2020"],
|
"lib": ["es2022"],
|
||||||
"module": "node16",
|
"module": "node16",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"target": "es2020"
|
"target": "es2020"
|
||||||
|
Loading…
Reference in New Issue
Block a user