Mark no-auto-link-without-protocol as deprecated

* Add internal support for deprecated packages in tooling
* Remove `remark-lint-no-auto-link-without-protocol` from presets
* Add info to `remark-lint-no-auto-link-without-protocol` on why it’s deprecated

Related to remarkjs/remark#863.
This commit is contained in:
Titus Wormer 2021-10-08 13:09:59 +02:00
parent 1c176e470c
commit c5c3832ef9
No known key found for this signature in database
GPG Key ID: E6E581152ED04E2E
13 changed files with 338 additions and 436 deletions

View File

@ -107,7 +107,6 @@ Rules][external].
* [`list-item-spacing`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-spacing) — warn when list looseness is incorrect
* [`maximum-heading-length`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-maximum-heading-length) — warn when headings are too long
* [`maximum-line-length`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-maximum-line-length) — warn when lines are too long
* [`no-auto-link-without-protocol`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-auto-link-without-protocol) — warn for angle bracketed links without protocol
* [`no-blockquote-without-marker`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker) — warn when blank lines without markers (\`>\`) are found in a block quote
* [`no-consecutive-blank-lines`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-consecutive-blank-lines) — warn for too many consecutive blank lines
* [`no-duplicate-defined-urls`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-defined-urls) — warn on definitions that define the same urls

View File

@ -3,18 +3,12 @@
* @copyright 2015 Titus Wormer
* @license MIT
* @module no-auto-link-without-protocol
* @fileoverview
* Warn for autolinks without protocol.
* Autolinks are URLs enclosed in `<` (less than) and `>` (greater than)
* characters.
*
* ## Fix
*
* [`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify)
* adds a protocol where needed.
*
* See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown)
* on how to automatically fix warnings for this rule.
* @deprecated
* This rule is no longer recommended for use.
* With CommonMark, all autolinks (except for emails) are required to have a
* protocol.
* Otherwise they dont parse.
* The previous suggestion to add a protocol to email autolinks was wrong.
*
* @example
* {"name": "ok.md"}

View File

