Skip to content

Commit

Permalink
Add better support for gfm, directives, math, mdx
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Dec 16, 2023
1 parent 4057f15 commit 655ba54
Show file tree
Hide file tree
Showing 43 changed files with 981 additions and 187 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,10 @@
"remark": "^15.0.0",
"remark-cli": "^12.0.0",
"remark-comment-config": "^8.0.0",
"remark-directive": "^3.0.0",
"remark-gfm": "^4.0.0",
"remark-github": "^12.0.0",
"remark-math": "^6.0.0",
"remark-mdx": "^3.0.0",
"remark-toc": "^9.0.0",
"remark-validate-links": "^13.0.0",
Expand Down
10 changes: 10 additions & 0 deletions packages/remark-lint-definition-case/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@
* {"name": "not-ok.md", "label": "output"}
*
* 1:1-1:47: Do not use uppercase characters in definition labels
*
* @example
* {"gfm": true, "label": "input", "name": "gfm.md"}
*
* [^X]: Footnote definitions (from GFM) are checked too.
*
* @example
* {"gfm": true, "label": "output", "name": "gfm.md"}
*
* 1:1-1:55: Do not use uppercase characters in definition labels
*/

/**
Expand Down
19 changes: 19 additions & 0 deletions packages/remark-lint-definition-case/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,23 @@ No messages.
1:1-1:47: Do not use uppercase characters in definition labels
```

##### `gfm.md`

###### In

> 👉 **Note**: this example uses
> GFM ([`remark-gfm`][github-remark-gfm]).
```markdown
[^X]: Footnote definitions (from GFM) are checked too.
```

###### Out

```text
1:1-1:55: Do not use uppercase characters in definition labels
```

## Compatibility

Projects maintained by the unified collective are compatible with maintained
Expand Down Expand Up @@ -236,6 +253,8 @@ abide by its terms.

[github-gist-esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

[github-remark-gfm]: https://github.com/remarkjs/remark-gfm

[github-remark-lint]: https://github.com/remarkjs/remark-lint

[github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
Expand Down
5 changes: 4 additions & 1 deletion packages/remark-lint-definition-spacing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*
* This package checks the whitepsace in definition labels.
*
* GFM footnotes are not affected by this rule as footnote labels cannot
* contain whitespace.
*
* ## When should I use this?
*
* You can use this package to check that definition labels are consistent.
Expand Down Expand Up @@ -79,7 +82,7 @@ const remarkLintDefinitionSpacing = lintRule(
const value = String(file)

visit(tree, function (node) {
if (node.type === 'definition' || node.type === 'footnoteDefinition') {
if (node.type === 'definition') {
const end = pointEnd(node)
const start = pointStart(node)

Expand Down
3 changes: 3 additions & 0 deletions packages/remark-lint-definition-spacing/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ a definition label.

This package checks the whitepsace in definition labels.

GFM footnotes are not affected by this rule as footnote labels cannot
contain whitespace.

## When should I use this?

You can use this package to check that definition labels are consistent.
Expand Down
27 changes: 19 additions & 8 deletions packages/remark-lint-file-extension/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
*
* ###### Parameters
*
* * `options` (`string`, default: `'md'`)
* — preferred file extension
* * `options` (`Array<string>` or `string`, default: `['mdx', 'md']`)
* — allowed file extension(s)
*
* ###### Returns
*
Expand Down Expand Up @@ -50,7 +50,7 @@
* @example
* {"name": "readme.mkd", "label": "output", "positionless": true}
*
* 1:1: Incorrect extension: use `md`
* 1:1: Incorrect extension: use `mdx` or `md`
*
* @example
* {"name": "readme.mkd", "config": "mkd"}
Expand All @@ -61,6 +61,12 @@
*/

import {lintRule} from 'unified-lint-rule'
import {quotation} from 'quotation'

/** @type {ReadonlyArray<string>} */
const defaultExtensions = ['mdx', 'md']

