remark-lint/packages/remark-lint-no-heading-indent/index.js
2023-12-13 16:54:41 +01:00

137 lines
3.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* remark-lint rule to warn when headings are indented.
*
* ## What is this?
*
* This package checks the indent of headings.
*
* ## When should I use this?
*
* You can use this package to check that headings are consistent.
*
* ## API
*
* ### `unified().use(remarkLintNoHeadingIndent)`
*
* Warn when headings are indented.
*
* ###### Parameters
*
* There are no options.
*
* ###### Returns
*
* Transform ([`Transformer` from `unified`][github-unified-transformer]).
*
* ## Recommendation
*
* There is no specific handling of indented headings (or anything else) in
* markdown.
* While it is possible to use an indent to headings on their text:
*
* ```markdown
* # One
* ## Two
* ### Three
* #### Four
* ```
*
* …such style is uncommon, a bit hard to maintain, and its impossible to add a
* heading with a rank of 5 as it would form indented code instead.
* Hence, its recommended to not indent headings and to turn this rule on.
*
* ## Fix
*
* [`remark-stringify`][github-remark-stringify] formats headings without indent.
*
* [api-remark-lint-no-heading-indent]: #unifieduseremarklintnoheadingindent
* [github-remark-stringify]: https://github.com/remarkjs/remark/tree/main/packages/remark-stringify
* [github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
*
* @module no-heading-indent
* @author Titus Wormer
* @copyright 2015 Titus Wormer
* @license MIT
* @example
* {"name": "ok.md"}
*
* #␠Hello world
*
* Foo
* -----
*
* #␠Hello world␠#
*
* Bar
* =====
*
* @example
* {"name": "not-ok.md", "label": "input"}
*
* ␠␠␠# Hello world
*
* ␠Foo
* -----
*
* ␠# Hello world #
*
* ␠␠␠Bar
* =====
*
* @example
* {"name": "not-ok.md", "label": "output"}
*
* 1:4: Remove 3 spaces before this heading
* 3:2: Remove 1 space before this heading
* 6:2: Remove 1 space before this heading
* 8:4: Remove 3 spaces before this heading
*/
/**
* @typedef {import('mdast').Root} Root
*/
import plural from 'pluralize'
import {lintRule} from 'unified-lint-rule'
import {pointStart} from 'unist-util-position'
import {visit} from 'unist-util-visit'
const remarkLintNoHeadingIndent = lintRule(
{
origin: 'remark-lint:no-heading-indent',
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-indent#readme'
},
/**
* @param {Root} tree
* Tree.
* @returns {undefined}
* Nothing.
*/
function (tree, file) {
visit(tree, 'heading', function (node, _, parent) {
const start = pointStart(node)
// Note: its rather complex to detect what the expected indent is in block
// quotes and lists, so lets only do directly in root for now.
if (!start || (parent && parent.type !== 'root')) {
return
}
const diff = start.column - 1
if (diff) {
file.message(
'Remove ' +
diff +
' ' +
plural('space', diff) +
' before this heading',
start
)
}
})
}
)
export default remarkLintNoHeadingIndent