@ -1,7 +1,7 @@
{
"name": "remark-lint-no-auto-link-without-protocol",
"version": "3.1.0",
"description": "remark-lint rule to warn for angle bracketed links without protocol",
"description": "Deprecated",
"license": "MIT",
"keywords": [
"remark",

View File

@ -10,112 +10,11 @@
[![Backers][backers-badge]][collective]
[![Chat][chat-badge]][chat]
Warn for autolinks without protocol.
Autolinks are URLs enclosed in `<` (less than) and `>` (greater than)
characters.
## Fix
[`remark-stringify`](https://github.com/remarkjs/remark/tree/HEAD/packages/remark-stringify)
adds a protocol where needed.
See [Using remark to fix your Markdown](https://github.com/remarkjs/remark-lint#using-remark-to-fix-your-markdown)
on how to automatically fix warnings for this rule.
## Presets
This rule is included in the following presets:
| Preset | Setting |
| - | - |
| [`remark-preset-lint-markdown-style-guide`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-preset-lint-markdown-style-guide) | |
| [`remark-preset-lint-recommended`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-preset-lint-recommended) | |
## Example
##### `ok.md`
###### In
```markdown
<http://www.example.com>
<mailto:foo@bar.com>
Most Markdown vendors dont recognize the following as a link:
<www.example.com>
```
###### Out
No messages.
##### `not-ok.md`
###### In
```markdown
<foo@bar.com>
```
###### Out
```text
1:1-1:14: All automatic links must start with a protocol
```
## Install
This package is [ESM only][esm]:
Node 12+ is needed to use it and it must be `imported`ed instead of `required`d.
[npm][]:
```sh
npm install remark-lint-no-auto-link-without-protocol
```
This package exports no identifiers.
The default export is `remarkLintNoAutoLinkWithoutProtocol`.
## Use
You probably want to use it on the CLI through a config file:
```diff
"remarkConfig": {
"plugins": [
"lint",
+ "lint-no-auto-link-without-protocol",
]
}
```
Or use it on the CLI directly
```sh
remark -u lint -u lint-no-auto-link-without-protocol readme.md
```
Or use this on the API:
```diff
import {remark} from 'remark'
import {reporter} from 'vfile-reporter'
import remarkLint from 'remark-lint'
import remarkLintNoAutoLinkWithoutProtocol from 'remark-lint-no-auto-link-without-protocol'
remark()
.use(remarkLint)
+ .use(remarkLintNoAutoLinkWithoutProtocol)
.process('_Emphasis_ and **importance**')
.then((file) => {
console.error(reporter(file))
})
```
This rule is no longer recommended for use.
With CommonMark, all autolinks (except for emails) are required to have a
protocol.
Otherwise they dont parse.
The previous suggestion to add a protocol to email autolinks was wrong.
## Contribute
@ -157,10 +56,6 @@ abide by its terms.
[chat]: https://github.com/remarkjs/remark/discussions
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[npm]: https://docs.npmjs.com/cli/install
[health]: https://github.com/remarkjs/.github
[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md

View File

@ -144,7 +144,6 @@ import remarkLintStrongMarker from 'remark-lint-strong-marker'
import remarkLintEmphasisMarker from 'remark-lint-emphasis-marker'
import remarkLintNoEmphasisAsHeading from 'remark-lint-no-emphasis-as-heading'
import remarkLintNoLiteralUrls from 'remark-lint-no-literal-urls'
import remarkLintNoAutoLinkWithoutProtocol from 'remark-lint-no-auto-link-without-protocol'
/** @type {Preset} */
const remarkPresetLintMarkdownStyleGuide = {
@ -281,10 +280,7 @@ const remarkPresetLintMarkdownStyleGuide = {
remarkLintNoEmphasisAsHeading,
// http://www.cirosantilli.com/markdown-style-guide/#automatic-links-without-angle-brackets
remarkLintNoLiteralUrls,
// http://www.cirosantilli.com/markdown-style-guide/#content-of-automatic-links
remarkLintNoAutoLinkWithoutProtocol
remarkLintNoLiteralUrls
// http://www.cirosantilli.com/markdown-style-guide/#email-automatic-links.
// Not checked.

View File

@ -54,7 +54,6 @@
"remark-lint-list-item-spacing": "^4.0.0",
"remark-lint-maximum-heading-length": "^3.0.0",
"remark-lint-maximum-line-length": "^3.0.0",
"remark-lint-no-auto-link-without-protocol": "^3.0.0",
"remark-lint-no-blockquote-without-marker": "^5.0.0",
"remark-lint-no-consecutive-blank-lines": "^4.0.0",
"remark-lint-no-duplicate-headings": "^3.0.0",

View File

@ -154,7 +154,6 @@ This preset configures [`remark-lint`](https://github.com/remarkjs/remark-lint)
| [`remark-lint-emphasis-marker`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-emphasis-marker) | `'*'` |
| [`remark-lint-no-emphasis-as-heading`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-emphasis-as-heading) | |
| [`remark-lint-no-literal-urls`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-literal-urls) | |
| [`remark-lint-no-auto-link-without-protocol`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-auto-link-without-protocol) | |
## Install

View File

@ -12,7 +12,6 @@ import remarkLint from 'remark-lint'
import remarkLintFinalNewline from 'remark-lint-final-newline'
import remarkLintListItemBulletIndent from 'remark-lint-list-item-bullet-indent'
import remarkLintListItemIndent from 'remark-lint-list-item-indent'
import remarkLintNoAutoLinkWithoutProtocol from 'remark-lint-no-auto-link-without-protocol'
import remarkLintNoBlockquoteWithoutMarker from 'remark-lint-no-blockquote-without-marker'
import remarkLintNoLiteralUrls from 'remark-lint-no-literal-urls'
import remarkLintOrderedListMarkerStyle from 'remark-lint-ordered-list-marker-style'
@ -34,8 +33,6 @@ const remarkPresetLintRecommended = {
// Rendering across vendors differs greatly if using other styles.
remarkLintListItemBulletIndent,
[remarkLintListItemIndent, 'tab-size'],
// Differs or unsupported across vendors.
remarkLintNoAutoLinkWithoutProtocol,
remarkLintNoBlockquoteWithoutMarker,
remarkLintNoLiteralUrls,
[remarkLintOrderedListMarkerStyle, '.'],

View File

@ -38,7 +38,6 @@
"remark-lint-hard-break-spaces": "^3.0.0",
"remark-lint-list-item-bullet-indent": "^4.0.0",
"remark-lint-list-item-indent": "^3.0.0",
"remark-lint-no-auto-link-without-protocol": "^3.0.0",
"remark-lint-no-blockquote-without-marker": "^5.0.0",
"remark-lint-no-duplicate-definitions": "^3.0.0",
"remark-lint-no-heading-content-indent": "^4.0.0",

View File

@ -22,7 +22,6 @@ This preset configures [`remark-lint`](https://github.com/remarkjs/remark-lint)
| [`remark-lint-final-newline`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-final-newline) | |
| [`remark-lint-list-item-bullet-indent`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent) | |
| [`remark-lint-list-item-indent`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-indent) | `'tab-size'` |
| [`remark-lint-no-auto-link-without-protocol`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-auto-link-without-protocol) | |
| [`remark-lint-no-blockquote-without-marker`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker) | |
| [`remark-lint-no-literal-urls`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-literal-urls) | |
| [`remark-lint-ordered-list-marker-style`](https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-ordered-list-marker-style) | `'.'` |

View File

@ -179,321 +179,327 @@ presets(root).then((presetObjects) => {
}
]
},
...descriptionContent,
{
...descriptionContent
]
if (!info.deprecated) {
children.push({
type: 'heading',
depth: 2,
children: [{type: 'text', value: 'Presets'}]
}
]
if (includes.length === 0) {
children.push({
type: 'paragraph',
children: [
{
type: 'text',
value: 'This rule is not included in any default preset'
}
]
})
} else {
children.push(
{
if (includes.length === 0) {
children.push({
type: 'paragraph',
children: [
{
type: 'text',
value: 'This rule is included in the following presets:'
value: 'This rule is not included in any default preset'
}
]
},
{
type: 'table',
align: [],
children: [
{
type: 'tableRow',
children: [
{
type: 'tableCell',
children: [{type: 'text', value: 'Preset'}]
},
{
type: 'tableCell',
children: [{type: 'text', value: 'Setting'}]
}
]
},
...includes.map((preset) => {
const option = preset.packages[basename]
/** @type {TableContent} */
const row = {
})
} else {
children.push(
{
type: 'paragraph',
children: [
{
type: 'text',
value: 'This rule is included in the following presets:'
}
]
},
{
type: 'table',
align: [],
children: [
{
type: 'tableRow',
children: [
{
type: 'tableCell',
children: [
{
type: 'link',
url: remote + '/tree/main/packages/' + preset.name,
title: null,
children: [{type: 'inlineCode', value: preset.name}]
}
]
children: [{type: 'text', value: 'Preset'}]
},
{
type: 'tableCell',
children: option
? [{type: 'inlineCode', value: inspect(option)}]
: []
children: [{type: 'text', value: 'Setting'}]
}
]
}
},
...includes.map((preset) => {
const option = preset.packages[basename]
return row
})
]
}
)
}
/** @type {TableContent} */
const row = {
type: 'tableRow',
children: [
{
type: 'tableCell',
children: [
{
type: 'link',
url: remote + '/tree/main/packages/' + preset.name,
title: null,
children: [{type: 'inlineCode', value: preset.name}]
}
]
},
{
type: 'tableCell',
children: option
? [{type: 'inlineCode', value: inspect(option)}]
: []
}
]
}
let first = true
/** @type {string} */
let setting
return row
})
]
}
)
}
for (setting in tests) {
if (own.call(tests, setting)) {
const fixtures = tests[setting]
let first = true
/** @type {string} */
let setting
if (first) {
children.push({
type: 'heading',
depth: 2,
children: [{type: 'text', value: 'Example'}]
})
first = false
}
/** @type {string} */
let fileName
for (fileName in fixtures) {
if (own.call(fixtures, fileName)) {
const fixture = fixtures[fileName]
const label = inspect(JSON.parse(setting))
let clean = fixture.input
for (setting in tests) {
if (own.call(tests, setting)) {
const fixtures = tests[setting]
if (first) {
children.push({
type: 'heading',
depth: 5,
children: [{type: 'inlineCode', value: fileName}]
depth: 2,
children: [{type: 'text', value: 'Example'}]
})
first = false
}
if (label !== 'true') {
children.push({
type: 'paragraph',
children: [
{type: 'text', value: 'When configured with '},
{type: 'inlineCode', value: label},
{type: 'text', value: '.'}
]
})
}
/** @type {string} */
let fileName
for (fileName in fixtures) {
if (own.call(fixtures, fileName)) {
const fixture = fixtures[fileName]
const label = inspect(JSON.parse(setting))
let clean = fixture.input
if (
fixture.input !== null &&
fixture.input !== undefined &&
fixture.input.trim() !== ''
) {
children.push({
type: 'heading',
depth: 6,
children: [{type: 'text', value: 'In'}]
depth: 5,
children: [{type: 'inlineCode', value: fileName}]
})
if (fixture.gfm) {
hasGfm = true
if (label !== 'true') {
children.push({
type: 'paragraph',
children: [
{type: 'text', value: 'Note: this example uses '},
{
type: 'linkReference',
label: 'GFM',
identifier: 'gfm',
referenceType: 'collapsed',
children: [{type: 'text', value: 'GFM'}]
},
{type: 'text', value: 'When configured with '},
{type: 'inlineCode', value: label},
{type: 'text', value: '.'}
]
})
}
let index = -1
while (++index < characters.length) {
const char = characters[index]
const next = clean.replace(char.in, char.out)
if (
fixture.input !== null &&
fixture.input !== undefined &&
fixture.input.trim() !== ''
) {
children.push({
type: 'heading',
depth: 6,
children: [{type: 'text', value: 'In'}]
})
if (clean !== next) {
if (fixture.gfm) {
hasGfm = true
children.push({
type: 'paragraph',
children: [
{type: 'text', value: 'Note: '},
{type: 'inlineCode', value: char.char},
{type: 'text', value: ' represents ' + char.name + '.'}
{type: 'text', value: 'Note: this example uses '},
{
type: 'linkReference',
label: 'GFM',
identifier: 'gfm',
referenceType: 'collapsed',
children: [{type: 'text', value: 'GFM'}]
},
{type: 'text', value: '.'}
]
})
clean = next
}
let index = -1
while (++index < characters.length) {
const char = characters[index]
const next = clean.replace(char.in, char.out)
if (clean !== next) {
children.push({
type: 'paragraph',
children: [
{type: 'text', value: 'Note: '},
{type: 'inlineCode', value: char.char},
{type: 'text', value: ' represents ' + char.name + '.'}
]
})
clean = next
}
}
children.push({
type: 'code',
lang: 'markdown',
value: fixture.input
})
}
children.push({
type: 'code',
lang: 'markdown',
value: fixture.input
type: 'heading',
depth: 6,
children: [{type: 'text', value: 'Out'}]
})
}
children.push({
type: 'heading',
depth: 6,
children: [{type: 'text', value: 'Out'}]
})
if (fixture.output.length === 0) {
children.push({
type: 'paragraph',
children: [{type: 'text', value: 'No messages.'}]
})
} else {
children.push({
type: 'code',
lang: 'text',
value: fixture.output.join('\n')
})
if (fixture.output.length === 0) {
children.push({
type: 'paragraph',
children: [{type: 'text', value: 'No messages.'}]
})
} else {
children.push({
type: 'code',
lang: 'text',
value: fixture.output.join('\n')
})
}
}
}
}
}
children.push(
{
type: 'heading',
depth: 2,
children: [{type: 'text', value: 'Install'}]
},
{
type: 'paragraph',
children: [
{type: 'text', value: 'This package is '},
{
type: 'linkReference',
identifier: 'esm',
referenceType: 'full',
children: [{type: 'text', value: 'ESM only'}]
},
{
type: 'text',
value: ':\nNode 12+ is needed to use it and it must be '
},
{type: 'inlineCode', value: 'imported'},
{type: 'text', value: 'ed instead of '},
{type: 'inlineCode', value: 'required'},
{type: 'text', value: 'd.'}
]
},
{
type: 'paragraph',
children: [
{
type: 'linkReference',
identifier: 'npm',
referenceType: 'collapsed',
children: [{type: 'text', value: 'npm'}]
},
{type: 'text', value: ':'}
]
},
{type: 'code', lang: 'sh', value: 'npm install ' + basename},
{
type: 'paragraph',
children: [
{
type: 'text',
value:
'This package exports no identifiers.\nThe default export is '
},
{
type: 'inlineCode',
value: basename.replace(/-(\w)/g, (_, /** @type {string} */ $1) =>
$1.toUpperCase()
)
},
{type: 'text', value: '.'}
]
},
{type: 'heading', depth: 2, children: [{type: 'text', value: 'Use'}]},
{
type: 'paragraph',
children: [
{
type: 'text',
value:
'You probably want to use it on the CLI through a config file:'
}
]
},
{
type: 'code',
lang: 'diff',
value: [
' …',
' "remarkConfig": {',
' "plugins": [',
' …',
' "lint",',
'+ "' + short + '",',
' …',
' ]',
' }',
' …'
].join('\n')
},
{
type: 'paragraph',
children: [{type: 'text', value: 'Or use it on the CLI directly'}]
},
{
type: 'code',
lang: 'sh',
value: 'remark -u lint -u ' + short + ' readme.md'
},
{
type: 'paragraph',
children: [{type: 'text', value: 'Or use this on the API:'}]
},
{
type: 'code',
lang: 'diff',
value: [
" import {remark} from 'remark'",
" import {reporter} from 'vfile-reporter'",
" import remarkLint from 'remark-lint'",
' import ' + camelcased + " from '" + basename + "'",
'',
' remark()',
' .use(remarkLint)',
'+ .use(' + camelcased + ')',
" .process('_Emphasis_ and **importance**')",
' .then((file) => {',
' console.error(reporter(file))',
' })'
].join('\n')
}
)
}
children.push(
{
type: 'heading',
depth: 2,
children: [{type: 'text', value: 'Install'}]
},
{
type: 'paragraph',
children: [
{type: 'text', value: 'This package is '},
{
type: 'linkReference',
identifier: 'esm',
referenceType: 'full',
children: [{type: 'text', value: 'ESM only'}]
},
{
type: 'text',
value: ':\nNode 12+ is needed to use it and it must be '
},
{type: 'inlineCode', value: 'imported'},
{type: 'text', value: 'ed instead of '},
{type: 'inlineCode', value: 'required'},
{type: 'text', value: 'd.'}
]
},
{
type: 'paragraph',
children: [
{
type: 'linkReference',
identifier: 'npm',
referenceType: 'collapsed',
children: [{type: 'text', value: 'npm'}]
},
{type: 'text', value: ':'}
]
},
{type: 'code', lang: 'sh', value: 'npm install ' + basename},
{
type: 'paragraph',
children: [
{
type: 'text',
value:
'This package exports no identifiers.\nThe default export is '
},
{
type: 'inlineCode',
value: basename.replace(/-(\w)/g, (_, /** @type {string} */ $1) =>
$1.toUpperCase()
)
},
{type: 'text', value: '.'}
]
},
{type: 'heading', depth: 2, children: [{type: 'text', value: 'Use'}]},
{
type: 'paragraph',
children: [
{
type: 'text',
value:
'You probably want to use it on the CLI through a config file:'
}
]
},
{
type: 'code',
lang: 'diff',
value: [
' …',
' "remarkConfig": {',
' "plugins": [',
' …',
' "lint",',
'+ "' + short + '",',
' …',
' ]',
' }',
' …'
].join('\n')
},
{
type: 'paragraph',
children: [{type: 'text', value: 'Or use it on the CLI directly'}]
},
{
type: 'code',
lang: 'sh',
value: 'remark -u lint -u ' + short + ' readme.md'
},
{
type: 'paragraph',
children: [{type: 'text', value: 'Or use this on the API:'}]
},
{
type: 'code',
lang: 'diff',
value: [
" import {remark} from 'remark'",
" import {reporter} from 'vfile-reporter'",
" import remarkLint from 'remark-lint'",
' import ' + camelcased + " from '" + basename + "'",
'',
' remark()',
' .use(remarkLint)',
'+ .use(' + camelcased + ')',
" .process('_Emphasis_ and **importance**')",
' .then((file) => {',
' console.error(reporter(file))',
' })'
].join('\n')
},
{
type: 'heading',
depth: 2,
@ -630,17 +636,25 @@ presets(root).then((presetObjects) => {
type: 'definition',
identifier: 'chat',
url: 'https://github.com/remarkjs/remark/discussions'
},
{
type: 'definition',
identifier: 'esm',
url: 'https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c'
},
{
type: 'definition',
identifier: 'npm',
url: 'https://docs.npmjs.com/cli/install'
},
}
)
if (!info.deprecated) {
children.push(
{
type: 'definition',
identifier: 'esm',
url: 'https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c'
},
{
type: 'definition',
identifier: 'npm',
url: 'https://docs.npmjs.com/cli/install'
}
)
}
children.push(
{
type: 'definition',
identifier: 'health',

View File

@ -23,38 +23,43 @@ export default function listOfRules() {
type: 'list',
ordered: false,
spread: false,
children: rules(root).map((basename) => {
const name = basename.slice('remark-lint-'.length)
/** @type {PackageJson} */
const pack = JSON.parse(
String(fs.readFileSync(path.join(root, basename, 'package.json')))
)
const description = String(pack.description || '').replace(
/^remark-lint rule to ?/i,
''
)
children: rules(root)
.map((basename) => {
const name = basename.slice('remark-lint-'.length)
/** @type {PackageJson} */
const pack = JSON.parse(
String(fs.readFileSync(path.join(root, basename, 'package.json')))
)
const description = String(pack.description || '').replace(
/^remark-lint rule to ?/i,
''
)
const deprecated = /^deprecated/i.test(description)
/** @type {ListItem} */
const item = {
type: 'listItem',
spread: false,
children: [
{
type: 'paragraph',
children: [
{
type: 'link',
url: repoUrl(pack),
children: [{type: 'inlineCode', value: name}]
},
{type: 'text', value: ' — ' + description}
]
}
]
}
/** @type {ListItem} */
const item = {
type: 'listItem',
spread: false,
children: deprecated
? []
: [
{
type: 'paragraph',
children: [
{
type: 'link',
url: repoUrl(pack),
children: [{type: 'inlineCode', value: name}]
},
{type: 'text', value: ' — ' + description}
]
}
]
}
return item
})
return item
})
.filter((d) => d.children.length > 0)
}
return [start, list, end]

View File

@ -2,6 +2,7 @@
* @typedef Rule
* @property {string} ruleId
* @property {string} description
* @property {boolean} deprecated
* @property {Record<string, Checks>} tests
* @property {string} filePath
*
@ -26,6 +27,7 @@ import strip from 'strip-indent'
* @param {string} filePath
* @returns {Rule}
*/
/* eslint-disable-next-line complexity */
export function rule(filePath) {
const ruleId = path.basename(filePath).slice('remark-lint-'.length)
/** @type {Record<string, Checks>} */
@ -34,6 +36,7 @@ export function rule(filePath) {
const tags = parse(code, {spacing: 'preserve'})[0].tags
const moduleTag = tags.find((d) => d.tag === 'module')
const fileoverviewTag = tags.find((d) => d.tag === 'fileoverview')
const deprecatedTag = tags.find((d) => d.tag === 'deprecated')
/* c8 ignore next 3 */
if (!moduleTag) {
@ -41,12 +44,14 @@ export function rule(filePath) {
}
/* c8 ignore next 3 */
if (!fileoverviewTag) {
throw new Error('Expected `@fileoverview` in JSDoc')
if (!fileoverviewTag && !deprecatedTag) {
throw new Error('Expected `@fileoverview` (or `@deprecated`) in JSDoc')
}
const name = moduleTag.name
let description = fileoverviewTag.description
let description =
(fileoverviewTag && fileoverviewTag.description) ||
(deprecatedTag && deprecatedTag.description)
/* c8 ignore next 3 */
if (name !== ruleId) {
@ -55,7 +60,7 @@ export function rule(filePath) {
/* c8 ignore next 3 */
if (!description) {
throw new Error(ruleId + ' is missing a `@fileoverview`')
throw new Error(ruleId + ' is missing a `@fileoverview` or `@deprecated`')
}
description = strip(description)
@ -64,6 +69,7 @@ export function rule(filePath) {
const result = {
ruleId,
description: description.trim(),
deprecated: Boolean(deprecatedTag),
tests,
filePath
}