const listFormat = new Intl.ListFormat('en', {type: 'disjunction'})

const remarkLintFileExtension = lintRule(
{
Expand All @@ -70,17 +76,22 @@ const remarkLintFileExtension = lintRule(
/**
* @param {Root} _
* Tree.
* @param {string | null | undefined} [options='md']
* @param {ReadonlyArray<string> | string | null | undefined} [options='md']
* Configuration (default: `'md'`).
* @returns {undefined}
* Nothing.
*/
function (_, file, options) {
const option = options || 'md'
const ext = file.extname
const extensions =
typeof options === 'string' ? [options] : options || defaultExtensions
const extname = file.extname
const extension = extname ? extname.slice(1) : undefined

if (ext && ext.slice(1) !== option) {
file.message('Incorrect extension: use `' + option + '`')
if (extension && !extensions.includes(extension)) {
file.message(
'Incorrect extension: use ' +
listFormat.format(quotation(extensions, '`'))
)
}
}
)
Expand Down
1 change: 1 addition & 0 deletions packages/remark-lint-file-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
],
"dependencies": {
"@types/mdast": "^4.0.0",
"quotation": "^2.0.0",
"unified-lint-rule": "^2.0.0"
},
"scripts": {},
Expand Down
6 changes: 3 additions & 3 deletions packages/remark-lint-file-extension/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ Warn for unexpected extensions.
###### Parameters

* `options` (`string`, default: `'md'`)
preferred file extension
* `options` (`Array<string>` or `string`, default: `['mdx', 'md']`)
allowed file extension(s)

###### Returns

Expand Down Expand Up @@ -162,7 +162,7 @@ No messages.
###### Out

```text
1:1: Incorrect extension: use `md`
1:1: Incorrect extension: use `mdx` or `md`
```

##### `readme.mkd`
Expand Down
2 changes: 0 additions & 2 deletions packages/remark-lint-final-definition/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ const remarkLintFinalDefinition = lintRule(
definitions.push(node)
} else if (
node.type === 'root' ||
node.type === 'blockquote' ||
node.type === 'listItem' ||
// Ignore HTML comments.
(node.type === 'html' && /^[\t ]*<!--/.test(node.value)) ||
// Ignore MDX comments.
Expand Down
56 changes: 26 additions & 30 deletions packages/remark-lint-first-heading-level/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
* In some cases a different rank makes more sense,
* such as when building a blog and generating the primary heading from
* frontmatter metadata,
* in which case a value of `2` can be defined here.
* in which case a value of `2` can be defined here or the rule can be turned
* off.
*
* [api-depth]: #depth
* [api-options]: #options
Expand Down Expand Up @@ -145,9 +146,9 @@
* 1:1-1:14: First heading level should be `2`
*
* @example
* {"name": "ok.mdx", "mdx": true}
* {"mdx": true, "name": "ok.mdx"}
*
* In <b>MDX</b>, JSX is supported.
* In MDX, <b>JSX</b> is supported.
*
* <h1>First heading</h1>
*/
Expand All @@ -172,7 +173,7 @@ import {position} from 'unist-util-position'
import {EXIT, visit} from 'unist-util-visit'

const htmlRe = /<h([1-6])/
const jsxNameRe = /h([1-6])/
const jsxNameRe = /^h([1-6])$/

const remarkLintFirstHeadingLevel = lintRule(
{
Expand All @@ -191,36 +192,31 @@ const remarkLintFirstHeadingLevel = lintRule(
const option = options || 1

visit(tree, function (node) {
const place = position(node)
/** @type {Depth | undefined} */
let rank

if (place) {
/** @type {Depth | undefined} */
let rank

if (node.type === 'heading') {
rank = node.depth
} else if (node.type === 'html') {
const results = node.value.match(htmlRe)
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
} else if (
(node.type === 'mdxJsxFlowElement' ||
node.type === 'mdxJsxTextElement') &&
node.name
) {
const results = node.name.match(jsxNameRe)
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
}
if (node.type === 'heading') {
rank = node.depth
} else if (node.type === 'html') {
const results = node.value.match(htmlRe)
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
} else if (
(node.type === 'mdxJsxFlowElement' ||
node.type === 'mdxJsxTextElement') &&
node.name
) {
const results = node.name.match(jsxNameRe)
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
}

if (rank) {
if (rank !== option) {
file.message(
'First heading level should be `' + option + '`',
place
)
}
if (rank) {
const place = position(node)

return EXIT
if (place && rank !== option) {
file.message('First heading level should be `' + option + '`', place)
}

return EXIT
}
})
}
Expand Down
5 changes: 3 additions & 2 deletions packages/remark-lint-first-heading-level/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ rank `1`.
In some cases a different rank makes more sense,
such as when building a blog and generating the primary heading from
frontmatter metadata,
in which case a value of `2` can be defined here.
in which case a value of `2` can be defined here or the rule can be turned
off.
## Examples
Expand Down Expand Up @@ -313,7 +314,7 @@ Paragraph.
> MDX ([`remark-mdx`][github-remark-mdx]).
```mdx
In <b>MDX</b>, JSX is supported.
In MDX, <b>JSX</b> is supported.

<h1>First heading</h1>
```
Expand Down
56 changes: 49 additions & 7 deletions packages/remark-lint-heading-increment/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,36 @@
* {"name": "not-ok.md", "label": "output"}
*
* 3:1-3:10: Heading levels should increment by one level at a time
*
* @example
* {"name": "html.md"}
*
* In markdown, <b>HTML</b> is supported.
*
* <h1>First heading</h1>
*
* @example
* {"name": "ok.mdx", "mdx": true}
*
* In MDX, <b>JSX</b> is supported.
*
* <h1>First heading</h1>
*/

/**
* @typedef {import('mdast').Heading} Heading
* @typedef {import('mdast').Root} Root
*/

/// <reference types="mdast-util-mdx" />

import {lintRule} from 'unified-lint-rule'
import {position} from 'unist-util-position'
import {visit} from 'unist-util-visit'

const htmlRe = /<h([1-6])/
const jsxNameRe = /^h([1-6])$/

const remarkLintHeadingIncrement = lintRule(
{
origin: 'remark-lint:heading-increment',
Expand All @@ -88,18 +107,41 @@ const remarkLintHeadingIncrement = lintRule(
/** @type {Heading['depth'] | undefined} */
let previous

visit(tree, 'heading', function (node) {
visit(tree, function (node) {
const place = position(node)

if (place) {
if (previous && node.depth > previous + 1) {
file.message(
'Heading levels should increment by one level at a time',
place
)
/** @type {Heading['depth'] | undefined} */
let rank

if (node.type === 'heading') {
rank = node.depth
} else if (node.type === 'html') {
const results = node.value.match(htmlRe)
rank = results
? /** @type {Heading['depth']} */ (Number(results[1]))
: undefined
} else if (
(node.type === 'mdxJsxFlowElement' ||
node.type === 'mdxJsxTextElement') &&
node.name
) {
const results = node.name.match(jsxNameRe)
rank = results
? /** @type {Heading['depth']} */ (Number(results[1]))
: undefined
}

previous = node.depth
if (rank) {
if (previous && rank > previous + 1) {
file.message(
'Heading levels should increment by one level at a time',
place
)
}

previous = rank
}
}
})
}
Expand Down
1 change: 1 addition & 0 deletions packages/remark-lint-heading-increment/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
],
"dependencies": {
"@types/mdast": "^4.0.0",
"mdast-util-mdx": "^3.0.0",
"unified-lint-rule": "^2.0.0",
"unist-util-position": "^5.0.0",
"unist-util-visit": "^5.0.0"
Expand Down

0 comments on commit 655ba54

Please sign in to comment.