mirror of
https://github.com/remarkjs/remark-lint.git
synced 2024-10-05 23:57:47 +03:00
file-extension: add option to disallow extensionless
This commit is contained in:
parent
655ba54202
commit
18e669f77a
@ -15,18 +15,37 @@
|
|||||||
*
|
*
|
||||||
* Warn for unexpected extensions.
|
* Warn for unexpected extensions.
|
||||||
*
|
*
|
||||||
* > 👉 **Note**: does not warn when files have no file extensions (such as
|
|
||||||
* > `AUTHORS` or `LICENSE`).
|
|
||||||
*
|
|
||||||
* ###### Parameters
|
* ###### Parameters
|
||||||
*
|
*
|
||||||
* * `options` (`Array<string>` or `string`, default: `['mdx', 'md']`)
|
* * `options` ([`Extensions`][api-extensions] or [`Options`][api-options],
|
||||||
* — allowed file extension(s)
|
* optional)
|
||||||
|
* — configuration
|
||||||
*
|
*
|
||||||
* ###### Returns
|
* ###### Returns
|
||||||
*
|
*
|
||||||
* Transform ([`Transformer` from `unified`][github-unified-transformer]).
|
* Transform ([`Transformer` from `unified`][github-unified-transformer]).
|
||||||
*
|
*
|
||||||
|
* ### `Extensions`
|
||||||
|
*
|
||||||
|
* File extension(s) (TypeScript type).
|
||||||
|
*
|
||||||
|
* ###### Type
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* type Extensions = Array<string> | string
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ### `Options`
|
||||||
|
*
|
||||||
|
* Configuration (TypeScript type).
|
||||||
|
*
|
||||||
|
* ###### Fields
|
||||||
|
*
|
||||||
|
* * `allowExtensionless` (`boolean`, default: `true`)
|
||||||
|
* — allow no file extension such as `AUTHORS` or `LICENSE`
|
||||||
|
* * `extensions` ([`Extensions`][api-extensions], default: `['mdx', 'md']`)
|
||||||
|
* — allowed file extension(s)
|
||||||
|
*
|
||||||
* ## Recommendation
|
* ## Recommendation
|
||||||
*
|
*
|
||||||
* Use `md` as it’s the most common.
|
* Use `md` as it’s the most common.
|
||||||
@ -34,6 +53,8 @@
|
|||||||
* GFM, frontmatter, or math).
|
* GFM, frontmatter, or math).
|
||||||
* Do not use `md` for MDX: use `mdx` instead.
|
* Do not use `md` for MDX: use `mdx` instead.
|
||||||
*
|
*
|
||||||
|
* [api-extensions]: #extensions
|
||||||
|
* [api-options]: #options
|
||||||
* [api-remark-lint-file-extension]: #unifieduseremarklintfileextension-options
|
* [api-remark-lint-file-extension]: #unifieduseremarklintfileextension-options
|
||||||
* [github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
|
* [github-unified-transformer]: https://github.com/unifiedjs/unified#transformer
|
||||||
*
|
*
|
||||||
@ -45,21 +66,44 @@
|
|||||||
* {"name": "readme.md"}
|
* {"name": "readme.md"}
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
|
* {"name": "readme.mdx"}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
* {"name": "readme"}
|
* {"name": "readme"}
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* {"name": "readme.mkd", "label": "output", "positionless": true}
|
* {"config": {"allowExtensionless": false}, "label": "output", "name": "readme", "positionless": true}
|
||||||
*
|
*
|
||||||
* 1:1: Incorrect extension: use `mdx` or `md`
|
* 1:1: Incorrect extension: use `mdx` or `md`
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* {"name": "readme.mkd", "config": "mkd"}
|
* {"label": "output", "name": "readme.mkd", "positionless": true}
|
||||||
|
*
|
||||||
|
* 1:1: Incorrect extension: use `mdx` or `md`
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* {"config": "mkd", "name": "readme.mkd"}
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* {"config": ["mkd"], "name": "readme.mkd"}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('mdast').Root} Root
|
* @typedef {import('mdast').Root} Root
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {ReadonlyArray<string> | string} Extensions
|
||||||
|
* File extension(s).
|
||||||
|
*
|
||||||
|
* @typedef Options
|
||||||
|
* Configuration.
|
||||||
|
* @property {boolean | null | undefined} [allowExtensionless=true]
|
||||||
|
* Allow no file extension such as `AUTHORS` or `LICENSE` (default: `true`).
|
||||||
|
* @property {Extensions | null | undefined} [extensions=['mdx', 'md']]
|
||||||
|
* Allowed file extension(s) (default: `['mdx', 'md']`).
|
||||||
|
*/
|
||||||
|
|
||||||
import {lintRule} from 'unified-lint-rule'
|
import {lintRule} from 'unified-lint-rule'
|
||||||
import {quotation} from 'quotation'
|
import {quotation} from 'quotation'
|
||||||
|
|
||||||
@ -76,18 +120,42 @@ const remarkLintFileExtension = lintRule(
|
|||||||
/**
|
/**
|
||||||
* @param {Root} _
|
* @param {Root} _
|
||||||
* Tree.
|
* Tree.
|
||||||
* @param {ReadonlyArray<string> | string | null | undefined} [options='md']
|
* @param {Readonly<Extensions> | Readonly<Options> | null | undefined} [options]
|
||||||
* Configuration (default: `'md'`).
|
* Configuration (optional).
|
||||||
* @returns {undefined}
|
* @returns {undefined}
|
||||||
* Nothing.
|
* Nothing.
|
||||||
*/
|
*/
|
||||||
function (_, file, options) {
|
function (_, file, options) {
|
||||||
const extensions =
|
let extensions = defaultExtensions
|
||||||
typeof options === 'string' ? [options] : options || defaultExtensions
|
let allowExtensionless = true
|
||||||
|
/** @type {Readonly<Extensions> | null | undefined} */
|
||||||
|
let extensionsValue
|
||||||
|
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
// TS fails on `isArray` w/ readonly.
|
||||||
|
extensionsValue = /** @type {ReadonlyArray<string>} */ (options)
|
||||||
|
} else if (typeof options === 'string') {
|
||||||
|
extensionsValue = options
|
||||||
|
} else if (options) {
|
||||||
|
// TS fails on `isArray` w/ readonly.
|
||||||
|
const settings = /** @type {Options} */ (options)
|
||||||
|
extensionsValue = settings.extensions
|
||||||
|
|
||||||
|
if (settings.allowExtensionless === false) {
|
||||||
|
allowExtensionless = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(extensionsValue)) {
|
||||||
|
extensions = /** @type {ReadonlyArray<string>} */ (extensionsValue)
|
||||||
|
} else if (typeof extensionsValue === 'string') {
|
||||||
|
extensions = [extensionsValue]
|
||||||
|
}
|
||||||
|
|
||||||
const extname = file.extname
|
const extname = file.extname
|
||||||
const extension = extname ? extname.slice(1) : undefined
|
const extension = extname ? extname.slice(1) : undefined
|
||||||
|
|
||||||
if (extension && !extensions.includes(extension)) {
|
if (extension ? !extensions.includes(extension) : !allowExtensionless) {
|
||||||
file.message(
|
file.message(
|
||||||
'Incorrect extension: use ' +
|
'Incorrect extension: use ' +
|
||||||
listFormat.format(quotation(extensions, '`'))
|
listFormat.format(quotation(extensions, '`'))
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
* [Use](#use)
|
* [Use](#use)
|
||||||
* [API](#api)
|
* [API](#api)
|
||||||
* [`unified().use(remarkLintFileExtension[, options])`](#unifieduseremarklintfileextension-options)
|
* [`unified().use(remarkLintFileExtension[, options])`](#unifieduseremarklintfileextension-options)
|
||||||
|
* [`Extensions`](#extensions)
|
||||||
|
* [`Options`](#options)
|
||||||
* [Recommendation](#recommendation)
|
* [Recommendation](#recommendation)
|
||||||
* [Examples](#examples)
|
* [Examples](#examples)
|
||||||
* [Compatibility](#compatibility)
|
* [Compatibility](#compatibility)
|
||||||
@ -116,7 +118,9 @@ On the CLI in a config file (here a `package.json`):
|
|||||||
## API
|
## API
|
||||||
|
|
||||||
This package exports no identifiers.
|
This package exports no identifiers.
|
||||||
It exports no additional [TypeScript][typescript] types.
|
It exports the [TypeScript][typescript] types
|
||||||
|
[`Extensions`][api-extensions] and
|
||||||
|
[`Options`][api-options].
|
||||||
The default export is
|
The default export is
|
||||||
[`remarkLintFileExtension`][api-remark-lint-file-extension].
|
[`remarkLintFileExtension`][api-remark-lint-file-extension].
|
||||||
|
|
||||||
@ -124,18 +128,37 @@ The default export is
|
|||||||
|
|
||||||
Warn for unexpected extensions.
|
Warn for unexpected extensions.
|
||||||
|
|
||||||
> 👉 **Note**: does not warn when files have no file extensions (such as
|
|
||||||
> `AUTHORS` or `LICENSE`).
|
|
||||||
|
|
||||||
###### Parameters
|
###### Parameters
|
||||||
|
|
||||||
* `options` (`Array<string>` or `string`, default: `['mdx', 'md']`)
|
* `options` ([`Extensions`][api-extensions] or [`Options`][api-options],
|
||||||
— allowed file extension(s)
|
optional)
|
||||||
|
— configuration
|
||||||
|
|
||||||
###### Returns
|
###### Returns
|
||||||
|
|
||||||
Transform ([`Transformer` from `unified`][github-unified-transformer]).
|
Transform ([`Transformer` from `unified`][github-unified-transformer]).
|
||||||
|
|
||||||
|
### `Extensions`
|
||||||
|
|
||||||
|
File extension(s) (TypeScript type).
|
||||||
|
|
||||||
|
###### Type
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type Extensions = Array<string> | string
|
||||||
|
```
|
||||||
|
|
||||||
|
### `Options`
|
||||||
|
|
||||||
|
Configuration (TypeScript type).
|
||||||
|
|
||||||
|
###### Fields
|
||||||
|
|
||||||
|
* `allowExtensionless` (`boolean`, default: `true`)
|
||||||
|
— allow no file extension such as `AUTHORS` or `LICENSE`
|
||||||
|
* `extensions` ([`Extensions`][api-extensions], default: `['mdx', 'md']`)
|
||||||
|
— allowed file extension(s)
|
||||||
|
|
||||||
## Recommendation
|
## Recommendation
|
||||||
|
|
||||||
Use `md` as it’s the most common.
|
Use `md` as it’s the most common.
|
||||||
@ -151,12 +174,28 @@ Do not use `md` for MDX: use `mdx` instead.
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
|
##### `readme.mdx`
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
##### `readme`
|
##### `readme`
|
||||||
|
|
||||||
###### Out
|
###### Out
|
||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
|
##### `readme`
|
||||||
|
|
||||||
|
When configured with `{ allowExtensionless: false }`.
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
```text
|
||||||
|
1:1: Incorrect extension: use `mdx` or `md`
|
||||||
|
```
|
||||||
|
|
||||||
##### `readme.mkd`
|
##### `readme.mkd`
|
||||||
|
|
||||||
###### Out
|
###### Out
|
||||||
@ -173,6 +212,14 @@ When configured with `'mkd'`.
|
|||||||
|
|
||||||
No messages.
|
No messages.
|
||||||
|
|
||||||
|
##### `readme.mkd`
|
||||||
|
|
||||||
|
When configured with `[ 'mkd' ]`.
|
||||||
|
|
||||||
|
###### Out
|
||||||
|
|
||||||
|
No messages.
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
Projects maintained by the unified collective are compatible with maintained
|
Projects maintained by the unified collective are compatible with maintained
|
||||||
@ -198,6 +245,10 @@ abide by its terms.
|
|||||||
|
|
||||||
[MIT][file-license] © [Titus Wormer][author]
|
[MIT][file-license] © [Titus Wormer][author]
|
||||||
|
|
||||||
|
[api-extensions]: #extensions
|
||||||
|
|
||||||
|
[api-options]: #options
|
||||||
|
|
||||||
[api-remark-lint-file-extension]: #unifieduseremarklintfileextension-options
|
[api-remark-lint-file-extension]: #unifieduseremarklintfileextension-options
|
||||||
|
|
||||||
[author]: https://wooorm.com
|
[author]: https://wooorm.com
|
||||||
|
Loading…
Reference in New Issue
Block a user