mirror of
https://github.com/remarkjs/remark-lint.git
synced 2024-10-05 15:49:09 +03:00
Refactor code-style
This commit is contained in:
parent
0e79b65cc7
commit
19251fc5ab
@ -40,7 +40,7 @@ npm install remark-lint remark-cli
|
||||
We will also use some utilities:
|
||||
|
||||
```sh
|
||||
npm install unified-lint-rule unist-util-generated unist-util-visit
|
||||
npm install unified-lint-rule unist-util-visit
|
||||
```
|
||||
|
||||
These will help us creating and managing our custom rules.
|
||||
|
@ -134,6 +134,7 @@
|
||||
"type-coverage": "^2.0.0",
|
||||
"type-fest": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unist-builder": "^4.0.0",
|
||||
"unist-util-remove-position": "^5.0.0",
|
||||
"vfile": "^6.0.0",
|
||||
|
@ -79,39 +79,42 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {import('mdast').Blockquote} Blockquote
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {'consistent' | number} Options
|
||||
* Options.
|
||||
* @typedef {number | 'consistent'} Options
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import pluralize from 'pluralize'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import plural from 'pluralize'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintBlockquoteIndentation = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:blockquote-indentation',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-blockquote-indentation#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'consistent') => {
|
||||
visit(tree, 'blockquote', (node) => {
|
||||
if (generated(node) || node.children.length === 0) {
|
||||
return
|
||||
}
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='consistent']
|
||||
* Configuration (default: `'consistent'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
let option = options || 'consistent'
|
||||
|
||||
visit(tree, 'blockquote', function (node) {
|
||||
const start = pointStart(node)
|
||||
const head = pointStart(node.children[0])
|
||||
/* c8 ignore next -- we get here if we have offsets. */
|
||||
const count = head && start ? head.column - start.column : undefined
|
||||
|
||||
if (typeof count === 'number') {
|
||||
if (head && start) {
|
||||
const count = head.column - start.column
|
||||
|
||||
if (option === 'consistent') {
|
||||
option = count
|
||||
} else {
|
||||
@ -125,9 +128,9 @@ const remarkLintBlockquoteIndentation = lintRule(
|
||||
' ' +
|
||||
abs +
|
||||
' ' +
|
||||
plural('space', abs) +
|
||||
pluralize('space', abs) +
|
||||
' between block quote and content',
|
||||
pointStart(node.children[0])
|
||||
head
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -38,9 +38,7 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
@ -54,7 +52,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,37 +92,44 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Styles | 'consistent'} Options
|
||||
* Configuration.
|
||||
*
|
||||
* @typedef Styles
|
||||
* Styles.
|
||||
* @property {'x' | 'X' | 'consistent'} [checked='consistent']
|
||||
* @property {'X' | 'x' | 'consistent' | null | undefined} [checked='consistent']
|
||||
* Preferred style to use for checked checkboxes (default: `'consistent'`).
|
||||
* @property {' ' | '\t' | 'consistent'} [unchecked='consistent']
|
||||
* @property {'\t' | ' ' | 'consistent' | null | undefined} [unchecked='consistent']
|
||||
* Preferred style to use for unchecked checkboxes (default: `'consistent'`).
|
||||
*
|
||||
* @typedef {'consistent' | Styles} Options
|
||||
* Options.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintCheckboxCharacterStyle = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:checkbox-character-style',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-checkbox-character-style#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'consistent') => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options]
|
||||
* Configuration (optional).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const value = String(file)
|
||||
/** @type {'x' | 'X' | 'consistent'} */
|
||||
/** @type {'X' | 'x' | 'consistent'} */
|
||||
let checked = 'consistent'
|
||||
/** @type {' ' | '\x09' | 'consistent'} */
|
||||
/** @type {'\x09' | ' ' | 'consistent'} */
|
||||
let unchecked = 'consistent'
|
||||
|
||||
if (typeof option === 'object') {
|
||||
checked = option.checked || 'consistent'
|
||||
unchecked = option.unchecked || 'consistent'
|
||||
if (options && typeof options === 'object') {
|
||||
checked = options.checked || 'consistent'
|
||||
unchecked = options.unchecked || 'consistent'
|
||||
}
|
||||
|
||||
if (unchecked !== 'consistent' && unchecked !== ' ' && unchecked !== '\t') {
|
||||
@ -141,7 +148,7 @@ const remarkLintCheckboxCharacterStyle = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
visit(tree, 'listItem', (node) => {
|
||||
visit(tree, 'listItem', function (node) {
|
||||
const head = node.children[0]
|
||||
const point = pointStart(head)
|
||||
|
||||
@ -149,8 +156,8 @@ const remarkLintCheckboxCharacterStyle = lintRule(
|
||||
// A list item cannot be checked and empty, according to GFM.
|
||||
if (
|
||||
!point ||
|
||||
typeof node.checked !== 'boolean' ||
|
||||
!head ||
|
||||
typeof node.checked !== 'boolean' ||
|
||||
typeof point.offset !== 'number'
|
||||
) {
|
||||
return
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -66,21 +66,26 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {location} from 'vfile-location'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {location} from 'vfile-location'
|
||||
|
||||
const remarkLintCheckboxContentIndent = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:checkbox-content-indent',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-checkbox-content-indent#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
const value = String(file)
|
||||
const loc = location(file)
|
||||
|
||||
visit(tree, 'listItem', (node) => {
|
||||
visit(tree, 'listItem', function (node) {
|
||||
const head = node.children[0]
|
||||
const point = pointStart(head)
|
||||
|
||||
@ -88,8 +93,8 @@ const remarkLintCheckboxContentIndent = lintRule(
|
||||
// A list item cannot be checked and empty, according to GFM.
|
||||
if (
|
||||
!point ||
|
||||
typeof node.checked !== 'boolean' ||
|
||||
!head ||
|
||||
typeof node.checked !== 'boolean' ||
|
||||
typeof point.offset !== 'number'
|
||||
) {
|
||||
return
|
||||
@ -100,8 +105,7 @@ const remarkLintCheckboxContentIndent = lintRule(
|
||||
value.slice(point.offset - 4, point.offset + 1)
|
||||
)
|
||||
|
||||
// Failsafe to make sure we don‘t crash if there actually isn’t a checkbox.
|
||||
/* c8 ignore next */
|
||||
/* c8 ignore next -- make sure we don’t crash if there actually isn’t a checkbox. */
|
||||
if (!match) return
|
||||
|
||||
// Move past checkbox.
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
|
@ -131,29 +131,38 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {'fenced' | 'indented'} Style
|
||||
* @typedef {Style | 'consistent'} Options
|
||||
* Configuration.
|
||||
*
|
||||
* @typedef {'indented' | 'fenced'} Style
|
||||
* Styles.
|
||||
* @typedef {'consistent' | Style} Options
|
||||
* Options.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
|
||||
const remarkLintCodeBlockStyle = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:code-block-style',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-code-block-style#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'consistent') => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='consistent']
|
||||
* Configuration (default: `'consistent'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
let option = options || 'consistent'
|
||||
const value = String(file)
|
||||
|
||||
if (
|
||||
option !== 'consistent' &&
|
||||
option !== 'fenced' &&
|
||||
option !== 'indented'
|
||||
option !== 'indented' &&
|
||||
option !== 'fenced'
|
||||
) {
|
||||
file.fail(
|
||||
'Incorrect code block style `' +
|
||||
@ -162,22 +171,22 @@ const remarkLintCodeBlockStyle = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
visit(tree, 'code', (node) => {
|
||||
const initial = pointStart(node)
|
||||
const final = pointEnd(node)
|
||||
visit(tree, 'code', function (node) {
|
||||
const end = pointEnd(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (
|
||||
!initial ||
|
||||
!final ||
|
||||
typeof initial.offset !== 'number' ||
|
||||
typeof final.offset !== 'number'
|
||||
!start ||
|
||||
!end ||
|
||||
typeof start.offset !== 'number' ||
|
||||
typeof end.offset !== 'number'
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const current =
|
||||
node.lang ||
|
||||
/^\s*([~`])\1{2,}/.test(value.slice(initial.offset, final.offset))
|
||||
/^\s*([~`])\1{2,}/.test(value.slice(start.offset, end.offset))
|
||||
? 'fenced'
|
||||
: 'indented'
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
@ -51,7 +50,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,8 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
|
||||
const label = /^\s*\[((?:\\[\s\S]|[^[\]])+)]/
|
||||
|
||||
@ -52,20 +52,25 @@ const remarkLintDefinitionCase = lintRule(
|
||||
origin: 'remark-lint:definition-case',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-definition-case#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
const value = String(file)
|
||||
|
||||
visit(tree, (node) => {
|
||||
visit(tree, function (node) {
|
||||
if (node.type === 'definition' || node.type === 'footnoteDefinition') {
|
||||
const start = pointStart(node)
|
||||
const end = pointEnd(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (
|
||||
start &&
|
||||
end &&
|
||||
typeof start.offset === 'number' &&
|
||||
typeof end.offset === 'number'
|
||||
start &&
|
||||
typeof end.offset === 'number' &&
|
||||
typeof start.offset === 'number'
|
||||
) {
|
||||
const match = value.slice(start.offset, end.offset).match(label)
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -44,8 +44,8 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const label = /^\s*\[((?:\\[\s\S]|[^[\]])+)]/
|
||||
|
||||
@ -54,20 +54,25 @@ const remarkLintDefinitionSpacing = lintRule(
|
||||
origin: 'remark-lint:definition-spacing',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-definition-spacing#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
const value = String(file)
|
||||
|
||||
visit(tree, (node) => {
|
||||
visit(tree, function (node) {
|
||||
if (node.type === 'definition' || node.type === 'footnoteDefinition') {
|
||||
const start = pointStart(node)
|
||||
const end = pointEnd(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (
|
||||
start &&
|
||||
end &&
|
||||
typeof start.offset === 'number' &&
|
||||
typeof end.offset === 'number'
|
||||
start &&
|
||||
typeof end.offset === 'number' &&
|
||||
typeof start.offset === 'number'
|
||||
) {
|
||||
const match = value.slice(start.offset, end.offset).match(label)
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -93,22 +93,31 @@
|
||||
/**
|
||||
* @typedef {'*' | '_'} Marker
|
||||
* Styles.
|
||||
* @typedef {'consistent' | Marker} Options
|
||||
* Options.
|
||||
*
|
||||
* @typedef {Marker | 'consistent'} Options
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintEmphasisMarker = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:emphasis-marker',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-emphasis-marker#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'consistent') => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='consistent']
|
||||
* Configuration (default: `'consistent`').
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const value = String(file)
|
||||
let option = options || 'consistent'
|
||||
|
||||
if (option !== '*' && option !== '_' && option !== 'consistent') {
|
||||
file.fail(
|
||||
@ -118,7 +127,7 @@ const remarkLintEmphasisMarker = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
visit(tree, 'emphasis', (node) => {
|
||||
visit(tree, 'emphasis', function (node) {
|
||||
const start = pointStart(node)
|
||||
|
||||
if (start && typeof start.offset === 'number') {
|
||||
|
@ -36,7 +36,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
@ -51,7 +50,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,23 +100,23 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef FlagMap
|
||||
* Configuration.
|
||||
* @property {boolean | null | undefined} [allowEmpty=false]
|
||||
* Allow language flags to be omitted (default: `false`).
|
||||
* @property {Flags | null | undefined} [flags]
|
||||
* Language flags (optional).
|
||||
*
|
||||
* @typedef {Array<string>} Flags
|
||||
* Language flags.
|
||||
*
|
||||
* @typedef FlagMap
|
||||
* @typedef {FlagMap | Flags} Options
|
||||
* Configuration.
|
||||
* @property {Flags} [flags]
|
||||
* Language flags.
|
||||
* @property {boolean} [allowEmpty=false]
|
||||
* Allow language flags to be omitted (default: `false`).
|
||||
*
|
||||
* @typedef {Flags | FlagMap} Options
|
||||
* Options.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
|
||||
const fence = /^ {0,3}([~`])\1{2,}/
|
||||
|
||||
@ -125,34 +125,41 @@ const remarkLintFencedCodeFlag = lintRule(
|
||||
origin: 'remark-lint:fenced-code-flag',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-fenced-code-flag#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options]
|
||||
* Configuration (optional).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const value = String(file)
|
||||
let allowEmpty = false
|
||||
/** @type {Array<string>} */
|
||||
let allowed = []
|
||||
|
||||
if (typeof option === 'object') {
|
||||
if (Array.isArray(option)) {
|
||||
allowed = option
|
||||
if (options && typeof options === 'object') {
|
||||
if (Array.isArray(options)) {
|
||||
allowed = options
|
||||
} else {
|
||||
allowEmpty = Boolean(option.allowEmpty)
|
||||
allowEmpty = Boolean(options.allowEmpty)
|
||||
|
||||
if (option.flags) {
|
||||
allowed = option.flags
|
||||
if (options.flags) {
|
||||
allowed = options.flags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visit(tree, 'code', (node) => {
|
||||
const start = pointStart(node)
|
||||
visit(tree, 'code', function (node) {
|
||||
const end = pointEnd(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (
|
||||
start &&
|
||||
end &&
|
||||
typeof start.offset === 'number' &&
|
||||
typeof end.offset === 'number'
|
||||
start &&
|
||||
typeof end.offset === 'number' &&
|
||||
typeof start.offset === 'number'
|
||||
) {
|
||||
if (node.lang) {
|
||||
if (allowed.length > 0 && !allowed.includes(node.lang)) {
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -105,23 +105,32 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {'~' | '`'} Marker
|
||||
* @typedef {'`' | '~'} Marker
|
||||
* Styles.
|
||||
* @typedef {'consistent' | Marker} Options
|
||||
* Options.
|
||||
*
|
||||
* @typedef {Marker | 'consistent'} Options
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintFencedCodeMarker = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:fenced-code-marker',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-fenced-code-marker#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'consistent') => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='consistent']
|
||||
* Configuration (default: `'consistent'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
let option = options || 'consistent'
|
||||
const contents = String(file)
|
||||
|
||||
if (option !== 'consistent' && option !== '~' && option !== '`') {
|
||||
@ -132,7 +141,7 @@ const remarkLintFencedCodeMarker = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
visit(tree, 'code', (node) => {
|
||||
visit(tree, 'code', function (node) {
|
||||
const start = pointStart(node)
|
||||
|
||||
if (start && typeof start.offset === 'number') {
|
||||
@ -142,7 +151,7 @@ const remarkLintFencedCodeMarker = lintRule(
|
||||
.charAt(0)
|
||||
|
||||
// Ignore unfenced code blocks.
|
||||
if (marker === '~' || marker === '`') {
|
||||
if (marker === '`' || marker === '~') {
|
||||
if (option === 'consistent') {
|
||||
option = marker
|
||||
} else if (marker !== option) {
|
||||
|
@ -37,7 +37,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
@ -52,7 +51,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
/**
|
||||
* @typedef {string} Options
|
||||
* Options.
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
@ -57,8 +57,16 @@ const remarkLintFileExtension = lintRule(
|
||||
origin: 'remark-lint:file-extension',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-file-extension#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(_, file, option = 'md') => {
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options]
|
||||
* Configuration (default: `'md'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file, options) {
|
||||
const option = options || 'md'
|
||||
const ext = file.extname
|
||||
|
||||
if (ext && ext.slice(1) !== option) {
|
||||
|
@ -37,7 +37,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
@ -50,7 +49,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,27 +59,33 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintFinalDefinition = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:final-definition',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-definition#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
let last = 0
|
||||
|
||||
visit(
|
||||
tree,
|
||||
(node) => {
|
||||
function (node) {
|
||||
const start = pointStart(node)
|
||||
|
||||
// To do: ignore MDX comments?
|
||||
// Ignore generated and HTML comment nodes.
|
||||
if (
|
||||
node.type === 'root' ||
|
||||
!start ||
|
||||
node.type === 'root' ||
|
||||
(node.type === 'html' && /^\s*<!--/.test(node.value))
|
||||
) {
|
||||
return
|
||||
|
@ -37,7 +37,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -69,12 +69,18 @@ const remarkLintFinalNewline = lintRule(
|
||||
origin: 'remark-lint:final-newline',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(_, file) => {
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file) {
|
||||
const value = String(file)
|
||||
const last = value.length - 1
|
||||
|
||||
if (last > -1 && value.charAt(last) !== '\n') {
|
||||
// To do: warn at last character.
|
||||
file.message('Missing newline character at end of file')
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -108,20 +108,20 @@
|
||||
|
||||
/**
|
||||
* @typedef {import('mdast').Heading} Heading
|
||||
* @typedef {import('mdast').HTML} HTML
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Heading['depth']} Depth
|
||||
* Styles.
|
||||
*
|
||||
* @typedef {Depth} Options
|
||||
* Options.
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit, EXIT} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {position} from 'unist-util-position'
|
||||
import {EXIT, visit} from 'unist-util-visit'
|
||||
|
||||
const re = /<h([1-6])/
|
||||
|
||||
@ -130,22 +130,38 @@ const remarkLintFirstHeadingLevel = lintRule(
|
||||
origin: 'remark-lint:first-heading-level',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-first-heading-level#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 1) => {
|
||||
visit(tree, (node) => {
|
||||
if (!generated(node)) {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options=1]
|
||||
* Configuration (default: `1`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const option = options || 1
|
||||
|
||||
visit(tree, function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if (place) {
|
||||
/** @type {Depth | undefined} */
|
||||
let rank
|
||||
|
||||
// To do: MDX?
|
||||
if (node.type === 'heading') {
|
||||
rank = node.depth
|
||||
} else if (node.type === 'html') {
|
||||
rank = infer(node)
|
||||
const results = node.value.match(re)
|
||||
rank = results ? /** @type {Depth} */ (Number(results[1])) : undefined
|
||||
}
|
||||
|
||||
if (rank !== undefined) {
|
||||
if (rank) {
|
||||
if (rank !== option) {
|
||||
file.message('First heading level should be `' + option + '`', node)
|
||||
file.message(
|
||||
'First heading level should be `' + option + '`',
|
||||
place
|
||||
)
|
||||
}
|
||||
|
||||
return EXIT
|
||||
@ -156,13 +172,3 @@ const remarkLintFirstHeadingLevel = lintRule(
|
||||
)
|
||||
|
||||
export default remarkLintFirstHeadingLevel
|
||||
|
||||
/**
|
||||
* @param {HTML} node
|
||||
* @returns {Depth | undefined}
|
||||
*/
|
||||
function infer(node) {
|
||||
const results = node.value.match(re)
|
||||
// @ts-expect-error: can be casted fine.
|
||||
return results ? Number(results[1]) : undefined
|
||||
}
|
||||
|
@ -38,9 +38,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
@ -53,7 +52,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,19 +44,24 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
|
||||
const remarkLintHardBreakSpaces = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:hard-break-spaces',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-hard-break-spaces#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
const value = String(file)
|
||||
|
||||
visit(tree, 'break', (node) => {
|
||||
visit(tree, 'break', function (node) {
|
||||
const start = pointStart(node)
|
||||
const end = pointEnd(node)
|
||||
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -55,25 +55,32 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
|
||||
const remarkLintHeadingIncrement = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:heading-increment',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-heading-increment#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/** @type {Depth} */
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
/** @type {Depth | undefined} */
|
||||
let previous
|
||||
|
||||
visit(tree, 'heading', (node) => {
|
||||
if (!generated(node)) {
|
||||
visit(tree, 'heading', 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',
|
||||
node
|
||||
place
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -117,28 +117,38 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Type | 'consistent'} Options
|
||||
* Configuration.
|
||||
*
|
||||
* @typedef {'atx' | 'atx-closed' | 'setext'} Type
|
||||
* Styles.
|
||||
* @typedef {'consistent' | Type} Options
|
||||
* Options.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {headingStyle} from 'mdast-util-heading-style'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintHeadingStyle = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:heading-style',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-heading-style#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'consistent') => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='consistent']
|
||||
* Configuration (default: `'consistent'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
let option = options || 'consistent'
|
||||
|
||||
if (
|
||||
option !== 'consistent' &&
|
||||
option !== 'atx' &&
|
||||
option !== 'atx-closed' &&
|
||||
option !== 'consistent' &&
|
||||
option !== 'setext'
|
||||
) {
|
||||
file.fail(
|
||||
@ -148,14 +158,15 @@ const remarkLintHeadingStyle = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
visit(tree, 'heading', (node) => {
|
||||
if (!generated(node)) {
|
||||
visit(tree, 'heading', function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if (place) {
|
||||
if (option === 'consistent') {
|
||||
// Funky nodes perhaps cannot be detected.
|
||||
/* c8 ignore next */
|
||||
/* c8 ignore next -- funky nodes perhaps cannot be detected. */
|
||||
option = headingStyle(node) || 'consistent'
|
||||
} else if (headingStyle(node, option) !== option) {
|
||||
file.message('Headings should use ' + option, node)
|
||||
file.message('Headings should use ' + option, place)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -39,9 +39,8 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-heading-style": "^3.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
@ -54,7 +53,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@
|
||||
/**
|
||||
* @typedef {'unix' | 'windows'} Type
|
||||
* Styles.
|
||||
* @typedef {'consistent' | Type} Options
|
||||
* @typedef {Type | 'consistent'} Options
|
||||
* Options.
|
||||
*/
|
||||
|
||||
@ -86,8 +86,16 @@ const remarkLintLinebreakStyle = lintRule(
|
||||
origin: 'remark-lint:linebreak-style',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-linebreak-style#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(_, file, option = 'consistent') => {
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='consistent']
|
||||
* Configuration (default: `'consistent'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file, options) {
|
||||
let option = options || 'consistent'
|
||||
const value = String(file)
|
||||
const toPoint = location(value).toPoint
|
||||
let index = value.indexOf('\n')
|
||||
|
@ -41,7 +41,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"vfile-location": "^5.0.0"
|
||||
},
|
||||
@ -55,7 +54,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,16 +128,15 @@
|
||||
/**
|
||||
* @typedef {'"' | '\'' | '()'} Marker
|
||||
* Styles.
|
||||
* @typedef {'consistent' | Marker} Options
|
||||
* Options.
|
||||
*
|
||||
* @typedef {Marker | 'consistent'} Options
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {location} from 'vfile-location'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
|
||||
const own = {}.hasOwnProperty
|
||||
import {location} from 'vfile-location'
|
||||
|
||||
const markers = {
|
||||
'"': '"',
|
||||
@ -150,14 +149,22 @@ const remarkLintLinkTitleStyle = lintRule(
|
||||
origin: 'remark-lint:link-title-style',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-link-title-style#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'consistent') => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='consistent']
|
||||
* Configuration (default: `'consistent'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const value = String(file)
|
||||
const loc = location(file)
|
||||
// @ts-expect-error: allow other paren combos.
|
||||
const option = options || 'consistent'
|
||||
// @ts-expect-error: allow `(` too, even though untyped.
|
||||
let look = option === '()' || option === '(' ? ')' : option
|
||||
|
||||
if (look !== 'consistent' && !own.call(markers, look)) {
|
||||
if (look !== 'consistent' && !Object.hasOwn(markers, look)) {
|
||||
file.fail(
|
||||
'Incorrect link title style marker `' +
|
||||
look +
|
||||
@ -165,11 +172,11 @@ const remarkLintLinkTitleStyle = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
visit(tree, (node) => {
|
||||
visit(tree, function (node) {
|
||||
if (
|
||||
node.type === 'link' ||
|
||||
node.type === 'definition' ||
|
||||
node.type === 'image' ||
|
||||
node.type === 'definition'
|
||||
node.type === 'link'
|
||||
) {
|
||||
const tail =
|
||||
'children' in node
|
||||
@ -216,13 +223,14 @@ const remarkLintLinkTitleStyle = lintRule(
|
||||
} else if (look !== final) {
|
||||
const start = loc.toPoint(first)
|
||||
const end = loc.toPoint(last + 1)
|
||||
/* c8 ignore next -- we get here if we have offsets. */
|
||||
const place = start && end ? {start, end} : undefined
|
||||
|
||||
file.message(
|
||||
'Titles should use `' +
|
||||
(look === ')' ? '()' : look) +
|
||||
'` as a quote',
|
||||
/* c8 ignore next -- we get here if we have offsets. */
|
||||
start && end ? {start, end} : undefined
|
||||
place
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
|
@ -62,8 +62,9 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import plural from 'pluralize'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintListItemBulletIndent = lintRule(
|
||||
@ -71,24 +72,28 @@ const remarkLintListItemBulletIndent = lintRule(
|
||||
origin: 'remark-lint:list-item-bullet-indent',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'list', (list, _, grandparent) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'list', function (list, _, grandparent) {
|
||||
let index = -1
|
||||
const pointStartGrandparent = pointStart(grandparent)
|
||||
|
||||
while (++index < list.children.length) {
|
||||
const item = list.children[index]
|
||||
const itemStart = pointStart(item)
|
||||
|
||||
if (
|
||||
grandparent &&
|
||||
grandparent.type === 'root' &&
|
||||
grandparent.position &&
|
||||
typeof grandparent.position.start.column === 'number' &&
|
||||
item.position &&
|
||||
typeof item.position.start.column === 'number'
|
||||
pointStartGrandparent &&
|
||||
itemStart &&
|
||||
grandparent.type === 'root'
|
||||
) {
|
||||
const indent =
|
||||
item.position.start.column - grandparent.position.start.column
|
||||
const indent = itemStart.column - pointStartGrandparent.column
|
||||
|
||||
if (indent) {
|
||||
file.message(
|
||||
@ -96,7 +101,7 @@ const remarkLintListItemBulletIndent = lintRule(
|
||||
indent +
|
||||
' ' +
|
||||
plural('space', indent),
|
||||
item.position.start
|
||||
itemStart
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,8 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -45,21 +45,26 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import plural from 'pluralize'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintListItemContentIndent = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:list-item-content-indent',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-content-indent#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
const value = String(file)
|
||||
|
||||
visit(tree, 'listItem', (node) => {
|
||||
visit(tree, 'listItem', function (node) {
|
||||
let index = -1
|
||||
/** @type {number | undefined} */
|
||||
let style
|
||||
@ -68,11 +73,7 @@ const remarkLintListItemContentIndent = lintRule(
|
||||
const item = node.children[index]
|
||||
const begin = pointStart(item)
|
||||
|
||||
if (
|
||||
!begin ||
|
||||
typeof begin.column !== 'number' ||
|
||||
typeof begin.offset !== 'number'
|
||||
) {
|
||||
if (!begin || typeof begin.offset !== 'number') {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -155,26 +155,33 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {'tab-size' | 'space' | 'mixed'} Options
|
||||
* Options.
|
||||
* @typedef {'mixed' | 'space' | 'tab-size'} Options
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import plural from 'pluralize'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintListItemIndent = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:list-item-indent',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-indent#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 'tab-size') => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options='tab-size']
|
||||
* Configuration (default: `'tab-size'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const value = String(file)
|
||||
const option = options || 'tab-size'
|
||||
|
||||
if (option !== 'tab-size' && option !== 'space' && option !== 'mixed') {
|
||||
if (option !== 'mixed' && option !== 'space' && option !== 'tab-size') {
|
||||
file.fail(
|
||||
'Incorrect list-item indent style `' +
|
||||
option +
|
||||
@ -182,9 +189,7 @@ const remarkLintListItemIndent = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
visit(tree, 'list', (node) => {
|
||||
if (generated(node)) return
|
||||
|
||||
visit(tree, 'list', function (node) {
|
||||
const spread = node.spread
|
||||
let index = -1
|
||||
|
||||
|
@ -38,9 +38,7 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
|
@ -132,56 +132,68 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {import('mdast').Root} Root
|
||||
* @typedef {import('mdast').ListItem} ListItem
|
||||
*
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef Options
|
||||
* Options.
|
||||
* Configuration.
|
||||
* @property {boolean | null | undefined} [checkBlanks=false]
|
||||
* Adhere to CommonMark looseness instead of markdown-style-guide preference.
|
||||
* Follow CommonMark looseness instead of markdown-style-guide preference
|
||||
* (default: `false`).
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
|
||||
/** @type {Readonly<Options>} */
|
||||
const emptyOptions = {}
|
||||
|
||||
const remarkLintListItemSpacing = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:list-item-spacing',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-spacing#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = {}) => {
|
||||
const {checkBlanks} = option
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Readonly<Options> | null | undefined} [options]
|
||||
* Configuration (optional).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
// To do: change options? Follow CM by default?
|
||||
const settings = options || emptyOptions
|
||||
const checkBlanks = settings.checkBlanks || false
|
||||
const infer = checkBlanks ? inferBlankLine : inferMultiline
|
||||
|
||||
visit(tree, 'list', (node) => {
|
||||
if (!generated(node)) {
|
||||
let tight = true
|
||||
let index = -1
|
||||
visit(tree, 'list', function (node) {
|
||||
let tight = true
|
||||
let index = -1
|
||||
|
||||
while (++index < node.children.length) {
|
||||
if (infer(node.children[index])) {
|
||||
tight = false
|
||||
break
|
||||
}
|
||||
while (++index < node.children.length) {
|
||||
if (infer(node.children[index])) {
|
||||
tight = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
index = 0 // Skip over first.
|
||||
index = 0 // Skip over first.
|
||||
|
||||
while (++index < node.children.length) {
|
||||
const start = pointEnd(node.children[index - 1])
|
||||
const end = pointStart(node.children[index])
|
||||
while (++index < node.children.length) {
|
||||
const start = pointEnd(node.children[index - 1])
|
||||
const end = pointStart(node.children[index])
|
||||
|
||||
if (start && end && end.line - start.line < 2 !== tight) {
|
||||
file.message(
|
||||
tight
|
||||
? 'Extraneous new line after list item'
|
||||
: 'Missing new line after list item',
|
||||
{start, end}
|
||||
)
|
||||
}
|
||||
if (start && end && end.line - start.line < 2 !== tight) {
|
||||
file.message(
|
||||
tight
|
||||
? 'Extraneous new line after list item'
|
||||
: 'Missing new line after list item',
|
||||
{start, end}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -192,7 +204,9 @@ export default remarkLintListItemSpacing
|
||||
|
||||
/**
|
||||
* @param {ListItem} node
|
||||
* Item.
|
||||
* @returns {boolean}
|
||||
* Whether there’s a blank line between item children.
|
||||
*/
|
||||
function inferBlankLine(node) {
|
||||
let index = 0
|
||||
@ -212,7 +226,9 @@ function inferBlankLine(node) {
|
||||
|
||||
/**
|
||||
* @param {ListItem} node
|
||||
* Item.
|
||||
* @returns {boolean}
|
||||
* Whether `node` is multiline.
|
||||
*/
|
||||
function inferMultiline(node) {
|
||||
const end = pointEnd(node.children[node.children.length - 1])
|
||||
|
@ -38,9 +38,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
|
@ -48,26 +48,32 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {number} Options
|
||||
* Options.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {toString} from 'mdast-util-to-string'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintMaximumHeadingLength = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:maximum-heading-length',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-maximum-heading-length#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 60) => {
|
||||
visit(tree, 'heading', (node) => {
|
||||
if (!generated(node) && toString(node).length > option) {
|
||||
file.message('Use headings shorter than `' + option + '`', node)
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {number | null | undefined} [options=60]
|
||||
* Configuration (default: `60`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const option = options || 60
|
||||
|
||||
visit(tree, 'heading', function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if (place && toString(node).length > option) {
|
||||
file.message('Use headings shorter than `' + option + '`', place)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -37,9 +37,8 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
@ -52,7 +51,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,32 +111,37 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {number} Options
|
||||
* Options.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
|
||||
const remarkLintMaximumLineLength = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:maximum-line-length',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-maximum-line-length#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 80) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {number | null | undefined} [options=80]
|
||||
* Configuration (default: `80`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const value = String(file)
|
||||
const lines = value.split(/\r?\n/)
|
||||
const option = options || 80
|
||||
|
||||
visit(tree, (node) => {
|
||||
visit(tree, function (node) {
|
||||
// To do: add MDX types, etc.
|
||||
// To do: remove MDX 1?
|
||||
if (
|
||||
node.type === 'heading' ||
|
||||
node.type === 'table' ||
|
||||
node.type === 'code' ||
|
||||
node.type === 'definition' ||
|
||||
node.type === 'heading' ||
|
||||
node.type === 'html' ||
|
||||
node.type === 'table' ||
|
||||
// @ts-expect-error: These are from MDX@1 and MDX@2: <https://github.com/mdx-js/specification>.
|
||||
node.type === 'jsx' ||
|
||||
// @ts-expect-error: MDX
|
||||
@ -149,14 +154,14 @@ const remarkLintMaximumLineLength = lintRule(
|
||||
node.type === 'mdxTextExpression' ||
|
||||
// @ts-expect-error: MDX
|
||||
node.type === 'mdxjsEsm' ||
|
||||
node.type === 'yaml' ||
|
||||
// @ts-expect-error: YAML and TOML are from frontmatter.
|
||||
node.type === 'toml'
|
||||
// @ts-expect-error: TOML from frontmatter.
|
||||
node.type === 'toml' ||
|
||||
node.type === 'yaml'
|
||||
) {
|
||||
const start = pointStart(node)
|
||||
const end = pointEnd(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (start && end) {
|
||||
if (end && start) {
|
||||
allowList(start.line - 1, end.line)
|
||||
}
|
||||
}
|
||||
@ -166,14 +171,14 @@ const remarkLintMaximumLineLength = lintRule(
|
||||
// the wrap.
|
||||
// However, when they do, and there’s whitespace after it, they are not
|
||||
// allowed.
|
||||
visit(tree, (node, pos, parent) => {
|
||||
const initial = pointStart(node)
|
||||
visit(tree, function (node, pos, parent) {
|
||||
const final = pointEnd(node)
|
||||
const initial = pointStart(node)
|
||||
|
||||
if (
|
||||
(node.type === 'link' ||
|
||||
node.type === 'image' ||
|
||||
node.type === 'inlineCode') &&
|
||||
(node.type === 'image' ||
|
||||
node.type === 'inlineCode' ||
|
||||
node.type === 'link') &&
|
||||
initial &&
|
||||
final &&
|
||||
parent &&
|
||||
@ -219,7 +224,11 @@ const remarkLintMaximumLineLength = lintRule(
|
||||
* Allowlist from `initial` to `final`, zero-based.
|
||||
*
|
||||
* @param {number} initial
|
||||
* Initial line.
|
||||
* @param {number} final
|
||||
* Final line.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function allowList(initial, final) {
|
||||
while (initial < final) {
|
||||
|
@ -36,7 +36,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -35,10 +35,10 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {toString} from 'mdast-util-to-string'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
// Protocol expression.
|
||||
// See: <https://en.wikipedia.org/wiki/URI_scheme#Generic_syntax>.
|
||||
@ -49,9 +49,14 @@ const remarkLintNoAutoLinkWithoutProtocol = lintRule(
|
||||
origin: 'remark-lint:no-auto-link-without-protocol',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-auto-link-without-protocol#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'link', (node) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'link', function (node) {
|
||||
const end = pointEnd(node)
|
||||
const headStart = pointStart(node.children[0])
|
||||
const start = pointStart(node)
|
||||
@ -62,8 +67,8 @@ const remarkLintNoAutoLinkWithoutProtocol = lintRule(
|
||||
headStart &&
|
||||
start &&
|
||||
tailEnd &&
|
||||
start.column === headStart.column - 1 &&
|
||||
end.column === tailEnd.column + 1 &&
|
||||
start.column === headStart.column - 1 &&
|
||||
!protocol.test(toString(node))
|
||||
) {
|
||||
file.message('All automatic links must start with a protocol', node)
|
||||
|
@ -38,7 +38,6 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -68,21 +68,26 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {location} from 'vfile-location'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {location} from 'vfile-location'
|
||||
|
||||
const remarkLintNoBlockquoteWithoutMarker = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-blockquote-without-marker',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
const value = String(file)
|
||||
const loc = location(file)
|
||||
|
||||
visit(tree, 'blockquote', (node) => {
|
||||
visit(tree, 'blockquote', function (node) {
|
||||
let index = -1
|
||||
|
||||
while (++index < node.children.length) {
|
||||
|
@ -37,7 +37,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
|
@ -56,10 +56,10 @@
|
||||
* @typedef {import('unist').Point} Point
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import plural from 'pluralize'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
|
||||
const unknownContainerSize = new Set(['mdxJsxFlowElement', 'mdxJsxTextElement'])
|
||||
|
||||
@ -68,15 +68,20 @@ const remarkLintNoConsecutiveBlankLines = lintRule(
|
||||
origin: 'remark-lint:no-consecutive-blank-lines',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-consecutive-blank-lines#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, (node) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, function (node) {
|
||||
if ('children' in node) {
|
||||
const head = node.children[0]
|
||||
const start = pointStart(node)
|
||||
const head = node.children[0]
|
||||
const headStart = pointStart(head)
|
||||
|
||||
if (head && start && headStart) {
|
||||
if (head && headStart && start) {
|
||||
if (!unknownContainerSize.has(node.type)) {
|
||||
// Compare parent and first child.
|
||||
compare(start, headStart, 0)
|
||||
@ -118,8 +123,13 @@ const remarkLintNoConsecutiveBlankLines = lintRule(
|
||||
* difference exceeds `max`.
|
||||
*
|
||||
* @param {Point} start
|
||||
* Start.
|
||||
* @param {Point} end
|
||||
* End.
|
||||
* @param {0 | 1 | 2} max
|
||||
* Max.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function compare(start, end, max) {
|
||||
const diff = end.line - start.line
|
||||
|
@ -38,7 +38,6 @@
|
||||
"@types/mdast": "^4.0.0",
|
||||
"@types/unist": "^3.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -41,8 +41,7 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {pointStart, position} from 'unist-util-position'
|
||||
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
@ -51,26 +50,34 @@ const remarkLintNoDuplicateDefinedUrls = lintRule(
|
||||
origin: 'remark-lint:no-duplicate-defined-urls',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-defined-urls#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/** @type {Record<string, string>} */
|
||||
const map = Object.create(null)
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
/** @type {Map<string, string>} */
|
||||
const map = new Map()
|
||||
|
||||
visit(tree, 'definition', (node) => {
|
||||
if (!generated(node) && node.url) {
|
||||
visit(tree, 'definition', function (node) {
|
||||
const place = position(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (place && start && node.url) {
|
||||
const url = String(node.url).toUpperCase()
|
||||
const duplicate = map[url]
|
||||
const duplicate = map.get(url)
|
||||
|
||||
if (duplicate) {
|
||||
file.message(
|
||||
'Do not use different definitions with the same URL (' +
|
||||
duplicate +
|
||||
')',
|
||||
node
|
||||
place
|
||||
)
|
||||
}
|
||||
|
||||
map[url] = stringifyPosition(pointStart(node))
|
||||
map.set(url, stringifyPosition(start))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -37,9 +37,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-stringify-position": "^4.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -40,8 +40,7 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {pointStart, position} from 'unist-util-position'
|
||||
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
@ -50,29 +49,38 @@ const remarkLintNoDuplicateDefinitions = lintRule(
|
||||
origin: 'remark-lint:no-duplicate-definitions',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-definitions#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/** @type {Record<string, string>} */
|
||||
const map = Object.create(null)
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
/** @type {Map<string, string>} */
|
||||
const map = new Map()
|
||||
|
||||
visit(tree, function (node) {
|
||||
const place = position(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
visit(tree, (node) => {
|
||||
if (
|
||||
(node.type === 'definition' || node.type === 'footnoteDefinition') &&
|
||||
!generated(node)
|
||||
place &&
|
||||
start
|
||||
) {
|
||||
const identifier = node.identifier
|
||||
const duplicate = map[identifier]
|
||||
const duplicate = map.get(identifier)
|
||||
|
||||
if (duplicate) {
|
||||
file.message(
|
||||
'Do not use definitions with the same identifier (' +
|
||||
duplicate +
|
||||
')',
|
||||
node
|
||||
place
|
||||
)
|
||||
}
|
||||
|
||||
map[identifier] = stringifyPosition(pointStart(node))
|
||||
map.set(identifier, stringifyPosition(start))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -36,9 +36,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-stringify-position": "^4.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -77,41 +77,47 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||
import {toString} from 'mdast-util-to-string'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart, position} from 'unist-util-position'
|
||||
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoDuplicateHeadingsInSection = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-duplicate-headings-in-section',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-headings-in-section#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/** @type {Array<Record<string, Heading>>} */
|
||||
let stack = []
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
/** @type {Array<Map<string, string>>} */
|
||||
const stack = []
|
||||
|
||||
visit(tree, 'heading', (node) => {
|
||||
const depth = node.depth
|
||||
visit(tree, 'heading', function (node) {
|
||||
const value = toString(node).toUpperCase()
|
||||
const index = depth - 1
|
||||
const scope = stack[index] || (stack[index] = {})
|
||||
const duplicate = scope[value]
|
||||
const index = node.depth - 1
|
||||
const scope = stack[index] || (stack[index] = new Map())
|
||||
const duplicate = scope.get(value)
|
||||
const place = position(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (!generated(node) && duplicate) {
|
||||
if (place && duplicate) {
|
||||
file.message(
|
||||
'Do not use headings with similar content per section (' +
|
||||
stringifyPosition(pointStart(duplicate)) +
|
||||
duplicate +
|
||||
')',
|
||||
node
|
||||
place
|
||||
)
|
||||
}
|
||||
|
||||
scope[value] = node
|
||||
stack = stack.slice(0, depth)
|
||||
scope.set(value, stringifyPosition(start))
|
||||
// Drop things after it.
|
||||
stack.length = node.depth
|
||||
})
|
||||
}
|
||||
)
|
||||
|
@ -38,9 +38,7 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-stringify-position": "^4.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -51,27 +51,34 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||
import {toString} from 'mdast-util-to-string'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointStart, position} from 'unist-util-position'
|
||||
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoDuplicateHeadings = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-duplicate-headings',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-headings#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/** @type {Record<string, string>} */
|
||||
const map = Object.create(null)
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
/** @type {Map<string, string>} */
|
||||
const map = new Map()
|
||||
|
||||
visit(tree, 'heading', (node) => {
|
||||
if (!generated(node)) {
|
||||
visit(tree, 'heading', function (node) {
|
||||
const place = position(node)
|
||||
const start = pointStart(node)
|
||||
|
||||
if (place && start) {
|
||||
const value = toString(node).toUpperCase()
|
||||
const duplicate = map[value]
|
||||
const duplicate = map.get(value)
|
||||
|
||||
if (duplicate) {
|
||||
file.message(
|
||||
@ -80,7 +87,7 @@ const remarkLintNoDuplicateHeadings = lintRule(
|
||||
)
|
||||
}
|
||||
|
||||
map[value] = stringifyPosition(pointStart(node))
|
||||
map.set(value, stringifyPosition(start))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -37,9 +37,7 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-stringify-position": "^4.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -52,22 +52,28 @@
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {position} from 'unist-util-position'
|
||||
|
||||
const remarkLintNoEmphasisAsHeading = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-emphasis-as-heading',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-emphasis-as-heading#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'paragraph', (node, index, parent) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'paragraph', function (node, index, parent) {
|
||||
const head = node.children[0]
|
||||
const place = position(node)
|
||||
|
||||
if (
|
||||
place &&
|
||||
parent &&
|
||||
typeof index === 'number' &&
|
||||
!generated(node) &&
|
||||
node.children.length === 1 &&
|
||||
(head.type === 'emphasis' || head.type === 'strong')
|
||||
) {
|
||||
@ -81,7 +87,7 @@ const remarkLintNoEmphasisAsHeading = lintRule(
|
||||
) {
|
||||
file.message(
|
||||
'Don’t use emphasis to introduce a section, use a heading',
|
||||
node
|
||||
place
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -54,25 +54,32 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
|
||||
const remarkLintNoEmptyUrl = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-empty-url',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-empty-url#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, (node) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if (
|
||||
(node.type === 'link' ||
|
||||
(node.type === 'definition' ||
|
||||
node.type === 'image' ||
|
||||
node.type === 'definition') &&
|
||||
!generated(node) &&
|
||||
node.type === 'link') &&
|
||||
place &&
|
||||
!node.url
|
||||
) {
|
||||
file.message('Don’t use ' + node.type + 's without URL', node)
|
||||
file.message('Don’t use ' + node.type + 's without URL', place)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -38,9 +38,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -49,8 +49,13 @@ const remarkLintNoFileNameArticles = lintRule(
|
||||
origin: 'remark-lint:no-file-name-articles',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-file-name-articles#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(_, file) => {
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file) {
|
||||
const match = file.stem && file.stem.match(/^(the|teh|an?)\b/i)
|
||||
|
||||
if (match) {
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -34,8 +34,13 @@ const remarkLintNoFileNameConsecutiveDashes = lintRule(
|
||||
origin: 'remark-lint:no-file-name-consecutive-dashes',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-file-name-consecutive-dashes#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(_, file) => {
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file) {
|
||||
if (file.stem && /-{2,}/.test(file.stem)) {
|
||||
file.message('Do not use consecutive dashes in a file name')
|
||||
}
|
||||
|
@ -39,7 +39,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
/**
|
||||
* @typedef {RegExp | string} Options
|
||||
* Options.
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
@ -59,9 +59,16 @@ const remarkLintNoFileNameIrregularCharacters = lintRule(
|
||||
origin: 'remark-lint:no-file-name-irregular-characters',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-file-name-irregular-characters#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(_, file, option) => {
|
||||
let preferred = option || expression
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options]
|
||||
* Configuration (default: `/[^\\.a-zA-Z\d-]/`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file, options) {
|
||||
let preferred = options || expression
|
||||
|
||||
if (typeof preferred === 'string') {
|
||||
preferred = new RegExp('[^' + preferred + ']')
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -37,8 +37,13 @@ const remarkLintNofileNameMixedCase = lintRule(
|
||||
origin: 'remark-lint:no-file-name-mixed-case',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-file-name-mixed-case#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(_, file) => {
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file) {
|
||||
const name = file.stem
|
||||
|
||||
if (name && !(name === name.toLowerCase() || name === name.toUpperCase())) {
|
||||
|
@ -37,7 +37,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -39,8 +39,13 @@ const remarkLintNofileNameOuterDashes = lintRule(
|
||||
origin: 'remark-lint:no-file-name-outer-dashes',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-file-name-outer-dashes#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(_, file) => {
|
||||
/**
|
||||
* @param {Root} _
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (_, file) {
|
||||
if (file.stem && /^-|-$/.test(file.stem)) {
|
||||
file.message('Do not use initial or final dashes in a file name')
|
||||
}
|
||||
|
@ -38,7 +38,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -65,20 +65,25 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {headingStyle} from 'mdast-util-heading-style'
|
||||
import plural from 'pluralize'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoHeadingContentIndent = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-heading-content-indent',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-content-indent#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'heading', (node) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'heading', function (node) {
|
||||
const start = pointStart(node)
|
||||
const type = headingStyle(node, 'atx')
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-heading-style": "^3.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -74,19 +74,24 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import plural from 'pluralize'
|
||||
import {visit} from 'unist-util-visit'
|
||||
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'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'heading', (node, _, parent) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'heading', function (node, _, parent) {
|
||||
const start = pointStart(node)
|
||||
|
||||
// Note: it’s rather complex to detect what the expected indent is in block
|
||||
@ -104,7 +109,7 @@ const remarkLintNoHeadingIndent = lintRule(
|
||||
' ' +
|
||||
plural('space', diff) +
|
||||
' before this heading',
|
||||
pointStart(node)
|
||||
start
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -37,7 +37,6 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -40,8 +40,8 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
|
||||
const fence = '#######'
|
||||
|
||||
@ -50,10 +50,17 @@ const remarkLintNoHeadingLikeParagraph = lintRule(
|
||||
origin: 'remark-lint:no-heading-like-paragraph',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-like-paragraph#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'paragraph', (node) => {
|
||||
if (!generated(node)) {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'paragraph', function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if (place) {
|
||||
const head = node.children[0]
|
||||
|
||||
if (
|
||||
@ -63,7 +70,7 @@ const remarkLintNoHeadingLikeParagraph = lintRule(
|
||||
) {
|
||||
file.message(
|
||||
'This looks like a heading but has too many hashes',
|
||||
node
|
||||
place
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -61,27 +61,36 @@
|
||||
* Options.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {toString} from 'mdast-util-to-string'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoHeadingPunctuation = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-heading-punctuation',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-punctuation#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = '\\.,;:!?') => {
|
||||
const expression = new RegExp('[' + option + ']')
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options]
|
||||
* Configuration (default: `'\\.,;:!?'`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const expression = new RegExp('[' + (options || '\\.,;:!?') + ']')
|
||||
|
||||
visit(tree, 'heading', (node) => {
|
||||
if (!generated(node)) {
|
||||
visit(tree, 'heading', function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if (place) {
|
||||
const value = toString(node)
|
||||
const tail = value.charAt(value.length - 1)
|
||||
|
||||
if (expression.test(tail)) {
|
||||
file.message('Don’t add a trailing `' + tail + '` to headings', node)
|
||||
file.message('Don’t add a trailing `' + tail + '` to headings', place)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -37,9 +37,8 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -37,19 +37,25 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
|
||||
const remarkLintNoHtml = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-html',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-html#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'html', (node) => {
|
||||
if (!generated(node) && !/^\s*<!--/.test(node.value)) {
|
||||
file.message('Do not use HTML in markdown', node)
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'html', function (node) {
|
||||
const place = position(node)
|
||||
if (place && !/^\s*<!--/.test(node.value)) {
|
||||
file.message('Do not use HTML in markdown', place)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -35,9 +35,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -36,29 +36,33 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {toString} from 'mdast-util-to-string'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoInlinePadding = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-inline-padding',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-inline-padding#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
// Note: `emphasis`, `strong`, `delete` (GFM) can’t have padding anymore
|
||||
// since CM.
|
||||
visit(tree, (node) => {
|
||||
if (
|
||||
(node.type === 'link' || node.type === 'linkReference') &&
|
||||
!generated(node)
|
||||
) {
|
||||
visit(tree, function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if ((node.type === 'link' || node.type === 'linkReference') && place) {
|
||||
const value = toString(node)
|
||||
|
||||
if (value.charAt(0) === ' ' || value.charAt(value.length - 1) === ' ') {
|
||||
file.message('Don’t pad `' + node.type + '` with inner spaces', node)
|
||||
file.message('Don’t pad `' + node.type + '` with inner spaces', place)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -37,9 +37,8 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
@ -45,30 +45,37 @@
|
||||
* @typedef {import('mdast').Root} Root
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {toString} from 'mdast-util-to-string'
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoLiteralUrls = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-literal-urls',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-literal-urls#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
visit(tree, 'link', (node) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
visit(tree, 'link', function (node) {
|
||||
const value = toString(node)
|
||||
const start = pointStart(node)
|
||||
const end = pointEnd(node)
|
||||
const start = pointStart(node)
|
||||
const headStart = pointStart(node.children[0])
|
||||
const tailEnd = pointEnd(node.children[node.children.length - 1])
|
||||
|
||||
if (
|
||||
start &&
|
||||
end &&
|
||||
start.column === headStart?.column &&
|
||||
end.column === tailEnd?.column &&
|
||||
start &&
|
||||
headStart &&
|
||||
tailEnd &&
|
||||
end.column === tailEnd.column &&
|
||||
start.column === headStart.column &&
|
||||
(node.url === 'mailto:' + value || node.url === value)
|
||||
) {
|
||||
file.message('Don’t use literal URLs without angle brackets', node)
|
||||
|
@ -37,7 +37,6 @@
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
|
@ -82,15 +82,14 @@
|
||||
|
||||
/**
|
||||
* @typedef Options
|
||||
* Options.
|
||||
* Configuration.
|
||||
* @property {boolean | null | undefined} [exceptTightLists=false]
|
||||
* Allow tight list items.
|
||||
* Allow tight list items (default: `false`).
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
|
||||
const types = new Set([
|
||||
'paragraph',
|
||||
@ -109,18 +108,24 @@ const remarkLintNoMissingBlankLines = lintRule(
|
||||
origin: 'remark-lint:no-missing-blank-lines',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-missing-blank-lines#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = {}) => {
|
||||
const {exceptTightLists} = option
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options]
|
||||
* Configuration (optional).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const exceptTightLists = options ? options.exceptTightLists : false
|
||||
|
||||
visit(tree, (node, index, parent) => {
|
||||
visit(tree, function (node, index, parent) {
|
||||
const end = pointEnd(node)
|
||||
|
||||
if (
|
||||
end &&
|
||||
parent &&
|
||||
typeof index === 'number' &&
|
||||
!generated(node) &&
|
||||
end &&
|
||||
(!exceptTightLists || parent.type !== 'listItem')
|
||||
) {
|
||||
const next = parent.children[index + 1]
|
||||
|
@ -36,9 +36,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
|
@ -49,34 +49,44 @@
|
||||
|
||||
/**
|
||||
* @typedef {Heading['depth']} Options
|
||||
* Options.
|
||||
* Configuration.
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit} from 'unist-util-visit'
|
||||
import {pointStart} from 'unist-util-position'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {pointStart, position} from 'unist-util-position'
|
||||
import {stringifyPosition} from 'unist-util-stringify-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoMultipleToplevelHeadings = lintRule(
|
||||
{
|
||||
origin: 'remark-lint:no-multiple-toplevel-headings',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-multiple-toplevel-headings#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, Options>} */
|
||||
(tree, file, option = 1) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @param {Options | null | undefined} [options=1]
|
||||
* Configuration (default: `1`).
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file, options) {
|
||||
const option = options || 1
|
||||
/** @type {string | undefined} */
|
||||
let duplicate
|
||||
|
||||
visit(tree, 'heading', (node) => {
|
||||
if (!generated(node) && node.depth === option) {
|
||||
visit(tree, 'heading', function (node) {
|
||||
const start = pointStart(node)
|
||||
const place = position(node)
|
||||
|
||||
if (start && place && node.depth === option) {
|
||||
if (duplicate) {
|
||||
file.message(
|
||||
'Don’t use multiple top level headings (' + duplicate + ')',
|
||||
node
|
||||
place
|
||||
)
|
||||
} else {
|
||||
duplicate = stringifyPosition(pointStart(node))
|
||||
duplicate = stringifyPosition(start)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -36,9 +36,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-stringify-position": "^4.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
@ -53,7 +51,8 @@
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"capitalized-comments": "off"
|
||||
"capitalized-comments": "off",
|
||||
"unicorn/prefer-default-parameters": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +92,8 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {visit, SKIP} from 'unist-util-visit'
|
||||
import {pointStart, pointEnd} from 'unist-util-position'
|
||||
import {pointEnd, pointStart} from 'unist-util-position'
|
||||
import {SKIP, visit} from 'unist-util-visit'
|
||||
import {location} from 'vfile-location'
|
||||
|
||||
const remarkLintNoParagraphContentIndent = lintRule(
|
||||
@ -101,12 +101,17 @@ const remarkLintNoParagraphContentIndent = lintRule(
|
||||
origin: 'remark-lint:no-paragraph-content-indent',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-paragraph-content-indent#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
const value = String(file)
|
||||
const loc = location(value)
|
||||
|
||||
visit(tree, 'paragraph', (node, _, parent) => {
|
||||
visit(tree, 'paragraph', function (node, _, parent) {
|
||||
const end = pointEnd(node)?.line
|
||||
let line = pointStart(node)?.line
|
||||
/** @type {number | undefined} */
|
||||
|
@ -37,7 +37,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
|
@ -47,7 +47,7 @@
|
||||
*/
|
||||
|
||||
import {lintRule} from 'unified-lint-rule'
|
||||
import {generated} from 'unist-util-generated'
|
||||
import {position} from 'unist-util-position'
|
||||
import {visit} from 'unist-util-visit'
|
||||
|
||||
const remarkLintNoReferenceLikeUrl = lintRule(
|
||||
@ -55,21 +55,27 @@ const remarkLintNoReferenceLikeUrl = lintRule(
|
||||
origin: 'remark-lint:no-reference-like-url',
|
||||
url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-reference-like-url#readme'
|
||||
},
|
||||
/** @type {import('unified-lint-rule').Rule<Root, void>} */
|
||||
(tree, file) => {
|
||||
/** @type {Array<string>} */
|
||||
const identifiers = []
|
||||
/**
|
||||
* @param {Root} tree
|
||||
* Tree.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function (tree, file) {
|
||||
/** @type {Set<string>} */
|
||||
const identifiers = new Set()
|
||||
|
||||
visit(tree, 'definition', (node) => {
|
||||
if (!generated(node)) {
|
||||
identifiers.push(node.identifier.toLowerCase())
|
||||
}
|
||||
visit(tree, 'definition', function (node) {
|
||||
identifiers.add(node.identifier.toLowerCase())
|
||||
})
|
||||
|
||||
visit(tree, (node) => {
|
||||
visit(tree, function (node) {
|
||||
const place = position(node)
|
||||
|
||||
if (
|
||||
place &&
|
||||
(node.type === 'image' || node.type === 'link') &&
|
||||
identifiers.includes(node.url.toLowerCase())
|
||||
identifiers.has(node.url.toLowerCase())
|
||||
) {
|
||||
file.message(
|
||||
'Did you mean to use `[' +
|
||||
@ -78,7 +84,7 @@ const remarkLintNoReferenceLikeUrl = lintRule(
|
||||
'`(' +
|
||||
node.url +
|
||||
')`, a reference?',
|
||||
node
|
||||
place
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -37,9 +37,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unified-lint-rule": "^2.0.0",
|
||||
"unist-util-generated": "^3.0.0",
|
||||
"unist-util-position": "^5.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"scripts": {},
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user