Initial import with skill sheet working

This commit is contained in:
2024-12-04 00:11:23 +01:00
commit 9050c80ab4
4488 changed files with 671048 additions and 0 deletions

24
node_modules/eslint-plugin-jsdoc/LICENSE generated vendored Normal file
View File

@ -0,0 +1,24 @@
Copyright (c) 2018, Gajus Kuizinas (http://gajus.com/)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

318
node_modules/eslint-plugin-jsdoc/README.md generated vendored Normal file
View File

@ -0,0 +1,318 @@
<a name="user-content-eslint-plugin-jsdoc"></a>
<a name="eslint-plugin-jsdoc"></a>
# eslint-plugin-jsdoc
[![NPM version](https://img.shields.io/npm/v/eslint-plugin-jsdoc.svg?style=flat-square)](https://www.npmjs.org/package/eslint-plugin-jsdoc)
[![Travis build status](https://img.shields.io/travis/gajus/eslint-plugin-jsdoc/master.svg?style=flat-square)](https://travis-ci.org/gajus/eslint-plugin-jsdoc)
[![js-canonical-style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)
[![Discord Chat](https://img.shields.io/badge/chat-on%20disord-green.svg?logo=discord)](https://discord.gg/kFFy3nc)
JSDoc linting rules for ESLint.
* [eslint-plugin-jsdoc](#user-content-eslint-plugin-jsdoc)
* [Installation](#user-content-eslint-plugin-jsdoc-installation)
* [Configuration](#user-content-eslint-plugin-jsdoc-configuration)
* [Flat config](#user-content-eslint-plugin-jsdoc-configuration-flat-config)
* [`eslintrc`](#user-content-eslint-plugin-jsdoc-configuration-eslintrc)
* [Options](#user-content-eslint-plugin-jsdoc-options)
* [Settings](#user-content-eslint-plugin-jsdoc-settings)
* [Advanced](#user-content-eslint-plugin-jsdoc-advanced)
* [Processors](#user-content-eslint-plugin-jsdoc-processors)
* [Rules](#user-content-eslint-plugin-jsdoc-rules)
<a name="user-content-eslint-plugin-jsdoc-installation"></a>
<a name="eslint-plugin-jsdoc-installation"></a>
## Installation
Install [ESLint](https://www.github.com/eslint/eslint) either locally or
globally.
```sh
npm install --save-dev eslint
```
If you have installed `ESLint` globally, you have to install JSDoc plugin
globally too. Otherwise, install it locally.
```sh
npm install --save-dev eslint-plugin-jsdoc
```
<a name="user-content-eslint-plugin-jsdoc-configuration"></a>
<a name="eslint-plugin-jsdoc-configuration"></a>
## Configuration
<a name="user-content-eslint-plugin-jsdoc-configuration-flat-config"></a>
<a name="eslint-plugin-jsdoc-configuration-flat-config"></a>
### Flat config
```js
import jsdoc from 'eslint-plugin-jsdoc';
const config = [
// configuration included in plugin
jsdoc.configs['flat/recommended'],
// other configuration objects...
{
files: ['**/*.js'],
plugins: {
jsdoc,
},
rules: {
'jsdoc/require-description': 'warn'
}
}
];
export default config;
```
<a name="user-content-eslint-plugin-jsdoc-configuration-eslintrc"></a>
<a name="eslint-plugin-jsdoc-configuration-eslintrc"></a>
### <code>eslintrc</code>
Add `plugins` section to [.eslintrc.*](https://eslint.org/docs/user-guide/configuring#configuration-file-formats)
and specify `eslint-plugin-jsdoc` as a plugin.
```json
{
"plugins": [
"jsdoc"
]
}
```
Finally, enable all of the rules that you would like to use.
```javascript
{
"rules": {
"jsdoc/check-access": 1, // Recommended
"jsdoc/check-alignment": 1, // Recommended
"jsdoc/check-examples": 1,
"jsdoc/check-indentation": 1,
"jsdoc/check-line-alignment": 1,
"jsdoc/check-param-names": 1, // Recommended
"jsdoc/check-template-names": 1,
"jsdoc/check-property-names": 1, // Recommended
"jsdoc/check-syntax": 1,
"jsdoc/check-tag-names": 1, // Recommended
"jsdoc/check-types": 1, // Recommended
"jsdoc/check-values": 1, // Recommended
"jsdoc/empty-tags": 1, // Recommended
"jsdoc/implements-on-classes": 1, // Recommended
"jsdoc/informative-docs": 1,
"jsdoc/match-description": 1,
"jsdoc/multiline-blocks": 1, // Recommended
"jsdoc/no-bad-blocks": 1,
"jsdoc/no-blank-block-descriptions": 1,
"jsdoc/no-defaults": 1,
"jsdoc/no-missing-syntax": 1,
"jsdoc/no-multi-asterisks": 1, // Recommended
"jsdoc/no-restricted-syntax": 1,
"jsdoc/no-types": 1,
"jsdoc/no-undefined-types": 1, // Recommended
"jsdoc/require-asterisk-prefix": 1,
"jsdoc/require-description": 1,
"jsdoc/require-description-complete-sentence": 1,
"jsdoc/require-example": 1,
"jsdoc/require-file-overview": 1,
"jsdoc/require-hyphen-before-param-description": 1,
"jsdoc/require-jsdoc": 1, // Recommended
"jsdoc/require-param": 1, // Recommended
"jsdoc/require-param-description": 1, // Recommended
"jsdoc/require-param-name": 1, // Recommended
"jsdoc/require-param-type": 1, // Recommended
"jsdoc/require-property": 1, // Recommended
"jsdoc/require-property-description": 1, // Recommended
"jsdoc/require-property-name": 1, // Recommended
"jsdoc/require-property-type": 1, // Recommended
"jsdoc/require-returns": 1, // Recommended
"jsdoc/require-returns-check": 1, // Recommended
"jsdoc/require-returns-description": 1, // Recommended
"jsdoc/require-returns-type": 1, // Recommended
"jsdoc/require-template": 1,
"jsdoc/require-throws": 1,
"jsdoc/require-yields": 1, // Recommended
"jsdoc/require-yields-check": 1, // Recommended
"jsdoc/sort-tags": 1,
"jsdoc/tag-lines": 1, // Recommended
"jsdoc/valid-types": 1 // Recommended
}
}
```
Or you can simply add the following to [.eslintrc.*](https://eslint.org/docs/user-guide/configuring#configuration-file-formats),
which enables the rules commented above as "recommended":
```json
{
"extends": ["plugin:jsdoc/recommended"]
}
```
You can then selectively add to or override the recommended rules.
Alternatively, if you wish to have all linting issues reported
as failing errors, you may use the "recommended-error" config:
```json
{
"extends": ["plugin:jsdoc/recommended-error"]
}
```
If you plan to use TypeScript syntax (and not just "typescript"
`mode` to indicate the JSDoc flavor is TypeScript), you can use:
```json
{
"extends": ["plugin:jsdoc/recommended-typescript"]
}
```
...or to report with failing errors instead of mere warnings:
```json
{
"extends": ["plugin:jsdoc/recommended-typescript-error"]
}
```
If you are not using TypeScript syntax (your source files are still `.js` files)
but you are using the TypeScript flavor within JSDoc (i.e., the default
"typescript" `mode` in `eslint-plugin-jsdoc`) and you are perhaps using
`allowJs` and `checkJs` options of TypeScript's `tsconfig.json`), you may
use:
```json
{
"extends": ["plugin:jsdoc/recommended-typescript-flavor"]
}
```
...or to report with failing errors instead of mere warnings:
```json
{
"extends": ["plugin:jsdoc/recommended-typescript-flavor-error"]
}
```
<a name="user-content-eslint-plugin-jsdoc-options"></a>
<a name="eslint-plugin-jsdoc-options"></a>
## Options
Rules may, as per the [ESLint user guide](https://eslint.org/docs/user-guide/configuring), have their own individual options. In `eslint-plugin-jsdoc`, a few options,
such as, `exemptedBy` and `contexts`, may be used across different rules.
`eslint-plugin-jsdoc` options, if present, are generally in the form of an
object supplied as the second argument in an array after the error level
(any exceptions to this format are explained within that rule's docs).
```js
// `.eslintrc.js`
{
rules: {
'jsdoc/require-example': [
// The Error level should be `error`, `warn`, or `off` (or 2, 1, or 0)
'error',
// The options vary by rule, but are generally added to an options
// object as follows:
{
checkConstructors: true,
exemptedBy: ['type']
}
]
}
}
```
<a name="user-content-eslint-plugin-jsdoc-settings"></a>
<a name="eslint-plugin-jsdoc-settings"></a>
## Settings
See [Settings](./docs/settings.md#readme).
<a name="user-content-eslint-plugin-jsdoc-advanced"></a>
<a name="eslint-plugin-jsdoc-advanced"></a>
## Advanced
See [Advanced](./docs/advanced.md#readme).
<a name="user-content-eslint-plugin-jsdoc-processors"></a>
<a name="eslint-plugin-jsdoc-processors"></a>
## Processors
See our `@example` and other item [processors](./docs/processors.md#readme).
<a name="user-content-eslint-plugin-jsdoc-rules"></a>
<a name="eslint-plugin-jsdoc-rules"></a>
## Rules
Problems reported by rules which have a wrench :wrench: below can be fixed automatically by running ESLint on the command line with `--fix` option.
Note that a number of fixable rules have an `enableFixer` option which can
be set to `false` to disable the fixer (or in the case of `check-param-names`,
`check-property-names`, and `no-blank-blocks`, set to `true` to enable a
non-default-recommended fixer).
|recommended|fixable|rule|description|
|-|-|-|-|
|:heavy_check_mark:|| [check-access](./docs/rules/check-access.md#readme) | Enforces valid `@access` tags|
|:heavy_check_mark:|:wrench:| [check-alignment](./docs/rules/check-alignment.md#readme)|Enforces alignment of JSDoc block asterisks|
|||[check-examples](./docs/rules/check-examples.md#readme)|Linting of JavaScript within `@example`|
|||[check-indentation](./docs/rules/check-indentation.md#readme)|Checks for invalid padding inside JSDoc blocks|
||:wrench:|[check-line-alignment](./docs/rules/check-line-alignment.md#readme)|Reports invalid alignment of JSDoc block lines.|
|:heavy_check_mark:|:wrench:|[check-param-names](./docs/rules/check-param-names.md#readme)|Checks for dupe `@param` names, that nested param names have roots, and that parameter names in function declarations match jsdoc param names.|
|:heavy_check_mark:|:wrench:|[check-property-names](./docs/rules/check-property-names.md#readme)|Checks for dupe `@property` names, that nested property names have roots|
|||[check-syntax](./docs/rules/check-syntax.md#readme)|Reports use against current mode (currently only prohibits Closure-specific syntax)|
|:heavy_check_mark:|:wrench:|[check-tag-names](./docs/rules/check-tag-names.md#readme)|Reports invalid jsdoc (block) tag names|
| || [check-template-names](./docs/rules/check-template-names.md#readme)|Checks that any `@template` names are actually used in the connected `@typedef` or type alias.
|:heavy_check_mark:|:wrench:|[check-types](./docs/rules/check-types.md#readme)|Reports types deemed invalid (customizable and with defaults, for preventing and/or recommending replacements)|
|:heavy_check_mark:||[check-values](./docs/rules/check-values.md#readme)|Checks for expected content within some miscellaneous tags (`@version`, `@since`, `@license`, `@author`)|
| || [convert-to-jsdoc-comments](./docs/rules/convert-to-jsdoc-comments.md#readme) | Converts line and block comments preceding or following specified nodes into JSDoc comments|
|:heavy_check_mark:|:wrench:|[empty-tags](./docs/rules/empty-tags.md#readme)|Checks tags that are expected to be empty (e.g., `@abstract` or `@async`), reporting if they have content|
|:heavy_check_mark:||[implements-on-classes](./docs/rules/implements-on-classes.md#readme)|Prohibits use of `@implements` on non-constructor functions (to enforce the tag only being used on classes/constructors)|
|||[informative-docs](./docs/rules/informative-docs.md#readme)|Reports on JSDoc texts that serve only to restate their attached name.|
|||[match-description](./docs/rules/match-description.md#readme)|Defines customizable regular expression rules for your tag descriptions|
||:wrench:|[match-name](./docs/rules/match-name.md#readme)|Reports the name portion of a JSDoc tag if matching or not matching a given regular expression|
|:heavy_check_mark:|:wrench:|[multiline-blocks](./docs/rules/multiline-blocks.md#readme)|Controls how and whether jsdoc blocks can be expressed as single or multiple line blocks|
||:wrench:|[no-bad-blocks](./docs/rules/no-bad-blocks.md#readme)|This rule checks for multi-line-style comments which fail to meet the criteria of a jsdoc block|
||:wrench:|[no-blank-block-descriptions](./docs/rules/no-blank-block-descriptions.md#readme)|If tags are present, this rule will prevent empty lines in the block description. If no tags are present, this rule will prevent extra empty lines in the block description.|
||:wrench:|[no-blank-blocks](./docs/rules/no-blank-blocks.md#readme)|Reports and optionally removes blocks with whitespace only|
|:heavy_check_mark:|:wrench:|[no-defaults](./docs/rules/no-defaults.md#readme)|This rule reports defaults being used on the relevant portion of `@param` or `@default`|
|||[no-missing-syntax](./docs/rules/no-missing-syntax.md#readme)|This rule lets you report if certain always expected comment structures are missing.|
|:heavy_check_mark:|:wrench:|[no-multi-asterisks](./docs/rules/no-multi-asterisks.md#readme)|Prevents use of multiple asterisks at the beginning of lines|
|||[no-restricted-syntax](./docs/rules/no-restricted-syntax.md#readme)|Reports when certain comment structures are present|
|On in TS|:wrench:|[no-types](./docs/rules/no-types.md#readme)|Prohibits types on `@param` or `@returns` (redundant with TypeScript)|
|:heavy_check_mark: (off in TS and TS flavor)||[no-undefined-types](./docs/rules/no-undefined-types.md#readme)|Besides some expected built-in types, prohibits any types not specified as globals or within `@typedef` |
||:wrench:|[require-asterisk-prefix](./docs/rules/require-asterisk-prefix.md#readme)|Requires that each JSDoc line starts with an `*`|
|||[require-description](./docs/rules/require-description.md#readme)|Requires that all functions (and potentially other contexts) have a description.|
||:wrench:|[require-description-complete-sentence](./docs/rules/require-description-complete-sentence.md#readme)|Requires that block description, explicit `@description`, and `@param`/`@returns` tag descriptions are written in complete sentences|
||:wrench:|[require-example](./docs/rules/require-example.md#readme)|Requires that all functions (and potentially other contexts) have examples.|
|||[require-file-overview](./docs/rules/require-file-overview.md#readme)|By default, requires a single `@file` tag at the beginning of each linted file|
||:wrench:|[require-hyphen-before-param-description](./docs/rules/require-hyphen-before-param-description.md#readme)|Requires a hyphen before `@param` descriptions (and optionally before `@property` descriptions)|
|:heavy_check_mark:|:wrench:|[require-jsdoc](./docs/rules/require-jsdoc.md#readme)|Checks for presence of jsdoc comments, on functions and potentially other contexts (optionally limited to exports).|
|:heavy_check_mark:|:wrench:|[require-param](./docs/rules/require-param.md#readme)|Requires that all function parameters are documented with a `@param` tag.|
|:heavy_check_mark:||[require-param-description](./docs/rules/require-param-description.md#readme)|Requires that each `@param` tag has a `description` value.|
|:heavy_check_mark:||[require-param-name](./docs/rules/require-param-name.md#readme)|Requires that all `@param` tags have names.|
|:heavy_check_mark: (off in TS)||[require-param-type](./docs/rules/require-param-type.md#readme)|Requires that each `@param` tag has a type value (within curly brackets).|
|:heavy_check_mark:|:wrench:|[require-property](./docs/rules/require-property.md#readme)|Requires that all `@typedef` and `@namespace` tags have `@property` tags when their type is a plain `object`, `Object`, or `PlainObject`.|
|:heavy_check_mark:||[require-property-description](./docs/rules/require-property-description.md#readme)|Requires that each `@property` tag has a `description` value.|
|:heavy_check_mark:||[require-property-name](./docs/rules/require-property-name.md#readme)|Requires that all `@property` tags have names.|
|:heavy_check_mark: (off in TS)||[require-property-type](./docs/rules/require-property-type.md#readme)|Requires that each `@property` tag has a type value (within curly brackets).|
|:heavy_check_mark:||[require-returns](./docs/rules/require-returns.md#readme)|Requires that return statements are documented.|
|:heavy_check_mark:||[require-returns-check](./docs/rules/require-returns-check.md#readme)|Requires a return statement be present in a function body if a `@returns` tag is specified in the jsdoc comment block (and reports if multiple `@returns` tags are present).|
|:heavy_check_mark:||[require-returns-description](./docs/rules/require-returns-description.md#readme)|Requires that the `@returns` tag has a `description` value (not including `void`/`undefined` type returns).|
|:heavy_check_mark: (off in TS)||[require-returns-type](./docs/rules/require-returns-type.md#readme)|Requires that `@returns` tag has a type value (in curly brackets).|
| || [require-template](./docs/rules/require-template.md#readme) | Requires `@template` tags be present when type parameters are used.|
|||[require-throws](./docs/rules/require-throws.md#readme)|Requires that throw statements are documented|
|:heavy_check_mark:||[require-yields](./docs/rules/require-yields.md#readme)|Requires that yields are documented|
|:heavy_check_mark:||[require-yields-check](./docs/rules/require-yields-check.md#readme)|Ensures that if a `@yields` is present that a `yield` (or `yield` with a value) is present in the function body (or that if a `@next` is present that there is a `yield` with a return value present)|
|||[sort-tags](./docs/rules/sort-tags.md#readme)|Sorts tags by a specified sequence according to tag name, optionally adding line breaks between tag groups|
|:heavy_check_mark:|:wrench:|[tag-lines](./docs/rules/tag-lines.md#readme)|Enforces lines (or no lines) between tags|
||:wrench:|[text-escaping](./docs/rules/text-escaping.md#readme)|This rule can auto-escape certain characters that are input within block and tag descriptions|
|:heavy_check_mark:||[valid-types](./docs/rules/valid-types.md#readme)|Requires all types/namepaths to be valid JSDoc, Closure compiler, or TypeScript types (configurable in settings)|

38
node_modules/eslint-plugin-jsdoc/dist/WarnSettings.cjs generated vendored Normal file
View File

@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
const WarnSettings = function () {
/** @type {WeakMap<object, Set<string>>} */
const warnedSettings = new WeakMap();
return {
/**
* Warn only once for each context and setting
* @param {{}} context
* @param {string} setting
* @returns {boolean}
*/
hasBeenWarned(context, setting) {
return warnedSettings.has(context) && /** @type {Set<string>} */warnedSettings.get(context).has(setting);
},
/**
* @param {{}} context
* @param {string} setting
* @returns {void}
*/
markSettingAsWarned(context, setting) {
// c8 ignore else
if (!warnedSettings.has(context)) {
warnedSettings.set(context, new Set());
}
/** @type {Set<string>} */
warnedSettings.get(context).add(setting);
}
};
};
var _default = exports.default = WarnSettings;
module.exports = exports.default;
//# sourceMappingURL=WarnSettings.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"WarnSettings.cjs","names":["WarnSettings","warnedSettings","WeakMap","hasBeenWarned","context","setting","has","get","markSettingAsWarned","set","Set","add","_default","exports","default","module"],"sources":["../src/WarnSettings.js"],"sourcesContent":["const WarnSettings = function () {\n /** @type {WeakMap<object, Set<string>>} */\n const warnedSettings = new WeakMap();\n\n return {\n /**\n * Warn only once for each context and setting\n * @param {{}} context\n * @param {string} setting\n * @returns {boolean}\n */\n hasBeenWarned (context, setting) {\n return warnedSettings.has(context) && /** @type {Set<string>} */ (\n warnedSettings.get(context)\n ).has(setting);\n },\n\n /**\n * @param {{}} context\n * @param {string} setting\n * @returns {void}\n */\n markSettingAsWarned (context, setting) {\n // c8 ignore else\n if (!warnedSettings.has(context)) {\n warnedSettings.set(context, new Set());\n }\n\n /** @type {Set<string>} */ (warnedSettings.get(context)).add(setting);\n },\n };\n};\n\nexport default WarnSettings;\n"],"mappings":";;;;;;AAAA,MAAMA,YAAY,GAAG,SAAAA,CAAA,EAAY;EAC/B;EACA,MAAMC,cAAc,GAAG,IAAIC,OAAO,CAAC,CAAC;EAEpC,OAAO;IACL;AACJ;AACA;AACA;AACA;AACA;IACIC,aAAaA,CAAEC,OAAO,EAAEC,OAAO,EAAE;MAC/B,OAAOJ,cAAc,CAACK,GAAG,CAACF,OAAO,CAAC,IAAI,0BACpCH,cAAc,CAACM,GAAG,CAACH,OAAO,CAAC,CAC3BE,GAAG,CAACD,OAAO,CAAC;IAChB,CAAC;IAED;AACJ;AACA;AACA;AACA;IACIG,mBAAmBA,CAAEJ,OAAO,EAAEC,OAAO,EAAE;MACrC;MACA,IAAI,CAACJ,cAAc,CAACK,GAAG,CAACF,OAAO,CAAC,EAAE;QAChCH,cAAc,CAACQ,GAAG,CAACL,OAAO,EAAE,IAAIM,GAAG,CAAC,CAAC,CAAC;MACxC;;MAEA;MAA4BT,cAAc,CAACM,GAAG,CAACH,OAAO,CAAC,CAAEO,GAAG,CAACN,OAAO,CAAC;IACvE;EACF,CAAC;AACH,CAAC;AAAC,IAAAO,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEad,YAAY;AAAAe,MAAA,CAAAF,OAAA,GAAAA,OAAA,CAAAC,OAAA","ignoreList":[]}

View File

@ -0,0 +1,323 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _commentParser = require("comment-parser");
/**
* Transform based on https://github.com/syavorsky/comment-parser/blob/master/src/transforms/align.ts
*
* It contains some customizations to align based on the tags, and some custom options.
*/
/**
* @typedef {{
* hasNoTypes: boolean,
* maxNamedTagLength: import('./iterateJsdoc.js').Integer,
* maxUnnamedTagLength: import('./iterateJsdoc.js').Integer
* }} TypelessInfo
*/
const {
rewireSource
} = _commentParser.util;
/**
* @typedef {{
* name: import('./iterateJsdoc.js').Integer,
* start: import('./iterateJsdoc.js').Integer,
* tag: import('./iterateJsdoc.js').Integer,
* type: import('./iterateJsdoc.js').Integer
* }} Width
*/
/** @type {Width} */
const zeroWidth = {
name: 0,
start: 0,
tag: 0,
type: 0
};
/**
* @param {string[]} tags
* @param {import('./iterateJsdoc.js').Integer} index
* @param {import('comment-parser').Line[]} source
* @returns {boolean}
*/
const shouldAlign = (tags, index, source) => {
const tag = source[index].tokens.tag.replace('@', '');
const includesTag = tags.includes(tag);
if (includesTag) {
return true;
}
if (tag !== '') {
return false;
}
for (let iterator = index; iterator >= 0; iterator--) {
const previousTag = source[iterator].tokens.tag.replace('@', '');
if (previousTag !== '') {
if (tags.includes(previousTag)) {
return true;
}
return false;
}
}
return true;
};
/**
* @param {string[]} tags
* @returns {(
* width: Width,
* line: {
* tokens: import('comment-parser').Tokens
* },
* index: import('./iterateJsdoc.js').Integer,
* source: import('comment-parser').Line[]
* ) => Width}
*/
const getWidth = tags => {
return (width, {
tokens
}, index, source) => {
if (!shouldAlign(tags, index, source)) {
return width;
}
return {
name: Math.max(width.name, tokens.name.length),
start: tokens.delimiter === '/**' ? tokens.start.length : width.start,
tag: Math.max(width.tag, tokens.tag.length),
type: Math.max(width.type, tokens.type.length)
};
};
};
/**
* @param {{
* description: string;
* tags: import('comment-parser').Spec[];
* problems: import('comment-parser').Problem[];
* }} fields
* @returns {TypelessInfo}
*/
const getTypelessInfo = fields => {
const hasNoTypes = fields.tags.every(({
type
}) => {
return !type;
});
const maxNamedTagLength = Math.max(...fields.tags.map(({
tag,
name
}) => {
return name.length === 0 ? -1 : tag.length;
}).filter(length => {
return length !== -1;
})) + 1;
const maxUnnamedTagLength = Math.max(...fields.tags.map(({
tag,
name
}) => {
return name.length === 0 ? tag.length : -1;
}).filter(length => {
return length !== -1;
})) + 1;
return {
hasNoTypes,
maxNamedTagLength,
maxUnnamedTagLength
};
};
/**
* @param {import('./iterateJsdoc.js').Integer} len
* @returns {string}
*/
const space = len => {
return ''.padStart(len, ' ');
};
/**
* @param {{
* customSpacings: import('../src/rules/checkLineAlignment.js').CustomSpacings,
* tags: string[],
* indent: string,
* preserveMainDescriptionPostDelimiter: boolean,
* wrapIndent: string,
* disableWrapIndent: boolean,
* }} cfg
* @returns {(
* block: import('comment-parser').Block
* ) => import('comment-parser').Block}
*/
const alignTransform = ({
customSpacings,
tags,
indent,
preserveMainDescriptionPostDelimiter,
wrapIndent,
disableWrapIndent
}) => {
let intoTags = false;
/** @type {Width} */
let width;
/**
* @param {import('comment-parser').Tokens} tokens
* @param {TypelessInfo} typelessInfo
* @returns {import('comment-parser').Tokens}
*/
const alignTokens = (tokens, typelessInfo) => {
const nothingAfter = {
delim: false,
name: false,
tag: false,
type: false
};
if (tokens.description === '') {
nothingAfter.name = true;
tokens.postName = '';
if (tokens.name === '') {
nothingAfter.type = true;
tokens.postType = '';
if (tokens.type === '') {
nothingAfter.tag = true;
tokens.postTag = '';
/* c8 ignore next: Never happens because the !intoTags return. But it's here for consistency with the original align transform */
if (tokens.tag === '') {
nothingAfter.delim = true;
}
}
}
}
let untypedNameAdjustment = 0;
let untypedTypeAdjustment = 0;
if (typelessInfo.hasNoTypes) {
nothingAfter.tag = true;
tokens.postTag = '';
if (tokens.name === '') {
untypedNameAdjustment = typelessInfo.maxNamedTagLength - tokens.tag.length;
} else {
untypedNameAdjustment = typelessInfo.maxNamedTagLength > typelessInfo.maxUnnamedTagLength ? 0 : Math.max(0, typelessInfo.maxUnnamedTagLength - (tokens.tag.length + tokens.name.length + 1));
untypedTypeAdjustment = typelessInfo.maxNamedTagLength - tokens.tag.length;
}
}
// Todo: Avoid fixing alignment of blocks with multiline wrapping of type
if (tokens.tag === '' && tokens.type) {
return tokens;
}
const spacings = {
postDelimiter: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postDelimiter) || 1,
postName: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postName) || 1,
postTag: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postTag) || 1,
postType: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postType) || 1
};
tokens.postDelimiter = nothingAfter.delim ? '' : space(spacings.postDelimiter);
if (!nothingAfter.tag) {
tokens.postTag = space(width.tag - tokens.tag.length + spacings.postTag);
}
if (!nothingAfter.type) {
tokens.postType = space(width.type - tokens.type.length + spacings.postType + untypedTypeAdjustment);
}
if (!nothingAfter.name) {
// If post name is empty for all lines (name width 0), don't add post name spacing.
tokens.postName = width.name === 0 ? '' : space(width.name - tokens.name.length + spacings.postName + untypedNameAdjustment);
}
return tokens;
};
/**
* @param {import('comment-parser').Line} line
* @param {import('./iterateJsdoc.js').Integer} index
* @param {import('comment-parser').Line[]} source
* @param {TypelessInfo} typelessInfo
* @param {string|false} indentTag
* @returns {import('comment-parser').Line}
*/
const update = (line, index, source, typelessInfo, indentTag) => {
/** @type {import('comment-parser').Tokens} */
const tokens = {
...line.tokens
};
if (tokens.tag !== '') {
intoTags = true;
}
const isEmpty = tokens.tag === '' && tokens.name === '' && tokens.type === '' && tokens.description === '';
// dangling '*/'
if (tokens.end === '*/' && isEmpty) {
tokens.start = indent + ' ';
return {
...line,
tokens
};
}
switch (tokens.delimiter) {
case '/**':
tokens.start = indent;
break;
case '*':
tokens.start = indent + ' ';
break;
default:
tokens.delimiter = '';
// compensate delimiter
tokens.start = indent + ' ';
}
if (!intoTags) {
if (tokens.description === '') {
tokens.postDelimiter = '';
} else if (!preserveMainDescriptionPostDelimiter) {
tokens.postDelimiter = ' ';
}
return {
...line,
tokens
};
}
const postHyphenSpacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postHyphen) ?? 1;
const hyphenSpacing = /^\s*-\s+/u;
tokens.description = tokens.description.replace(hyphenSpacing, '-' + ''.padStart(postHyphenSpacing, ' '));
// Not align.
if (shouldAlign(tags, index, source)) {
alignTokens(tokens, typelessInfo);
if (!disableWrapIndent && indentTag) {
tokens.postDelimiter += wrapIndent;
}
}
return {
...line,
tokens
};
};
return ({
source,
...fields
}) => {
width = source.reduce(getWidth(tags), {
...zeroWidth
});
const typelessInfo = getTypelessInfo(fields);
let tagIndentMode = false;
return rewireSource({
...fields,
source: source.map((line, index) => {
const indentTag = !disableWrapIndent && tagIndentMode && !line.tokens.tag && line.tokens.description;
const ret = update(line, index, source, typelessInfo, indentTag);
if (!disableWrapIndent && line.tokens.tag) {
tagIndentMode = true;
}
return ret;
})
});
};
};
var _default = exports.default = alignTransform;
module.exports = exports.default;
//# sourceMappingURL=alignTransform.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
const defaultTagOrder = [{
tags: [
// Brief descriptions
'summary', 'typeSummary',
// Module/file-level
'module', 'exports', 'file', 'fileoverview', 'overview', 'import',
// Identifying (name, type)
'template', 'typedef', 'interface', 'record', 'name', 'kind', 'type', 'alias', 'external', 'host', 'callback', 'func', 'function', 'method', 'class', 'constructor',
// Relationships
'modifies', 'mixes', 'mixin', 'mixinClass', 'mixinFunction', 'namespace', 'borrows', 'constructs', 'lends', 'implements', 'requires',
// Long descriptions
'desc', 'description', 'classdesc', 'tutorial', 'copyright', 'license',
// Simple annotations
// TypeScript
'internal', 'overload', 'const', 'constant', 'final', 'global', 'readonly', 'abstract', 'virtual', 'var', 'member', 'memberof', 'memberof!', 'inner', 'instance', 'inheritdoc', 'inheritDoc', 'override', 'hideconstructor',
// Core function/object info
'param', 'arg', 'argument', 'prop', 'property', 'return', 'returns',
// Important behavior details
'async', 'generator', 'default', 'defaultvalue', 'enum', 'augments', 'extends', 'throws', 'exception', 'yield', 'yields', 'event', 'fires', 'emits', 'listens', 'this',
// TypeScript
'satisfies',
// Access
'static', 'private', 'protected', 'public', 'access', 'package', '-other',
// Supplementary descriptions
'see', 'example',
// METADATA
// Other Closure (undocumented) metadata
'closurePrimitive', 'customElement', 'expose', 'hidden', 'idGenerator', 'meaning', 'ngInject', 'owner', 'wizaction',
// Other Closure (documented) metadata
'define', 'dict', 'export', 'externs', 'implicitCast', 'noalias', 'nocollapse', 'nocompile', 'noinline', 'nosideeffects', 'polymer', 'polymerBehavior', 'preserve', 'struct', 'suppress', 'unrestricted',
// @homer0/prettier-plugin-jsdoc metadata
'category',
// Non-Closure metadata
'ignore', 'author', 'version', 'variation', 'since', 'deprecated', 'todo']
}];
var _default = exports.default = defaultTagOrder;
module.exports = exports.default;
//# sourceMappingURL=defaultTagOrder.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"defaultTagOrder.cjs","names":["defaultTagOrder","tags","_default","exports","default","module"],"sources":["../src/defaultTagOrder.js"],"sourcesContent":["const defaultTagOrder = [\n {\n tags: [\n // Brief descriptions\n 'summary',\n 'typeSummary',\n\n // Module/file-level\n 'module',\n 'exports',\n 'file',\n 'fileoverview',\n 'overview',\n 'import',\n\n // Identifying (name, type)\n 'template',\n 'typedef',\n 'interface',\n 'record',\n 'name',\n 'kind',\n 'type',\n 'alias',\n 'external',\n 'host',\n 'callback',\n 'func',\n 'function',\n 'method',\n 'class',\n 'constructor',\n\n // Relationships\n 'modifies',\n 'mixes',\n 'mixin',\n 'mixinClass',\n 'mixinFunction',\n 'namespace',\n 'borrows',\n 'constructs',\n 'lends',\n 'implements',\n 'requires',\n\n // Long descriptions\n 'desc',\n 'description',\n 'classdesc',\n 'tutorial',\n 'copyright',\n 'license',\n\n // Simple annotations\n\n // TypeScript\n 'internal',\n 'overload',\n\n 'const',\n 'constant',\n 'final',\n 'global',\n 'readonly',\n 'abstract',\n 'virtual',\n 'var',\n 'member',\n 'memberof',\n 'memberof!',\n 'inner',\n 'instance',\n 'inheritdoc',\n 'inheritDoc',\n 'override',\n 'hideconstructor',\n\n // Core function/object info\n 'param',\n 'arg',\n 'argument',\n 'prop',\n 'property',\n 'return',\n 'returns',\n\n // Important behavior details\n 'async',\n 'generator',\n 'default',\n 'defaultvalue',\n 'enum',\n 'augments',\n 'extends',\n 'throws',\n 'exception',\n 'yield',\n 'yields',\n 'event',\n 'fires',\n 'emits',\n 'listens',\n 'this',\n\n // TypeScript\n 'satisfies',\n\n // Access\n 'static',\n 'private',\n 'protected',\n 'public',\n 'access',\n 'package',\n\n '-other',\n\n // Supplementary descriptions\n 'see',\n 'example',\n\n // METADATA\n\n // Other Closure (undocumented) metadata\n 'closurePrimitive',\n 'customElement',\n 'expose',\n 'hidden',\n 'idGenerator',\n 'meaning',\n 'ngInject',\n 'owner',\n 'wizaction',\n\n // Other Closure (documented) metadata\n 'define',\n 'dict',\n 'export',\n 'externs',\n 'implicitCast',\n 'noalias',\n 'nocollapse',\n 'nocompile',\n 'noinline',\n 'nosideeffects',\n 'polymer',\n 'polymerBehavior',\n 'preserve',\n 'struct',\n 'suppress',\n 'unrestricted',\n\n // @homer0/prettier-plugin-jsdoc metadata\n 'category',\n\n // Non-Closure metadata\n 'ignore',\n 'author',\n 'version',\n 'variation',\n 'since',\n 'deprecated',\n 'todo',\n ],\n },\n];\n\nexport default defaultTagOrder;\n"],"mappings":";;;;;;AAAA,MAAMA,eAAe,GAAG,CACtB;EACEC,IAAI,EAAE;EACJ;EACA,SAAS,EACT,aAAa;EAEb;EACA,QAAQ,EACR,SAAS,EACT,MAAM,EACN,cAAc,EACd,UAAU,EACV,QAAQ;EAER;EACA,UAAU,EACV,SAAS,EACT,WAAW,EACX,QAAQ,EACR,MAAM,EACN,MAAM,EACN,MAAM,EACN,OAAO,EACP,UAAU,EACV,MAAM,EACN,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa;EAEb;EACA,UAAU,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,eAAe,EACf,WAAW,EACX,SAAS,EACT,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,UAAU;EAEV;EACA,MAAM,EACN,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,SAAS;EAET;;EAEA;EACA,UAAU,EACV,UAAU,EAEV,OAAO,EACP,UAAU,EACV,OAAO,EACP,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,UAAU,EACV,WAAW,EACX,OAAO,EACP,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,iBAAiB;EAEjB;EACA,OAAO,EACP,KAAK,EACL,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,SAAS;EAET;EACA,OAAO,EACP,WAAW,EACX,SAAS,EACT,cAAc,EACd,MAAM,EACN,UAAU,EACV,SAAS,EACT,QAAQ,EACR,WAAW,EACX,OAAO,EACP,QAAQ,EACR,OAAO,EACP,OAAO,EACP,OAAO,EACP,SAAS,EACT,MAAM;EAEN;EACA,WAAW;EAEX;EACA,QAAQ,EACR,SAAS,EACT,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,SAAS,EAET,QAAQ;EAER;EACA,KAAK,EACL,SAAS;EAET;;EAEA;EACA,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,SAAS,EACT,UAAU,EACV,OAAO,EACP,WAAW;EAEX;EACA,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,SAAS,EACT,cAAc,EACd,SAAS,EACT,YAAY,EACZ,WAAW,EACX,UAAU,EACV,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,QAAQ,EACR,UAAU,EACV,cAAc;EAEd;EACA,UAAU;EAEV;EACA,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,WAAW,EACX,OAAO,EACP,YAAY,EACZ,MAAM;AAEV,CAAC,CACF;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEaJ,eAAe;AAAAK,MAAA,CAAAF,OAAA,GAAAA,OAAA,CAAAC,OAAA","ignoreList":[]}

730
node_modules/eslint-plugin-jsdoc/dist/exportParser.cjs generated vendored Normal file
View File

@ -0,0 +1,730 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _debug = _interopRequireDefault(require("debug"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const debug = (0, _debug.default)('requireExportJsdoc');
/**
* @typedef {{
* value: string
* }} ValueObject
*/
/**
* @typedef {{
* type?: string,
* value?: ValueObject|import('eslint').Rule.Node,
* props: {
* [key: string]: CreatedNode|null,
* },
* special?: true,
* globalVars?: CreatedNode,
* exported?: boolean,
* ANONYMOUS_DEFAULT?: import('eslint').Rule.Node
* }} CreatedNode
*/
/**
* @returns {CreatedNode}
*/
const createNode = function () {
return {
props: {}
};
};
/**
* @param {CreatedNode|null} symbol
* @returns {string|null}
*/
const getSymbolValue = function (symbol) {
/* c8 ignore next 3 */
if (!symbol) {
return null;
}
/* c8 ignore else */
if (symbol.type === 'literal') {
return /** @type {ValueObject} */symbol.value.value;
}
/* c8 ignore next */
return null;
};
/**
*
* @param {import('estree').Identifier} node
* @param {CreatedNode} globals
* @param {CreatedNode} scope
* @param {SymbolOptions} opts
* @returns {CreatedNode|null}
*/
const getIdentifier = function (node, globals, scope, opts) {
if (opts.simpleIdentifier) {
// Type is Identier for noncomputed properties
const identifierLiteral = createNode();
identifierLiteral.type = 'literal';
identifierLiteral.value = {
value: node.name
};
return identifierLiteral;
}
/* c8 ignore next */
const block = scope || globals;
// As scopes are not currently supported, they are not traversed upwards recursively
if (block.props[node.name]) {
return block.props[node.name];
}
// Seems this will only be entered once scopes added and entered
/* c8 ignore next 3 */
if (globals.props[node.name]) {
return globals.props[node.name];
}
return null;
};
/**
* @callback CreateSymbol
* @param {import('eslint').Rule.Node|null} node
* @param {CreatedNode} globals
* @param {import('eslint').Rule.Node|null} value
* @param {CreatedNode} [scope]
* @param {boolean|SymbolOptions} [isGlobal]
* @returns {CreatedNode|null}
*/
/** @type {CreateSymbol} */
let createSymbol; // eslint-disable-line prefer-const
/* eslint-disable complexity -- Temporary */
/**
* @typedef {{
* simpleIdentifier?: boolean
* }} SymbolOptions
*/
/**
*
* @param {import('eslint').Rule.Node} node
* @param {CreatedNode} globals
* @param {CreatedNode} scope
* @param {SymbolOptions} [opt]
* @returns {CreatedNode|null}
*/
const getSymbol = function (node, globals, scope, opt) {
/* eslint-enable complexity -- Temporary */
const opts = opt || {};
/* c8 ignore next */
switch (node.type) {
case 'Identifier':
{
return getIdentifier(node, globals, scope, opts);
}
case 'MemberExpression':
{
const obj = getSymbol( /** @type {import('eslint').Rule.Node} */
node.object, globals, scope, opts);
const propertySymbol = getSymbol( /** @type {import('eslint').Rule.Node} */
node.property, globals, scope, {
simpleIdentifier: !node.computed
});
const propertyValue = getSymbolValue(propertySymbol);
/* c8 ignore else */
if (obj && propertyValue && obj.props[propertyValue]) {
const block = obj.props[propertyValue];
return block;
}
/* c8 ignore next 10 */
/*
if (opts.createMissingProps && propertyValue) {
obj.props[propertyValue] = createNode();
return obj.props[propertyValue];
}
*/
debug(`MemberExpression: Missing property ${/** @type {import('estree').PrivateIdentifier} */node.property.name}`);
/* c8 ignore next 2 */
return null;
}
case 'ClassExpression':
{
return getSymbol( /** @type {import('eslint').Rule.Node} */
node.body, globals, scope, opts);
}
/* c8 ignore next 7 -- No longer needed? */
// @ts-expect-error TS OK
case 'TSTypeAliasDeclaration':
// @ts-expect-error TS OK
// Fallthrough
case 'TSEnumDeclaration':
// @ts-expect-error TS OK
case 'TSInterfaceDeclaration':
case 'ClassDeclaration':
case 'FunctionExpression':
case 'FunctionDeclaration':
case 'ArrowFunctionExpression':
{
const val = createNode();
val.props.prototype = createNode();
val.props.prototype.type = 'object';
val.type = 'object';
val.value = node;
return val;
}
case 'AssignmentExpression':
{
return createSymbol( /** @type {import('eslint').Rule.Node} */
node.left, globals, /** @type {import('eslint').Rule.Node} */
node.right, scope, opts);
}
case 'ClassBody':
{
const val = createNode();
for (const method of node.body) {
val.props[/** @type {import('estree').Identifier} */( /** @type {import('estree').MethodDefinition} */method.key).name] = createNode();
/** @type {{[key: string]: CreatedNode}} */
val.props[/** @type {import('estree').Identifier} */( /** @type {import('estree').MethodDefinition} */method.key).name].type = 'object';
/** @type {{[key: string]: CreatedNode}} */
val.props[/** @type {import('estree').Identifier} */( /** @type {import('estree').MethodDefinition} */method.key).name].value = /** @type {import('eslint').Rule.Node} */
/** @type {import('estree').MethodDefinition} */method.value;
}
val.type = 'object';
val.value = node.parent;
return val;
}
case 'ObjectExpression':
{
const val = createNode();
val.type = 'object';
for (const prop of node.properties) {
if ([
// typescript-eslint, espree, acorn, etc.
'SpreadElement',
// @babel/eslint-parser
'ExperimentalSpreadProperty'].includes(prop.type)) {
continue;
}
const propVal = getSymbol( /** @type {import('eslint').Rule.Node} */
/** @type {import('estree').Property} */
prop.value, globals, scope, opts);
/* c8 ignore next 8 */
if (propVal) {
val.props[/** @type {import('estree').PrivateIdentifier} */
( /** @type {import('estree').Property} */prop.key).name] = propVal;
}
}
return val;
}
case 'Literal':
{
const val = createNode();
val.type = 'literal';
val.value = node;
return val;
}
}
/* c8 ignore next */
return null;
};
/**
*
* @param {CreatedNode} block
* @param {string} name
* @param {CreatedNode|null} value
* @param {CreatedNode} globals
* @param {boolean|SymbolOptions|undefined} isGlobal
* @returns {void}
*/
const createBlockSymbol = function (block, name, value, globals, isGlobal) {
block.props[name] = value;
if (isGlobal && globals.props.window && globals.props.window.special) {
globals.props.window.props[name] = value;
}
};
createSymbol = function (node, globals, value, scope, isGlobal) {
const block = scope || globals;
/* c8 ignore next 3 */
if (!node) {
return null;
}
let symbol;
switch (node.type) {
case 'FunctionDeclaration':
/* c8 ignore next */
// @ts-expect-error TS OK
// Fall through
case 'TSEnumDeclaration':
case 'TSInterfaceDeclaration':
/* c8 ignore next */
// @ts-expect-error TS OK
// Fall through
case 'TSTypeAliasDeclaration':
case 'ClassDeclaration':
{
const nde = /** @type {import('estree').ClassDeclaration} */node;
/* c8 ignore else */
if (nde.id && nde.id.type === 'Identifier') {
return createSymbol( /** @type {import('eslint').Rule.Node} */nde.id, globals, node, globals);
}
/* c8 ignore next 2 */
break;
}
case 'Identifier':
{
const nde = /** @type {import('estree').Identifier} */node;
if (value) {
const valueSymbol = getSymbol(value, globals, block);
/* c8 ignore else */
if (valueSymbol) {
createBlockSymbol(block, nde.name, valueSymbol, globals, isGlobal);
return block.props[nde.name];
}
/* c8 ignore next */
debug('Identifier: Missing value symbol for %s', nde.name);
} else {
createBlockSymbol(block, nde.name, createNode(), globals, isGlobal);
return block.props[nde.name];
}
/* c8 ignore next 2 */
break;
}
case 'MemberExpression':
{
const nde = /** @type {import('estree').MemberExpression} */node;
symbol = getSymbol( /** @type {import('eslint').Rule.Node} */nde.object, globals, block);
const propertySymbol = getSymbol( /** @type {import('eslint').Rule.Node} */nde.property, globals, block, {
simpleIdentifier: !nde.computed
});
const propertyValue = getSymbolValue(propertySymbol);
if (symbol && propertyValue) {
createBlockSymbol(symbol, propertyValue, getSymbol( /** @type {import('eslint').Rule.Node} */
value, globals, block), globals, isGlobal);
return symbol.props[propertyValue];
}
debug('MemberExpression: Missing symbol: %s', /** @type {import('estree').Identifier} */nde.property.name);
break;
}
}
return null;
};
/**
* Creates variables from variable definitions
* @param {import('eslint').Rule.Node} node
* @param {CreatedNode} globals
* @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opts
* @returns {void}
*/
const initVariables = function (node, globals, opts) {
switch (node.type) {
case 'Program':
{
for (const childNode of node.body) {
initVariables( /** @type {import('eslint').Rule.Node} */
childNode, globals, opts);
}
break;
}
case 'ExpressionStatement':
{
initVariables( /** @type {import('eslint').Rule.Node} */
node.expression, globals, opts);
break;
}
case 'VariableDeclaration':
{
for (const declaration of node.declarations) {
// let and const
const symbol = createSymbol( /** @type {import('eslint').Rule.Node} */
declaration.id, globals, null, globals);
if (opts.initWindow && node.kind === 'var' && globals.props.window) {
// If var, also add to window
globals.props.window.props[/** @type {import('estree').Identifier} */
declaration.id.name] = symbol;
}
}
break;
}
case 'ExportNamedDeclaration':
{
if (node.declaration) {
initVariables( /** @type {import('eslint').Rule.Node} */
node.declaration, globals, opts);
}
break;
}
}
};
/* eslint-disable complexity -- Temporary */
/**
* Populates variable maps using AST
* @param {import('eslint').Rule.Node} node
* @param {CreatedNode} globals
* @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
* @param {true} [isExport]
* @returns {boolean}
*/
const mapVariables = function (node, globals, opt, isExport) {
/* eslint-enable complexity -- Temporary */
/* c8 ignore next */
const opts = opt || {};
/* c8 ignore next */
switch (node.type) {
case 'Program':
{
if (opts.ancestorsOnly) {
return false;
}
for (const childNode of node.body) {
mapVariables( /** @type {import('eslint').Rule.Node} */
childNode, globals, opts);
}
break;
}
case 'ExpressionStatement':
{
mapVariables( /** @type {import('eslint').Rule.Node} */
node.expression, globals, opts);
break;
}
case 'AssignmentExpression':
{
createSymbol( /** @type {import('eslint').Rule.Node} */
node.left, globals, /** @type {import('eslint').Rule.Node} */
node.right);
break;
}
case 'VariableDeclaration':
{
for (const declaration of node.declarations) {
const isGlobal = Boolean(opts.initWindow && node.kind === 'var' && globals.props.window);
const symbol = createSymbol( /** @type {import('eslint').Rule.Node} */
declaration.id, globals, /** @type {import('eslint').Rule.Node} */
declaration.init, globals, isGlobal);
if (symbol && isExport) {
symbol.exported = true;
}
}
break;
}
case 'FunctionDeclaration':
{
/* c8 ignore next 10 */
if ( /** @type {import('estree').Identifier} */node.id.type === 'Identifier') {
createSymbol( /** @type {import('eslint').Rule.Node} */
node.id, globals, node, globals, true);
}
break;
}
case 'ExportDefaultDeclaration':
{
const symbol = createSymbol( /** @type {import('eslint').Rule.Node} */
node.declaration, globals, /** @type {import('eslint').Rule.Node} */
node.declaration);
if (symbol) {
symbol.exported = true;
/* c8 ignore next 6 */
} else {
// if (!node.id) {
globals.ANONYMOUS_DEFAULT = /** @type {import('eslint').Rule.Node} */
node.declaration;
}
break;
}
case 'ExportNamedDeclaration':
{
if (node.declaration) {
if (node.declaration.type === 'VariableDeclaration') {
mapVariables( /** @type {import('eslint').Rule.Node} */
node.declaration, globals, opts, true);
} else {
const symbol = createSymbol( /** @type {import('eslint').Rule.Node} */
node.declaration, globals, /** @type {import('eslint').Rule.Node} */
node.declaration);
/* c8 ignore next 3 */
if (symbol) {
symbol.exported = true;
}
}
}
for (const specifier of node.specifiers) {
mapVariables( /** @type {import('eslint').Rule.Node} */
specifier, globals, opts);
}
break;
}
case 'ExportSpecifier':
{
const symbol = getSymbol( /** @type {import('eslint').Rule.Node} */
node.local, globals, globals);
/* c8 ignore next 3 */
if (symbol) {
symbol.exported = true;
}
break;
}
case 'ClassDeclaration':
{
createSymbol( /** @type {import('eslint').Rule.Node|null} */node.id, globals, /** @type {import('eslint').Rule.Node} */node.body, globals);
break;
}
default:
{
/* c8 ignore next */
return false;
}
}
return true;
};
/**
*
* @param {import('eslint').Rule.Node} node
* @param {CreatedNode|ValueObject|string|undefined|
* import('eslint').Rule.Node} block
* @param {(CreatedNode|ValueObject|string|
* import('eslint').Rule.Node)[]} [cache]
* @returns {boolean}
*/
const findNode = function (node, block, cache) {
let blockCache = cache || [];
if (!block || blockCache.includes(block)) {
return false;
}
blockCache = blockCache.slice();
blockCache.push(block);
if (typeof block === 'object' && 'type' in block && (block.type === 'object' || block.type === 'MethodDefinition') && block.value === node) {
return true;
}
if (typeof block !== 'object') {
return false;
}
const props = 'props' in block && block.props || 'body' in block && block.body;
for (const propval of Object.values(props || {})) {
if (Array.isArray(propval)) {
/* c8 ignore next 5 */
if (propval.some(val => {
return findNode(node, val, blockCache);
})) {
return true;
}
} else if (findNode(node, propval, blockCache)) {
return true;
}
}
return false;
};
const exportTypes = new Set(['ExportNamedDeclaration', 'ExportDefaultDeclaration']);
const ignorableNestedTypes = new Set(['FunctionDeclaration', 'ArrowFunctionExpression', 'FunctionExpression']);
/**
* @param {import('eslint').Rule.Node} nde
* @returns {import('eslint').Rule.Node|false}
*/
const getExportAncestor = function (nde) {
let node = nde;
let idx = 0;
const ignorableIfDeep = ignorableNestedTypes.has(nde === null || nde === void 0 ? void 0 : nde.type);
while (node) {
// Ignore functions nested more deeply than say `export default function () {}`
if (idx >= 2 && ignorableIfDeep) {
break;
}
if (exportTypes.has(node.type)) {
return node;
}
node = node.parent;
idx++;
}
return false;
};
const canBeExportedByAncestorType = new Set(['TSPropertySignature', 'TSMethodSignature', 'ClassProperty', 'PropertyDefinition', 'Method']);
const canExportChildrenType = new Set(['TSInterfaceBody', 'TSInterfaceDeclaration', 'TSTypeLiteral', 'TSTypeAliasDeclaration', 'TSTypeParameterInstantiation', 'TSTypeReference', 'ClassDeclaration', 'ClassBody', 'ClassDefinition', 'ClassExpression', 'Program']);
/**
* @param {import('eslint').Rule.Node} nde
* @returns {false|import('eslint').Rule.Node}
*/
const isExportByAncestor = function (nde) {
if (!canBeExportedByAncestorType.has(nde.type)) {
return false;
}
let node = nde.parent;
while (node) {
if (exportTypes.has(node.type)) {
return node;
}
if (!canExportChildrenType.has(node.type)) {
return false;
}
node = node.parent;
}
return false;
};
/**
*
* @param {CreatedNode} block
* @param {import('eslint').Rule.Node} node
* @param {CreatedNode[]} [cache] Currently unused
* @returns {boolean}
*/
const findExportedNode = function (block, node, cache) {
/* c8 ignore next 3 */
if (block === null) {
return false;
}
const blockCache = cache || [];
const {
props
} = block;
for (const propval of Object.values(props)) {
const pval = /** @type {CreatedNode} */propval;
blockCache.push(pval);
if (pval.exported && (node === pval.value || findNode(node, pval.value))) {
return true;
}
// No need to check `propval` for exported nodes as ESM
// exports are only global
}
return false;
};
/**
*
* @param {import('eslint').Rule.Node} node
* @param {CreatedNode} globals
* @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
* @returns {boolean}
*/
const isNodeExported = function (node, globals, opt) {
var _globals$props$module;
const moduleExports = (_globals$props$module = globals.props.module) === null || _globals$props$module === void 0 || (_globals$props$module = _globals$props$module.props) === null || _globals$props$module === void 0 ? void 0 : _globals$props$module.exports;
if (opt.initModuleExports && moduleExports && findNode(node, moduleExports)) {
return true;
}
if (opt.initWindow && globals.props.window && findNode(node, globals.props.window)) {
return true;
}
if (opt.esm && findExportedNode(globals, node)) {
return true;
}
return false;
};
/**
*
* @param {import('eslint').Rule.Node} node
* @param {CreatedNode} globalVars
* @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opts
* @returns {boolean}
*/
const parseRecursive = function (node, globalVars, opts) {
// Iterate from top using recursion - stop at first processed node from top
if (node.parent && parseRecursive(node.parent, globalVars, opts)) {
return true;
}
return mapVariables(node, globalVars, opts);
};
/**
*
* @param {import('eslint').Rule.Node} ast
* @param {import('eslint').Rule.Node} node
* @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
* @returns {CreatedNode}
*/
const parse = function (ast, node, opt) {
/* c8 ignore next 6 */
const opts = opt || {
ancestorsOnly: false,
esm: true,
initModuleExports: true,
initWindow: true
};
const globalVars = createNode();
if (opts.initModuleExports) {
globalVars.props.module = createNode();
globalVars.props.module.props.exports = createNode();
globalVars.props.exports = globalVars.props.module.props.exports;
}
if (opts.initWindow) {
globalVars.props.window = createNode();
globalVars.props.window.special = true;
}
if (opts.ancestorsOnly) {
parseRecursive(node, globalVars, opts);
} else {
initVariables(ast, globalVars, opts);
mapVariables(ast, globalVars, opts);
}
return {
globalVars,
props: {}
};
};
const accessibilityNodes = new Set(['PropertyDefinition', 'MethodDefinition']);
/**
*
* @param {import('eslint').Rule.Node} node
* @returns {boolean}
*/
const isPrivate = node => {
return accessibilityNodes.has(node.type) && 'accessibility' in node && node.accessibility !== 'public' && node.accessibility !== undefined || 'key' in node && node.key.type === 'PrivateIdentifier';
};
/**
*
* @param {import('eslint').Rule.Node} node
* @param {import('eslint').SourceCode} sourceCode
* @param {import('./rules/requireJsdoc.js').RequireJsdocOpts} opt
* @param {import('./iterateJsdoc.js').Settings} settings
* @returns {boolean}
*/
const isUncommentedExport = function (node, sourceCode, opt, settings) {
// console.log({node});
// Optimize with ancestor check for esm
if (opt.esm) {
if (isPrivate(node) || node.parent && isPrivate(node.parent)) {
return false;
}
const exportNode = getExportAncestor(node);
// Is export node comment
if (exportNode && !(0, _jsdoccomment.findJSDocComment)(exportNode, sourceCode, settings)) {
return true;
}
/**
* Some typescript types are not in variable map, but inherit exported (interface property and method)
*/
if (isExportByAncestor(node) && !(0, _jsdoccomment.findJSDocComment)(node, sourceCode, settings)) {
return true;
}
}
const ast = /** @type {unknown} */sourceCode.ast;
const parseResult = parse( /** @type {import('eslint').Rule.Node} */
ast, node, opt);
return isNodeExported(node, /** @type {CreatedNode} */parseResult.globalVars, opt);
};
var _default = exports.default = {
isUncommentedExport,
parse
};
module.exports = exports.default;
//# sourceMappingURL=exportParser.cjs.map

File diff suppressed because one or more lines are too long

247
node_modules/eslint-plugin-jsdoc/dist/generateRule.cjs generated vendored Normal file
View File

@ -0,0 +1,247 @@
"use strict";
var _url = require("url");
var _fs = require("fs");
var _promises = _interopRequireDefault(require("fs/promises"));
var _path = require("path");
var _camelcase = _interopRequireDefault(require("camelcase"));
var _openEditor = _interopRequireDefault(require("open-editor"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /* eslint-disable no-console -- CLI */ /**
* @example
*
* ```shell
* npm run create-rule my-new-rule -- --recommended
* ```
*/
const _dirname = (0, _path.dirname)((0, _url.fileURLToPath)(require('url').pathToFileURL(__filename).toString()));
// Todo: Would ideally have prompts, e.g., to ask for whether
// type was problem/layout, etc.
const [,, ruleName, ...options] = process.argv;
const recommended = options.includes('--recommended');
(async () => {
if (!ruleName) {
console.error('Please supply a rule name');
return;
}
if (/[A-Z]/u.test(ruleName)) {
console.error('Please ensure the rule has no capital letters');
return;
}
const ruleNamesPath = './test/rules/ruleNames.json';
// @ts-expect-error Older types?
const ruleNames = JSON.parse(await _promises.default.readFile(ruleNamesPath));
if (!ruleNames.includes(ruleName)) {
ruleNames.push(ruleName);
ruleNames.sort();
}
await _promises.default.writeFile(ruleNamesPath, JSON.stringify(ruleNames, null, 2) + '\n');
console.log('ruleNames', ruleNames);
const ruleTemplate = `import iterateJsdoc from '../iterateJsdoc.js';
export default iterateJsdoc(({
context,
utils,
}) => {
// Rule here
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: '',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/${ruleName}.md#repos-sticky-header',
},
schema: [
{
additionalProperties: false,
properties: {
// Option properties here (or remove the object)
},
type: 'object',
},
],
type: 'suggestion',
},
});
`;
const camelCasedRuleName = (0, _camelcase.default)(ruleName);
const rulePath = `./src/rules/${camelCasedRuleName}.js`;
if (!(0, _fs.existsSync)(rulePath)) {
await _promises.default.writeFile(rulePath, ruleTemplate);
}
const ruleTestTemplate = `export default {
invalid: [
{
code: \`
\`,
errors: [
{
line: 2,
message: '',
},
],
},
],
valid: [
{
code: \`
\`,
},
],
};
`;
const ruleTestPath = `./test/rules/assertions/${camelCasedRuleName}.js`;
if (!(0, _fs.existsSync)(ruleTestPath)) {
await _promises.default.writeFile(ruleTestPath, ruleTestTemplate);
}
const ruleReadmeTemplate = `# \`${ruleName}\`
|||
|---|---|
|Context|everywhere|
|Tags|\`\`|
|Recommended|${recommended ? 'true' : 'false'}|
|Settings||
|Options||
## Failing examples
<!-- assertions-failing ${camelCasedRuleName} -->
## Passing examples
<!-- assertions-passing ${camelCasedRuleName} -->
`;
const ruleReadmePath = `./.README/rules/${ruleName}.md`;
if (!(0, _fs.existsSync)(ruleReadmePath)) {
await _promises.default.writeFile(ruleReadmePath, ruleReadmeTemplate);
}
/**
* @param {object} cfg
* @param {string} cfg.path
* @param {RegExp} cfg.oldRegex
* @param {string} cfg.checkName
* @param {string} cfg.newLine
* @param {boolean} [cfg.oldIsCamel]
* @returns {Promise<void>}
*/
const replaceInOrder = async ({
path,
oldRegex,
checkName,
newLine,
oldIsCamel
}) => {
/**
* @typedef {number} Integer
*/
/**
* @typedef {{
* matchedLine: string,
* offset: Integer,
* oldRule: string,
* }} OffsetInfo
*/
/**
* @type {OffsetInfo[]}
*/
const offsets = [];
let readme = await _promises.default.readFile(path, 'utf8');
readme.replace(oldRegex,
/**
* @param {string} matchedLine
* @param {string} n1
* @param {Integer} offset
* @param {string} str
* @param {object} groups
* @param {string} groups.oldRule
* @returns {string}
*/
(matchedLine, n1, offset, str, {
oldRule
}) => {
offsets.push({
matchedLine,
offset,
oldRule
});
return matchedLine;
});
offsets.sort(({
oldRule
}, {
oldRule: oldRuleB
}) => {
return oldRule < oldRuleB ? -1 : oldRule > oldRuleB ? 1 : 0;
});
let alreadyIncluded = false;
const itemIndex = offsets.findIndex(({
oldRule
}) => {
alreadyIncluded ||= oldIsCamel ? camelCasedRuleName === oldRule : ruleName === oldRule;
return oldIsCamel ? camelCasedRuleName < oldRule : ruleName < oldRule;
});
let item = itemIndex !== undefined && offsets[itemIndex];
if (item && itemIndex === 0 &&
// This property would not always be sufficient but in this case it is.
oldIsCamel) {
item.offset = 0;
}
if (!item) {
item = /** @type {OffsetInfo} */offsets.pop();
item.offset += item.matchedLine.length;
}
if (alreadyIncluded) {
console.log(`Rule name is already present in ${checkName}.`);
} else {
readme = readme.slice(0, item.offset) + (item.offset ? '\n' : '') + newLine + (item.offset ? '' : '\n') + readme.slice(item.offset);
await _promises.default.writeFile(path, readme);
}
};
// await replaceInOrder({
// checkName: 'README',
// newLine: `{"gitdown": "include", "file": "./rules/${ruleName}.md"}`,
// oldRegex: /\n\{"gitdown": "include", "file": ".\/rules\/(?<oldRule>[^.]*).md"\}/gu,
// path: './.README/README.md',
// });
await replaceInOrder({
checkName: 'index import',
newLine: `import ${camelCasedRuleName} from './rules/${camelCasedRuleName}.js';`,
oldIsCamel: true,
oldRegex: /\nimport (?<oldRule>[^ ]*) from '.\/rules\/\1\.js';/gu,
path: './src/index.js'
});
await replaceInOrder({
checkName: 'index recommended',
newLine: `${' '.repeat(6)}'jsdoc/${ruleName}': ${recommended ? 'warnOrError' : '\'off\''},`,
oldRegex: /\n\s{6}'jsdoc\/(?<oldRule>[^']*)': .*?,/gu,
path: './src/index.js'
});
await replaceInOrder({
checkName: 'index rules',
newLine: `${' '.repeat(4)}'${ruleName}': ${camelCasedRuleName},`,
oldRegex: /\n\s{4}'(?<oldRule>[^']*)': [^,]*,/gu,
path: './src/index.js'
});
await Promise.resolve().then(() => _interopRequireWildcard(require('./generateDocs.js')));
/*
console.log('Paths to open for further editing\n');
console.log(`open ${ruleReadmePath}`);
console.log(`open ${rulePath}`);
console.log(`open ${ruleTestPath}\n`);
*/
// Set chdir as somehow still in operation from other test
process.chdir((0, _path.resolve)(_dirname, '../../'));
await (0, _openEditor.default)([
// Could even add editor line column numbers like `${rulePath}:1:1`
ruleReadmePath, ruleTestPath, rulePath]);
})();
//# sourceMappingURL=generateRule.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,293 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
/**
* @typedef {Map<string, Map<string, (string|boolean)>>} TagStructure
*/
/**
* @param {import('./jsdocUtils.js').ParserMode} mode
* @returns {TagStructure}
*/
const getDefaultTagStructureForMode = mode => {
const isJsdoc = mode === 'jsdoc';
const isClosure = mode === 'closure';
const isTypescript = mode === 'typescript';
const isPermissive = mode === 'permissive';
const isJsdocOrPermissive = isJsdoc || isPermissive;
const isJsdocOrTypescript = isJsdoc || isTypescript;
const isTypescriptOrClosure = isTypescript || isClosure;
const isClosureOrPermissive = isClosure || isPermissive;
const isJsdocTypescriptOrPermissive = isJsdocOrTypescript || isPermissive;
// Properties:
// `namepathRole` - 'namepath-referencing'|'namepath-defining'|'namepath-or-url-referencing'|'text'|false
// `typeAllowed` - boolean
// `nameRequired` - boolean
// `typeRequired` - boolean
// `typeOrNameRequired` - boolean
// All of `typeAllowed` have a signature with "type" except for
// `augments`/`extends` ("namepath")
// `param`/`arg`/`argument` (no signature)
// `property`/`prop` (no signature)
// `modifies` (undocumented)
// None of the `namepathRole: 'namepath-defining'` show as having curly
// brackets for their name/namepath
// Among `namepath-defining` and `namepath-referencing`, these do not seem
// to allow curly brackets in their doc signature or examples (`modifies`
// references namepaths within its type brackets and `param` is
// name-defining but not namepath-defining, so not part of these groups)
// Todo: Should support special processing for "name" as distinct from
// "namepath" (e.g., param can't define a namepath)
// Todo: Should support a `tutorialID` type (for `@tutorial` block and
// inline)
/**
* @type {TagStructure}
*/
return new Map([['alias', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "namepath" (and no counter-examples)
['namepathRole', 'namepath-defining'],
// "namepath"
['typeOrNameRequired', true]])], ['arg', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', 'namepath-defining'],
// See `param`
['nameRequired', true],
// Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['argument', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', 'namepath-defining'],
// See `param`
['nameRequired', true],
// Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['augments', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "namepath" (and no counter-examples)
['namepathRole', 'namepath-referencing'],
// Does not show curly brackets in either the signature or examples
['typeAllowed', true],
// "namepath"
['typeOrNameRequired', true]])], ['borrows', new Map( /** @type {[string, string|boolean][]} */[
// `borrows` has a different format, however, so needs special parsing;
// seems to require both, and as "namepath"'s
['namepathRole', 'namepath-referencing'],
// "namepath"
['typeOrNameRequired', true]])], ['callback', new Map( /** @type {[string, string|boolean][]} */[
// Seems to require a "namepath" in the signature (with no
// counter-examples); TypeScript does not enforce but seems
// problematic as not attached so presumably not useable without it
['namepathRole', 'namepath-defining'],
// "namepath"
['nameRequired', true]])], ['class', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'],
// Not in use, but should be this value if using to power `empty-tags`
['nameAllowed', true], ['typeAllowed', true]])], ['const', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'], ['typeAllowed', true]])], ['constant', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'], ['typeAllowed', true]])], ['constructor', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'], ['typeAllowed', true]])], ['constructs', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'], ['nameRequired', false], ['typeAllowed', false]])], ['define', new Map( /** @type {[string, string|boolean][]} */[['typeRequired', isClosure]])], ['emits', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "name" (of an event) and no counter-examples
['namepathRole', 'namepath-referencing'], ['nameRequired', true], ['typeAllowed', false]])], ['enum', new Map( /** @type {[string, string|boolean][]} */[
// Has example showing curly brackets but not in doc signature
['typeAllowed', true]])], ['event', new Map( /** @type {[string, string|boolean][]} */[
// The doc signature of `event` seems to require a "name"
['nameRequired', true],
// Appears to require a "name" in its signature, albeit somewhat
// different from other "name"'s (including as described
// at https://jsdoc.app/about-namepaths.html )
['namepathRole', 'namepath-defining']])], ['exception', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])],
// Closure
['export', new Map( /** @type {[string, string|boolean][]} */[['typeAllowed', isClosureOrPermissive]])], ['exports', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', 'namepath-defining'], ['nameRequired', isJsdoc], ['typeAllowed', isClosureOrPermissive]])], ['extends', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "namepath" (and no counter-examples)
['namepathRole', 'namepath-referencing'],
// Does not show curly brackets in either the signature or examples
['typeAllowed', isTypescriptOrClosure || isPermissive], ['nameRequired', isJsdoc],
// "namepath"
['typeOrNameRequired', isTypescriptOrClosure || isPermissive]])], ['external', new Map( /** @type {[string, string|boolean][]} */[
// Appears to require a "name" in its signature, albeit somewhat
// different from other "name"'s (including as described
// at https://jsdoc.app/about-namepaths.html )
['namepathRole', 'namepath-defining'],
// "name" (and a special syntax for the `external` name)
['nameRequired', true], ['typeAllowed', false]])], ['fires', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "name" (of an event) and no
// counter-examples
['namepathRole', 'namepath-referencing'], ['nameRequired', true], ['typeAllowed', false]])], ['function', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'], ['nameRequired', false], ['typeAllowed', false]])], ['func', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining']])], ['host', new Map( /** @type {[string, string|boolean][]} */[
// Appears to require a "name" in its signature, albeit somewhat
// different from other "name"'s (including as described
// at https://jsdoc.app/about-namepaths.html )
['namepathRole', 'namepath-defining'],
// See `external`
['nameRequired', true], ['typeAllowed', false]])], ['interface', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name" in signature, but indicates as optional
['namepathRole', isJsdocTypescriptOrPermissive ? 'namepath-defining' : false],
// Not in use, but should be this value if using to power `empty-tags`
['nameAllowed', isClosure], ['typeAllowed', false]])], ['internal', new Map( /** @type {[string, string|boolean][]} */[
// https://www.typescriptlang.org/tsconfig/#stripInternal
['namepathRole', false],
// Not in use, but should be this value if using to power `empty-tags`
['nameAllowed', false]])], ['implements', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the doc signature and examples
// "typeExpression"
['typeRequired', true]])], ['lends', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "namepath" (and no counter-examples)
['namepathRole', 'namepath-referencing'],
// "namepath"
['typeOrNameRequired', true]])], ['link', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a namepath OR URL and might be checked as such.
['namepathRole', 'namepath-or-url-referencing']])], ['linkcode', new Map( /** @type {[string, string|boolean][]} */[
// Synonym for "link"
// Signature seems to require a namepath OR URL and might be checked as such.
['namepathRole', 'namepath-or-url-referencing']])], ['linkplain', new Map( /** @type {[string, string|boolean][]} */[
// Synonym for "link"
// Signature seems to require a namepath OR URL and might be checked as such.
['namepathRole', 'namepath-or-url-referencing']])], ['listens', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "name" (of an event) and no
// counter-examples
['namepathRole', 'namepath-referencing'], ['nameRequired', true], ['typeAllowed', false]])], ['member', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'],
// Has example showing curly brackets but not in doc signature
['typeAllowed', true]])], ['memberof', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "namepath" (and no counter-examples),
// though it allows an incomplete namepath ending with connecting symbol
['namepathRole', 'namepath-referencing'],
// "namepath"
['typeOrNameRequired', true]])], ['memberof!', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "namepath" (and no counter-examples),
// though it allows an incomplete namepath ending with connecting symbol
['namepathRole', 'namepath-referencing'],
// "namepath"
['typeOrNameRequired', true]])], ['method', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining']])], ['mixes', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "OtherObjectPath" with no
// counter-examples
['namepathRole', 'namepath-referencing'],
// "OtherObjectPath"
['typeOrNameRequired', true]])], ['mixin', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'], ['nameRequired', false], ['typeAllowed', false]])], ['modifies', new Map( /** @type {[string, string|boolean][]} */[
// Has no documentation, but test example has curly brackets, and
// "name" would be suggested rather than "namepath" based on example;
// not sure if name is required
['typeAllowed', true]])], ['module', new Map( /** @type {[string, string|boolean][]} */[
// Optional "name" and no curly brackets
// this block impacts `no-undefined-types` and `valid-types` (search for
// "isNamepathDefiningTag|tagMightHaveNamepath|tagMightHaveEitherTypeOrNamePosition")
['namepathRole', isJsdoc ? 'namepath-defining' : 'text'],
// Shows the signature with curly brackets but not in the example
['typeAllowed', true]])], ['name', new Map( /** @type {[string, string|boolean][]} */[
// Seems to require a "namepath" in the signature (with no
// counter-examples)
['namepathRole', 'namepath-defining'],
// "namepath"
['nameRequired', true],
// "namepath"
['typeOrNameRequired', true]])], ['namespace', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'],
// Shows the signature with curly brackets but not in the example
['typeAllowed', true]])], ['package', new Map( /** @type {[string, string|boolean][]} */[
// Shows the signature with curly brackets but not in the example
// "typeExpression"
['typeAllowed', isClosureOrPermissive]])], ['param', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', 'namepath-defining'],
// Though no signature provided requiring, per
// https://jsdoc.app/tags-param.html:
// "The @param tag requires you to specify the name of the parameter you
// are documenting."
['nameRequired', true],
// Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['private', new Map( /** @type {[string, string|boolean][]} */[
// Shows the signature with curly brackets but not in the example
// "typeExpression"
['typeAllowed', isClosureOrPermissive]])], ['prop', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', 'namepath-defining'],
// See `property`
['nameRequired', true],
// Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['property', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', 'namepath-defining'],
// No docs indicate required, but since parallel to `param`, we treat as
// such:
['nameRequired', true],
// Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['protected', new Map( /** @type {[string, string|boolean][]} */[
// Shows the signature with curly brackets but not in the example
// "typeExpression"
['typeAllowed', isClosureOrPermissive]])], ['public', new Map( /** @type {[string, string|boolean][]} */[
// Does not show a signature nor show curly brackets in the example
['typeAllowed', isClosureOrPermissive]])], ['requires', new Map( /** @type {[string, string|boolean][]} */[
// <someModuleName>
['namepathRole', 'namepath-referencing'], ['nameRequired', true], ['typeAllowed', false]])], ['returns', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['return', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['satisfies', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the doc signature and examples
['typeRequired', true]])], ['see', new Map( /** @type {[string, string|boolean][]} */[
// Signature allows for "namepath" or text, so user must configure to
// 'namepath-referencing' to enforce checks
['namepathRole', 'text']])], ['static', new Map( /** @type {[string, string|boolean][]} */[
// Does not show a signature nor show curly brackets in the example
['typeAllowed', isClosureOrPermissive]])], ['suppress', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', !isClosure], ['typeRequired', isClosure]])], ['template', new Map( /** @type {[string, string|boolean][]} */[['namepathRole', isJsdoc ? 'text' : 'namepath-referencing'], ['nameRequired', !isJsdoc],
// Though defines `namepathRole: 'namepath-defining'` in a sense, it is
// not parseable in the same way for template (e.g., allowing commas),
// so not adding
['typeAllowed', isTypescriptOrClosure || isPermissive]])], ['this', new Map( /** @type {[string, string|boolean][]} */[
// Signature seems to require a "namepath" (and no counter-examples)
// Not used with namepath in Closure/TypeScript, however
['namepathRole', isJsdoc ? 'namepath-referencing' : false], ['typeRequired', isTypescriptOrClosure],
// namepath
['typeOrNameRequired', isJsdoc]])], ['throws', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['tutorial', new Map( /** @type {[string, string|boolean][]} */[
// (a tutorial ID)
['nameRequired', true], ['typeAllowed', false]])], ['type', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the doc signature and examples
// "typeName"
['typeRequired', true]])], ['typedef', new Map( /** @type {[string, string|boolean][]} */[
// Seems to require a "namepath" in the signature (with no
// counter-examples)
['namepathRole', 'namepath-defining'],
// TypeScript may allow it to be dropped if followed by @property or @member;
// also shown as missing in Closure
// "namepath"
['nameRequired', isJsdocOrPermissive],
// Is not `typeRequired` for TypeScript because it gives an error:
// JSDoc '@typedef' tag should either have a type annotation or be followed by '@property' or '@member' tags.
// Has example showing curly brackets but not in doc signature
['typeAllowed', true],
// TypeScript may allow it to be dropped if followed by @property or @member
// "namepath"
['typeOrNameRequired', !isTypescript]])], ['var', new Map( /** @type {[string, string|boolean][]} */[
// Allows for "name"'s in signature, but indicated as optional
['namepathRole', 'namepath-defining'],
// Has example showing curly brackets but not in doc signature
['typeAllowed', true]])], ['yields', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['yield', new Map( /** @type {[string, string|boolean][]} */[
// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])]]);
};
var _default = exports.default = getDefaultTagStructureForMode;
module.exports = exports.default;
//# sourceMappingURL=getDefaultTagStructureForMode.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,541 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getJsdocProcessorPlugin = void 0;
var _nodeFs = require("node:fs");
var _nodePath = require("node:path");
var _nodeUrl = require("node:url");
var espree = _interopRequireWildcard(require("espree"));
var _jsdocUtils = require("./jsdocUtils.cjs");
var _jsdoccomment = require("@es-joy/jsdoccomment");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
// Todo: Support TS by fenced block type
const _dirname = (0, _nodePath.dirname)((0, _nodeUrl.fileURLToPath)(require('url').pathToFileURL(__filename).toString()));
const {
version
} = JSON.parse(
// @ts-expect-error `Buffer` is ok for `JSON.parse`
(0, _nodeFs.readFileSync)((0, _nodePath.join)(_dirname, '../package.json')));
// const zeroBasedLineIndexAdjust = -1;
const likelyNestedJSDocIndentSpace = 1;
const preTagSpaceLength = 1;
// If a space is present, we should ignore it
const firstLinePrefixLength = preTagSpaceLength;
const hasCaptionRegex = /^\s*<caption>([\s\S]*?)<\/caption>/u;
/**
* @param {string} str
* @returns {string}
*/
const escapeStringRegexp = str => {
return str.replaceAll(/[.*+?^${}()|[\]\\]/gu, '\\$&');
};
/**
* @param {string} str
* @param {string} ch
* @returns {import('./iterateJsdoc.js').Integer}
*/
const countChars = (str, ch) => {
return (str.match(new RegExp(escapeStringRegexp(ch), 'gu')) || []).length;
};
/**
* @param {string} text
* @returns {[
* import('./iterateJsdoc.js').Integer,
* import('./iterateJsdoc.js').Integer
* ]}
*/
const getLinesCols = text => {
const matchLines = countChars(text, '\n');
const colDelta = matchLines ? text.slice(text.lastIndexOf('\n') + 1).length : text.length;
return [matchLines, colDelta];
};
/**
* @typedef {number} Integer
*/
/**
* @typedef {object} JsdocProcessorOptions
* @property {boolean} [captionRequired]
* @property {Integer} [paddedIndent]
* @property {boolean} [checkDefaults]
* @property {boolean} [checkParams]
* @property {boolean} [checkExamples]
* @property {boolean} [checkProperties]
* @property {string} [matchingFileName]
* @property {string} [matchingFileNameDefaults]
* @property {string} [matchingFileNameParams]
* @property {string} [matchingFileNameProperties]
* @property {string} [exampleCodeRegex]
* @property {string} [rejectExampleCodeRegex]
* @property {"script"|"module"} [sourceType]
* @property {import('eslint').Linter.FlatConfigParserModule} [parser]
*/
/**
* We use a function for the ability of the user to pass in a config, but
* without requiring all users of the plugin to do so.
* @param {JsdocProcessorOptions} [options]
*/
const getJsdocProcessorPlugin = (options = {}) => {
const {
exampleCodeRegex = null,
rejectExampleCodeRegex = null,
checkExamples = true,
checkDefaults = false,
checkParams = false,
checkProperties = false,
matchingFileName = null,
matchingFileNameDefaults = null,
matchingFileNameParams = null,
matchingFileNameProperties = null,
paddedIndent = 0,
captionRequired = false,
sourceType = 'module',
parser = undefined
} = options;
/** @type {RegExp} */
let exampleCodeRegExp;
/** @type {RegExp} */
let rejectExampleCodeRegExp;
if (exampleCodeRegex) {
exampleCodeRegExp = (0, _jsdocUtils.getRegexFromString)(exampleCodeRegex);
}
if (rejectExampleCodeRegex) {
rejectExampleCodeRegExp = (0, _jsdocUtils.getRegexFromString)(rejectExampleCodeRegex);
}
/**
* @type {{
* targetTagName: string,
* ext: string,
* codeStartLine: number,
* codeStartCol: number,
* nonJSPrefacingCols: number,
* commentLineCols: [number, number]
* }[]}
*/
const otherInfo = [];
/** @type {import('eslint').Linter.LintMessage[]} */
let extraMessages = [];
/**
* @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
* @param {string} jsFileName
* @param {[number, number]} commentLineCols
*/
const getTextsAndFileNames = (jsdoc, jsFileName, commentLineCols) => {
/**
* @type {{
* text: string,
* filename: string|null|undefined
* }[]}
*/
const textsAndFileNames = [];
/**
* @param {{
* filename: string|null,
* defaultFileName: string|undefined,
* source: string,
* targetTagName: string,
* rules?: import('eslint').Linter.RulesRecord|undefined,
* lines?: import('./iterateJsdoc.js').Integer,
* cols?: import('./iterateJsdoc.js').Integer,
* skipInit?: boolean,
* ext: string,
* sources?: {
* nonJSPrefacingCols: import('./iterateJsdoc.js').Integer,
* nonJSPrefacingLines: import('./iterateJsdoc.js').Integer,
* string: string,
* }[],
* tag?: import('comment-parser').Spec & {
* line?: import('./iterateJsdoc.js').Integer,
* }|{
* line: import('./iterateJsdoc.js').Integer,
* }
* }} cfg
*/
const checkSource = ({
filename,
ext,
defaultFileName,
lines = 0,
cols = 0,
skipInit,
source,
targetTagName,
sources = [],
tag = {
line: 0
}
}) => {
if (!skipInit) {
sources.push({
nonJSPrefacingCols: cols,
nonJSPrefacingLines: lines,
string: source
});
}
/**
* @param {{
* nonJSPrefacingCols: import('./iterateJsdoc.js').Integer,
* nonJSPrefacingLines: import('./iterateJsdoc.js').Integer,
* string: string
* }} cfg
*/
const addSourceInfo = function ({
nonJSPrefacingCols,
nonJSPrefacingLines,
string
}) {
const src = paddedIndent ? string.replaceAll(new RegExp(`(^|\n) {${paddedIndent}}(?!$)`, 'gu'), '\n') : string;
// Programmatic ESLint API: https://eslint.org/docs/developer-guide/nodejs-api
const file = filename || defaultFileName;
if (!('line' in tag)) {
tag.line = tag.source[0].number;
}
// NOTE: `tag.line` can be 0 if of form `/** @tag ... */`
const codeStartLine =
/**
* @type {import('comment-parser').Spec & {
* line: import('./iterateJsdoc.js').Integer,
* }}
*/
tag.line + nonJSPrefacingLines;
const codeStartCol = likelyNestedJSDocIndentSpace;
textsAndFileNames.push({
text: src,
filename: file
});
otherInfo.push({
targetTagName,
ext,
codeStartLine,
codeStartCol,
nonJSPrefacingCols,
commentLineCols
});
};
for (const targetSource of sources) {
addSourceInfo(targetSource);
}
};
/**
*
* @param {string|null} filename
* @param {string} [ext] Since `eslint-plugin-markdown` v2, and
* ESLint 7, this is the default which other JS-fenced rules will used.
* Formerly "md" was the default.
* @returns {{
* defaultFileName: string|undefined,
* filename: string|null,
* ext: string
* }}
*/
const getFilenameInfo = (filename, ext = 'md/*.js') => {
let defaultFileName;
if (!filename) {
if (typeof jsFileName === 'string' && jsFileName.includes('.')) {
defaultFileName = jsFileName.replace(/\.[^.]*$/u, `.${ext}`);
} else {
defaultFileName = `dummy.${ext}`;
}
}
return {
ext,
defaultFileName,
filename
};
};
if (checkDefaults) {
const filenameInfo = getFilenameInfo(matchingFileNameDefaults, 'jsdoc-defaults');
(0, _jsdocUtils.forEachPreferredTag)(jsdoc, 'default', (tag, targetTagName) => {
if (!tag.description.trim()) {
return;
}
checkSource({
source: `(${(0, _jsdocUtils.getTagDescription)(tag)})`,
targetTagName,
...filenameInfo
});
});
}
if (checkParams) {
const filenameInfo = getFilenameInfo(matchingFileNameParams, 'jsdoc-params');
(0, _jsdocUtils.forEachPreferredTag)(jsdoc, 'param', (tag, targetTagName) => {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: `(${tag.default})`,
targetTagName,
...filenameInfo
});
});
}
if (checkProperties) {
const filenameInfo = getFilenameInfo(matchingFileNameProperties, 'jsdoc-properties');
(0, _jsdocUtils.forEachPreferredTag)(jsdoc, 'property', (tag, targetTagName) => {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: `(${tag.default})`,
targetTagName,
...filenameInfo
});
});
}
if (!checkExamples) {
return textsAndFileNames;
}
const tagName = /** @type {string} */(0, _jsdocUtils.getPreferredTagName)(jsdoc, {
tagName: 'example'
});
if (!(0, _jsdocUtils.hasTag)(jsdoc, tagName)) {
return textsAndFileNames;
}
const matchingFilenameInfo = getFilenameInfo(matchingFileName);
(0, _jsdocUtils.forEachPreferredTag)(jsdoc, 'example', (tag, targetTagName) => {
let source = /** @type {string} */(0, _jsdocUtils.getTagDescription)(tag);
const match = source.match(hasCaptionRegex);
if (captionRequired && (!match || !match[1].trim())) {
extraMessages.push({
line: 1 + commentLineCols[0] + (tag.line ?? tag.source[0].number),
column: commentLineCols[1] + 1,
severity: 2,
message: `@${targetTagName} error - Caption is expected for examples.`,
ruleId: 'jsdoc/example-missing-caption'
});
return;
}
source = source.replace(hasCaptionRegex, '');
const [lines, cols] = match ? getLinesCols(match[0]) : [0, 0];
if (exampleCodeRegex && !exampleCodeRegExp.test(source) || rejectExampleCodeRegex && rejectExampleCodeRegExp.test(source)) {
return;
}
const sources = [];
let skipInit = false;
if (exampleCodeRegex) {
let nonJSPrefacingCols = 0;
let nonJSPrefacingLines = 0;
let startingIndex = 0;
let lastStringCount = 0;
let exampleCode;
exampleCodeRegExp.lastIndex = 0;
while ((exampleCode = exampleCodeRegExp.exec(source)) !== null) {
const {
index,
'0': n0,
'1': n1
} = exampleCode;
// Count anything preceding user regex match (can affect line numbering)
const preMatch = source.slice(startingIndex, index);
const [preMatchLines, colDelta] = getLinesCols(preMatch);
let nonJSPreface;
let nonJSPrefaceLineCount;
if (n1) {
const idx = n0.indexOf(n1);
nonJSPreface = n0.slice(0, idx);
nonJSPrefaceLineCount = countChars(nonJSPreface, '\n');
} else {
nonJSPreface = '';
nonJSPrefaceLineCount = 0;
}
nonJSPrefacingLines += lastStringCount + preMatchLines + nonJSPrefaceLineCount;
// Ignore `preMatch` delta if newlines here
if (nonJSPrefaceLineCount) {
const charsInLastLine = nonJSPreface.slice(nonJSPreface.lastIndexOf('\n') + 1).length;
nonJSPrefacingCols += charsInLastLine;
} else {
nonJSPrefacingCols += colDelta + nonJSPreface.length;
}
const string = n1 || n0;
sources.push({
nonJSPrefacingCols,
nonJSPrefacingLines,
string
});
startingIndex = exampleCodeRegExp.lastIndex;
lastStringCount = countChars(string, '\n');
if (!exampleCodeRegExp.global) {
break;
}
}
skipInit = true;
}
checkSource({
cols,
lines,
skipInit,
source,
sources,
tag,
targetTagName,
...matchingFilenameInfo
});
});
return textsAndFileNames;
};
// See https://eslint.org/docs/latest/extend/plugins#processors-in-plugins
// See https://eslint.org/docs/latest/extend/custom-processors
// From https://github.com/eslint/eslint/issues/14745#issuecomment-869457265
/*
{
"files": ["*.js", "*.ts"],
"processor": "jsdoc/example" // a pretended value here
},
{
"files": [
"*.js/*_jsdoc-example.js",
"*.ts/*_jsdoc-example.js",
"*.js/*_jsdoc-example.ts"
],
"rules": {
// specific rules for examples in jsdoc only here
// And other rules for `.js` and `.ts` will also be enabled for them
}
}
*/
return {
meta: {
name: 'eslint-plugin-jsdoc/processor',
version
},
processors: {
examples: {
meta: {
name: 'eslint-plugin-jsdoc/preprocessor',
version
},
/**
* @param {string} text
* @param {string} filename
*/
preprocess(text, filename) {
try {
let ast;
// May be running a second time so catch and ignore
try {
ast = parser
// @ts-expect-error Ok
? parser.parseForESLint(text, {
ecmaVersion: 'latest',
sourceType,
comment: true
}).ast : espree.parse(text, {
ecmaVersion: 'latest',
sourceType,
comment: true
});
} catch (err) {
return [text];
}
/** @type {[number, number][]} */
const commentLineCols = [];
const jsdocComments = /** @type {import('estree').Comment[]} */(
/**
* @type {import('estree').Program & {
* comments?: import('estree').Comment[]
* }}
*/
ast.comments).filter(comment => {
return /^\*\s/u.test(comment.value);
}).map(comment => {
/* c8 ignore next -- Unsupporting processors only? */
const [start] = comment.range ?? [];
const textToStart = text.slice(0, start);
const [lines, cols] = getLinesCols(textToStart);
// const lines = [...textToStart.matchAll(/\n/gu)].length
// const lastLinePos = textToStart.lastIndexOf('\n');
// const cols = lastLinePos === -1
// ? 0
// : textToStart.slice(lastLinePos).length;
commentLineCols.push([lines, cols]);
return (0, _jsdoccomment.parseComment)(comment);
});
return [text, ...jsdocComments.flatMap((jsdoc, idx) => {
return getTextsAndFileNames(jsdoc, filename, commentLineCols[idx]);
}).filter(Boolean)];
/* c8 ignore next 3 */
} catch (err) {
console.log('err', filename, err);
}
},
/**
* @param {import('eslint').Linter.LintMessage[][]} messages
* @param {string} filename
*/
postprocess([jsMessages, ...messages], filename) {
messages.forEach((message, idx) => {
const {
targetTagName,
codeStartLine,
codeStartCol,
nonJSPrefacingCols,
commentLineCols
} = otherInfo[idx];
message.forEach(msg => {
const {
message,
ruleId,
severity,
fatal,
line,
column,
endColumn,
endLine
// Todo: Make fixable
// fix
// fix: {range: [number, number], text: string}
// suggestions: {desc: , messageId:, fix: }[],
} = msg;
const [codeCtxLine, codeCtxColumn] = commentLineCols;
const startLine = codeCtxLine + codeStartLine + line;
const startCol = 1 +
// Seems to need one more now
codeCtxColumn + codeStartCol + (
// This might not work for line 0, but line 0 is unlikely for examples
line <= 1 ? nonJSPrefacingCols + firstLinePrefixLength : preTagSpaceLength) + column;
msg.message = '@' + targetTagName + ' ' + (severity === 2 ? 'error' : 'warning') + (ruleId ? ' (' + ruleId + ')' : '') + ': ' + (fatal ? 'Fatal: ' : '') + message;
msg.line = startLine;
msg.column = startCol;
msg.endLine = endLine ? startLine + endLine : startLine;
// added `- column` to offset what `endColumn` already seemed to include
msg.endColumn = endColumn ? startCol - column + endColumn : startCol;
});
});
const ret = [...jsMessages].concat(...messages, ...extraMessages);
extraMessages = [];
return ret;
},
supportsAutofix: true
}
}
};
};
exports.getJsdocProcessorPlugin = getJsdocProcessorPlugin;
//# sourceMappingURL=getJsdocProcessorPlugin.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,17 @@
"use strict";
var _synckit = require("synckit");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
(0, _synckit.runAsWorker)(async imprt => {
const {
parseImports
} = await Promise.resolve().then(() => _interopRequireWildcard(require('parse-imports')));
try {
// ESLint doesn't support async rules
return [...(await parseImports(imprt))];
} catch (err) {
return false;
}
});
//# sourceMappingURL=import-worker.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"import-worker.cjs","names":["_synckit","require","_getRequireWildcardCache","e","WeakMap","r","t","_interopRequireWildcard","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","runAsWorker","imprt","parseImports","Promise","resolve","then","err"],"sources":["../src/import-worker.mjs"],"sourcesContent":["import { runAsWorker } from 'synckit'\n\nrunAsWorker(async (imprt) => {\n const { parseImports } = await import('parse-imports');\n try {\n // ESLint doesn't support async rules\n return [...await parseImports(imprt)];\n } catch (err) {\n return false;\n }\n})\n"],"mappings":";;AAAA,IAAAA,QAAA,GAAAC,OAAA;AAAqC,SAAAC,yBAAAC,CAAA,6BAAAC,OAAA,mBAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,CAAA,WAAAA,CAAA,GAAAG,CAAA,GAAAD,CAAA,KAAAF,CAAA;AAAA,SAAAI,wBAAAJ,CAAA,EAAAE,CAAA,SAAAA,CAAA,IAAAF,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,eAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,WAAAM,OAAA,EAAAN,CAAA,QAAAG,CAAA,GAAAJ,wBAAA,CAAAG,CAAA,OAAAC,CAAA,IAAAA,CAAA,CAAAI,GAAA,CAAAP,CAAA,UAAAG,CAAA,CAAAK,GAAA,CAAAR,CAAA,OAAAS,CAAA,KAAAC,SAAA,UAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,CAAA,IAAAf,CAAA,oBAAAe,CAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAjB,CAAA,EAAAe,CAAA,SAAAG,CAAA,GAAAP,CAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAd,CAAA,EAAAe,CAAA,UAAAG,CAAA,KAAAA,CAAA,CAAAV,GAAA,IAAAU,CAAA,CAAAC,GAAA,IAAAP,MAAA,CAAAC,cAAA,CAAAJ,CAAA,EAAAM,CAAA,EAAAG,CAAA,IAAAT,CAAA,CAAAM,CAAA,IAAAf,CAAA,CAAAe,CAAA,YAAAN,CAAA,CAAAH,OAAA,GAAAN,CAAA,EAAAG,CAAA,IAAAA,CAAA,CAAAgB,GAAA,CAAAnB,CAAA,EAAAS,CAAA,GAAAA,CAAA;AAErC,IAAAW,oBAAW,EAAC,MAAOC,KAAK,IAAK;EAC3B,MAAM;IAAEC;EAAa,CAAC,GAAG,MAAAC,OAAA,CAAAC,OAAA,GAAAC,IAAA,OAAArB,uBAAA,CAAAN,OAAA,CAAa,eAAe,GAAC;EACtD,IAAI;IACF;IACA,OAAO,CAAC,IAAG,MAAMwB,YAAY,CAACD,KAAK,CAAC,EAAC;EACvC,CAAC,CAAC,OAAOK,GAAG,EAAE;IACZ,OAAO,KAAK;EACd;AACF,CAAC,CAAC","ignoreList":[]}

View File

@ -0,0 +1,11 @@
import { runAsWorker } from 'synckit'
runAsWorker(async (imprt) => {
const { parseImports } = await import('parse-imports');
try {
// ESLint doesn't support async rules
return [...await parseImports(imprt)];
} catch (err) {
return false;
}
})

359
node_modules/eslint-plugin-jsdoc/dist/index.cjs generated vendored Normal file
View File

@ -0,0 +1,359 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _checkAccess = _interopRequireDefault(require("./rules/checkAccess.cjs"));
var _checkAlignment = _interopRequireDefault(require("./rules/checkAlignment.cjs"));
var _checkExamples = _interopRequireDefault(require("./rules/checkExamples.cjs"));
var _checkIndentation = _interopRequireDefault(require("./rules/checkIndentation.cjs"));
var _checkLineAlignment = _interopRequireDefault(require("./rules/checkLineAlignment.cjs"));
var _checkParamNames = _interopRequireDefault(require("./rules/checkParamNames.cjs"));
var _checkPropertyNames = _interopRequireDefault(require("./rules/checkPropertyNames.cjs"));
var _checkSyntax = _interopRequireDefault(require("./rules/checkSyntax.cjs"));
var _checkTagNames = _interopRequireDefault(require("./rules/checkTagNames.cjs"));
var _checkTemplateNames = _interopRequireDefault(require("./rules/checkTemplateNames.cjs"));
var _checkTypes = _interopRequireDefault(require("./rules/checkTypes.cjs"));
var _checkValues = _interopRequireDefault(require("./rules/checkValues.cjs"));
var _convertToJsdocComments = _interopRequireDefault(require("./rules/convertToJsdocComments.cjs"));
var _emptyTags = _interopRequireDefault(require("./rules/emptyTags.cjs"));
var _implementsOnClasses = _interopRequireDefault(require("./rules/implementsOnClasses.cjs"));
var _importsAsDependencies = _interopRequireDefault(require("./rules/importsAsDependencies.cjs"));
var _informativeDocs = _interopRequireDefault(require("./rules/informativeDocs.cjs"));
var _matchDescription = _interopRequireDefault(require("./rules/matchDescription.cjs"));
var _matchName = _interopRequireDefault(require("./rules/matchName.cjs"));
var _multilineBlocks = _interopRequireDefault(require("./rules/multilineBlocks.cjs"));
var _noBadBlocks = _interopRequireDefault(require("./rules/noBadBlocks.cjs"));
var _noBlankBlockDescriptions = _interopRequireDefault(require("./rules/noBlankBlockDescriptions.cjs"));
var _noBlankBlocks = _interopRequireDefault(require("./rules/noBlankBlocks.cjs"));
var _noDefaults = _interopRequireDefault(require("./rules/noDefaults.cjs"));
var _noMissingSyntax = _interopRequireDefault(require("./rules/noMissingSyntax.cjs"));
var _noMultiAsterisks = _interopRequireDefault(require("./rules/noMultiAsterisks.cjs"));
var _noRestrictedSyntax = _interopRequireDefault(require("./rules/noRestrictedSyntax.cjs"));
var _noTypes = _interopRequireDefault(require("./rules/noTypes.cjs"));
var _noUndefinedTypes = _interopRequireDefault(require("./rules/noUndefinedTypes.cjs"));
var _requireAsteriskPrefix = _interopRequireDefault(require("./rules/requireAsteriskPrefix.cjs"));
var _requireDescription = _interopRequireDefault(require("./rules/requireDescription.cjs"));
var _requireDescriptionCompleteSentence = _interopRequireDefault(require("./rules/requireDescriptionCompleteSentence.cjs"));
var _requireExample = _interopRequireDefault(require("./rules/requireExample.cjs"));
var _requireFileOverview = _interopRequireDefault(require("./rules/requireFileOverview.cjs"));
var _requireHyphenBeforeParamDescription = _interopRequireDefault(require("./rules/requireHyphenBeforeParamDescription.cjs"));
var _requireJsdoc = _interopRequireDefault(require("./rules/requireJsdoc.cjs"));
var _requireParam = _interopRequireDefault(require("./rules/requireParam.cjs"));
var _requireParamDescription = _interopRequireDefault(require("./rules/requireParamDescription.cjs"));
var _requireParamName = _interopRequireDefault(require("./rules/requireParamName.cjs"));
var _requireParamType = _interopRequireDefault(require("./rules/requireParamType.cjs"));
var _requireProperty = _interopRequireDefault(require("./rules/requireProperty.cjs"));
var _requirePropertyDescription = _interopRequireDefault(require("./rules/requirePropertyDescription.cjs"));
var _requirePropertyName = _interopRequireDefault(require("./rules/requirePropertyName.cjs"));
var _requirePropertyType = _interopRequireDefault(require("./rules/requirePropertyType.cjs"));
var _requireReturns = _interopRequireDefault(require("./rules/requireReturns.cjs"));
var _requireReturnsCheck = _interopRequireDefault(require("./rules/requireReturnsCheck.cjs"));
var _requireReturnsDescription = _interopRequireDefault(require("./rules/requireReturnsDescription.cjs"));
var _requireReturnsType = _interopRequireDefault(require("./rules/requireReturnsType.cjs"));
var _requireTemplate = _interopRequireDefault(require("./rules/requireTemplate.cjs"));
var _requireThrows = _interopRequireDefault(require("./rules/requireThrows.cjs"));
var _requireYields = _interopRequireDefault(require("./rules/requireYields.cjs"));
var _requireYieldsCheck = _interopRequireDefault(require("./rules/requireYieldsCheck.cjs"));
var _sortTags = _interopRequireDefault(require("./rules/sortTags.cjs"));
var _tagLines = _interopRequireDefault(require("./rules/tagLines.cjs"));
var _textEscaping = _interopRequireDefault(require("./rules/textEscaping.cjs"));
var _validTypes = _interopRequireDefault(require("./rules/validTypes.cjs"));
var _getJsdocProcessorPlugin = require("./getJsdocProcessorPlugin.cjs");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @type {import('eslint').ESLint.Plugin & {
* configs: Record<
* "recommended"|"recommended-error"|"recommended-typescript"|
* "recommended-typescript-error"|"recommended-typescript-flavor"|
* "recommended-typescript-flavor-error"|"flat/recommended"|
* "flat/recommended-error"|"flat/recommended-typescript"|
* "flat/recommended-typescript-error"|
* "flat/recommended-typescript-flavor"|
* "flat/recommended-typescript-flavor-error",
* import('eslint').Linter.FlatConfig
* >
* }}
*/
const index = {
// @ts-expect-error Ok
configs: {},
rules: {
'check-access': _checkAccess.default,
'check-alignment': _checkAlignment.default,
'check-examples': _checkExamples.default,
'check-indentation': _checkIndentation.default,
'check-line-alignment': _checkLineAlignment.default,
'check-param-names': _checkParamNames.default,
'check-property-names': _checkPropertyNames.default,
'check-syntax': _checkSyntax.default,
'check-tag-names': _checkTagNames.default,
'check-template-names': _checkTemplateNames.default,
'check-types': _checkTypes.default,
'check-values': _checkValues.default,
'convert-to-jsdoc-comments': _convertToJsdocComments.default,
'empty-tags': _emptyTags.default,
'implements-on-classes': _implementsOnClasses.default,
'imports-as-dependencies': _importsAsDependencies.default,
'informative-docs': _informativeDocs.default,
'match-description': _matchDescription.default,
'match-name': _matchName.default,
'multiline-blocks': _multilineBlocks.default,
'no-bad-blocks': _noBadBlocks.default,
'no-blank-block-descriptions': _noBlankBlockDescriptions.default,
'no-blank-blocks': _noBlankBlocks.default,
'no-defaults': _noDefaults.default,
'no-missing-syntax': _noMissingSyntax.default,
'no-multi-asterisks': _noMultiAsterisks.default,
'no-restricted-syntax': _noRestrictedSyntax.default,
'no-types': _noTypes.default,
'no-undefined-types': _noUndefinedTypes.default,
'require-asterisk-prefix': _requireAsteriskPrefix.default,
'require-description': _requireDescription.default,
'require-description-complete-sentence': _requireDescriptionCompleteSentence.default,
'require-example': _requireExample.default,
'require-file-overview': _requireFileOverview.default,
'require-hyphen-before-param-description': _requireHyphenBeforeParamDescription.default,
'require-jsdoc': _requireJsdoc.default,
'require-param': _requireParam.default,
'require-param-description': _requireParamDescription.default,
'require-param-name': _requireParamName.default,
'require-param-type': _requireParamType.default,
'require-property': _requireProperty.default,
'require-property-description': _requirePropertyDescription.default,
'require-property-name': _requirePropertyName.default,
'require-property-type': _requirePropertyType.default,
'require-returns': _requireReturns.default,
'require-returns-check': _requireReturnsCheck.default,
'require-returns-description': _requireReturnsDescription.default,
'require-returns-type': _requireReturnsType.default,
'require-template': _requireTemplate.default,
'require-throws': _requireThrows.default,
'require-yields': _requireYields.default,
'require-yields-check': _requireYieldsCheck.default,
'sort-tags': _sortTags.default,
'tag-lines': _tagLines.default,
'text-escaping': _textEscaping.default,
'valid-types': _validTypes.default
}
};
/**
* @param {"warn"|"error"} warnOrError
* @param {string} [flatName]
* @returns {import('eslint').Linter.FlatConfig}
*/
const createRecommendedRuleset = (warnOrError, flatName) => {
return {
...(flatName ? {
name: 'jsdoc/' + flatName
} : {}),
// @ts-expect-error Ok
plugins: flatName ? {
jsdoc: index
} : ['jsdoc'],
rules: {
'jsdoc/check-access': warnOrError,
'jsdoc/check-alignment': warnOrError,
'jsdoc/check-examples': 'off',
'jsdoc/check-indentation': 'off',
'jsdoc/check-line-alignment': 'off',
'jsdoc/check-param-names': warnOrError,
'jsdoc/check-property-names': warnOrError,
'jsdoc/check-syntax': 'off',
'jsdoc/check-tag-names': warnOrError,
'jsdoc/check-template-names': 'off',
'jsdoc/check-types': warnOrError,
'jsdoc/check-values': warnOrError,
'jsdoc/convert-to-jsdoc-comments': 'off',
'jsdoc/empty-tags': warnOrError,
'jsdoc/implements-on-classes': warnOrError,
'jsdoc/imports-as-dependencies': 'off',
'jsdoc/informative-docs': 'off',
'jsdoc/match-description': 'off',
'jsdoc/match-name': 'off',
'jsdoc/multiline-blocks': warnOrError,
'jsdoc/no-bad-blocks': 'off',
'jsdoc/no-blank-block-descriptions': 'off',
'jsdoc/no-blank-blocks': 'off',
'jsdoc/no-defaults': warnOrError,
'jsdoc/no-missing-syntax': 'off',
'jsdoc/no-multi-asterisks': warnOrError,
'jsdoc/no-restricted-syntax': 'off',
'jsdoc/no-types': 'off',
'jsdoc/no-undefined-types': warnOrError,
'jsdoc/require-asterisk-prefix': 'off',
'jsdoc/require-description': 'off',
'jsdoc/require-description-complete-sentence': 'off',
'jsdoc/require-example': 'off',
'jsdoc/require-file-overview': 'off',
'jsdoc/require-hyphen-before-param-description': 'off',
'jsdoc/require-jsdoc': warnOrError,
'jsdoc/require-param': warnOrError,
'jsdoc/require-param-description': warnOrError,
'jsdoc/require-param-name': warnOrError,
'jsdoc/require-param-type': warnOrError,
'jsdoc/require-property': warnOrError,
'jsdoc/require-property-description': warnOrError,
'jsdoc/require-property-name': warnOrError,
'jsdoc/require-property-type': warnOrError,
'jsdoc/require-returns': warnOrError,
'jsdoc/require-returns-check': warnOrError,
'jsdoc/require-returns-description': warnOrError,
'jsdoc/require-returns-type': warnOrError,
'jsdoc/require-template': 'off',
'jsdoc/require-throws': 'off',
'jsdoc/require-yields': warnOrError,
'jsdoc/require-yields-check': warnOrError,
'jsdoc/sort-tags': 'off',
'jsdoc/tag-lines': warnOrError,
'jsdoc/text-escaping': 'off',
'jsdoc/valid-types': warnOrError
}
};
};
/**
* @param {"warn"|"error"} warnOrError
* @param {string} [flatName]
* @returns {import('eslint').Linter.FlatConfig}
*/
const createRecommendedTypeScriptRuleset = (warnOrError, flatName) => {
const ruleset = createRecommendedRuleset(warnOrError, flatName);
return {
...ruleset,
rules: {
...ruleset.rules,
/* eslint-disable indent -- Extra indent to avoid use by auto-rule-editing */
'jsdoc/check-tag-names': [warnOrError, {
typed: true
}],
'jsdoc/no-types': warnOrError,
'jsdoc/no-undefined-types': 'off',
'jsdoc/require-param-type': 'off',
'jsdoc/require-property-type': 'off',
'jsdoc/require-returns-type': 'off'
/* eslint-enable indent */
}
};
};
/**
* @param {"warn"|"error"} warnOrError
* @param {string} [flatName]
* @returns {import('eslint').Linter.FlatConfig}
*/
const createRecommendedTypeScriptFlavorRuleset = (warnOrError, flatName) => {
const ruleset = createRecommendedRuleset(warnOrError, flatName);
return {
...ruleset,
rules: {
...ruleset.rules,
/* eslint-disable indent -- Extra indent to avoid use by auto-rule-editing */
'jsdoc/no-undefined-types': 'off'
/* eslint-enable indent */
}
};
};
/* c8 ignore next 3 -- TS */
if (!index.configs) {
throw new Error('TypeScript guard');
}
index.configs.recommended = createRecommendedRuleset('warn');
index.configs['recommended-error'] = createRecommendedRuleset('error');
index.configs['recommended-typescript'] = createRecommendedTypeScriptRuleset('warn');
index.configs['recommended-typescript-error'] = createRecommendedTypeScriptRuleset('error');
index.configs['recommended-typescript-flavor'] = createRecommendedTypeScriptFlavorRuleset('warn');
index.configs['recommended-typescript-flavor-error'] = createRecommendedTypeScriptFlavorRuleset('error');
index.configs['flat/recommended'] = createRecommendedRuleset('warn', 'flat/recommended');
index.configs['flat/recommended-error'] = createRecommendedRuleset('error', 'flat/recommended-error');
index.configs['flat/recommended-typescript'] = createRecommendedTypeScriptRuleset('warn', 'flat/recommended-typescript');
index.configs['flat/recommended-typescript-error'] = createRecommendedTypeScriptRuleset('error', 'flat/recommended-typescript-error');
index.configs['flat/recommended-typescript-flavor'] = createRecommendedTypeScriptFlavorRuleset('warn', 'flat/recommended-typescript-flavor');
index.configs['flat/recommended-typescript-flavor-error'] = createRecommendedTypeScriptFlavorRuleset('error', 'flat/recommended-typescript-flavor-error');
index.configs.examples = /** @type {import('eslint').Linter.FlatConfig[]} */[{
name: 'jsdoc/examples/processor',
files: ['**/*.js'],
plugins: {
examples: (0, _getJsdocProcessorPlugin.getJsdocProcessorPlugin)()
},
processor: 'examples/examples'
}, {
name: 'jsdoc/examples/rules',
files: ['**/*.md/*.js'],
rules: {
// "always" newline rule at end unlikely in sample code
'eol-last': 0,
// Wouldn't generally expect example paths to resolve relative to JS file
'import/no-unresolved': 0,
// Snippets likely too short to always include import/export info
'import/unambiguous': 0,
'jsdoc/require-file-overview': 0,
// The end of a multiline comment would end the comment the example is in.
'jsdoc/require-jsdoc': 0,
// Unlikely to have inadvertent debugging within examples
'no-console': 0,
// Often wish to start `@example` code after newline; also may use
// empty lines for spacing
'no-multiple-empty-lines': 0,
// Many variables in examples will be `undefined`
'no-undef': 0,
// Common to define variables for clarity without always using them
'no-unused-vars': 0,
// See import/no-unresolved
'node/no-missing-import': 0,
'node/no-missing-require': 0,
// Can generally look nicer to pad a little even if code imposes more stringency
'padded-blocks': 0
}
}];
index.configs['default-expressions'] = /** @type {import('eslint').Linter.FlatConfig[]} */[{
files: ['**/*.js'],
name: 'jsdoc/default-expressions/processor',
plugins: {
examples: (0, _getJsdocProcessorPlugin.getJsdocProcessorPlugin)({
checkDefaults: true,
checkParams: true,
checkProperties: true
})
},
processor: 'examples/examples'
}, {
name: 'jsdoc/default-expressions/rules',
files: ['**/*.jsdoc-defaults', '**/*.jsdoc-params', '**/*.jsdoc-properties'],
rules: {
...index.configs.examples[1].rules,
'chai-friendly/no-unused-expressions': 0,
'no-empty-function': 0,
'no-new': 0,
'no-unused-expressions': 0,
quotes: ['error', 'double'],
semi: ['error', 'never'],
strict: 0
}
}];
index.configs['examples-and-default-expressions'] = /** @type {import('eslint').Linter.FlatConfig[]} */[{
name: 'jsdoc/examples-and-default-expressions',
plugins: {
examples: (0, _getJsdocProcessorPlugin.getJsdocProcessorPlugin)({
checkDefaults: true,
checkParams: true,
checkProperties: true
})
}
}, ...index.configs.examples.map(config => {
return {
...config,
plugins: {}
};
}), ...index.configs['default-expressions'].map(config => {
return {
...config,
plugins: {}
};
})];
var _default = exports.default = index;
module.exports = exports.default;
//# sourceMappingURL=index.cjs.map

1
node_modules/eslint-plugin-jsdoc/dist/index.cjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

19
node_modules/eslint-plugin-jsdoc/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,19 @@
export default index;
/**
* @type {import('eslint').ESLint.Plugin & {
* configs: Record<
* "recommended"|"recommended-error"|"recommended-typescript"|
* "recommended-typescript-error"|"recommended-typescript-flavor"|
* "recommended-typescript-flavor-error"|"flat/recommended"|
* "flat/recommended-error"|"flat/recommended-typescript"|
* "flat/recommended-typescript-error"|
* "flat/recommended-typescript-flavor"|
* "flat/recommended-typescript-flavor-error",
* import('eslint').Linter.FlatConfig
* >
* }}
*/
declare const index: import("eslint").ESLint.Plugin & {
configs: Record<"recommended" | "recommended-error" | "recommended-typescript" | "recommended-typescript-error" | "recommended-typescript-flavor" | "recommended-typescript-flavor-error" | "flat/recommended" | "flat/recommended-error" | "flat/recommended-typescript" | "flat/recommended-typescript-error" | "flat/recommended-typescript-flavor" | "flat/recommended-typescript-flavor-error", import("eslint").Linter.FlatConfig>;
};
//# sourceMappingURL=index.d.ts.map

1
node_modules/eslint-plugin-jsdoc/dist/index.d.ts.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":";AA2DA;;;;;;;;;;;;;GAaG;AACH,qBAbU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,GAAG;IAC1C,OAAW,EAAE,MAAM,CACnB,aAAmB,GAAC,mBAAmB,GAAC,wBAAwB,GAChE,8BAAsC,GAAC,+BAA+B,GACtE,qCAA6C,GAAC,kBAAkB,GAChE,wBAAgC,GAAC,6BAA6B,GAC9D,mCAA2C,GAC3C,oCAA4C,GAC5C,0CAAkD,EAClD,OAAa,QAAQ,EAAE,MAAM,CAAC,UAAU,CACnC,CAAA;CACF,CA+DF"}

2066
node_modules/eslint-plugin-jsdoc/dist/iterateJsdoc.cjs generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1537
node_modules/eslint-plugin-jsdoc/dist/jsdocUtils.cjs generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const accessLevels = ['package', 'private', 'protected', 'public'];
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('access', (jsdocParameter, targetTagName) => {
const desc = jsdocParameter.name + ' ' + jsdocParameter.description;
if (!accessLevels.includes(desc.trim())) {
report(`Missing valid JSDoc @${targetTagName} level.`, null, jsdocParameter);
}
});
const accessLength = utils.getTags('access').length;
const individualTagLength = utils.getPresentTags(accessLevels).length;
if (accessLength && individualTagLength) {
report('The @access tag may not be used with specific access-control tags (@package, @private, @protected, or @public).');
}
if (accessLength > 1 || individualTagLength > 1) {
report('At most one access-control tag may be present on a jsdoc block.');
}
}, {
checkPrivate: true,
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that `@access` tags have a valid value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-access.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkAccess.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkAccess.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","accessLevels","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdocParameter","targetTagName","desc","name","description","includes","trim","accessLength","getTags","length","individualTagLength","getPresentTags","checkPrivate","iterateAllJsdocs","meta","docs","url","type","module"],"sources":["../../src/rules/checkAccess.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nconst accessLevels = [\n 'package', 'private', 'protected', 'public',\n];\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('access', (jsdocParameter, targetTagName) => {\n const desc = jsdocParameter.name + ' ' + jsdocParameter.description;\n\n if (!accessLevels.includes(desc.trim())) {\n report(\n `Missing valid JSDoc @${targetTagName} level.`,\n null,\n jsdocParameter,\n );\n }\n });\n const accessLength = utils.getTags('access').length;\n const individualTagLength = utils.getPresentTags(accessLevels).length;\n if (accessLength && individualTagLength) {\n report(\n 'The @access tag may not be used with specific access-control tags (@package, @private, @protected, or @public).',\n );\n }\n\n if (accessLength > 1 || individualTagLength > 1) {\n report(\n 'At most one access-control tag may be present on a jsdoc block.',\n );\n }\n}, {\n checkPrivate: true,\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Checks that `@access` tags have a valid value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-access.md#repos-sticky-header',\n },\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C,MAAMG,YAAY,GAAG,CACnB,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAC5C;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAH,OAAA,GAEa,IAAAI,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,QAAQ,EAAE,CAACC,cAAc,EAAEC,aAAa,KAAK;IACrE,MAAMC,IAAI,GAAGF,cAAc,CAACG,IAAI,GAAG,GAAG,GAAGH,cAAc,CAACI,WAAW;IAEnE,IAAI,CAACX,YAAY,CAACY,QAAQ,CAACH,IAAI,CAACI,IAAI,CAAC,CAAC,CAAC,EAAE;MACvCT,MAAM,CACJ,wBAAwBI,aAAa,SAAS,EAC9C,IAAI,EACJD,cACF,CAAC;IACH;EACF,CAAC,CAAC;EACF,MAAMO,YAAY,GAAGT,KAAK,CAACU,OAAO,CAAC,QAAQ,CAAC,CAACC,MAAM;EACnD,MAAMC,mBAAmB,GAAGZ,KAAK,CAACa,cAAc,CAAClB,YAAY,CAAC,CAACgB,MAAM;EACrE,IAAIF,YAAY,IAAIG,mBAAmB,EAAE;IACvCb,MAAM,CACJ,iHACF,CAAC;EACH;EAEA,IAAIU,YAAY,GAAG,CAAC,IAAIG,mBAAmB,GAAG,CAAC,EAAE;IAC/Cb,MAAM,CACJ,iEACF,CAAC;EACH;AACF,CAAC,EAAE;EACDe,YAAY,EAAE,IAAI;EAClBC,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJX,WAAW,EAAE,gDAAgD;MAC7DY,GAAG,EAAE;IACP,CAAC;IACDC,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAAvB,OAAA,GAAAA,OAAA,CAAAH,OAAA","ignoreList":[]}

View File

@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} string
* @returns {string}
*/
const trimStart = string => {
return string.replace(/^\s+/u, '');
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdocNode,
report,
indent
}) => {
// `indent` is whitespace from line 1 (`/**`), so slice and account for "/".
const indentLevel = indent.length + 1;
const sourceLines = sourceCode.getText(jsdocNode).split('\n').slice(1).map(line => {
return line.split('*')[0];
}).filter(line => {
return !trimStart(line).length;
});
/** @type {import('eslint').Rule.ReportFixer} */
const fix = fixer => {
const replacement = sourceCode.getText(jsdocNode).split('\n').map((line, index) => {
// Ignore the first line and all lines not starting with `*`
const ignored = !index || trimStart(line.split('*')[0]).length;
return ignored ? line : `${indent} ${trimStart(line)}`;
}).join('\n');
return fixer.replaceText(jsdocNode, replacement);
};
sourceLines.some((line, lineNum) => {
if (line.length !== indentLevel) {
report('Expected JSDoc block to be aligned.', fix, {
line: lineNum + 1
});
return true;
}
return false;
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid alignment of JSDoc block asterisks.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-alignment.md#repos-sticky-header'
},
fixable: 'code',
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkAlignment.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkAlignment.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","trimStart","string","replace","_default","exports","iterateJsdoc","sourceCode","jsdocNode","report","indent","indentLevel","length","sourceLines","getText","split","slice","map","line","filter","fix","fixer","replacement","index","ignored","join","replaceText","some","lineNum","iterateAllJsdocs","meta","docs","description","url","fixable","type","module"],"sources":["../../src/rules/checkAlignment.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\n/**\n * @param {string} string\n * @returns {string}\n */\nconst trimStart = (string) => {\n return string.replace(/^\\s+/u, '');\n};\n\nexport default iterateJsdoc(({\n sourceCode,\n jsdocNode,\n report,\n indent,\n}) => {\n // `indent` is whitespace from line 1 (`/**`), so slice and account for \"/\".\n const indentLevel = indent.length + 1;\n const sourceLines = sourceCode.getText(jsdocNode).split('\\n')\n .slice(1)\n .map((line) => {\n return line.split('*')[0];\n })\n .filter((line) => {\n return !trimStart(line).length;\n });\n\n /** @type {import('eslint').Rule.ReportFixer} */\n const fix = (fixer) => {\n const replacement = sourceCode.getText(jsdocNode).split('\\n')\n .map((line, index) => {\n // Ignore the first line and all lines not starting with `*`\n const ignored = !index || trimStart(line.split('*')[0]).length;\n\n return ignored ? line : `${indent} ${trimStart(line)}`;\n })\n .join('\\n');\n\n return fixer.replaceText(jsdocNode, replacement);\n };\n\n sourceLines.some((line, lineNum) => {\n if (line.length !== indentLevel) {\n report('Expected JSDoc block to be aligned.', fix, {\n line: lineNum + 1,\n });\n\n return true;\n }\n\n return false;\n });\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Reports invalid alignment of JSDoc block asterisks.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-alignment.md#repos-sticky-header',\n },\n fixable: 'code',\n type: 'layout',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C;AACA;AACA;AACA;AACA,MAAMG,SAAS,GAAIC,MAAM,IAAK;EAC5B,OAAOA,MAAM,CAACC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;AACpC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAL,OAAA,GAEa,IAAAM,qBAAY,EAAC,CAAC;EAC3BC,UAAU;EACVC,SAAS;EACTC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ;EACA,MAAMC,WAAW,GAAGD,MAAM,CAACE,MAAM,GAAG,CAAC;EACrC,MAAMC,WAAW,GAAGN,UAAU,CAACO,OAAO,CAACN,SAAS,CAAC,CAACO,KAAK,CAAC,IAAI,CAAC,CAC1DC,KAAK,CAAC,CAAC,CAAC,CACRC,GAAG,CAAEC,IAAI,IAAK;IACb,OAAOA,IAAI,CAACH,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;EAC3B,CAAC,CAAC,CACDI,MAAM,CAAED,IAAI,IAAK;IAChB,OAAO,CAACjB,SAAS,CAACiB,IAAI,CAAC,CAACN,MAAM;EAChC,CAAC,CAAC;;EAEJ;EACA,MAAMQ,GAAG,GAAIC,KAAK,IAAK;IACrB,MAAMC,WAAW,GAAGf,UAAU,CAACO,OAAO,CAACN,SAAS,CAAC,CAACO,KAAK,CAAC,IAAI,CAAC,CAC1DE,GAAG,CAAC,CAACC,IAAI,EAAEK,KAAK,KAAK;MACpB;MACA,MAAMC,OAAO,GAAG,CAACD,KAAK,IAAItB,SAAS,CAACiB,IAAI,CAACH,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAACH,MAAM;MAE9D,OAAOY,OAAO,GAAGN,IAAI,GAAG,GAAGR,MAAM,IAAIT,SAAS,CAACiB,IAAI,CAAC,EAAE;IACxD,CAAC,CAAC,CACDO,IAAI,CAAC,IAAI,CAAC;IAEb,OAAOJ,KAAK,CAACK,WAAW,CAAClB,SAAS,EAAEc,WAAW,CAAC;EAClD,CAAC;EAEDT,WAAW,CAACc,IAAI,CAAC,CAACT,IAAI,EAAEU,OAAO,KAAK;IAClC,IAAIV,IAAI,CAACN,MAAM,KAAKD,WAAW,EAAE;MAC/BF,MAAM,CAAC,qCAAqC,EAAEW,GAAG,EAAE;QACjDF,IAAI,EAAEU,OAAO,GAAG;MAClB,CAAC,CAAC;MAEF,OAAO,IAAI;IACb;IAEA,OAAO,KAAK;EACd,CAAC,CAAC;AACJ,CAAC,EAAE;EACDC,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,qDAAqD;MAClEC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA/B,OAAA,GAAAA,OAAA,CAAAL,OAAA","ignoreList":[]}

View File

@ -0,0 +1,512 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _eslint = _interopRequireWildcard(require("eslint"));
var _semver = _interopRequireDefault(require("semver"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// Todo: When replace `CLIEngine` with `ESLint` when feature set complete per https://github.com/eslint/eslint/issues/14745
// https://github.com/eslint/eslint/blob/master/docs/user-guide/migrating-to-7.0.0.md#-the-cliengine-class-has-been-deprecated
const {
// @ts-expect-error Older ESLint
CLIEngine
} = _eslint.default;
const zeroBasedLineIndexAdjust = -1;
const likelyNestedJSDocIndentSpace = 1;
const preTagSpaceLength = 1;
// If a space is present, we should ignore it
const firstLinePrefixLength = preTagSpaceLength;
const hasCaptionRegex = /^\s*<caption>([\s\S]*?)<\/caption>/u;
/**
* @param {string} str
* @returns {string}
*/
const escapeStringRegexp = str => {
return str.replaceAll(/[.*+?^${}()|[\]\\]/gu, '\\$&');
};
/**
* @param {string} str
* @param {string} ch
* @returns {import('../iterateJsdoc.js').Integer}
*/
const countChars = (str, ch) => {
return (str.match(new RegExp(escapeStringRegexp(ch), 'gu')) || []).length;
};
/** @type {import('eslint').Linter.RulesRecord} */
const defaultMdRules = {
// "always" newline rule at end unlikely in sample code
'eol-last': 0,
// Wouldn't generally expect example paths to resolve relative to JS file
'import/no-unresolved': 0,
// Snippets likely too short to always include import/export info
'import/unambiguous': 0,
'jsdoc/require-file-overview': 0,
// The end of a multiline comment would end the comment the example is in.
'jsdoc/require-jsdoc': 0,
// Unlikely to have inadvertent debugging within examples
'no-console': 0,
// Often wish to start `@example` code after newline; also may use
// empty lines for spacing
'no-multiple-empty-lines': 0,
// Many variables in examples will be `undefined`
'no-undef': 0,
// Common to define variables for clarity without always using them
'no-unused-vars': 0,
// See import/no-unresolved
'node/no-missing-import': 0,
'node/no-missing-require': 0,
// Can generally look nicer to pad a little even if code imposes more stringency
'padded-blocks': 0
};
/** @type {import('eslint').Linter.RulesRecord} */
const defaultExpressionRules = {
...defaultMdRules,
'chai-friendly/no-unused-expressions': 'off',
'no-empty-function': 'off',
'no-new': 'off',
'no-unused-expressions': 'off',
quotes: ['error', 'double'],
semi: ['error', 'never'],
strict: 'off'
};
/**
* @param {string} text
* @returns {[
* import('../iterateJsdoc.js').Integer,
* import('../iterateJsdoc.js').Integer
* ]}
*/
const getLinesCols = text => {
const matchLines = countChars(text, '\n');
const colDelta = matchLines ? text.slice(text.lastIndexOf('\n') + 1).length : text.length;
return [matchLines, colDelta];
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils,
context,
globalState
}) => {
if (_semver.default.gte(_eslint.ESLint.version, '8.0.0')) {
report('This rule does not work for ESLint 8+; you should disable this rule and use' + 'the processor mentioned in the docs.', null, {
column: 1,
line: 1
});
return;
}
if (!globalState.has('checkExamples-matchingFileName')) {
globalState.set('checkExamples-matchingFileName', new Map());
}
const matchingFileNameMap = /** @type {Map<string, string>} */
globalState.get('checkExamples-matchingFileName');
const options = context.options[0] || {};
let {
exampleCodeRegex = null,
rejectExampleCodeRegex = null
} = options;
const {
checkDefaults = false,
checkParams = false,
checkProperties = false,
noDefaultExampleRules = false,
checkEslintrc = true,
matchingFileName = null,
matchingFileNameDefaults = null,
matchingFileNameParams = null,
matchingFileNameProperties = null,
paddedIndent = 0,
baseConfig = {},
configFile,
allowInlineConfig = true,
reportUnusedDisableDirectives = true,
captionRequired = false
} = options;
// Make this configurable?
/**
* @type {never[]}
*/
const rulePaths = [];
const mdRules = noDefaultExampleRules ? undefined : defaultMdRules;
const expressionRules = noDefaultExampleRules ? undefined : defaultExpressionRules;
if (exampleCodeRegex) {
exampleCodeRegex = utils.getRegexFromString(exampleCodeRegex);
}
if (rejectExampleCodeRegex) {
rejectExampleCodeRegex = utils.getRegexFromString(rejectExampleCodeRegex);
}
/**
* @param {{
* filename: string,
* defaultFileName: string|undefined,
* source: string,
* targetTagName: string,
* rules?: import('eslint').Linter.RulesRecord|undefined,
* lines?: import('../iterateJsdoc.js').Integer,
* cols?: import('../iterateJsdoc.js').Integer,
* skipInit?: boolean,
* sources?: {
* nonJSPrefacingCols: import('../iterateJsdoc.js').Integer,
* nonJSPrefacingLines: import('../iterateJsdoc.js').Integer,
* string: string,
* }[],
* tag?: import('comment-parser').Spec & {
* line?: import('../iterateJsdoc.js').Integer,
* }|{
* line: import('../iterateJsdoc.js').Integer,
* }
* }} cfg
*/
const checkSource = ({
filename,
defaultFileName,
rules = expressionRules,
lines = 0,
cols = 0,
skipInit,
source,
targetTagName,
sources = [],
tag = {
line: 0
}
}) => {
if (!skipInit) {
sources.push({
nonJSPrefacingCols: cols,
nonJSPrefacingLines: lines,
string: source
});
}
// Todo: Make fixable
/**
* @param {{
* nonJSPrefacingCols: import('../iterateJsdoc.js').Integer,
* nonJSPrefacingLines: import('../iterateJsdoc.js').Integer,
* string: string
* }} cfg
*/
const checkRules = function ({
nonJSPrefacingCols,
nonJSPrefacingLines,
string
}) {
const cliConfig = {
allowInlineConfig,
baseConfig,
configFile,
reportUnusedDisableDirectives,
rulePaths,
rules,
useEslintrc: checkEslintrc
};
const cliConfigStr = JSON.stringify(cliConfig);
const src = paddedIndent ? string.replaceAll(new RegExp(`(^|\n) {${paddedIndent}}(?!$)`, 'gu'), '\n') : string;
// Programmatic ESLint API: https://eslint.org/docs/developer-guide/nodejs-api
const fileNameMapKey = filename ? 'a' + cliConfigStr + filename : 'b' + cliConfigStr + defaultFileName;
const file = filename || defaultFileName;
let cliFile;
if (matchingFileNameMap.has(fileNameMapKey)) {
cliFile = matchingFileNameMap.get(fileNameMapKey);
} else {
const cli = new CLIEngine(cliConfig);
let config;
if (filename || checkEslintrc) {
config = cli.getConfigForFile(file);
}
// We need a new instance to ensure that the rules that may only
// be available to `file` (if it has its own `.eslintrc`),
// will be defined.
cliFile = new CLIEngine({
allowInlineConfig,
baseConfig: {
...baseConfig,
...config
},
configFile,
reportUnusedDisableDirectives,
rulePaths,
rules,
useEslintrc: false
});
matchingFileNameMap.set(fileNameMapKey, cliFile);
}
const {
results: [{
messages
}]
} = cliFile.executeOnText(src);
if (!('line' in tag)) {
tag.line = tag.source[0].number;
}
// NOTE: `tag.line` can be 0 if of form `/** @tag ... */`
const codeStartLine =
/**
* @type {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer,
* }}
*/
tag.line + nonJSPrefacingLines;
const codeStartCol = likelyNestedJSDocIndentSpace;
for (const {
message,
line,
column,
severity,
ruleId
} of messages) {
const startLine = codeStartLine + line + zeroBasedLineIndexAdjust;
const startCol = codeStartCol + (
// This might not work for line 0, but line 0 is unlikely for examples
line <= 1 ? nonJSPrefacingCols + firstLinePrefixLength : preTagSpaceLength) + column;
report('@' + targetTagName + ' ' + (severity === 2 ? 'error' : 'warning') + (ruleId ? ' (' + ruleId + ')' : '') + ': ' + message, null, {
column: startCol,
line: startLine
});
}
};
for (const targetSource of sources) {
checkRules(targetSource);
}
};
/**
*
* @param {string} filename
* @param {string} [ext] Since `eslint-plugin-markdown` v2, and
* ESLint 7, this is the default which other JS-fenced rules will used.
* Formerly "md" was the default.
* @returns {{defaultFileName: string|undefined, filename: string}}
*/
const getFilenameInfo = (filename, ext = 'md/*.js') => {
let defaultFileName;
if (!filename) {
const jsFileName = context.getFilename();
if (typeof jsFileName === 'string' && jsFileName.includes('.')) {
defaultFileName = jsFileName.replace(/\.[^.]*$/u, `.${ext}`);
} else {
defaultFileName = `dummy.${ext}`;
}
}
return {
defaultFileName,
filename
};
};
if (checkDefaults) {
const filenameInfo = getFilenameInfo(matchingFileNameDefaults, 'jsdoc-defaults');
utils.forEachPreferredTag('default', (tag, targetTagName) => {
if (!tag.description.trim()) {
return;
}
checkSource({
source: `(${utils.getTagDescription(tag)})`,
targetTagName,
...filenameInfo
});
});
}
if (checkParams) {
const filenameInfo = getFilenameInfo(matchingFileNameParams, 'jsdoc-params');
utils.forEachPreferredTag('param', (tag, targetTagName) => {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: `(${tag.default})`,
targetTagName,
...filenameInfo
});
});
}
if (checkProperties) {
const filenameInfo = getFilenameInfo(matchingFileNameProperties, 'jsdoc-properties');
utils.forEachPreferredTag('property', (tag, targetTagName) => {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: `(${tag.default})`,
targetTagName,
...filenameInfo
});
});
}
const tagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'example'
});
if (!utils.hasTag(tagName)) {
return;
}
const matchingFilenameInfo = getFilenameInfo(matchingFileName);
utils.forEachPreferredTag('example', (tag, targetTagName) => {
let source = /** @type {string} */utils.getTagDescription(tag);
const match = source.match(hasCaptionRegex);
if (captionRequired && (!match || !match[1].trim())) {
report('Caption is expected for examples.', null, tag);
}
source = source.replace(hasCaptionRegex, '');
const [lines, cols] = match ? getLinesCols(match[0]) : [0, 0];
if (exampleCodeRegex && !exampleCodeRegex.test(source) || rejectExampleCodeRegex && rejectExampleCodeRegex.test(source)) {
return;
}
const sources = [];
let skipInit = false;
if (exampleCodeRegex) {
let nonJSPrefacingCols = 0;
let nonJSPrefacingLines = 0;
let startingIndex = 0;
let lastStringCount = 0;
let exampleCode;
exampleCodeRegex.lastIndex = 0;
while ((exampleCode = exampleCodeRegex.exec(source)) !== null) {
const {
index,
'0': n0,
'1': n1
} = exampleCode;
// Count anything preceding user regex match (can affect line numbering)
const preMatch = source.slice(startingIndex, index);
const [preMatchLines, colDelta] = getLinesCols(preMatch);
let nonJSPreface;
let nonJSPrefaceLineCount;
if (n1) {
const idx = n0.indexOf(n1);
nonJSPreface = n0.slice(0, idx);
nonJSPrefaceLineCount = countChars(nonJSPreface, '\n');
} else {
nonJSPreface = '';
nonJSPrefaceLineCount = 0;
}
nonJSPrefacingLines += lastStringCount + preMatchLines + nonJSPrefaceLineCount;
// Ignore `preMatch` delta if newlines here
if (nonJSPrefaceLineCount) {
const charsInLastLine = nonJSPreface.slice(nonJSPreface.lastIndexOf('\n') + 1).length;
nonJSPrefacingCols += charsInLastLine;
} else {
nonJSPrefacingCols += colDelta + nonJSPreface.length;
}
const string = n1 || n0;
sources.push({
nonJSPrefacingCols,
nonJSPrefacingLines,
string
});
startingIndex = exampleCodeRegex.lastIndex;
lastStringCount = countChars(string, '\n');
if (!exampleCodeRegex.global) {
break;
}
}
skipInit = true;
}
checkSource({
cols,
lines,
rules: mdRules,
skipInit,
source,
sources,
tag,
targetTagName,
...matchingFilenameInfo
});
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Ensures that (JavaScript) examples within JSDoc adhere to ESLint rules.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-examples.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
allowInlineConfig: {
default: true,
type: 'boolean'
},
baseConfig: {
type: 'object'
},
captionRequired: {
default: false,
type: 'boolean'
},
checkDefaults: {
default: false,
type: 'boolean'
},
checkEslintrc: {
default: true,
type: 'boolean'
},
checkParams: {
default: false,
type: 'boolean'
},
checkProperties: {
default: false,
type: 'boolean'
},
configFile: {
type: 'string'
},
exampleCodeRegex: {
type: 'string'
},
matchingFileName: {
type: 'string'
},
matchingFileNameDefaults: {
type: 'string'
},
matchingFileNameParams: {
type: 'string'
},
matchingFileNameProperties: {
type: 'string'
},
noDefaultExampleRules: {
default: false,
type: 'boolean'
},
paddedIndent: {
default: 0,
type: 'integer'
},
rejectExampleCodeRegex: {
type: 'string'
},
reportUnusedDisableDirectives: {
default: true,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkExamples.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} str
* @param {string[]} excludeTags
* @returns {string}
*/
const maskExcludedContent = (str, excludeTags) => {
const regContent = new RegExp(`([ \\t]+\\*)[ \\t]@(?:${excludeTags.join('|')})(?=[ \\n])([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*@\\w+\\s|\\/))`, 'gu');
return str.replace(regContent, (_match, margin, code) => {
return (margin + '\n').repeat(code.match(/\n/gu).length);
});
};
/**
* @param {string} str
* @returns {string}
*/
const maskCodeBlocks = str => {
const regContent = /([ \t]+\*)[ \t]```[^\n]*?([\w|\W]*?\n)(?=[ \t]*\*(?:[ \t]*(?:```|@\w+\s)|\/))/gu;
return str.replaceAll(regContent, (_match, margin, code) => {
return (margin + '\n').repeat(code.match(/\n/gu).length);
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdocNode,
report,
context
}) => {
const options = context.options[0] || {};
const /** @type {{excludeTags: string[]}} */{
excludeTags = ['example']
} = options;
const reg = /^(?:\/?\**|[ \t]*)\*[ \t]{2}/gmu;
const textWithoutCodeBlocks = maskCodeBlocks(sourceCode.getText(jsdocNode));
const text = excludeTags.length ? maskExcludedContent(textWithoutCodeBlocks, excludeTags) : textWithoutCodeBlocks;
if (reg.test(text)) {
const lineBreaks = text.slice(0, reg.lastIndex).match(/\n/gu) || [];
report('There must be no indentation.', null, {
line: lineBreaks.length
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid padding inside JSDoc blocks.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
excludeTags: {
items: {
pattern: '^\\S+$',
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkIndentation.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkIndentation.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","maskExcludedContent","str","excludeTags","regContent","RegExp","join","replace","_match","margin","code","repeat","match","length","maskCodeBlocks","replaceAll","_default","exports","iterateJsdoc","sourceCode","jsdocNode","report","context","options","reg","textWithoutCodeBlocks","getText","text","test","lineBreaks","slice","lastIndex","line","iterateAllJsdocs","meta","docs","description","url","schema","additionalProperties","properties","items","pattern","type","module"],"sources":["../../src/rules/checkIndentation.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\n/**\n * @param {string} str\n * @param {string[]} excludeTags\n * @returns {string}\n */\nconst maskExcludedContent = (str, excludeTags) => {\n const regContent = new RegExp(`([ \\\\t]+\\\\*)[ \\\\t]@(?:${excludeTags.join('|')})(?=[ \\\\n])([\\\\w|\\\\W]*?\\\\n)(?=[ \\\\t]*\\\\*(?:[ \\\\t]*@\\\\w+\\\\s|\\\\/))`, 'gu');\n\n return str.replace(regContent, (_match, margin, code) => {\n return (margin + '\\n').repeat(code.match(/\\n/gu).length);\n });\n};\n\n/**\n * @param {string} str\n * @returns {string}\n */\nconst maskCodeBlocks = (str) => {\n const regContent = /([ \\t]+\\*)[ \\t]```[^\\n]*?([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*(?:```|@\\w+\\s)|\\/))/gu;\n\n return str.replaceAll(regContent, (_match, margin, code) => {\n return (margin + '\\n').repeat(code.match(/\\n/gu).length);\n });\n};\n\nexport default iterateJsdoc(({\n sourceCode,\n jsdocNode,\n report,\n context,\n}) => {\n const options = context.options[0] || {};\n const /** @type {{excludeTags: string[]}} */ {\n excludeTags = [\n 'example',\n ],\n } = options;\n\n const reg = /^(?:\\/?\\**|[ \\t]*)\\*[ \\t]{2}/gmu;\n const textWithoutCodeBlocks = maskCodeBlocks(sourceCode.getText(jsdocNode));\n const text = excludeTags.length ? maskExcludedContent(textWithoutCodeBlocks, excludeTags) : textWithoutCodeBlocks;\n\n if (reg.test(text)) {\n const lineBreaks = text.slice(0, reg.lastIndex).match(/\\n/gu) || [];\n report('There must be no indentation.', null, {\n line: lineBreaks.length,\n });\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Reports invalid padding inside JSDoc blocks.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n excludeTags: {\n items: {\n pattern: '^\\\\S+$',\n type: 'string',\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'layout',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C;AACA;AACA;AACA;AACA;AACA,MAAMG,mBAAmB,GAAGA,CAACC,GAAG,EAAEC,WAAW,KAAK;EAChD,MAAMC,UAAU,GAAG,IAAIC,MAAM,CAAC,yBAAyBF,WAAW,CAACG,IAAI,CAAC,GAAG,CAAC,kEAAkE,EAAE,IAAI,CAAC;EAErJ,OAAOJ,GAAG,CAACK,OAAO,CAACH,UAAU,EAAE,CAACI,MAAM,EAAEC,MAAM,EAAEC,IAAI,KAAK;IACvD,OAAO,CAACD,MAAM,GAAG,IAAI,EAAEE,MAAM,CAACD,IAAI,CAACE,KAAK,CAAC,MAAM,CAAC,CAACC,MAAM,CAAC;EAC1D,CAAC,CAAC;AACJ,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMC,cAAc,GAAIZ,GAAG,IAAK;EAC9B,MAAME,UAAU,GAAG,iFAAiF;EAEpG,OAAOF,GAAG,CAACa,UAAU,CAACX,UAAU,EAAE,CAACI,MAAM,EAAEC,MAAM,EAAEC,IAAI,KAAK;IAC1D,OAAO,CAACD,MAAM,GAAG,IAAI,EAAEE,MAAM,CAACD,IAAI,CAACE,KAAK,CAAC,MAAM,CAAC,CAACC,MAAM,CAAC;EAC1D,CAAC,CAAC;AACJ,CAAC;AAAC,IAAAG,QAAA,GAAAC,OAAA,CAAAjB,OAAA,GAEa,IAAAkB,qBAAY,EAAC,CAAC;EAC3BC,UAAU;EACVC,SAAS;EACTC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,MAAMC,OAAO,GAAGD,OAAO,CAACC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EACxC,MAAM,sCAAuC;IAC3CpB,WAAW,GAAG,CACZ,SAAS;EAEb,CAAC,GAAGoB,OAAO;EAEX,MAAMC,GAAG,GAAG,iCAAiC;EAC7C,MAAMC,qBAAqB,GAAGX,cAAc,CAACK,UAAU,CAACO,OAAO,CAACN,SAAS,CAAC,CAAC;EAC3E,MAAMO,IAAI,GAAGxB,WAAW,CAACU,MAAM,GAAGZ,mBAAmB,CAACwB,qBAAqB,EAAEtB,WAAW,CAAC,GAAGsB,qBAAqB;EAEjH,IAAID,GAAG,CAACI,IAAI,CAACD,IAAI,CAAC,EAAE;IAClB,MAAME,UAAU,GAAGF,IAAI,CAACG,KAAK,CAAC,CAAC,EAAEN,GAAG,CAACO,SAAS,CAAC,CAACnB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;IACnES,MAAM,CAAC,+BAA+B,EAAE,IAAI,EAAE;MAC5CW,IAAI,EAAEH,UAAU,CAAChB;IACnB,CAAC,CAAC;EACJ;AACF,CAAC,EAAE;EACDoB,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,8CAA8C;MAC3DC,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVrC,WAAW,EAAE;UACXsC,KAAK,EAAE;YACLC,OAAO,EAAE,QAAQ;YACjBC,IAAI,EAAE;UACR,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA3B,OAAA,GAAAA,OAAA,CAAAjB,OAAA","ignoreList":[]}

View File

@ -0,0 +1,321 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _alignTransform = _interopRequireDefault(require("../alignTransform.cjs"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _commentParser = require("comment-parser");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const {
flow: commentFlow
} = _commentParser.transforms;
/**
* @typedef {{
* postDelimiter: import('../iterateJsdoc.js').Integer,
* postHyphen: import('../iterateJsdoc.js').Integer,
* postName: import('../iterateJsdoc.js').Integer,
* postTag: import('../iterateJsdoc.js').Integer,
* postType: import('../iterateJsdoc.js').Integer,
* }} CustomSpacings
*/
/**
* @param {import('../iterateJsdoc.js').Utils} utils
* @param {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer
* }} tag
* @param {CustomSpacings} customSpacings
*/
const checkNotAlignedPerTag = (utils, tag, customSpacings) => {
/*
start +
delimiter +
postDelimiter +
tag +
postTag +
type +
postType +
name +
postName +
description +
end +
lineEnd
*/
/**
* @typedef {"tag"|"type"|"name"|"description"} ContentProp
*/
/** @type {("postDelimiter"|"postTag"|"postType"|"postName")[]} */
let spacerProps;
/** @type {ContentProp[]} */
let contentProps;
const mightHaveNamepath = utils.tagMightHaveNamepath(tag.tag);
if (mightHaveNamepath) {
spacerProps = ['postDelimiter', 'postTag', 'postType', 'postName'];
contentProps = ['tag', 'type', 'name', 'description'];
} else {
spacerProps = ['postDelimiter', 'postTag', 'postType'];
contentProps = ['tag', 'type', 'description'];
}
const {
tokens
} = tag.source[0];
/**
* @param {import('../iterateJsdoc.js').Integer} idx
* @param {(notRet: boolean, contentProp: ContentProp) => void} [callbck]
*/
const followedBySpace = (idx, callbck) => {
const nextIndex = idx + 1;
return spacerProps.slice(nextIndex).some((spacerProp, innerIdx) => {
const contentProp = contentProps[nextIndex + innerIdx];
const spacePropVal = tokens[spacerProp];
const ret = spacePropVal;
if (callbck) {
callbck(!ret, contentProp);
}
return ret && (callbck || !contentProp);
});
};
const postHyphenSpacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postHyphen) ?? 1;
const exactHyphenSpacing = new RegExp(`^\\s*-\\s{${postHyphenSpacing},${postHyphenSpacing}}(?!\\s)`, 'u');
const hasNoHyphen = !/^\s*-(?!$)(?=\s)/u.test(tokens.description);
const hasExactHyphenSpacing = exactHyphenSpacing.test(tokens.description);
// If checking alignment on multiple lines, need to check other `source`
// items
// Go through `post*` spacing properties and exit to indicate problem if
// extra spacing detected
const ok = !spacerProps.some((spacerProp, idx) => {
const contentProp = contentProps[idx];
const contentPropVal = tokens[contentProp];
const spacerPropVal = tokens[spacerProp];
const spacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings[spacerProp]) || 1;
// There will be extra alignment if...
// 1. The spaces don't match the space it should have (1 or custom spacing) OR
return spacerPropVal.length !== spacing && spacerPropVal.length !== 0 ||
// 2. There is a (single) space, no immediate content, and yet another
// space is found subsequently (not separated by intervening content)
spacerPropVal && !contentPropVal && followedBySpace(idx);
}) && (hasNoHyphen || hasExactHyphenSpacing);
if (ok) {
return;
}
const fix = () => {
for (const [idx, spacerProp] of spacerProps.entries()) {
const contentProp = contentProps[idx];
const contentPropVal = tokens[contentProp];
if (contentPropVal) {
const spacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings[spacerProp]) || 1;
tokens[spacerProp] = ''.padStart(spacing, ' ');
followedBySpace(idx, (hasSpace, contentPrp) => {
if (hasSpace) {
tokens[contentPrp] = '';
}
});
} else {
tokens[spacerProp] = '';
}
}
if (!hasExactHyphenSpacing) {
const hyphenSpacing = /^\s*-\s+/u;
tokens.description = tokens.description.replace(hyphenSpacing, '-' + ''.padStart(postHyphenSpacing, ' '));
}
utils.setTag(tag, tokens);
};
utils.reportJSDoc('Expected JSDoc block lines to not be aligned.', tag, fix, true);
};
/**
* @param {object} cfg
* @param {CustomSpacings} cfg.customSpacings
* @param {string} cfg.indent
* @param {import('comment-parser').Block} cfg.jsdoc
* @param {import('eslint').Rule.Node & {
* range: [number, number]
* }} cfg.jsdocNode
* @param {boolean} cfg.preserveMainDescriptionPostDelimiter
* @param {import('../iterateJsdoc.js').Report} cfg.report
* @param {string[]} cfg.tags
* @param {import('../iterateJsdoc.js').Utils} cfg.utils
* @param {string} cfg.wrapIndent
* @param {boolean} cfg.disableWrapIndent
* @returns {void}
*/
const checkAlignment = ({
customSpacings,
indent,
jsdoc,
jsdocNode,
preserveMainDescriptionPostDelimiter,
report,
tags,
utils,
wrapIndent,
disableWrapIndent
}) => {
const transform = commentFlow((0, _alignTransform.default)({
customSpacings,
indent,
preserveMainDescriptionPostDelimiter,
tags,
wrapIndent,
disableWrapIndent
}));
const transformedJsdoc = transform(jsdoc);
const comment = '/*' +
/**
* @type {import('eslint').Rule.Node & {
* range: [number, number], value: string
* }}
*/
jsdocNode.value + '*/';
const formatted = utils.stringify(transformedJsdoc).trimStart();
if (comment !== formatted) {
report('Expected JSDoc block lines to be aligned.', /** @type {import('eslint').Rule.ReportFixer} */fixer => {
return fixer.replaceText(jsdocNode, formatted);
});
}
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
indent,
jsdoc,
jsdocNode,
report,
context,
utils
}) => {
const {
tags: applicableTags = ['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return'],
preserveMainDescriptionPostDelimiter,
customSpacings,
wrapIndent = '',
disableWrapIndent = false
} = context.options[1] || {};
if (context.options[0] === 'always') {
// Skip if it contains only a single line.
if (!(
/**
* @type {import('eslint').Rule.Node & {
* range: [number, number], value: string
* }}
*/
jsdocNode.value.includes('\n'))) {
return;
}
checkAlignment({
customSpacings,
indent,
jsdoc,
jsdocNode,
preserveMainDescriptionPostDelimiter,
report,
tags: applicableTags,
utils,
wrapIndent,
disableWrapIndent
});
return;
}
const foundTags = utils.getPresentTags(applicableTags);
if (context.options[0] !== 'any') {
for (const tag of foundTags) {
checkNotAlignedPerTag(utils,
/**
* @type {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer
* }}
*/
tag, customSpacings);
}
}
for (const tag of foundTags) {
if (tag.source.length > 1) {
let idx = 0;
for (const {
tokens
// Avoid the tag line
} of tag.source.slice(1)) {
idx++;
if (!tokens.description ||
// Avoid first lines after multiline type
tokens.type || tokens.name) {
continue;
}
// Don't include a single separating space/tab
if (!disableWrapIndent && tokens.postDelimiter.slice(1) !== wrapIndent) {
utils.reportJSDoc('Expected wrap indent', {
line: tag.source[0].number + idx
}, () => {
tokens.postDelimiter = tokens.postDelimiter.charAt(0) + wrapIndent;
});
return;
}
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid alignment of JSDoc block lines.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-line-alignment.md#repos-sticky-header'
},
fixable: 'whitespace',
schema: [{
enum: ['always', 'never', 'any'],
type: 'string'
}, {
additionalProperties: false,
properties: {
customSpacings: {
additionalProperties: false,
properties: {
postDelimiter: {
type: 'integer'
},
postHyphen: {
type: 'integer'
},
postName: {
type: 'integer'
},
postTag: {
type: 'integer'
},
postType: {
type: 'integer'
}
}
},
preserveMainDescriptionPostDelimiter: {
default: false,
type: 'boolean'
},
tags: {
items: {
type: 'string'
},
type: 'array'
},
wrapIndent: {
type: 'string'
},
disableWrapIndent: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkLineAlignment.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,329 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} targetTagName
* @param {boolean} allowExtraTrailingParamDocs
* @param {boolean} checkDestructured
* @param {boolean} checkRestProperty
* @param {RegExp} checkTypesRegex
* @param {boolean} disableExtraPropertyReporting
* @param {boolean} disableMissingParamChecks
* @param {boolean} enableFixer
* @param {import('../jsdocUtils.js').ParamNameInfo[]} functionParameterNames
* @param {import('comment-parser').Block} jsdoc
* @param {import('../iterateJsdoc.js').Utils} utils
* @param {import('../iterateJsdoc.js').Report} report
* @returns {boolean}
*/
const validateParameterNames = (targetTagName, allowExtraTrailingParamDocs, checkDestructured, checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, disableMissingParamChecks, enableFixer, functionParameterNames, jsdoc, utils, report) => {
const paramTags = Object.entries(jsdoc.tags).filter(([, tag]) => {
return tag.tag === targetTagName;
});
const paramTagsNonNested = paramTags.filter(([, tag]) => {
return !tag.name.includes('.');
});
let dotted = 0;
let thisOffset = 0;
// eslint-disable-next-line complexity
return paramTags.some(([, tag], index) => {
/** @type {import('../iterateJsdoc.js').Integer} */
let tagsIndex;
const dupeTagInfo = paramTags.find(([tgsIndex, tg], idx) => {
tagsIndex = Number(tgsIndex);
return tg.name === tag.name && idx !== index;
});
if (dupeTagInfo) {
utils.reportJSDoc(`Duplicate @${targetTagName} "${tag.name}"`, dupeTagInfo[1], enableFixer ? () => {
utils.removeTag(tagsIndex);
} : null);
return true;
}
if (tag.name.includes('.')) {
dotted++;
return false;
}
let functionParameterName = functionParameterNames[index - dotted + thisOffset];
if (functionParameterName === 'this' && tag.name.trim() !== 'this') {
++thisOffset;
functionParameterName = functionParameterNames[index - dotted + thisOffset];
}
if (!functionParameterName) {
if (allowExtraTrailingParamDocs) {
return false;
}
report(`@${targetTagName} "${tag.name}" does not match an existing function parameter.`, null, tag);
return true;
}
if (typeof functionParameterName === 'object' && 'name' in functionParameterName && Array.isArray(functionParameterName.name)) {
const actualName = tag.name.trim();
const expectedName = functionParameterName.name[index];
if (actualName === expectedName) {
thisOffset--;
return false;
}
report(`Expected @${targetTagName} name to be "${expectedName}". Got "${actualName}".`, null, tag);
return true;
}
if (Array.isArray(functionParameterName)) {
if (!checkDestructured) {
return false;
}
if (tag.type && tag.type.search(checkTypesRegex) === -1) {
return false;
}
const [parameterName, {
names: properties,
hasPropertyRest,
rests,
annotationParamName
}] =
/**
* @type {[string | undefined, import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string | undefined;
}]} */
functionParameterName;
if (annotationParamName !== undefined) {
const name = tag.name.trim();
if (name !== annotationParamName) {
report(`@${targetTagName} "${name}" does not match parameter name "${annotationParamName}"`, null, tag);
}
}
const tagName = parameterName === undefined ? tag.name.trim() : parameterName;
const expectedNames = properties.map(name => {
return `${tagName}.${name}`;
});
const actualNames = paramTags.map(([, paramTag]) => {
return paramTag.name.trim();
});
const actualTypes = paramTags.map(([, paramTag]) => {
return paramTag.type;
});
const missingProperties = [];
/** @type {string[]} */
const notCheckingNames = [];
for (const [idx, name] of expectedNames.entries()) {
if (notCheckingNames.some(notCheckingName => {
return name.startsWith(notCheckingName);
})) {
continue;
}
const actualNameIdx = actualNames.findIndex(actualName => {
return utils.comparePaths(name)(actualName);
});
if (actualNameIdx === -1) {
if (!checkRestProperty && rests[idx]) {
continue;
}
const missingIndex = actualNames.findIndex(actualName => {
return utils.pathDoesNotBeginWith(name, actualName);
});
const line = tag.source[0].number - 1 + (missingIndex > -1 ? missingIndex : actualNames.length);
missingProperties.push({
name,
tagPlacement: {
line: line === 0 ? 1 : line
}
});
} else if (actualTypes[actualNameIdx].search(checkTypesRegex) === -1 && actualTypes[actualNameIdx] !== '') {
notCheckingNames.push(name);
}
}
const hasMissing = missingProperties.length;
if (hasMissing) {
for (const {
tagPlacement,
name: missingProperty
} of missingProperties) {
report(`Missing @${targetTagName} "${missingProperty}"`, null, tagPlacement);
}
}
if (!hasPropertyRest || checkRestProperty) {
/** @type {[string, import('comment-parser').Spec][]} */
const extraProperties = [];
for (const [idx, name] of actualNames.entries()) {
const match = name.startsWith(tag.name.trim() + '.');
if (match && !expectedNames.some(utils.comparePaths(name)) && !utils.comparePaths(name)(tag.name) && (!disableExtraPropertyReporting || properties.some(prop => {
return prop.split('.').length >= name.split('.').length - 1;
}))) {
extraProperties.push([name, paramTags[idx][1]]);
}
}
if (extraProperties.length) {
for (const [extraProperty, tg] of extraProperties) {
report(`@${targetTagName} "${extraProperty}" does not exist on ${tag.name}`, null, tg);
}
return true;
}
}
return hasMissing;
}
let funcParamName;
if (typeof functionParameterName === 'object') {
const {
name
} = functionParameterName;
funcParamName = name;
} else {
funcParamName = functionParameterName;
}
if (funcParamName !== tag.name.trim()) {
// Todo: Improve for array or object child items
const actualNames = paramTagsNonNested.map(([, {
name
}]) => {
return name.trim();
});
const expectedNames = functionParameterNames.map((item, idx) => {
var _item$;
if (
/**
* @type {[string|undefined, (import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string,
})]} */
item !== null && item !== void 0 && (_item$ = item[1]) !== null && _item$ !== void 0 && _item$.names) {
return actualNames[idx];
}
return item;
}).filter(item => {
return item !== 'this';
});
// When disableMissingParamChecks is true tag names can be omitted.
// Report when the tag names do not match the expected names or they are used out of order.
if (disableMissingParamChecks) {
const usedExpectedNames = expectedNames.map(a => a === null || a === void 0 ? void 0 : a.toString()).filter(expectedName => expectedName && actualNames.includes(expectedName));
const usedInOrder = actualNames.every((actualName, idx) => actualName === usedExpectedNames[idx]);
if (usedInOrder) {
return false;
}
}
report(`Expected @${targetTagName} names to be "${expectedNames.map(expectedName => {
return typeof expectedName === 'object' && 'name' in expectedName && expectedName.restElement ? '...' + expectedName.name : expectedName;
}).join(', ')}". Got "${actualNames.join(', ')}".`, null, tag);
return true;
}
return false;
});
};
/**
* @param {string} targetTagName
* @param {boolean} _allowExtraTrailingParamDocs
* @param {{
* name: string,
* idx: import('../iterateJsdoc.js').Integer
* }[]} jsdocParameterNames
* @param {import('comment-parser').Block} jsdoc
* @param {Function} report
* @returns {boolean}
*/
const validateParameterNamesDeep = (targetTagName, _allowExtraTrailingParamDocs, jsdocParameterNames, jsdoc, report) => {
/** @type {string} */
let lastRealParameter;
return jsdocParameterNames.some(({
name: jsdocParameterName,
idx
}) => {
const isPropertyPath = jsdocParameterName.includes('.');
if (isPropertyPath) {
if (!lastRealParameter) {
report(`@${targetTagName} path declaration ("${jsdocParameterName}") appears before any real parameter.`, null, jsdoc.tags[idx]);
return true;
}
let pathRootNodeName = jsdocParameterName.slice(0, jsdocParameterName.indexOf('.'));
if (pathRootNodeName.endsWith('[]')) {
pathRootNodeName = pathRootNodeName.slice(0, -2);
}
if (pathRootNodeName !== lastRealParameter) {
report(`@${targetTagName} path declaration ("${jsdocParameterName}") root node name ("${pathRootNodeName}") ` + `does not match previous real parameter name ("${lastRealParameter}").`, null, jsdoc.tags[idx]);
return true;
}
} else {
lastRealParameter = jsdocParameterName;
}
return false;
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
utils
}) => {
const {
allowExtraTrailingParamDocs,
checkDestructured = true,
checkRestProperty = false,
checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
enableFixer = false,
useDefaultObjectProperties = false,
disableExtraPropertyReporting = false,
disableMissingParamChecks = false
} = context.options[0] || {};
const checkTypesRegex = utils.getRegexFromString(checkTypesPattern);
const jsdocParameterNamesDeep = utils.getJsdocTagsDeep('param');
if (!jsdocParameterNamesDeep || !jsdocParameterNamesDeep.length) {
return;
}
const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties);
const targetTagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'param'
});
const isError = validateParameterNames(targetTagName, allowExtraTrailingParamDocs, checkDestructured, checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, disableMissingParamChecks, enableFixer, functionParameterNames, jsdoc, utils, report);
if (isError || !checkDestructured) {
return;
}
validateParameterNamesDeep(targetTagName, allowExtraTrailingParamDocs, jsdocParameterNamesDeep, jsdoc, report);
}, {
contextDefaults: ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'TSDeclareFunction',
// Add this to above defaults
'TSMethodSignature'],
meta: {
docs: {
description: 'Ensures that parameter names in JSDoc match those in the function declaration.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-param-names.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
allowExtraTrailingParamDocs: {
type: 'boolean'
},
checkDestructured: {
type: 'boolean'
},
checkRestProperty: {
type: 'boolean'
},
checkTypesPattern: {
type: 'string'
},
disableExtraPropertyReporting: {
type: 'boolean'
},
disableMissingParamChecks: {
type: 'boolean'
},
enableFixer: {
type: 'boolean'
},
useDefaultObjectProperties: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkParamNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} targetTagName
* @param {boolean} enableFixer
* @param {import('comment-parser').Block} jsdoc
* @param {import('../iterateJsdoc.js').Utils} utils
* @returns {boolean}
*/
const validatePropertyNames = (targetTagName, enableFixer, jsdoc, utils) => {
const propertyTags = Object.entries(jsdoc.tags).filter(([, tag]) => {
return tag.tag === targetTagName;
});
return propertyTags.some(([, tag], index) => {
/** @type {import('../iterateJsdoc.js').Integer} */
let tagsIndex;
const dupeTagInfo = propertyTags.find(([tgsIndex, tg], idx) => {
tagsIndex = Number(tgsIndex);
return tg.name === tag.name && idx !== index;
});
if (dupeTagInfo) {
utils.reportJSDoc(`Duplicate @${targetTagName} "${tag.name}"`, dupeTagInfo[1], enableFixer ? () => {
utils.removeTag(tagsIndex);
} : null);
return true;
}
return false;
});
};
/**
* @param {string} targetTagName
* @param {{
* idx: number;
* name: string;
* type: string;
* }[]} jsdocPropertyNames
* @param {import('comment-parser').Block} jsdoc
* @param {Function} report
*/
const validatePropertyNamesDeep = (targetTagName, jsdocPropertyNames, jsdoc, report) => {
/** @type {string} */
let lastRealProperty;
return jsdocPropertyNames.some(({
name: jsdocPropertyName,
idx
}) => {
const isPropertyPath = jsdocPropertyName.includes('.');
if (isPropertyPath) {
if (!lastRealProperty) {
report(`@${targetTagName} path declaration ("${jsdocPropertyName}") appears before any real property.`, null, jsdoc.tags[idx]);
return true;
}
let pathRootNodeName = jsdocPropertyName.slice(0, jsdocPropertyName.indexOf('.'));
if (pathRootNodeName.endsWith('[]')) {
pathRootNodeName = pathRootNodeName.slice(0, -2);
}
if (pathRootNodeName !== lastRealProperty) {
report(`@${targetTagName} path declaration ("${jsdocPropertyName}") root node name ("${pathRootNodeName}") ` + `does not match previous real property name ("${lastRealProperty}").`, null, jsdoc.tags[idx]);
return true;
}
} else {
lastRealProperty = jsdocPropertyName;
}
return false;
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
utils
}) => {
const {
enableFixer = false
} = context.options[0] || {};
const jsdocPropertyNamesDeep = utils.getJsdocTagsDeep('property');
if (!jsdocPropertyNamesDeep || !jsdocPropertyNamesDeep.length) {
return;
}
const targetTagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'property'
});
const isError = validatePropertyNames(targetTagName, enableFixer, jsdoc, utils);
if (isError) {
return;
}
validatePropertyNamesDeep(targetTagName, jsdocPropertyNamesDeep, jsdoc, report);
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Ensures that property names in JSDoc are not duplicated on the same block and that nested properties have defined roots.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-property-names.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
enableFixer: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkPropertyNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
settings
}) => {
const {
mode
} = settings;
// Don't check for "permissive" and "closure"
if (mode === 'jsdoc' || mode === 'typescript') {
for (const tag of jsdoc.tags) {
if (tag.type.slice(-1) === '=') {
report('Syntax should not be Google Closure Compiler style.', null, tag);
break;
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports against syntax not valid for the mode (e.g., Google Closure Compiler in non-Closure mode).',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-syntax.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkSyntax.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkSyntax.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","jsdoc","report","settings","mode","tag","tags","type","slice","iterateAllJsdocs","meta","docs","description","url","module"],"sources":["../../src/rules/checkSyntax.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n jsdoc,\n report,\n settings,\n}) => {\n const {\n mode,\n } = settings;\n\n // Don't check for \"permissive\" and \"closure\"\n if (mode === 'jsdoc' || mode === 'typescript') {\n for (const tag of jsdoc.tags) {\n if (tag.type.slice(-1) === '=') {\n report('Syntax should not be Google Closure Compiler style.', null, tag);\n break;\n }\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Reports against syntax not valid for the mode (e.g., Google Closure Compiler in non-Closure mode).',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-syntax.md#repos-sticky-header',\n },\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,KAAK;EACLC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC;EACF,CAAC,GAAGD,QAAQ;;EAEZ;EACA,IAAIC,IAAI,KAAK,OAAO,IAAIA,IAAI,KAAK,YAAY,EAAE;IAC7C,KAAK,MAAMC,GAAG,IAAIJ,KAAK,CAACK,IAAI,EAAE;MAC5B,IAAID,GAAG,CAACE,IAAI,CAACC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;QAC9BN,MAAM,CAAC,qDAAqD,EAAE,IAAI,EAAEG,GAAG,CAAC;QACxE;MACF;IACF;EACF;AACF,CAAC,EAAE;EACDI,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,oGAAoG;MACjHC,GAAG,EAAE;IACP,CAAC;IACDN,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAO,MAAA,CAAAf,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,215 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _escapeStringRegexp = _interopRequireDefault(require("escape-string-regexp"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/
const jsxTagNames = new Set(['jsx', 'jsxFrag', 'jsxImportSource', 'jsxRuntime']);
const typedTagsAlwaysUnnecessary = new Set(['augments', 'callback', 'class', 'enum', 'implements', 'private', 'property', 'protected', 'public', 'readonly', 'this', 'type', 'typedef']);
const typedTagsNeedingName = new Set(['template']);
const typedTagsUnnecessaryOutsideDeclare = new Set(['abstract', 'access', 'class', 'constant', 'constructs', 'default', 'enum', 'export', 'exports', 'function', 'global', 'inherits', 'instance', 'interface', 'member', 'memberof', 'memberOf', 'method', 'mixes', 'mixin', 'module', 'name', 'namespace', 'override', 'property', 'requires', 'static', 'this']);
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdoc,
report,
utils,
context,
node,
settings,
jsdocNode
}) => {
const
/**
* @type {{
* definedTags: string[],
* enableFixer: boolean,
* jsxTags: boolean,
* typed: boolean
}} */
{
definedTags = [],
enableFixer = true,
jsxTags,
typed
} = context.options[0] || {};
/** @type {(string|undefined)[]} */
let definedPreferredTags = [];
const {
tagNamePreference,
structuredTags
} = settings;
const definedStructuredTags = Object.keys(structuredTags);
const definedNonPreferredTags = Object.keys(tagNamePreference);
if (definedNonPreferredTags.length) {
definedPreferredTags = Object.values(tagNamePreference).map(preferredTag => {
if (typeof preferredTag === 'string') {
// May become an empty string but will be filtered out below
return preferredTag;
}
if (!preferredTag) {
return undefined;
}
if (typeof preferredTag !== 'object') {
utils.reportSettings('Invalid `settings.jsdoc.tagNamePreference`. Values must be falsy, a string, or an object.');
}
return preferredTag.replacement;
}).filter(Boolean);
}
/**
* @param {import('eslint').Rule.Node} subNode
* @returns {boolean}
*/
const isInAmbientContext = subNode => {
return subNode.type === 'Program' ? context.getFilename().endsWith('.d.ts') : Boolean( /** @type {import('@typescript-eslint/types').TSESTree.VariableDeclaration} */subNode.declare) || isInAmbientContext(subNode.parent);
};
/**
* @param {import('comment-parser').Spec} jsdocTag
* @returns {boolean}
*/
const tagIsRedundantWhenTyped = jsdocTag => {
var _node$parent;
if (!typedTagsUnnecessaryOutsideDeclare.has(jsdocTag.tag)) {
return false;
}
if (jsdocTag.tag === 'default') {
return false;
}
if (node === null) {
return false;
}
if (context.getFilename().endsWith('.d.ts') && ['Program', null, undefined].includes(node === null || node === void 0 || (_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type)) {
return false;
}
if (isInAmbientContext( /** @type {import('eslint').Rule.Node} */node)) {
return false;
}
return true;
};
/**
* @param {string} message
* @param {import('comment-parser').Spec} jsdocTag
* @param {import('../iterateJsdoc.js').Integer} tagIndex
* @param {Partial<import('comment-parser').Tokens>} [additionalTagChanges]
* @returns {void}
*/
const reportWithTagRemovalFixer = (message, jsdocTag, tagIndex, additionalTagChanges) => {
utils.reportJSDoc(message, jsdocTag, enableFixer ? () => {
if (jsdocTag.description.trim()) {
utils.changeTag(jsdocTag, {
postType: '',
type: '',
...additionalTagChanges
});
} else {
utils.removeTag(tagIndex, {
removeEmptyBlock: true
});
}
} : null, true);
};
/**
* @param {import('comment-parser').Spec} jsdocTag
* @param {import('../iterateJsdoc.js').Integer} tagIndex
* @returns {boolean}
*/
const checkTagForTypedValidity = (jsdocTag, tagIndex) => {
if (typedTagsAlwaysUnnecessary.has(jsdocTag.tag)) {
reportWithTagRemovalFixer(`'@${jsdocTag.tag}' is redundant when using a type system.`, jsdocTag, tagIndex, {
postTag: '',
tag: ''
});
return true;
}
if (tagIsRedundantWhenTyped(jsdocTag)) {
reportWithTagRemovalFixer(`'@${jsdocTag.tag}' is redundant outside of ambient (\`declare\`/\`.d.ts\`) contexts when using a type system.`, jsdocTag, tagIndex);
return true;
}
if (typedTagsNeedingName.has(jsdocTag.tag) && !jsdocTag.name) {
reportWithTagRemovalFixer(`'@${jsdocTag.tag}' without a name is redundant when using a type system.`, jsdocTag, tagIndex);
return true;
}
return false;
};
for (let tagIndex = 0; tagIndex < jsdoc.tags.length; tagIndex += 1) {
const jsdocTag = jsdoc.tags[tagIndex];
const tagName = jsdocTag.tag;
if (jsxTags && jsxTagNames.has(tagName)) {
continue;
}
if (typed && checkTagForTypedValidity(jsdocTag, tagIndex)) {
continue;
}
const validTags = [...definedTags, ...( /** @type {string[]} */definedPreferredTags), ...definedNonPreferredTags, ...definedStructuredTags, ...(typed ? typedTagsNeedingName : [])];
if (utils.isValidTag(tagName, validTags)) {
let preferredTagName = utils.getPreferredTagName({
allowObjectReturn: true,
defaultMessage: `Blacklisted tag found (\`@${tagName}\`)`,
tagName
});
if (!preferredTagName) {
continue;
}
let message;
if (typeof preferredTagName === 'object') {
({
message,
replacement: preferredTagName
} = /** @type {{message: string; replacement?: string | undefined;}} */
preferredTagName);
}
if (!message) {
message = `Invalid JSDoc tag (preference). Replace "${tagName}" JSDoc tag with "${preferredTagName}".`;
}
if (preferredTagName !== tagName) {
report(message, fixer => {
const replacement = sourceCode.getText(jsdocNode).replace(new RegExp(`@${(0, _escapeStringRegexp.default)(tagName)}\\b`, 'u'), `@${preferredTagName}`);
return fixer.replaceText(jsdocNode, replacement);
}, jsdocTag);
}
} else {
report(`Invalid JSDoc tag name "${tagName}".`, null, jsdocTag);
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid block tag names.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-tag-names.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
definedTags: {
items: {
type: 'string'
},
type: 'array'
},
enableFixer: {
type: 'boolean'
},
jsxTags: {
type: 'boolean'
},
typed: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkTagNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,173 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
utils,
node,
settings,
report
}) => {
const {
mode
} = settings;
const templateTags = utils.getTags('template');
const usedNames = new Set();
/**
* @param {string} potentialType
*/
const checkForUsedTypes = potentialType => {
let parsedType;
try {
parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode);
} catch {
return;
}
(0, _jsdoccomment.traverse)(parsedType, nde => {
const {
type,
value
} = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
usedNames.add(value);
}
});
};
const checkParamsAndReturnsTags = () => {
const paramName = /** @type {string} */utils.getPreferredTagName({
tagName: 'param'
});
const paramTags = utils.getTags(paramName);
for (const paramTag of paramTags) {
checkForUsedTypes(paramTag.type);
}
const returnsName = /** @type {string} */utils.getPreferredTagName({
tagName: 'returns'
});
const returnsTags = utils.getTags(returnsName);
for (const returnsTag of returnsTags) {
checkForUsedTypes(returnsTag.type);
}
};
const checkTemplateTags = () => {
for (const tag of templateTags) {
const {
name
} = tag;
const names = name.split(/,\s*/);
for (const name of names) {
if (!usedNames.has(name)) {
report(`@template ${name} not in use`, null, tag);
}
}
}
};
/**
* @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|
* import('@typescript-eslint/types').TSESTree.ClassDeclaration|
* import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|
* import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration
* @param {boolean} [checkParamsAndReturns]
*/
const checkParameters = (aliasDeclaration, checkParamsAndReturns) => {
/* c8 ignore next -- Guard */
const {
params
} = aliasDeclaration.typeParameters ?? {
params: []
};
for (const {
name: {
name
}
} of params) {
usedNames.add(name);
}
if (checkParamsAndReturns) {
checkParamsAndReturnsTags();
}
checkTemplateTags();
};
const handleTypeAliases = () => {
var _nde$declaration;
const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node;
if (!nde) {
return;
}
switch (nde.type) {
case 'ExportDefaultDeclaration':
case 'ExportNamedDeclaration':
switch ((_nde$declaration = nde.declaration) === null || _nde$declaration === void 0 ? void 0 : _nde$declaration.type) {
case 'FunctionDeclaration':
checkParameters(nde.declaration, true);
break;
case 'ClassDeclaration':
case 'TSTypeAliasDeclaration':
case 'TSInterfaceDeclaration':
checkParameters(nde.declaration);
break;
}
break;
case 'FunctionDeclaration':
checkParameters(nde, true);
break;
case 'ClassDeclaration':
case 'TSTypeAliasDeclaration':
case 'TSInterfaceDeclaration':
checkParameters(nde);
break;
}
};
const callbackTags = utils.getTags('callback');
const functionTags = utils.getTags('function');
if (callbackTags.length || functionTags.length) {
checkParamsAndReturnsTags();
checkTemplateTags();
return;
}
const typedefTags = utils.getTags('typedef');
if (!typedefTags.length || typedefTags.length >= 2) {
handleTypeAliases();
return;
}
const potentialTypedefType = typedefTags[0].type;
checkForUsedTypes(potentialTypedefType);
const propertyName = /** @type {string} */utils.getPreferredTagName({
tagName: 'property'
});
const propertyTags = utils.getTags(propertyName);
for (const propertyTag of propertyTags) {
checkForUsedTypes(propertyTag.type);
}
for (const tag of templateTags) {
const {
name
} = tag;
const names = name.split(/,\s*/);
for (const name of names) {
if (!usedNames.has(name)) {
report(`@template ${name} not in use`, null, tag);
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that any `@template` names are actually used in the connected `@typedef` or type alias.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-template.md#repos-sticky-header'
},
schema: [],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkTemplateNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,396 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _jsdoccomment = require("@es-joy/jsdoccomment");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const strictNativeTypes = ['undefined', 'null', 'boolean', 'number', 'bigint', 'string', 'symbol', 'object', 'Array', 'Function', 'Date', 'RegExp'];
/**
* Adjusts the parent type node `meta` for generic matches (or type node
* `type` for `JsdocTypeAny`) and sets the type node `value`.
* @param {string} type The actual type
* @param {string} preferred The preferred type
* @param {boolean} isGenericMatch
* @param {string} typeNodeName
* @param {import('jsdoc-type-pratt-parser').NonRootResult} node
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @returns {void}
*/
const adjustNames = (type, preferred, isGenericMatch, typeNodeName, node, parentNode) => {
let ret = preferred;
if (isGenericMatch) {
const parentMeta = /** @type {import('jsdoc-type-pratt-parser').GenericResult} */parentNode.meta;
if (preferred === '[]') {
parentMeta.brackets = 'square';
parentMeta.dot = false;
ret = 'Array';
} else {
const dotBracketEnd = preferred.match(/\.(?:<>)?$/u);
if (dotBracketEnd) {
parentMeta.brackets = 'angle';
parentMeta.dot = true;
ret = preferred.slice(0, -dotBracketEnd[0].length);
} else {
const bracketEnd = preferred.endsWith('<>');
if (bracketEnd) {
parentMeta.brackets = 'angle';
parentMeta.dot = false;
ret = preferred.slice(0, -2);
} else if ((parentMeta === null || parentMeta === void 0 ? void 0 : parentMeta.brackets) === 'square' && (typeNodeName === '[]' || typeNodeName === 'Array')) {
parentMeta.brackets = 'angle';
parentMeta.dot = false;
}
}
}
} else if (type === 'JsdocTypeAny') {
node.type = 'JsdocTypeName';
}
/** @type {import('jsdoc-type-pratt-parser').NameResult} */
node.value = ret.replace(/(?:\.|<>|\.<>|\[\])$/u, '');
// For bare pseudo-types like `<>`
if (!ret) {
/** @type {import('jsdoc-type-pratt-parser').NameResult} */node.value = typeNodeName;
}
};
/**
* @param {boolean} [upperCase]
* @returns {string}
*/
const getMessage = upperCase => {
return 'Use object shorthand or index signatures instead of ' + '`' + (upperCase ? 'O' : 'o') + 'bject`, e.g., `{[key: string]: string}`';
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdocNode,
sourceCode,
report,
utils,
settings,
context
}) => {
const jsdocTagsWithPossibleType = utils.filterTags(tag => {
return Boolean(utils.tagMightHaveTypePosition(tag.tag));
});
const
/**
* @type {{
* preferredTypes: import('../iterateJsdoc.js').PreferredTypes,
* structuredTags: import('../iterateJsdoc.js').StructuredTags,
* mode: import('../jsdocUtils.js').ParserMode
* }}
*/
{
preferredTypes: preferredTypesOriginal,
structuredTags,
mode
} = settings;
const injectObjectPreferredTypes = !('Object' in preferredTypesOriginal || 'object' in preferredTypesOriginal || 'object.<>' in preferredTypesOriginal || 'Object.<>' in preferredTypesOriginal || 'object<>' in preferredTypesOriginal);
/**
* @type {{
* message: string,
* replacement: false
* }}
*/
const info = {
message: getMessage(),
replacement: false
};
/**
* @type {{
* message: string,
* replacement: false
* }}
*/
const infoUC = {
message: getMessage(true),
replacement: false
};
/** @type {import('../iterateJsdoc.js').PreferredTypes} */
const typeToInject = mode === 'typescript' ? {
Object: 'object',
'object.<>': info,
'Object.<>': infoUC,
'object<>': info,
'Object<>': infoUC
} : {
Object: 'object',
'object.<>': 'Object<>',
'Object.<>': 'Object<>',
'object<>': 'Object<>'
};
/** @type {import('../iterateJsdoc.js').PreferredTypes} */
const preferredTypes = {
...(injectObjectPreferredTypes ? typeToInject : {}),
...preferredTypesOriginal
};
const
/**
* @type {{
* noDefaults: boolean,
* unifyParentAndChildTypeChecks: boolean,
* exemptTagContexts: ({
* tag: string,
* types: true|string[]
* })[]
* }}
*/
{
noDefaults,
unifyParentAndChildTypeChecks,
exemptTagContexts = []
} = context.options[0] || {};
/**
* Gets information about the preferred type: whether there is a matching
* preferred type, what the type is, and whether it is a match to a generic.
* @param {string} _type Not currently in use
* @param {string} typeNodeName
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @param {string|undefined} property
* @returns {[hasMatchingPreferredType: boolean, typeName: string, isGenericMatch: boolean]}
*/
const getPreferredTypeInfo = (_type, typeNodeName, parentNode, property) => {
let hasMatchingPreferredType = false;
let isGenericMatch = false;
let typeName = typeNodeName;
const isNameOfGeneric = parentNode !== undefined && parentNode.type === 'JsdocTypeGeneric' && property === 'left';
if (unifyParentAndChildTypeChecks || isNameOfGeneric) {
var _parentNode$meta, _parentNode$meta2;
const brackets = /** @type {import('jsdoc-type-pratt-parser').GenericResult} */parentNode === null || parentNode === void 0 || (_parentNode$meta = parentNode.meta) === null || _parentNode$meta === void 0 ? void 0 : _parentNode$meta.brackets;
const dot = /** @type {import('jsdoc-type-pratt-parser').GenericResult} */parentNode === null || parentNode === void 0 || (_parentNode$meta2 = parentNode.meta) === null || _parentNode$meta2 === void 0 ? void 0 : _parentNode$meta2.dot;
if (brackets === 'angle') {
const checkPostFixes = dot ? ['.', '.<>'] : ['<>'];
isGenericMatch = checkPostFixes.some(checkPostFix => {
if ((preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[typeNodeName + checkPostFix]) !== undefined) {
typeName += checkPostFix;
return true;
}
return false;
});
}
if (!isGenericMatch && property && /** @type {import('jsdoc-type-pratt-parser').NonRootResult} */parentNode.type === 'JsdocTypeGeneric') {
const checkPostFixes = dot ? ['.', '.<>'] : [brackets === 'angle' ? '<>' : '[]'];
isGenericMatch = checkPostFixes.some(checkPostFix => {
if ((preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[checkPostFix]) !== undefined) {
typeName = checkPostFix;
return true;
}
return false;
});
}
}
const directNameMatch = (preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[typeNodeName]) !== undefined && !Object.values(preferredTypes).includes(typeNodeName);
const unifiedSyntaxParentMatch = property && directNameMatch && unifyParentAndChildTypeChecks;
isGenericMatch = isGenericMatch || Boolean(unifiedSyntaxParentMatch);
hasMatchingPreferredType = isGenericMatch || directNameMatch && !property;
return [hasMatchingPreferredType, typeName, isGenericMatch];
};
/**
* Iterates strict types to see if any should be added to `invalidTypes` (and
* the the relevant strict type returned as the new preferred type).
* @param {string} typeNodeName
* @param {string|undefined} preferred
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @param {(string|false|undefined)[][]} invalidTypes
* @returns {string|undefined} The `preferred` type string, optionally changed
*/
const checkNativeTypes = (typeNodeName, preferred, parentNode, invalidTypes) => {
let changedPreferred = preferred;
for (const strictNativeType of strictNativeTypes) {
var _parentNode$elements, _parentNode$left, _parentNode$left2;
if (strictNativeType === 'object' && (
// This is not set to remap with exact type match (e.g.,
// `object: 'Object'`), so can ignore (including if circular)
!(preferredTypes !== null && preferredTypes !== void 0 && preferredTypes[typeNodeName]) ||
// Although present on `preferredTypes` for remapping, this is a
// parent object without a parent match (and not
// `unifyParentAndChildTypeChecks`) and we don't want
// `object<>` given TypeScript issue https://github.com/microsoft/TypeScript/issues/20555
/**
* @type {import('jsdoc-type-pratt-parser').GenericResult}
*/
parentNode !== null && parentNode !== void 0 && (_parentNode$elements = parentNode.elements) !== null && _parentNode$elements !== void 0 && _parentNode$elements.length && (
/**
* @type {import('jsdoc-type-pratt-parser').GenericResult}
*/
(parentNode === null || parentNode === void 0 || (_parentNode$left = parentNode.left) === null || _parentNode$left === void 0 ? void 0 : _parentNode$left.type) === 'JsdocTypeName' &&
/**
* @type {import('jsdoc-type-pratt-parser').GenericResult}
*/
(parentNode === null || parentNode === void 0 || (_parentNode$left2 = parentNode.left) === null || _parentNode$left2 === void 0 ? void 0 : _parentNode$left2.value) === 'Object'))) {
continue;
}
if (strictNativeType !== typeNodeName && strictNativeType.toLowerCase() === typeNodeName.toLowerCase() && (
// Don't report if user has own map for a strict native type
!preferredTypes || (preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[strictNativeType]) === undefined)) {
changedPreferred = strictNativeType;
invalidTypes.push([typeNodeName, changedPreferred]);
break;
}
}
return changedPreferred;
};
/**
* Collect invalid type info.
* @param {string} type
* @param {string} value
* @param {string} tagName
* @param {string} nameInTag
* @param {number} idx
* @param {string|undefined} property
* @param {import('jsdoc-type-pratt-parser').NonRootResult} node
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @param {(string|false|undefined)[][]} invalidTypes
* @returns {void}
*/
const getInvalidTypes = (type, value, tagName, nameInTag, idx, property, node, parentNode, invalidTypes) => {
let typeNodeName = type === 'JsdocTypeAny' ? '*' : value;
const [hasMatchingPreferredType, typeName, isGenericMatch] = getPreferredTypeInfo(type, typeNodeName, parentNode, property);
let preferred;
let types;
if (hasMatchingPreferredType) {
const preferredSetting = preferredTypes[typeName];
typeNodeName = typeName === '[]' ? typeName : typeNodeName;
if (!preferredSetting) {
invalidTypes.push([typeNodeName]);
} else if (typeof preferredSetting === 'string') {
preferred = preferredSetting;
invalidTypes.push([typeNodeName, preferred]);
} else if (preferredSetting && typeof preferredSetting === 'object') {
const nextItem = preferredSetting.skipRootChecking && jsdocTagsWithPossibleType[idx + 1];
if (!nextItem || !nextItem.name.startsWith(`${nameInTag}.`)) {
preferred = preferredSetting.replacement;
invalidTypes.push([typeNodeName, preferred, preferredSetting.message]);
}
} else {
utils.reportSettings('Invalid `settings.jsdoc.preferredTypes`. Values must be falsy, a string, or an object.');
return;
}
} else if (Object.entries(structuredTags).some(([tag, {
type: typs
}]) => {
types = typs;
return tag === tagName && Array.isArray(types) && !types.includes(typeNodeName);
})) {
invalidTypes.push([typeNodeName, types]);
} else if (!noDefaults && type === 'JsdocTypeName') {
preferred = checkNativeTypes(typeNodeName, preferred, parentNode, invalidTypes);
}
// For fixer
if (preferred) {
adjustNames(type, preferred, isGenericMatch, typeNodeName, node, parentNode);
}
};
for (const [idx, jsdocTag] of jsdocTagsWithPossibleType.entries()) {
/** @type {(string|false|undefined)[][]} */
const invalidTypes = [];
let typeAst;
try {
typeAst = mode === 'permissive' ? (0, _jsdoccomment.tryParse)(jsdocTag.type) : (0, _jsdoccomment.parse)(jsdocTag.type, mode);
} catch {
continue;
}
const {
tag: tagName,
name: nameInTag
} = jsdocTag;
(0, _jsdoccomment.traverse)(typeAst, (node, parentNode, property) => {
const {
type,
value
} =
/**
* @type {import('jsdoc-type-pratt-parser').NameResult}
*/
node;
if (!['JsdocTypeName', 'JsdocTypeAny'].includes(type)) {
return;
}
getInvalidTypes(type, value, tagName, nameInTag, idx, property, node, parentNode, invalidTypes);
});
if (invalidTypes.length) {
const fixedType = (0, _jsdoccomment.stringify)(typeAst);
/**
* @type {import('eslint').Rule.ReportFixer}
*/
const fix = fixer => {
return fixer.replaceText(jsdocNode, sourceCode.getText(jsdocNode).replace(`{${jsdocTag.type}}`, `{${fixedType}}`));
};
for (const [badType, preferredType = '', msg] of invalidTypes) {
const tagValue = jsdocTag.name ? ` "${jsdocTag.name}"` : '';
if (exemptTagContexts.some(({
tag,
types
}) => {
return tag === tagName && (types === true || types.includes(jsdocTag.type));
})) {
continue;
}
report(msg || `Invalid JSDoc @${tagName}${tagValue} type "${badType}"` + (preferredType ? '; ' : '.') + (preferredType ? `prefer: ${JSON.stringify(preferredType)}.` : ''), preferredType ? fix : null, jsdocTag, msg ? {
tagName,
tagValue
} : undefined);
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid types.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-types.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
exemptTagContexts: {
items: {
additionalProperties: false,
properties: {
tag: {
type: 'string'
},
types: {
oneOf: [{
type: 'boolean'
}, {
items: {
type: 'string'
},
type: 'array'
}]
}
},
type: 'object'
},
type: 'array'
},
noDefaults: {
type: 'boolean'
},
unifyParentAndChildTypeChecks: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkTypes.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,154 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _nodePath = require("node:path");
var _nodeUrl = require("node:url");
var _synckit = require("synckit");
var _semver = _interopRequireDefault(require("semver"));
var _spdxExpressionParse = _interopRequireDefault(require("spdx-expression-parse"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const _dirname = (0, _nodePath.dirname)((0, _nodeUrl.fileURLToPath)(require('url').pathToFileURL(__filename).toString()));
const pathName = (0, _nodePath.join)(_dirname, '../import-worker.mjs');
const allowedKinds = new Set(['class', 'constant', 'event', 'external', 'file', 'function', 'member', 'mixin', 'module', 'namespace', 'typedef']);
var _default = exports.default = (0, _iterateJsdoc.default)(({
utils,
report,
context,
settings
}) => {
const options = context.options[0] || {};
const {
allowedLicenses = null,
allowedAuthors = null,
numericOnlyVariation = false,
licensePattern = '/([^\n\r]*)/gu'
} = options;
utils.forEachPreferredTag('version', (jsdocParameter, targetTagName) => {
const version = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!version) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!_semver.default.valid(version)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}".`, null, jsdocParameter);
}
});
utils.forEachPreferredTag('kind', (jsdocParameter, targetTagName) => {
const kind = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!kind) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!allowedKinds.has(kind)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}"; ` + `must be one of: ${[...allowedKinds].join(', ')}.`, null, jsdocParameter);
}
});
if (numericOnlyVariation) {
utils.forEachPreferredTag('variation', (jsdocParameter, targetTagName) => {
const variation = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!variation) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!Number.isInteger(Number(variation)) || Number(variation) <= 0) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}".`, null, jsdocParameter);
}
});
}
utils.forEachPreferredTag('since', (jsdocParameter, targetTagName) => {
const version = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!version) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!_semver.default.valid(version)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}".`, null, jsdocParameter);
}
});
utils.forEachPreferredTag('license', (jsdocParameter, targetTagName) => {
const licenseRegex = utils.getRegexFromString(licensePattern, 'g');
const matches = /** @type {string} */utils.getTagDescription(jsdocParameter).matchAll(licenseRegex);
let positiveMatch = false;
for (const match of matches) {
const license = match[1] || match[0];
if (license) {
positiveMatch = true;
}
if (!license.trim()) {
// Avoid reporting again as empty match
if (positiveMatch) {
return;
}
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (allowedLicenses) {
if (allowedLicenses !== true && !allowedLicenses.includes(license)) {
report(`Invalid JSDoc @${targetTagName}: "${license}"; expected one of ${allowedLicenses.join(', ')}.`, null, jsdocParameter);
}
} else {
try {
(0, _spdxExpressionParse.default)(license);
} catch {
report(`Invalid JSDoc @${targetTagName}: "${license}"; expected SPDX expression: https://spdx.org/licenses/.`, null, jsdocParameter);
}
}
}
});
if (settings.mode === 'typescript') {
utils.forEachPreferredTag('import', tag => {
const {
type,
name,
description
} = tag;
const typePart = type ? `{${type}} ` : '';
const imprt = 'import ' + (description ? `${typePart}${name} ${description}` : `${typePart}${name}`);
const getImports = (0, _synckit.createSyncFn)(pathName);
if (!getImports(imprt)) {
report(`Bad @import tag`, null, tag);
}
});
}
utils.forEachPreferredTag('author', (jsdocParameter, targetTagName) => {
const author = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!author) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (allowedAuthors && !allowedAuthors.includes(author)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}"; expected one of ${allowedAuthors.join(', ')}.`, null, jsdocParameter);
}
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'This rule checks the values for a handful of tags: `@version`, `@since`, `@license` and `@author`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-values.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
allowedAuthors: {
items: {
type: 'string'
},
type: 'array'
},
allowedLicenses: {
anyOf: [{
items: {
type: 'string'
},
type: 'array'
}, {
type: 'boolean'
}]
},
licensePattern: {
type: 'string'
},
numericOnlyVariation: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkValues.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,312 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireWildcard(require("../iterateJsdoc.cjs"));
var _jsdocUtils = require("../jsdocUtils.cjs");
var _jsdoccomment = require("@es-joy/jsdoccomment");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/** @type {import('eslint').Rule.RuleModule} */
var _default = exports.default = {
create(context) {
/**
* @typedef {import('eslint').AST.Token | import('estree').Comment | {
* type: import('eslint').AST.TokenType|"Line"|"Block"|"Shebang",
* range: [number, number],
* value: string
* }} Token
*/
/**
* @callback AddComment
* @param {boolean|undefined} inlineCommentBlock
* @param {Token} comment
* @param {string} indent
* @param {number} lines
* @param {import('eslint').Rule.RuleFixer} fixer
*/
/* c8 ignore next -- Fallback to deprecated method */
const {
sourceCode = context.getSourceCode()
} = context;
const settings = (0, _iterateJsdoc.getSettings)(context);
if (!settings) {
return {};
}
const {
contexts = settings.contexts || [],
contextsAfter = ( /** @type {string[]} */[]),
contextsBeforeAndAfter = ['VariableDeclarator', 'TSPropertySignature', 'PropertyDefinition'],
enableFixer = true,
enforceJsdocLineStyle = 'multi',
lineOrBlockStyle = 'both',
allowedPrefixes = ['@ts-', 'istanbul ', 'c8 ', 'v8 ', 'eslint', 'prettier-']
} = context.options[0] ?? {};
let reportingNonJsdoc = false;
/**
* @param {string} messageId
* @param {import('estree').Comment|Token} comment
* @param {import('eslint').Rule.Node} node
* @param {import('eslint').Rule.ReportFixer} fixer
*/
const report = (messageId, comment, node, fixer) => {
var _comment$loc, _comment$loc2;
const loc = {
end: {
column: 0,
/* c8 ignore next 2 -- Guard */
// @ts-expect-error Ok
line: ((_comment$loc = comment.loc) === null || _comment$loc === void 0 || (_comment$loc = _comment$loc.start) === null || _comment$loc === void 0 ? void 0 : _comment$loc.line) ?? 1
},
start: {
column: 0,
/* c8 ignore next 2 -- Guard */
// @ts-expect-error Ok
line: ((_comment$loc2 = comment.loc) === null || _comment$loc2 === void 0 || (_comment$loc2 = _comment$loc2.start) === null || _comment$loc2 === void 0 ? void 0 : _comment$loc2.line) ?? 1
}
};
context.report({
fix: enableFixer ? fixer : null,
loc,
messageId,
node
});
};
/**
* @param {import('eslint').Rule.Node} node
* @param {import('eslint').AST.Token | import('estree').Comment | {
* type: import('eslint').AST.TokenType|"Line"|"Block"|"Shebang",
* range: [number, number],
* value: string
* }} comment
* @param {AddComment} addComment
* @param {import('../iterateJsdoc.js').Context[]} ctxts
*/
const getFixer = (node, comment, addComment, ctxts) => {
return /** @type {import('eslint').Rule.ReportFixer} */fixer => {
// Default to one line break if the `minLines`/`maxLines` settings allow
const lines = settings.minLines === 0 && settings.maxLines >= 1 ? 1 : settings.minLines;
let baseNode =
/**
* @type {import('@typescript-eslint/types').TSESTree.Node|import('eslint').Rule.Node}
*/
(0, _jsdoccomment.getReducedASTNode)(node, sourceCode);
const decorator = (0, _jsdoccomment.getDecorator)( /** @type {import('eslint').Rule.Node} */
baseNode);
if (decorator) {
baseNode = /** @type {import('@typescript-eslint/types').TSESTree.Decorator} */
decorator;
}
const indent = (0, _jsdocUtils.getIndent)({
text: sourceCode.getText( /** @type {import('eslint').Rule.Node} */baseNode, /** @type {import('eslint').AST.SourceLocation} */
( /** @type {import('eslint').Rule.Node} */baseNode.loc).start.column)
});
const {
inlineCommentBlock
} =
/**
* @type {{
* context: string,
* inlineCommentBlock: boolean,
* minLineCount: import('../iterateJsdoc.js').Integer
* }[]}
*/
ctxts.find(contxt => {
if (typeof contxt === 'string') {
return false;
}
const {
context: ctxt
} = contxt;
return ctxt === node.type;
}) || {};
return addComment(inlineCommentBlock, comment, indent, lines, fixer);
};
};
/**
* @param {import('eslint').AST.Token | import('estree').Comment | {
* type: import('eslint').AST.TokenType|"Line"|"Block"|"Shebang",
* range: [number, number],
* value: string
* }} comment
* @param {import('eslint').Rule.Node} node
* @param {AddComment} addComment
* @param {import('../iterateJsdoc.js').Context[]} ctxts
*/
const reportings = (comment, node, addComment, ctxts) => {
const fixer = getFixer(node, comment, addComment, ctxts);
if (comment.type === 'Block') {
if (lineOrBlockStyle === 'line') {
return;
}
report('blockCommentsJsdocStyle', comment, node, fixer);
return;
}
if (comment.type === 'Line') {
if (lineOrBlockStyle === 'block') {
return;
}
report('lineCommentsJsdocStyle', comment, node, fixer);
}
};
/**
* @type {import('../iterateJsdoc.js').CheckJsdoc}
*/
const checkNonJsdoc = (_info, _handler, node) => {
const comment = (0, _jsdoccomment.getNonJsdocComment)(sourceCode, node, settings);
if (!comment || /** @type {string[]} */
allowedPrefixes.some(prefix => {
return comment.value.trimStart().startsWith(prefix);
})) {
return;
}
reportingNonJsdoc = true;
/** @type {AddComment} */
const addComment = (inlineCommentBlock, comment, indent, lines, fixer) => {
const insertion = (inlineCommentBlock || enforceJsdocLineStyle === 'single' ? `/** ${comment.value.trim()} ` : `/**\n${indent}*${comment.value.trimEnd()}\n${indent}`) + `*/${'\n'.repeat((lines || 1) - 1)}`;
return fixer.replaceText( /** @type {import('eslint').AST.Token} */
comment, insertion);
};
reportings(comment, node, addComment, contexts);
};
/**
* @param {import('eslint').Rule.Node} node
* @param {import('../iterateJsdoc.js').Context[]} ctxts
*/
const checkNonJsdocAfter = (node, ctxts) => {
const comment = (0, _jsdoccomment.getFollowingComment)(sourceCode, node);
if (!comment || comment.value.startsWith('*') || /** @type {string[]} */
allowedPrefixes.some(prefix => {
return comment.value.trimStart().startsWith(prefix);
})) {
return;
}
/** @type {AddComment} */
const addComment = (inlineCommentBlock, comment, indent, lines, fixer) => {
const insertion = (inlineCommentBlock || enforceJsdocLineStyle === 'single' ? `/** ${comment.value.trim()} ` : `/**\n${indent}*${comment.value.trimEnd()}\n${indent}`) + `*/${'\n'.repeat((lines || 1) - 1)}${lines ? `\n${indent.slice(1)}` : ' '}`;
return [fixer.remove( /** @type {import('eslint').AST.Token} */
comment), fixer.insertTextBefore(node.type === 'VariableDeclarator' ? node.parent : node, insertion)];
};
reportings(comment, node, addComment, ctxts);
};
// Todo: add contexts to check after (and handle if want both before and after)
return {
...(0, _jsdocUtils.getContextObject)((0, _jsdocUtils.enforcedContexts)(context, true, settings), checkNonJsdoc),
...(0, _jsdocUtils.getContextObject)(contextsAfter, (_info, _handler, node) => {
checkNonJsdocAfter(node, contextsAfter);
}),
...(0, _jsdocUtils.getContextObject)(contextsBeforeAndAfter, (_info, _handler, node) => {
checkNonJsdoc({}, null, node);
if (!reportingNonJsdoc) {
checkNonJsdocAfter(node, contextsBeforeAndAfter);
}
})
};
},
meta: {
fixable: 'code',
messages: {
blockCommentsJsdocStyle: 'Block comments should be JSDoc-style.',
lineCommentsJsdocStyle: 'Line comments should be JSDoc-style.'
},
docs: {
description: 'Converts non-JSDoc comments preceding or following nodes into JSDoc ones',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/convert-to-jsdoc-comments.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
allowedPrefixes: {
type: 'array',
items: {
type: 'string'
}
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
}
},
type: 'object'
}]
},
type: 'array'
},
contextsAfter: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
}
},
type: 'object'
}]
},
type: 'array'
},
contextsBeforeAndAfter: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
type: 'boolean'
},
enforceJsdocLineStyle: {
type: 'string',
enum: ['multi', 'single']
},
lineOrBlockStyle: {
type: 'string',
enum: ['block', 'line', 'both']
}
},
type: 'object'
}],
type: 'suggestion'
}
};
module.exports = exports.default;
//# sourceMappingURL=convertToJsdocComments.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultEmptyTags = new Set(['abstract', 'async', 'generator', 'global', 'hideconstructor', 'ignore', 'inner', 'instance', 'override', 'readonly',
// jsdoc doesn't use this form in its docs, but allow for compatibility with
// TypeScript which allows and Closure which requires
'inheritDoc',
// jsdoc doesn't use but allow for TypeScript
'internal', 'overload']);
const emptyIfNotClosure = new Set(['package', 'private', 'protected', 'public', 'static',
// Closure doesn't allow with this casing
'inheritdoc']);
const emptyIfClosure = new Set(['interface']);
var _default = exports.default = (0, _iterateJsdoc.default)(({
settings,
jsdoc,
utils
}) => {
const emptyTags = utils.filterTags(({
tag: tagName
}) => {
return defaultEmptyTags.has(tagName) || utils.hasOptionTag(tagName) && jsdoc.tags.some(({
tag
}) => {
return tag === tagName;
}) || settings.mode === 'closure' && emptyIfClosure.has(tagName) || settings.mode !== 'closure' && emptyIfNotClosure.has(tagName);
});
for (const tag of emptyTags) {
const content = tag.name || tag.description || tag.type;
if (content.trim()) {
const fix = () => {
// By time of call in fixer, `tag` will have `line` added
utils.setTag(
/**
* @type {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer
* }}
*/
tag);
};
utils.reportJSDoc(`@${tag.tag} should be empty.`, tag, fix, true);
}
}
}, {
checkInternal: true,
checkPrivate: true,
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Expects specific tags to be empty of any content.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/empty-tags.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=emptyTags.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"emptyTags.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","defaultEmptyTags","Set","emptyIfNotClosure","emptyIfClosure","_default","exports","iterateJsdoc","settings","jsdoc","utils","emptyTags","filterTags","tag","tagName","has","hasOptionTag","tags","some","mode","content","name","description","type","trim","fix","setTag","reportJSDoc","checkInternal","checkPrivate","iterateAllJsdocs","meta","docs","url","fixable","schema","additionalProperties","properties","items","module"],"sources":["../../src/rules/emptyTags.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nconst defaultEmptyTags = new Set([\n 'abstract', 'async', 'generator', 'global', 'hideconstructor',\n 'ignore', 'inner', 'instance', 'override', 'readonly',\n\n // jsdoc doesn't use this form in its docs, but allow for compatibility with\n // TypeScript which allows and Closure which requires\n 'inheritDoc',\n\n // jsdoc doesn't use but allow for TypeScript\n 'internal',\n 'overload',\n]);\n\nconst emptyIfNotClosure = new Set([\n 'package', 'private', 'protected', 'public', 'static',\n\n // Closure doesn't allow with this casing\n 'inheritdoc',\n]);\n\nconst emptyIfClosure = new Set([\n 'interface',\n]);\n\nexport default iterateJsdoc(({\n settings,\n jsdoc,\n utils,\n}) => {\n const emptyTags = utils.filterTags(({\n tag: tagName,\n }) => {\n return defaultEmptyTags.has(tagName) ||\n utils.hasOptionTag(tagName) && jsdoc.tags.some(({\n tag,\n }) => {\n return tag === tagName;\n }) ||\n settings.mode === 'closure' && emptyIfClosure.has(tagName) ||\n settings.mode !== 'closure' && emptyIfNotClosure.has(tagName);\n });\n\n for (const tag of emptyTags) {\n const content = tag.name || tag.description || tag.type;\n if (content.trim()) {\n const fix = () => {\n // By time of call in fixer, `tag` will have `line` added\n utils.setTag(\n /**\n * @type {import('comment-parser').Spec & {\n * line: import('../iterateJsdoc.js').Integer\n * }}\n */ (tag),\n );\n };\n\n utils.reportJSDoc(`@${tag.tag} should be empty.`, tag, fix, true);\n }\n }\n}, {\n checkInternal: true,\n checkPrivate: true,\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Expects specific tags to be empty of any content.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/empty-tags.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n tags: {\n items: {\n type: 'string',\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C,MAAMG,gBAAgB,GAAG,IAAIC,GAAG,CAAC,CAC/B,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAC7D,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;AAErD;AACA;AACA,YAAY;AAEZ;AACA,UAAU,EACV,UAAU,CACX,CAAC;AAEF,MAAMC,iBAAiB,GAAG,IAAID,GAAG,CAAC,CAChC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ;AAErD;AACA,YAAY,CACb,CAAC;AAEF,MAAME,cAAc,GAAG,IAAIF,GAAG,CAAC,CAC7B,WAAW,CACZ,CAAC;AAAC,IAAAG,QAAA,GAAAC,OAAA,CAAAN,OAAA,GAEY,IAAAO,qBAAY,EAAC,CAAC;EAC3BC,QAAQ;EACRC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAMC,SAAS,GAAGD,KAAK,CAACE,UAAU,CAAC,CAAC;IAClCC,GAAG,EAAEC;EACP,CAAC,KAAK;IACJ,OAAOb,gBAAgB,CAACc,GAAG,CAACD,OAAO,CAAC,IAClCJ,KAAK,CAACM,YAAY,CAACF,OAAO,CAAC,IAAIL,KAAK,CAACQ,IAAI,CAACC,IAAI,CAAC,CAAC;MAC9CL;IACF,CAAC,KAAK;MACJ,OAAOA,GAAG,KAAKC,OAAO;IACxB,CAAC,CAAC,IACFN,QAAQ,CAACW,IAAI,KAAK,SAAS,IAAIf,cAAc,CAACW,GAAG,CAACD,OAAO,CAAC,IAC1DN,QAAQ,CAACW,IAAI,KAAK,SAAS,IAAIhB,iBAAiB,CAACY,GAAG,CAACD,OAAO,CAAC;EACjE,CAAC,CAAC;EAEF,KAAK,MAAMD,GAAG,IAAIF,SAAS,EAAE;IAC3B,MAAMS,OAAO,GAAGP,GAAG,CAACQ,IAAI,IAAIR,GAAG,CAACS,WAAW,IAAIT,GAAG,CAACU,IAAI;IACvD,IAAIH,OAAO,CAACI,IAAI,CAAC,CAAC,EAAE;MAClB,MAAMC,GAAG,GAAGA,CAAA,KAAM;QAChB;QACAf,KAAK,CAACgB,MAAM;QACV;AACV;AACA;AACA;AACA;QAAeb,GACP,CAAC;MACH,CAAC;MAEDH,KAAK,CAACiB,WAAW,CAAC,IAAId,GAAG,CAACA,GAAG,mBAAmB,EAAEA,GAAG,EAAEY,GAAG,EAAE,IAAI,CAAC;IACnE;EACF;AACF,CAAC,EAAE;EACDG,aAAa,EAAE,IAAI;EACnBC,YAAY,EAAE,IAAI;EAClBC,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJV,WAAW,EAAE,mDAAmD;MAChEW,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVpB,IAAI,EAAE;UACJqB,KAAK,EAAE;YACLf,IAAI,EAAE;UACR,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAgB,MAAA,CAAAjC,OAAA,GAAAA,OAAA,CAAAN,OAAA","ignoreList":[]}

View File

@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
const iteratingFunction = utils.isIteratingFunction();
if (iteratingFunction) {
if (utils.hasATag(['class', 'constructor']) || utils.isConstructor()) {
return;
}
} else if (!utils.isVirtualFunction()) {
return;
}
utils.forEachPreferredTag('implements', tag => {
report('@implements used on a non-constructor function', null, tag);
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Reports an issue with any non-constructor function using `@implements`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/implements-on-classes.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=implementsOnClasses.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"implementsOnClasses.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","iteratingFunction","isIteratingFunction","hasATag","isConstructor","isVirtualFunction","forEachPreferredTag","tag","contextDefaults","meta","docs","description","url","schema","additionalProperties","properties","contexts","items","anyOf","type","comment","context","module"],"sources":["../../src/rules/implementsOnClasses.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n const iteratingFunction = utils.isIteratingFunction();\n\n if (iteratingFunction) {\n if (utils.hasATag([\n 'class',\n 'constructor',\n ]) ||\n utils.isConstructor()\n ) {\n return;\n }\n } else if (!utils.isVirtualFunction()) {\n return;\n }\n\n utils.forEachPreferredTag('implements', (tag) => {\n report('@implements used on a non-constructor function', null, tag);\n });\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'Reports an issue with any non-constructor function using `@implements`.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/implements-on-classes.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,MAAMC,iBAAiB,GAAGD,KAAK,CAACE,mBAAmB,CAAC,CAAC;EAErD,IAAID,iBAAiB,EAAE;IACrB,IAAID,KAAK,CAACG,OAAO,CAAC,CAChB,OAAO,EACP,aAAa,CACd,CAAC,IACAH,KAAK,CAACI,aAAa,CAAC,CAAC,EACrB;MACA;IACF;EACF,CAAC,MAAM,IAAI,CAACJ,KAAK,CAACK,iBAAiB,CAAC,CAAC,EAAE;IACrC;EACF;EAEAL,KAAK,CAACM,mBAAmB,CAAC,YAAY,EAAGC,GAAG,IAAK;IAC/CR,MAAM,CAAC,gDAAgD,EAAE,IAAI,EAAEQ,GAAG,CAAC;EACrE,CAAC,CAAC;AACJ,CAAC,EAAE;EACDC,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,yEAAyE;MACtFC,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEC,IAAI,EAAE;YACR,CAAC,EACD;cACEL,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVK,OAAO,EAAE;kBACPD,IAAI,EAAE;gBACR,CAAC;gBACDE,OAAO,EAAE;kBACPF,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAG,MAAA,CAAAzB,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,106 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _fs = require("fs");
var _nodeModule = require("node:module");
var _path = require("path");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @type {Set<string>|null}
*/
let deps;
const setDeps = function () {
try {
const pkg = JSON.parse(
// @ts-expect-error It's ok
(0, _fs.readFileSync)((0, _path.join)(process.cwd(), './package.json')));
deps = new Set([...(pkg.dependencies ? /* c8 ignore next 2 */
Object.keys(pkg.dependencies) : []), ...(pkg.devDependencies ? /* c8 ignore next 2 */
Object.keys(pkg.devDependencies) : [])]);
/* c8 ignore next -- our package.json exists */
} catch (error) {
/* c8 ignore next -- our package.json exists */
deps = null;
/* c8 ignore next 4 -- our package.json exists */
/* eslint-disable no-console -- Inform user */
console.log(error);
/* eslint-enable no-console -- Inform user */
}
};
const moduleCheck = new Map();
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
settings,
utils
}) => {
if (deps === undefined) {
setDeps();
}
/* c8 ignore next 3 -- our package.json exists */
if (deps === null) {
return;
}
const {
mode
} = settings;
for (const tag of jsdoc.tags) {
let typeAst;
try {
typeAst = mode === 'permissive' ? (0, _jsdoccomment.tryParse)(tag.type) : (0, _jsdoccomment.parse)(tag.type, mode);
} catch {
continue;
}
// eslint-disable-next-line no-loop-func -- Safe
(0, _jsdoccomment.traverse)(typeAst, nde => {
/* c8 ignore next 3 -- TS guard */
if (deps === null) {
return;
}
if (nde.type === 'JsdocTypeImport') {
let mod = nde.element.value.replace(/^(@[^/]+\/[^/]+|[^/]+).*$/u, '$1');
if (/^[./]/u.test(mod)) {
return;
}
if ((0, _nodeModule.isBuiltin)(mod)) {
// mod = '@types/node';
// moduleCheck.set(mod, !deps.has(mod));
return;
} else if (!moduleCheck.has(mod)) {
let pkg;
try {
pkg = JSON.parse(
// @ts-expect-error It's ok
(0, _fs.readFileSync)((0, _path.join)(process.cwd(), 'node_modules', mod, './package.json')));
} catch {
// Ignore
}
if (!pkg || !pkg.types && !pkg.typings) {
mod = `@types/${mod}`;
}
moduleCheck.set(mod, !deps.has(mod));
}
if (moduleCheck.get(mod)) {
utils.reportJSDoc('import points to package which is not found in dependencies', tag);
}
}
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports if JSDoc `import()` statements point to a package which is not listed in `dependencies` or `devDependencies`',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/imports-as-dependencies.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=importsAsDependencies.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,148 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _areDocsInformative = require("are-docs-informative");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultAliases = {
a: ['an', 'our']
};
const defaultUselessWords = ['a', 'an', 'i', 'in', 'of', 's', 'the'];
/* eslint-disable complexity -- Temporary */
/**
* @param {import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node|null|undefined} node
* @returns {string[]}
*/
const getNamesFromNode = node => {
switch (node === null || node === void 0 ? void 0 : node.type) {
case 'AccessorProperty':
case 'MethodDefinition':
case 'PropertyDefinition':
case 'TSAbstractAccessorProperty':
case 'TSAbstractMethodDefinition':
case 'TSAbstractPropertyDefinition':
return [...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */node.parent.parent), ...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.key)];
case 'ExportDefaultDeclaration':
case 'ExportNamedDeclaration':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.ExportNamedDeclaration} */
node.declaration);
case 'ClassDeclaration':
case 'ClassExpression':
case 'FunctionDeclaration':
case 'FunctionExpression':
case 'TSModuleDeclaration':
case 'TSMethodSignature':
case 'TSDeclareFunction':
case 'TSEnumDeclaration':
case 'TSEnumMember':
case 'TSInterfaceDeclaration':
case 'TSTypeAliasDeclaration':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.ClassDeclaration} */
node.id);
case 'Identifier':
return [node.name];
case 'Property':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.key);
case 'VariableDeclaration':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.declarations[0]);
case 'VariableDeclarator':
return [...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.id), ...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.init)].filter(Boolean);
default:
return [];
}
};
/* eslint-enable complexity -- Temporary */
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
node,
report,
utils
}) => {
const /** @type {{aliases: {[key: string]: string[]}, excludedTags: string[], uselessWords: string[]}} */{
aliases = defaultAliases,
excludedTags = [],
uselessWords = defaultUselessWords
} = context.options[0] || {};
const nodeNames = getNamesFromNode(node);
/**
* @param {string} text
* @param {string} extraName
* @returns {boolean}
*/
const descriptionIsRedundant = (text, extraName = '') => {
const textTrimmed = text.trim();
return Boolean(textTrimmed) && !(0, _areDocsInformative.areDocsInformative)(textTrimmed, [extraName, nodeNames].filter(Boolean).join(' '), {
aliases,
uselessWords
});
};
const {
description,
lastDescriptionLine
} = utils.getDescription();
let descriptionReported = false;
for (const tag of jsdoc.tags) {
if (excludedTags.includes(tag.tag)) {
continue;
}
if (descriptionIsRedundant(tag.description, tag.name)) {
utils.reportJSDoc('This tag description only repeats the name it describes.', tag);
}
descriptionReported ||= tag.description === description && /** @type {import('comment-parser').Spec & {line: import('../iterateJsdoc.js').Integer}} */
tag.line === lastDescriptionLine;
}
if (!descriptionReported && descriptionIsRedundant(description)) {
report('This description only repeats the name it describes.');
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'This rule reports doc comments that only restate their attached name.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/informative-docs.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
aliases: {
patternProperties: {
'.*': {
items: {
type: 'string'
},
type: 'array'
}
}
},
excludedTags: {
items: {
type: 'string'
},
type: 'array'
},
uselessWords: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=informativeDocs.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,229 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// If supporting Node >= 10, we could loosen the default to this for the
// initial letter: \\p{Upper}
const matchDescriptionDefault = '^\n?([A-Z`\\d_][\\s\\S]*[.?!`]\\s*)?$';
/**
* @param {string} value
* @param {string} userDefault
* @returns {string}
*/
const stringOrDefault = (value, userDefault) => {
return typeof value === 'string' ? value : userDefault || matchDescriptionDefault;
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
context,
utils
}) => {
const {
mainDescription,
matchDescription,
message,
nonemptyTags = true,
tags = {}
} = context.options[0] || {};
/**
* @param {string} desc
* @param {import('comment-parser').Spec} [tag]
* @returns {void}
*/
const validateDescription = (desc, tag) => {
let mainDescriptionMatch = mainDescription;
let errorMessage = message;
if (typeof mainDescription === 'object') {
mainDescriptionMatch = mainDescription.match;
errorMessage = mainDescription.message;
}
if (mainDescriptionMatch === false && (!tag || !Object.prototype.hasOwnProperty.call(tags, tag.tag))) {
return;
}
let tagValue = mainDescriptionMatch;
if (tag) {
const tagName = tag.tag;
if (typeof tags[tagName] === 'object') {
tagValue = tags[tagName].match;
errorMessage = tags[tagName].message;
} else {
tagValue = tags[tagName];
}
}
const regex = utils.getRegexFromString(stringOrDefault(tagValue, matchDescription));
if (!regex.test(desc)) {
report(errorMessage || 'JSDoc description does not satisfy the regex pattern.', null, tag || {
// Add one as description would typically be into block
line: jsdoc.source[0].number + 1
});
}
};
const {
description
} = utils.getDescription();
if (description) {
validateDescription(description);
}
/**
* @param {string} tagName
* @returns {boolean}
*/
const hasNoTag = tagName => {
return !tags[tagName];
};
for (const tag of ['description', 'summary', 'file', 'classdesc']) {
utils.forEachPreferredTag(tag, (matchingJsdocTag, targetTagName) => {
const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
if (hasNoTag(targetTagName)) {
validateDescription(desc, matchingJsdocTag);
}
}, true);
}
if (nonemptyTags) {
for (const tag of ['copyright', 'example', 'see', 'todo']) {
utils.forEachPreferredTag(tag, (matchingJsdocTag, targetTagName) => {
const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
if (hasNoTag(targetTagName) && !/.+/u.test(desc)) {
report('JSDoc description must not be empty.', null, matchingJsdocTag);
}
});
}
}
if (!Object.keys(tags).length) {
return;
}
/**
* @param {string} tagName
* @returns {boolean}
*/
const hasOptionTag = tagName => {
return Boolean(tags[tagName]);
};
const whitelistedTags = utils.filterTags(({
tag: tagName
}) => {
return hasOptionTag(tagName);
});
const {
tagsWithNames,
tagsWithoutNames
} = utils.getTagsByType(whitelistedTags);
tagsWithNames.some(tag => {
const desc = /** @type {string} */utils.getTagDescription(tag).replace(/^[- ]*/u, '').trim();
return validateDescription(desc, tag);
});
tagsWithoutNames.some(tag => {
const desc = (tag.name + ' ' + utils.getTagDescription(tag)).trim();
return validateDescription(desc, tag);
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Enforces a regular expression pattern on descriptions.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/match-description.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
mainDescription: {
oneOf: [{
format: 'regex',
type: 'string'
}, {
type: 'boolean'
}, {
additionalProperties: false,
properties: {
match: {
oneOf: [{
format: 'regex',
type: 'string'
}, {
type: 'boolean'
}]
},
message: {
type: 'string'
}
},
type: 'object'
}]
},
matchDescription: {
format: 'regex',
type: 'string'
},
message: {
type: 'string'
},
nonemptyTags: {
type: 'boolean'
},
tags: {
patternProperties: {
'.*': {
oneOf: [{
format: 'regex',
type: 'string'
}, {
enum: [true],
type: 'boolean'
}, {
additionalProperties: false,
properties: {
match: {
oneOf: [{
format: 'regex',
type: 'string'
}, {
enum: [true],
type: 'boolean'
}]
},
message: {
type: 'string'
}
},
type: 'object'
}]
}
},
type: 'object'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=matchDescription.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,128 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// eslint-disable-next-line complexity
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
info: {
lastIndex
},
utils
}) => {
const {
match
} = context.options[0] || {};
if (!match) {
report('Rule `no-restricted-syntax` is missing a `match` option.');
return;
}
const {
allowName,
disallowName,
replacement,
tags = ['*']
} = match[( /** @type {import('../iterateJsdoc.js').Integer} */lastIndex)];
const allowNameRegex = allowName && utils.getRegexFromString(allowName);
const disallowNameRegex = disallowName && utils.getRegexFromString(disallowName);
let applicableTags = jsdoc.tags;
if (!tags.includes('*')) {
applicableTags = utils.getPresentTags(tags);
}
let reported = false;
for (const tag of applicableTags) {
const allowed = !allowNameRegex || allowNameRegex.test(tag.name);
const disallowed = disallowNameRegex && disallowNameRegex.test(tag.name);
const hasRegex = allowNameRegex || disallowNameRegex;
if (hasRegex && allowed && !disallowed) {
continue;
}
if (!hasRegex && reported) {
continue;
}
const fixer = () => {
for (const src of tag.source) {
if (src.tokens.name) {
src.tokens.name = src.tokens.name.replace(disallowNameRegex, replacement);
break;
}
}
};
let {
message
} = match[( /** @type {import('../iterateJsdoc.js').Integer} */lastIndex)];
if (!message) {
if (hasRegex) {
message = disallowed ? `Only allowing names not matching \`${disallowNameRegex}\` but found "${tag.name}".` : `Only allowing names matching \`${allowNameRegex}\` but found "${tag.name}".`;
} else {
message = `Prohibited context for "${tag.name}".`;
}
}
utils.reportJSDoc(message, hasRegex ? tag : null,
// We could match up
disallowNameRegex && replacement !== undefined ? fixer : null, false, {
// Could also supply `context`, `comment`, `tags`
allowName,
disallowName,
name: tag.name
});
if (!hasRegex) {
reported = true;
}
}
}, {
matchContext: true,
meta: {
docs: {
description: 'Reports the name portion of a JSDoc tag if matching or not matching a given regular expression.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/match-name.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
match: {
additionalProperties: false,
items: {
properties: {
allowName: {
type: 'string'
},
comment: {
type: 'string'
},
context: {
type: 'string'
},
disallowName: {
type: 'string'
},
message: {
type: 'string'
},
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
},
type: 'array'
}
},
required: ['match'],
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=matchName.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,237 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils
}) => {
const {
allowMultipleTags = true,
noFinalLineText = true,
noZeroLineText = true,
noSingleLineBlocks = false,
singleLineTags = ['lends', 'type'],
noMultilineBlocks = false,
minimumLengthForMultiline = Number.POSITIVE_INFINITY,
multilineTags = ['*']
} = context.options[0] || {};
const {
source: [{
tokens
}]
} = jsdoc;
const {
description,
tag
} = tokens;
const sourceLength = jsdoc.source.length;
/**
* @param {string} tagName
* @returns {boolean}
*/
const isInvalidSingleLine = tagName => {
return noSingleLineBlocks && (!tagName || !singleLineTags.includes(tagName) && !singleLineTags.includes('*'));
};
if (sourceLength === 1) {
if (!isInvalidSingleLine(tag.slice(1))) {
return;
}
const fixer = () => {
utils.makeMultiline();
};
utils.reportJSDoc('Single line blocks are not permitted by your configuration.', null, fixer, true);
return;
}
const lineChecks = () => {
if (noZeroLineText && (tag || description)) {
const fixer = () => {
const line = {
...tokens
};
utils.emptyTokens(tokens);
const {
tokens: {
delimiter,
start
}
} = jsdoc.source[1];
utils.addLine(1, {
...line,
delimiter,
start
});
};
utils.reportJSDoc('Should have no text on the "0th" line (after the `/**`).', null, fixer);
return;
}
const finalLine = jsdoc.source[jsdoc.source.length - 1];
const finalLineTokens = finalLine.tokens;
if (noFinalLineText && finalLineTokens.description.trim()) {
const fixer = () => {
const line = {
...finalLineTokens
};
line.description = line.description.trimEnd();
const {
delimiter
} = line;
for (const prop of ['delimiter', 'postDelimiter', 'tag', 'type', 'lineEnd', 'postType', 'postTag', 'name', 'postName', 'description']) {
finalLineTokens[(
/**
* @type {"delimiter"|"postDelimiter"|"tag"|"type"|
* "lineEnd"|"postType"|"postTag"|"name"|
* "postName"|"description"}
*/
prop)] = '';
}
utils.addLine(jsdoc.source.length - 1, {
...line,
delimiter,
end: ''
});
};
utils.reportJSDoc('Should have no text on the final line (before the `*/`).', null, fixer);
}
};
if (noMultilineBlocks) {
if (jsdoc.tags.length && (multilineTags.includes('*') || utils.hasATag(multilineTags))) {
lineChecks();
return;
}
if (jsdoc.description.length >= minimumLengthForMultiline) {
lineChecks();
return;
}
if (noSingleLineBlocks && (!jsdoc.tags.length || !utils.filterTags(({
tag: tg
}) => {
return !isInvalidSingleLine(tg);
}).length)) {
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but fixing would result in a single ' + 'line block which you have prohibited with `noSingleLineBlocks`.');
return;
}
if (jsdoc.tags.length > 1) {
if (!allowMultipleTags) {
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but the block has multiple tags.');
return;
}
} else if (jsdoc.tags.length === 1 && jsdoc.description.trim()) {
if (!allowMultipleTags) {
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but the block has a description with a tag.');
return;
}
} else {
const fixer = () => {
jsdoc.source = [{
number: 1,
source: '',
tokens: jsdoc.source.reduce((obj, {
tokens: {
description: desc,
tag: tg,
type: typ,
name: nme,
lineEnd,
postType,
postName,
postTag
}
}) => {
if (typ) {
obj.type = typ;
}
if (tg && typ && nme) {
obj.postType = postType;
}
if (nme) {
obj.name += nme;
}
if (nme && desc) {
obj.postName = postName;
}
obj.description += desc;
const nameOrDescription = obj.description || obj.name;
if (nameOrDescription && nameOrDescription.slice(-1) !== ' ') {
obj.description += ' ';
}
obj.lineEnd = lineEnd;
// Already filtered for multiple tags
obj.tag += tg;
if (tg) {
obj.postTag = postTag || ' ';
}
return obj;
}, utils.seedTokens({
delimiter: '/**',
end: '*/',
postDelimiter: ' '
}))
}];
};
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration.', null, fixer);
return;
}
}
lineChecks();
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Controls how and whether jsdoc blocks can be expressed as single or multiple line blocks.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/multiline-blocks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
allowMultipleTags: {
type: 'boolean'
},
minimumLengthForMultiline: {
type: 'integer'
},
multilineTags: {
anyOf: [{
enum: ['*'],
type: 'string'
}, {
items: {
type: 'string'
},
type: 'array'
}]
},
noFinalLineText: {
type: 'boolean'
},
noMultilineBlocks: {
type: 'boolean'
},
noSingleLineBlocks: {
type: 'boolean'
},
noZeroLineText: {
type: 'boolean'
},
singleLineTags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=multilineBlocks.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,87 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _commentParser = require("comment-parser");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// Neither a single nor 3+ asterisks are valid jsdoc per
// https://jsdoc.app/about-getting-started.html#adding-documentation-comments-to-your-code
const commentRegexp = /^\/\*(?!\*)/u;
const extraAsteriskCommentRegexp = /^\/\*{3,}/u;
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
sourceCode,
allComments,
makeReport
}) => {
const [{
ignore = ['ts-check', 'ts-expect-error', 'ts-ignore', 'ts-nocheck'],
preventAllMultiAsteriskBlocks = false
} = {}] = context.options;
let extraAsterisks = false;
const nonJsdocNodes = /** @type {import('estree').Node[]} */allComments.filter(comment => {
const commentText = sourceCode.getText(comment);
let sliceIndex = 2;
if (!commentRegexp.test(commentText)) {
var _extraAsteriskComment;
const multiline = (_extraAsteriskComment = extraAsteriskCommentRegexp.exec(commentText)) === null || _extraAsteriskComment === void 0 ? void 0 : _extraAsteriskComment[0];
if (!multiline) {
return false;
}
sliceIndex = multiline.length;
extraAsterisks = true;
if (preventAllMultiAsteriskBlocks) {
return true;
}
}
const tags = ((0, _commentParser.parse)(`${commentText.slice(0, 2)}*${commentText.slice(sliceIndex)}`)[0] || {}).tags ?? [];
return tags.length && !tags.some(({
tag
}) => {
return ignore.includes(tag);
});
});
if (!nonJsdocNodes.length) {
return;
}
for (const node of nonJsdocNodes) {
const report = /** @type {import('../iterateJsdoc.js').MakeReport} */makeReport(context, node);
// eslint-disable-next-line no-loop-func
const fix = /** @type {import('eslint').Rule.ReportFixer} */fixer => {
const text = sourceCode.getText(node);
return fixer.replaceText(node, extraAsterisks ? text.replace(extraAsteriskCommentRegexp, '/**') : text.replace('/*', '/**'));
};
report('Expected JSDoc-like comment to begin with two asterisks.', fix);
}
}, {
checkFile: true,
meta: {
docs: {
description: 'This rule checks for multi-line-style comments which fail to meet the criteria of a jsdoc block.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-bad-blocks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
ignore: {
items: {
type: 'string'
},
type: 'array'
},
preventAllMultiAsteriskBlocks: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=noBadBlocks.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const anyWhitespaceLines = /^\s*$/u;
const atLeastTwoLinesWhitespace = /^[ \t]*\n[ \t]*\n\s*$/u;
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
utils
}) => {
const {
description,
descriptions,
lastDescriptionLine
} = utils.getDescription();
const regex = jsdoc.tags.length ? anyWhitespaceLines : atLeastTwoLinesWhitespace;
if (descriptions.length && regex.test(description)) {
if (jsdoc.tags.length) {
utils.reportJSDoc('There should be no blank lines in block descriptions followed by tags.', {
line: lastDescriptionLine
}, () => {
utils.setBlockDescription(() => {
// Remove all lines
return [];
});
});
} else {
utils.reportJSDoc('There should be no extra blank lines in block descriptions not followed by tags.', {
line: lastDescriptionLine
}, () => {
utils.setBlockDescription((info, seedTokens) => {
return [
// Keep the starting line
{
number: 0,
source: '',
tokens: seedTokens({
...info,
description: ''
})
}];
});
});
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Detects and removes extra lines of a blank block description',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-block-descriptions.md#repos-sticky-header'
},
fixable: 'whitespace',
schema: [],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=noBlankBlockDescriptions.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noBlankBlockDescriptions.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","anyWhitespaceLines","atLeastTwoLinesWhitespace","_default","exports","iterateJsdoc","jsdoc","utils","description","descriptions","lastDescriptionLine","getDescription","regex","tags","length","test","reportJSDoc","line","setBlockDescription","info","seedTokens","number","source","tokens","iterateAllJsdocs","meta","docs","url","fixable","schema","type","module"],"sources":["../../src/rules/noBlankBlockDescriptions.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nconst anyWhitespaceLines = /^\\s*$/u;\nconst atLeastTwoLinesWhitespace = /^[ \\t]*\\n[ \\t]*\\n\\s*$/u;\n\nexport default iterateJsdoc(({\n jsdoc,\n utils,\n}) => {\n const {\n description,\n descriptions,\n lastDescriptionLine,\n } = utils.getDescription();\n\n const regex = jsdoc.tags.length ?\n anyWhitespaceLines :\n atLeastTwoLinesWhitespace;\n\n if (descriptions.length && regex.test(description)) {\n if (jsdoc.tags.length) {\n utils.reportJSDoc(\n 'There should be no blank lines in block descriptions followed by tags.',\n {\n line: lastDescriptionLine,\n },\n () => {\n utils.setBlockDescription(() => {\n // Remove all lines\n return [];\n });\n },\n );\n } else {\n utils.reportJSDoc(\n 'There should be no extra blank lines in block descriptions not followed by tags.',\n {\n line: lastDescriptionLine,\n },\n () => {\n utils.setBlockDescription((info, seedTokens) => {\n return [\n // Keep the starting line\n {\n number: 0,\n source: '',\n tokens: seedTokens({\n ...info,\n description: '',\n }),\n },\n ];\n });\n },\n );\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Detects and removes extra lines of a blank block description',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-block-descriptions.md#repos-sticky-header',\n },\n fixable: 'whitespace',\n schema: [],\n type: 'layout',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C,MAAMG,kBAAkB,GAAG,QAAQ;AACnC,MAAMC,yBAAyB,GAAG,wBAAwB;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAJ,OAAA,GAE5C,IAAAK,qBAAY,EAAC,CAAC;EAC3BC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC,WAAW;IACXC,YAAY;IACZC;EACF,CAAC,GAAGH,KAAK,CAACI,cAAc,CAAC,CAAC;EAE1B,MAAMC,KAAK,GAAGN,KAAK,CAACO,IAAI,CAACC,MAAM,GAC7Bb,kBAAkB,GAClBC,yBAAyB;EAE3B,IAAIO,YAAY,CAACK,MAAM,IAAIF,KAAK,CAACG,IAAI,CAACP,WAAW,CAAC,EAAE;IAClD,IAAIF,KAAK,CAACO,IAAI,CAACC,MAAM,EAAE;MACrBP,KAAK,CAACS,WAAW,CACf,wEAAwE,EACxE;QACEC,IAAI,EAAEP;MACR,CAAC,EACD,MAAM;QACJH,KAAK,CAACW,mBAAmB,CAAC,MAAM;UAC9B;UACA,OAAO,EAAE;QACX,CAAC,CAAC;MACJ,CACF,CAAC;IACH,CAAC,MAAM;MACLX,KAAK,CAACS,WAAW,CACf,kFAAkF,EAClF;QACEC,IAAI,EAAEP;MACR,CAAC,EACD,MAAM;QACJH,KAAK,CAACW,mBAAmB,CAAC,CAACC,IAAI,EAAEC,UAAU,KAAK;UAC9C,OAAO;UACL;UACA;YACEC,MAAM,EAAE,CAAC;YACTC,MAAM,EAAE,EAAE;YACVC,MAAM,EAAEH,UAAU,CAAC;cACjB,GAAGD,IAAI;cACPX,WAAW,EAAE;YACf,CAAC;UACH,CAAC,CACF;QACH,CAAC,CAAC;MACJ,CACF,CAAC;IACH;EACF;AACF,CAAC,EAAE;EACDgB,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJlB,WAAW,EAAE,8DAA8D;MAC3EmB,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,YAAY;IACrBC,MAAM,EAAE,EAAE;IACVC,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA3B,OAAA,GAAAA,OAAA,CAAAJ,OAAA","ignoreList":[]}

View File

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils
}) => {
if (jsdoc.tags.length) {
return;
}
const {
description,
lastDescriptionLine
} = utils.getDescription();
if (description.trim()) {
return;
}
const {
enableFixer
} = context.options[0] || {};
utils.reportJSDoc('No empty blocks', {
line: lastDescriptionLine
}, enableFixer ? () => {
jsdoc.source.splice(0, jsdoc.source.length);
} : null);
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Removes empty blocks with nothing but possibly line breaks',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-blocks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
enableFixer: {
type: 'boolean'
}
}
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noBlankBlocks.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noBlankBlocks.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","jsdoc","utils","tags","length","description","lastDescriptionLine","getDescription","trim","enableFixer","options","reportJSDoc","line","source","splice","iterateAllJsdocs","meta","docs","url","fixable","schema","additionalProperties","properties","type","module"],"sources":["../../src/rules/noBlankBlocks.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n jsdoc,\n utils,\n}) => {\n if (jsdoc.tags.length) {\n return;\n }\n\n const {\n description,\n lastDescriptionLine,\n } = utils.getDescription();\n if (description.trim()) {\n return;\n }\n\n const {\n enableFixer,\n } = context.options[0] || {};\n\n utils.reportJSDoc(\n 'No empty blocks',\n {\n line: lastDescriptionLine,\n },\n enableFixer ? () => {\n jsdoc.source.splice(0, jsdoc.source.length);\n } : null,\n );\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Removes empty blocks with nothing but possibly line breaks',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-blocks.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n enableFixer: {\n type: 'boolean',\n },\n },\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,IAAID,KAAK,CAACE,IAAI,CAACC,MAAM,EAAE;IACrB;EACF;EAEA,MAAM;IACJC,WAAW;IACXC;EACF,CAAC,GAAGJ,KAAK,CAACK,cAAc,CAAC,CAAC;EAC1B,IAAIF,WAAW,CAACG,IAAI,CAAC,CAAC,EAAE;IACtB;EACF;EAEA,MAAM;IACJC;EACF,CAAC,GAAGT,OAAO,CAACU,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EAE5BR,KAAK,CAACS,WAAW,CACf,iBAAiB,EACjB;IACEC,IAAI,EAAEN;EACR,CAAC,EACDG,WAAW,GAAG,MAAM;IAClBR,KAAK,CAACY,MAAM,CAACC,MAAM,CAAC,CAAC,EAAEb,KAAK,CAACY,MAAM,CAACT,MAAM,CAAC;EAC7C,CAAC,GAAG,IACN,CAAC;AACH,CAAC,EAAE;EACDW,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJZ,WAAW,EAAE,4DAA4D;MACzEa,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVb,WAAW,EAAE;UACXc,IAAI,EAAE;QACR;MACF;IACF,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA1B,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
utils
}) => {
const {
noOptionalParamNames
} = context.options[0] || {};
const paramTags = utils.getPresentTags(['param', 'arg', 'argument']);
for (const tag of paramTags) {
if (noOptionalParamNames && tag.optional) {
utils.reportJSDoc(`Optional param names are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
name: tag.name.replace(/([^=]*)(=.+)?/u, '$1')
});
});
} else if (tag.default) {
utils.reportJSDoc(`Defaults are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
name: tag.name.replace(/([^=]*)(=.+)?/u, '[$1]')
});
});
}
}
const defaultTags = utils.getPresentTags(['default', 'defaultvalue']);
for (const tag of defaultTags) {
if (tag.description.trim()) {
utils.reportJSDoc(`Default values are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
description: '',
postTag: ''
});
});
}
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'This rule reports defaults being used on the relevant portion of `@param` or `@default`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-defaults.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
noOptionalParamNames: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noDefaults.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noDefaults.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","utils","noOptionalParamNames","options","paramTags","getPresentTags","tag","optional","reportJSDoc","changeTag","name","replace","defaultTags","description","trim","postTag","contextDefaults","meta","docs","url","fixable","schema","additionalProperties","properties","contexts","items","anyOf","type","comment","module"],"sources":["../../src/rules/noDefaults.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n utils,\n}) => {\n const {\n noOptionalParamNames,\n } = context.options[0] || {};\n const paramTags = utils.getPresentTags([\n 'param', 'arg', 'argument',\n ]);\n for (const tag of paramTags) {\n if (noOptionalParamNames && tag.optional) {\n utils.reportJSDoc(`Optional param names are not permitted on @${tag.tag}.`, tag, () => {\n utils.changeTag(tag, {\n name: tag.name.replace(/([^=]*)(=.+)?/u, '$1'),\n });\n });\n } else if (tag.default) {\n utils.reportJSDoc(`Defaults are not permitted on @${tag.tag}.`, tag, () => {\n utils.changeTag(tag, {\n name: tag.name.replace(/([^=]*)(=.+)?/u, '[$1]'),\n });\n });\n }\n }\n\n const defaultTags = utils.getPresentTags([\n 'default', 'defaultvalue',\n ]);\n for (const tag of defaultTags) {\n if (tag.description.trim()) {\n utils.reportJSDoc(`Default values are not permitted on @${tag.tag}.`, tag, () => {\n utils.changeTag(tag, {\n description: '',\n postTag: '',\n });\n });\n }\n }\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'This rule reports defaults being used on the relevant portion of `@param` or `@default`.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-defaults.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n noOptionalParamNames: {\n type: 'boolean',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC;EACF,CAAC,GAAGF,OAAO,CAACG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EAC5B,MAAMC,SAAS,GAAGH,KAAK,CAACI,cAAc,CAAC,CACrC,OAAO,EAAE,KAAK,EAAE,UAAU,CAC3B,CAAC;EACF,KAAK,MAAMC,GAAG,IAAIF,SAAS,EAAE;IAC3B,IAAIF,oBAAoB,IAAII,GAAG,CAACC,QAAQ,EAAE;MACxCN,KAAK,CAACO,WAAW,CAAC,8CAA8CF,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QACrFL,KAAK,CAACQ,SAAS,CAACH,GAAG,EAAE;UACnBI,IAAI,EAAEJ,GAAG,CAACI,IAAI,CAACC,OAAO,CAAC,gBAAgB,EAAE,IAAI;QAC/C,CAAC,CAAC;MACJ,CAAC,CAAC;IACJ,CAAC,MAAM,IAAIL,GAAG,CAACV,OAAO,EAAE;MACtBK,KAAK,CAACO,WAAW,CAAC,kCAAkCF,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QACzEL,KAAK,CAACQ,SAAS,CAACH,GAAG,EAAE;UACnBI,IAAI,EAAEJ,GAAG,CAACI,IAAI,CAACC,OAAO,CAAC,gBAAgB,EAAE,MAAM;QACjD,CAAC,CAAC;MACJ,CAAC,CAAC;IACJ;EACF;EAEA,MAAMC,WAAW,GAAGX,KAAK,CAACI,cAAc,CAAC,CACvC,SAAS,EAAE,cAAc,CAC1B,CAAC;EACF,KAAK,MAAMC,GAAG,IAAIM,WAAW,EAAE;IAC7B,IAAIN,GAAG,CAACO,WAAW,CAACC,IAAI,CAAC,CAAC,EAAE;MAC1Bb,KAAK,CAACO,WAAW,CAAC,wCAAwCF,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QAC/EL,KAAK,CAACQ,SAAS,CAACH,GAAG,EAAE;UACnBO,WAAW,EAAE,EAAE;UACfE,OAAO,EAAE;QACX,CAAC,CAAC;MACJ,CAAC,CAAC;IACJ;EACF;AACF,CAAC,EAAE;EACDC,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJL,WAAW,EAAE,0FAA0F;MACvGM,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEC,IAAI,EAAE;YACR,CAAC,EACD;cACEL,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVK,OAAO,EAAE;kBACPD,IAAI,EAAE;gBACR,CAAC;gBACD3B,OAAO,EAAE;kBACP2B,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR,CAAC;QACDzB,oBAAoB,EAAE;UACpByB,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAE,MAAA,CAAA/B,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,176 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @typedef {{
* comment: string,
* context: string,
* message: string,
* minimum: import('../iterateJsdoc.js').Integer
* }} ContextObject
*/
/**
* @typedef {string|ContextObject} Context
*/
/**
* @param {import('../iterateJsdoc.js').StateObject} state
* @returns {void}
*/
const setDefaults = state => {
if (!state.selectorMap) {
state.selectorMap = {};
}
};
/**
* @param {import('../iterateJsdoc.js').StateObject} state
* @param {string} selector
* @param {string} comment
* @returns {void}
*/
const incrementSelector = (state, selector, comment) => {
if (!state.selectorMap[selector]) {
state.selectorMap[selector] = {};
}
if (!state.selectorMap[selector][comment]) {
state.selectorMap[selector][comment] = 0;
}
state.selectorMap[selector][comment]++;
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
info: {
comment
},
state,
utils
}) => {
if (!context.options[0]) {
// Handle error later
return;
}
/**
* @type {Context[]}
*/
const contexts = context.options[0].contexts;
const {
contextStr
} = utils.findContext(contexts, comment);
setDefaults(state);
incrementSelector(state, contextStr, String(comment));
}, {
contextSelected: true,
exit({
context,
settings,
state
}) {
if (!context.options.length && !settings.contexts) {
context.report({
loc: {
end: {
column: 1,
line: 1
},
start: {
column: 1,
line: 1
}
},
message: 'Rule `no-missing-syntax` is missing a `contexts` option.'
});
return;
}
setDefaults(state);
/**
* @type {Context[]}
*/
const contexts = (context.options[0] ?? {}).contexts ?? (settings === null || settings === void 0 ? void 0 : settings.contexts);
// Report when MISSING
contexts.some(cntxt => {
const contextStr = typeof cntxt === 'object' ? cntxt.context ?? 'any' : cntxt;
const comment = typeof cntxt === 'string' ? '' : cntxt === null || cntxt === void 0 ? void 0 : cntxt.comment;
const contextKey = contextStr === 'any' ? 'undefined' : contextStr;
if ((!state.selectorMap[contextKey] || !state.selectorMap[contextKey][comment] || state.selectorMap[contextKey][comment] < (
// @ts-expect-error comment would need an object, not string
(cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) ?? 1)) && (contextStr !== 'any' || Object.values(state.selectorMap).every(cmmnt => {
return !cmmnt[comment] || cmmnt[comment] < (
// @ts-expect-error comment would need an object, not string
(cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) ?? 1);
}))) {
const message = typeof cntxt === 'string' ? 'Syntax is required: {{context}}' : (cntxt === null || cntxt === void 0 ? void 0 : cntxt.message) ?? 'Syntax is required: {{context}}' + (comment ? ' with {{comment}}' : '');
context.report({
data: {
comment,
context: contextStr
},
loc: {
end: {
column: 1,
line: 1
},
start: {
column: 1,
line: 1
}
},
message
});
return true;
}
return false;
});
},
matchContext: true,
meta: {
docs: {
description: 'Reports when certain comment structures are always expected.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-missing-syntax.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
},
message: {
type: 'string'
},
minimum: {
type: 'integer'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noMissingSyntax.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const middleAsterisksBlockWS = /^([\t ]|\*(?!\*))+/u;
const middleAsterisksNoBlockWS = /^\*+/u;
const endAsterisksSingleLineBlockWS = /\*((?:\*|(?: |\t))*)\*$/u;
const endAsterisksMultipleLineBlockWS = /((?:\*|(?: |\t))*)\*$/u;
const endAsterisksSingleLineNoBlockWS = /\*(\**)\*$/u;
const endAsterisksMultipleLineNoBlockWS = /(\**)\*$/u;
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils
}) => {
const {
allowWhitespace = false,
preventAtEnd = true,
preventAtMiddleLines = true
} = context.options[0] || {};
const middleAsterisks = allowWhitespace ? middleAsterisksNoBlockWS : middleAsterisksBlockWS;
// eslint-disable-next-line complexity -- Todo
jsdoc.source.some(({
tokens,
number
}) => {
const {
delimiter,
tag,
name,
type,
description,
end,
postDelimiter
} = tokens;
if (preventAtMiddleLines && !end && !tag && !type && !name && (!allowWhitespace && middleAsterisks.test(description) || allowWhitespace && middleAsterisks.test(postDelimiter + description))) {
// console.log('description', JSON.stringify(description));
const fix = () => {
tokens.description = description.replace(middleAsterisks, '');
};
utils.reportJSDoc('Should be no multiple asterisks on middle lines.', {
line: number
}, fix, true);
return true;
}
if (!preventAtEnd || !end) {
return false;
}
const isSingleLineBlock = delimiter === '/**';
const delim = isSingleLineBlock ? '*' : delimiter;
const endAsterisks = allowWhitespace ? isSingleLineBlock ? endAsterisksSingleLineNoBlockWS : endAsterisksMultipleLineNoBlockWS : isSingleLineBlock ? endAsterisksSingleLineBlockWS : endAsterisksMultipleLineBlockWS;
const endingAsterisksAndSpaces = (allowWhitespace ? postDelimiter + description + delim : description + delim).match(endAsterisks);
if (!endingAsterisksAndSpaces || !isSingleLineBlock && endingAsterisksAndSpaces[1] && !endingAsterisksAndSpaces[1].trim()) {
return false;
}
const endFix = () => {
if (!isSingleLineBlock) {
tokens.delimiter = '';
}
tokens.description = (description + delim).replace(endAsterisks, '');
};
utils.reportJSDoc('Should be no multiple asterisks on end lines.', {
line: number
}, endFix, true);
return true;
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: '',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-multi-asterisks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
allowWhitespace: {
type: 'boolean'
},
preventAtEnd: {
type: 'boolean'
},
preventAtMiddleLines: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noMultiAsterisks.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
info: {
comment
},
report,
utils
}) => {
if (!context.options.length) {
report('Rule `no-restricted-syntax` is missing a `contexts` option.');
return;
}
const {
contexts
} = context.options[0];
const {
foundContext,
contextStr
} = utils.findContext(contexts, comment);
// We are not on the *particular* matching context/comment, so don't assume
// we need reporting
if (!foundContext) {
return;
}
const message = /** @type {import('../iterateJsdoc.js').ContextObject} */(foundContext === null || foundContext === void 0 ? void 0 : foundContext.message) ?? 'Syntax is restricted: {{context}}' + (comment ? ' with {{comment}}' : '');
report(message, null, null, comment ? {
comment,
context: contextStr
} : {
context: contextStr
});
}, {
contextSelected: true,
meta: {
docs: {
description: 'Reports when certain comment structures are present.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
},
message: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
required: ['contexts'],
type: 'object'
}],
type: 'suggestion'
},
nonGlobalSettings: true
});
module.exports = exports.default;
//# sourceMappingURL=noRestrictedSyntax.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noRestrictedSyntax.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","info","comment","report","utils","options","length","contexts","foundContext","contextStr","findContext","message","contextSelected","meta","docs","description","url","fixable","schema","additionalProperties","properties","items","anyOf","type","required","nonGlobalSettings","module"],"sources":["../../src/rules/noRestrictedSyntax.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n info: {\n comment,\n },\n report,\n utils,\n}) => {\n if (!context.options.length) {\n report('Rule `no-restricted-syntax` is missing a `contexts` option.');\n\n return;\n }\n\n const {\n contexts,\n } = context.options[0];\n\n const {\n foundContext,\n contextStr,\n } = utils.findContext(contexts, comment);\n\n // We are not on the *particular* matching context/comment, so don't assume\n // we need reporting\n if (!foundContext) {\n return;\n }\n\n const message = /** @type {import('../iterateJsdoc.js').ContextObject} */ (\n foundContext\n )?.message ??\n 'Syntax is restricted: {{context}}' +\n (comment ? ' with {{comment}}' : '');\n\n report(message, null, null, comment ? {\n comment,\n context: contextStr,\n } : {\n context: contextStr,\n });\n}, {\n contextSelected: true,\n meta: {\n docs: {\n description: 'Reports when certain comment structures are present.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n message: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n required: [\n 'contexts',\n ],\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n nonGlobalSettings: true,\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC,IAAI,EAAE;IACJC;EACF,CAAC;EACDC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,IAAI,CAACJ,OAAO,CAACK,OAAO,CAACC,MAAM,EAAE;IAC3BH,MAAM,CAAC,6DAA6D,CAAC;IAErE;EACF;EAEA,MAAM;IACJI;EACF,CAAC,GAAGP,OAAO,CAACK,OAAO,CAAC,CAAC,CAAC;EAEtB,MAAM;IACJG,YAAY;IACZC;EACF,CAAC,GAAGL,KAAK,CAACM,WAAW,CAACH,QAAQ,EAAEL,OAAO,CAAC;;EAExC;EACA;EACA,IAAI,CAACM,YAAY,EAAE;IACjB;EACF;EAEA,MAAMG,OAAO,GAAG,yDAA0D,CACxEH,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CACXG,OAAO,KACR,mCAAmC,IAChCT,OAAO,GAAG,mBAAmB,GAAG,EAAE,CAAC;EAExCC,MAAM,CAACQ,OAAO,EAAE,IAAI,EAAE,IAAI,EAAET,OAAO,GAAG;IACpCA,OAAO;IACPF,OAAO,EAAES;EACX,CAAC,GAAG;IACFT,OAAO,EAAES;EACX,CAAC,CAAC;AACJ,CAAC,EAAE;EACDG,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,sDAAsD;MACnEC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVb,QAAQ,EAAE;UACRc,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEC,IAAI,EAAE;YACR,CAAC,EACD;cACEJ,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVlB,OAAO,EAAE;kBACPqB,IAAI,EAAE;gBACR,CAAC;gBACDvB,OAAO,EAAE;kBACPuB,IAAI,EAAE;gBACR,CAAC;gBACDZ,OAAO,EAAE;kBACPY,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDC,QAAQ,EAAE,CACR,UAAU,CACX;MACDD,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR,CAAC;EACDE,iBAAiB,EAAE;AACrB,CAAC,CAAC;AAAAC,MAAA,CAAA5B,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {import('comment-parser').Line} line
*/
const removeType = ({
tokens
}) => {
tokens.postTag = '';
tokens.type = '';
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
utils
}) => {
if (!utils.isIteratingFunction() && !utils.isVirtualFunction()) {
return;
}
const tags = utils.getPresentTags(['param', 'arg', 'argument', 'returns', 'return']);
for (const tag of tags) {
if (tag.type) {
utils.reportJSDoc(`Types are not permitted on @${tag.tag}.`, tag, () => {
for (const source of tag.source) {
removeType(source);
}
});
}
}
}, {
contextDefaults: ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'TSDeclareFunction',
// Add this to above defaults
'TSMethodSignature'],
meta: {
docs: {
description: 'This rule reports types being used on `@param` or `@returns`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-types.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noTypes.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noTypes.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","removeType","tokens","postTag","type","_default","exports","iterateJsdoc","utils","isIteratingFunction","isVirtualFunction","tags","getPresentTags","tag","reportJSDoc","source","contextDefaults","meta","docs","description","url","fixable","schema","additionalProperties","properties","contexts","items","anyOf","comment","context","module"],"sources":["../../src/rules/noTypes.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\n/**\n * @param {import('comment-parser').Line} line\n */\nconst removeType = ({\n tokens,\n}) => {\n tokens.postTag = '';\n tokens.type = '';\n};\n\nexport default iterateJsdoc(({\n utils,\n}) => {\n if (!utils.isIteratingFunction() && !utils.isVirtualFunction()) {\n return;\n }\n\n const tags = utils.getPresentTags([\n 'param', 'arg', 'argument', 'returns', 'return',\n ]);\n\n for (const tag of tags) {\n if (tag.type) {\n utils.reportJSDoc(`Types are not permitted on @${tag.tag}.`, tag, () => {\n for (const source of tag.source) {\n removeType(source);\n }\n });\n }\n }\n}, {\n contextDefaults: [\n 'ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'TSDeclareFunction',\n // Add this to above defaults\n 'TSMethodSignature'\n ],\n meta: {\n docs: {\n description: 'This rule reports types being used on `@param` or `@returns`.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-types.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C;AACA;AACA;AACA,MAAMG,UAAU,GAAGA,CAAC;EAClBC;AACF,CAAC,KAAK;EACJA,MAAM,CAACC,OAAO,GAAG,EAAE;EACnBD,MAAM,CAACE,IAAI,GAAG,EAAE;AAClB,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAN,OAAA,GAEa,IAAAO,qBAAY,EAAC,CAAC;EAC3BC;AACF,CAAC,KAAK;EACJ,IAAI,CAACA,KAAK,CAACC,mBAAmB,CAAC,CAAC,IAAI,CAACD,KAAK,CAACE,iBAAiB,CAAC,CAAC,EAAE;IAC9D;EACF;EAEA,MAAMC,IAAI,GAAGH,KAAK,CAACI,cAAc,CAAC,CAChC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,CAChD,CAAC;EAEF,KAAK,MAAMC,GAAG,IAAIF,IAAI,EAAE;IACtB,IAAIE,GAAG,CAACT,IAAI,EAAE;MACZI,KAAK,CAACM,WAAW,CAAC,+BAA+BD,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QACtE,KAAK,MAAME,MAAM,IAAIF,GAAG,CAACE,MAAM,EAAE;UAC/Bd,UAAU,CAACc,MAAM,CAAC;QACpB;MACF,CAAC,CAAC;IACJ;EACF;AACF,CAAC,EAAE;EACDC,eAAe,EAAE,CACf,yBAAyB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,mBAAmB;EAC3F;EACA,mBAAmB,CACpB;EACDC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,+DAA+D;MAC5EC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEvB,IAAI,EAAE;YACR,CAAC,EACD;cACEmB,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVI,OAAO,EAAE;kBACPxB,IAAI,EAAE;gBACR,CAAC;gBACDyB,OAAO,EAAE;kBACPzB,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAA0B,MAAA,CAAAxB,OAAA,GAAAA,OAAA,CAAAN,OAAA","ignoreList":[]}

View File

@ -0,0 +1,300 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _path = require("path");
var _url = require("url");
var _synckit = require("synckit");
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _iterateJsdoc = _interopRequireWildcard(require("../iterateJsdoc.cjs"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const _dirname = (0, _path.dirname)((0, _url.fileURLToPath)(require('url').pathToFileURL(__filename).toString()));
const pathName = (0, _path.join)(_dirname, '../import-worker.mjs');
const extraTypes = ['null', 'undefined', 'void', 'string', 'boolean', 'object', 'function', 'symbol', 'number', 'bigint', 'NaN', 'Infinity', 'any', '*', 'never', 'unknown', 'const', 'this', 'true', 'false', 'Array', 'Object', 'RegExp', 'Date', 'Function'];
const typescriptGlobals = [
// https://www.typescriptlang.org/docs/handbook/utility-types.html
'Awaited', 'Partial', 'Required', 'Readonly', 'Record', 'Pick', 'Omit', 'Exclude', 'Extract', 'NonNullable', 'Parameters', 'ConstructorParameters', 'ReturnType', 'InstanceType', 'ThisParameterType', 'OmitThisParameter', 'ThisType', 'Uppercase', 'Lowercase', 'Capitalize', 'Uncapitalize'];
/**
* @param {string|false|undefined} [str]
* @returns {undefined|string|false}
*/
const stripPseudoTypes = str => {
return str && str.replace(/(?:\.|<>|\.<>|\[\])$/u, '');
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
node,
report,
settings,
sourceCode,
utils
}) => {
var _globalScope$childSco;
const {
scopeManager
} = sourceCode;
// When is this ever `null`?
const globalScope = /** @type {import('eslint').Scope.Scope} */
scopeManager.globalScope;
const
/**
* @type {{
* definedTypes: string[],
* disableReporting: boolean,
* markVariablesAsUsed: boolean
* }}
*/
{
definedTypes = [],
disableReporting = false,
markVariablesAsUsed = true
} = context.options[0] || {};
/** @type {(string|undefined)[]} */
let definedPreferredTypes = [];
const {
preferredTypes,
structuredTags,
mode
} = settings;
if (Object.keys(preferredTypes).length) {
definedPreferredTypes = /** @type {string[]} */Object.values(preferredTypes).map(preferredType => {
if (typeof preferredType === 'string') {
// May become an empty string but will be filtered out below
return stripPseudoTypes(preferredType);
}
if (!preferredType) {
return undefined;
}
if (typeof preferredType !== 'object') {
utils.reportSettings('Invalid `settings.jsdoc.preferredTypes`. Values must be falsy, a string, or an object.');
}
return stripPseudoTypes(preferredType.replacement);
}).filter(Boolean);
}
const comments = sourceCode.getAllComments().filter(comment => {
return /^\*\s/u.test(comment.value);
}).map(commentNode => {
return (0, _iterateJsdoc.parseComment)(commentNode, '');
});
const typedefDeclarations = comments.flatMap(doc => {
return doc.tags.filter(({
tag
}) => {
return utils.isNamepathDefiningTag(tag);
});
}).map(tag => {
return tag.name;
});
const importTags = settings.mode === 'typescript' ? ( /** @type {string[]} */comments.flatMap(doc => {
return doc.tags.filter(({
tag
}) => {
return tag === 'import';
});
}).flatMap(tag => {
const {
type,
name,
description
} = tag;
const typePart = type ? `{${type}} ` : '';
const imprt = 'import ' + (description ? `${typePart}${name} ${description}` : `${typePart}${name}`);
const getImports = (0, _synckit.createSyncFn)(pathName);
const imports = /** @type {import('parse-imports').Import[]} */getImports(imprt);
if (!imports) {
return null;
}
return imports.flatMap(({
importClause
}) => {
/* c8 ignore next */
const {
default: dflt,
named,
namespace
} = importClause || {};
const types = [];
if (dflt) {
types.push(dflt);
}
if (namespace) {
types.push(namespace);
}
if (named) {
for (const {
binding
} of named) {
types.push(binding);
}
}
return types;
});
}).filter(Boolean)) : [];
const ancestorNodes = [];
let currentNode = node;
// No need for Program node?
while ((_currentNode = currentNode) !== null && _currentNode !== void 0 && _currentNode.parent) {
var _currentNode;
ancestorNodes.push(currentNode);
currentNode = currentNode.parent;
}
/**
* @param {import('eslint').Rule.Node} ancestorNode
* @returns {import('comment-parser').Spec[]}
*/
const getTemplateTags = function (ancestorNode) {
const commentNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, ancestorNode, settings);
if (!commentNode) {
return [];
}
const jsdoc = (0, _iterateJsdoc.parseComment)(commentNode, '');
return jsdoc.tags.filter(tag => {
return tag.tag === 'template';
});
};
// `currentScope` may be `null` or `Program`, so in such a case,
// we look to present tags instead
const templateTags = ancestorNodes.length ? ancestorNodes.flatMap(ancestorNode => {
return getTemplateTags(ancestorNode);
}) : utils.getPresentTags(['template']);
const closureGenericTypes = templateTags.flatMap(tag => {
return utils.parseClosureTemplateTag(tag);
});
// In modules, including Node, there is a global scope at top with the
// Program scope inside
const cjsOrESMScope = ((_globalScope$childSco = globalScope.childScopes[0]) === null || _globalScope$childSco === void 0 || (_globalScope$childSco = _globalScope$childSco.block) === null || _globalScope$childSco === void 0 ? void 0 : _globalScope$childSco.type) === 'Program';
const allDefinedTypes = new Set(globalScope.variables.map(({
name
}) => {
return name;
})
// If the file is a module, concat the variables from the module scope.
.concat(cjsOrESMScope ? globalScope.childScopes.flatMap(({
variables
}) => {
return variables;
}).map(({
name
}) => {
return name;
/* c8 ignore next */
}) : []).concat(extraTypes).concat(typedefDeclarations).concat(importTags).concat(definedTypes).concat( /** @type {string[]} */definedPreferredTypes).concat(settings.mode === 'jsdoc' ? [] : [...(settings.mode === 'typescript' ? typescriptGlobals : []), ...closureGenericTypes]));
/**
* @typedef {{
* parsedType: import('jsdoc-type-pratt-parser').RootResult;
* tag: import('comment-parser').Spec|import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
* line?: import('../iterateJsdoc.js').Integer
* }
* }} TypeAndTagInfo
*/
/**
* @param {string} propertyName
* @returns {(tag: (import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
* name?: string,
* type?: string,
* line?: import('../iterateJsdoc.js').Integer
* })|import('comment-parser').Spec & {
* namepathOrURL?: string
* }
* ) => undefined|TypeAndTagInfo}
*/
const tagToParsedType = propertyName => {
return tag => {
try {
const potentialType = tag[( /** @type {"type"|"name"|"namepathOrURL"} */propertyName)];
return {
parsedType: mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode),
tag
};
} catch {
return undefined;
}
};
};
const typeTags = utils.filterTags(({
tag
}) => {
return tag !== 'import' && utils.tagMightHaveTypePosition(tag) && (tag !== 'suppress' || settings.mode !== 'closure');
}).map(tagToParsedType('type'));
const namepathReferencingTags = utils.filterTags(({
tag
}) => {
return utils.isNamepathReferencingTag(tag);
}).map(tagToParsedType('name'));
const namepathOrUrlReferencingTags = utils.filterAllTags(({
tag
}) => {
return utils.isNamepathOrUrlReferencingTag(tag);
}).map(tagToParsedType('namepathOrURL'));
const tagsWithTypes = /** @type {TypeAndTagInfo[]} */[...typeTags, ...namepathReferencingTags, ...namepathOrUrlReferencingTags
// Remove types which failed to parse
].filter(Boolean);
for (const {
tag,
parsedType
} of tagsWithTypes) {
(0, _jsdoccomment.traverse)(parsedType, nde => {
const {
type,
value
} = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
if (type === 'JsdocTypeName') {
var _structuredTags$tag$t;
const structuredTypes = (_structuredTags$tag$t = structuredTags[tag.tag]) === null || _structuredTags$tag$t === void 0 ? void 0 : _structuredTags$tag$t.type;
if (!allDefinedTypes.has(value) && (!Array.isArray(structuredTypes) || !structuredTypes.includes(value))) {
if (!disableReporting) {
report(`The type '${value}' is undefined.`, null, tag);
}
} else if (markVariablesAsUsed && !extraTypes.includes(value)) {
if (sourceCode.markVariableAsUsed) {
sourceCode.markVariableAsUsed(value);
/* c8 ignore next 3 */
} else {
context.markVariableAsUsed(value);
}
}
}
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that types in jsdoc comments are defined.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-undefined-types.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
definedTypes: {
items: {
type: 'string'
},
type: 'array'
},
disableReporting: {
type: 'boolean'
},
markVariablesAsUsed: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noUndefinedTypes.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,166 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils,
indent
}) => {
const [defaultRequireValue = 'always', {
tags: tagMap = {}
} = {}] = context.options;
const {
source
} = jsdoc;
const always = defaultRequireValue === 'always';
const never = defaultRequireValue === 'never';
/** @type {string} */
let currentTag;
source.some(({
number,
tokens
}) => {
var _tagMap$any2;
const {
delimiter,
tag,
end,
description
} = tokens;
/**
* @returns {void}
*/
const neverFix = () => {
tokens.delimiter = '';
tokens.postDelimiter = '';
};
/**
* @param {string} checkValue
* @returns {boolean}
*/
const checkNever = checkValue => {
var _tagMap$always, _tagMap$never;
if (delimiter && delimiter !== '/**' && (never && !((_tagMap$always = tagMap.always) !== null && _tagMap$always !== void 0 && _tagMap$always.includes(checkValue)) || (_tagMap$never = tagMap.never) !== null && _tagMap$never !== void 0 && _tagMap$never.includes(checkValue))) {
utils.reportJSDoc('Expected JSDoc line to have no prefix.', {
column: 0,
line: number
}, neverFix);
return true;
}
return false;
};
/**
* @returns {void}
*/
const alwaysFix = () => {
if (!tokens.start) {
tokens.start = indent + ' ';
}
tokens.delimiter = '*';
tokens.postDelimiter = tag || description ? ' ' : '';
};
/**
* @param {string} checkValue
* @returns {boolean}
*/
const checkAlways = checkValue => {
var _tagMap$never2, _tagMap$always2;
if (!delimiter && (always && !((_tagMap$never2 = tagMap.never) !== null && _tagMap$never2 !== void 0 && _tagMap$never2.includes(checkValue)) || (_tagMap$always2 = tagMap.always) !== null && _tagMap$always2 !== void 0 && _tagMap$always2.includes(checkValue))) {
utils.reportJSDoc('Expected JSDoc line to have the prefix.', {
column: 0,
line: number
}, alwaysFix);
return true;
}
return false;
};
if (tag) {
// Remove at sign
currentTag = tag.slice(1);
}
if (
// If this is the end but has a tag, the delimiter will also be
// populated and will be safely ignored later
end && !tag) {
return false;
}
if (!currentTag) {
var _tagMap$any;
if ((_tagMap$any = tagMap.any) !== null && _tagMap$any !== void 0 && _tagMap$any.includes('*description')) {
return false;
}
if (checkNever('*description')) {
return true;
}
if (checkAlways('*description')) {
return true;
}
return false;
}
if ((_tagMap$any2 = tagMap.any) !== null && _tagMap$any2 !== void 0 && _tagMap$any2.includes(currentTag)) {
return false;
}
if (checkNever(currentTag)) {
return true;
}
if (checkAlways(currentTag)) {
return true;
}
return false;
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that each JSDoc line starts with an `*`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-asterisk-prefix.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
enum: ['always', 'never', 'any'],
type: 'string'
}, {
additionalProperties: false,
properties: {
tags: {
properties: {
always: {
items: {
type: 'string'
},
type: 'array'
},
any: {
items: {
type: 'string'
},
type: 'array'
},
never: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireAsteriskPrefix.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} description
* @returns {import('../iterateJsdoc.js').Integer}
*/
const checkDescription = description => {
return description.trim().split('\n').filter(Boolean).length;
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
utils,
context
}) => {
if (utils.avoidDocs()) {
return;
}
const {
descriptionStyle = 'body'
} = context.options[0] || {};
let targetTagName = utils.getPreferredTagName({
// We skip reporting except when `@description` is essential to the rule,
// so user can block the tag and still meaningfully use this rule
// even if the tag is present (and `check-tag-names` is the one to
// normally report the fact that it is blocked but present)
skipReportingBlockedTag: descriptionStyle !== 'tag',
tagName: 'description'
});
if (!targetTagName) {
return;
}
const isBlocked = typeof targetTagName === 'object' && 'blocked' in targetTagName && targetTagName.blocked;
if (isBlocked) {
targetTagName = /** @type {{blocked: true; tagName: string;}} */targetTagName.tagName;
}
if (descriptionStyle !== 'tag') {
const {
description
} = utils.getDescription();
if (checkDescription(description || '')) {
return;
}
if (descriptionStyle === 'body') {
const descTags = utils.getPresentTags(['desc', 'description']);
if (descTags.length) {
const [{
tag: tagName
}] = descTags;
report(`Remove the @${tagName} tag to leave a plain block description or add additional description text above the @${tagName} line.`);
} else {
report('Missing JSDoc block description.');
}
return;
}
}
const functionExamples = isBlocked ? [] : jsdoc.tags.filter(({
tag
}) => {
return tag === targetTagName;
});
if (!functionExamples.length) {
report(descriptionStyle === 'any' ? `Missing JSDoc block description or @${targetTagName} declaration.` : `Missing JSDoc @${targetTagName} declaration.`);
return;
}
for (const example of functionExamples) {
if (!checkDescription(`${example.name} ${utils.getTagDescription(example)}`)) {
report(`Missing JSDoc @${targetTagName} description.`, null, example);
}
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that all functions have a description.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-description.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
checkConstructors: {
default: true,
type: 'boolean'
},
checkGetters: {
default: true,
type: 'boolean'
},
checkSetters: {
default: true,
type: 'boolean'
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
descriptionStyle: {
enum: ['body', 'tag', 'any'],
type: 'string'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireDescription.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,282 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _escapeStringRegexp = _interopRequireDefault(require("escape-string-regexp"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const otherDescriptiveTags = new Set([
// 'copyright' and 'see' might be good addition, but as the former may be
// sensitive text, and the latter may have just a link, they are not
// included by default
'summary', 'file', 'fileoverview', 'overview', 'classdesc', 'todo', 'deprecated', 'throws', 'exception', 'yields', 'yield']);
/**
* @param {string} text
* @returns {string[]}
*/
const extractParagraphs = text => {
return text.split(/(?<![;:])\n\n+/u);
};
/**
* @param {string} text
* @param {string|RegExp} abbreviationsRegex
* @returns {string[]}
*/
const extractSentences = (text, abbreviationsRegex) => {
const txt = text
// Remove all {} tags.
.replaceAll(/(?<!^)\{[\s\S]*?\}\s*/gu, '')
// Remove custom abbreviations
.replace(abbreviationsRegex, '');
const sentenceEndGrouping = /([.?!])(?:\s+|$)/ug;
const puncts = [...txt.matchAll(sentenceEndGrouping)].map(sentEnd => {
return sentEnd[0];
});
return txt.split(/[.?!](?:\s+|$)/u)
// Re-add the dot.
.map((sentence, idx) => {
return !puncts[idx] && /^\s*$/u.test(sentence) ? sentence : `${sentence}${puncts[idx] || ''}`;
});
};
/**
* @param {string} text
* @returns {boolean}
*/
const isNewLinePrecededByAPeriod = text => {
/** @type {boolean} */
let lastLineEndsSentence;
const lines = text.split('\n');
return !lines.some(line => {
if (lastLineEndsSentence === false && /^[A-Z][a-z]/u.test(line)) {
return true;
}
lastLineEndsSentence = /[.:?!|]$/u.test(line);
return false;
});
};
/**
* @param {string} str
* @returns {boolean}
*/
const isCapitalized = str => {
return str[0] === str[0].toUpperCase();
};
/**
* @param {string} str
* @returns {boolean}
*/
const isTable = str => {
return str.charAt(0) === '|';
};
/**
* @param {string} str
* @returns {string}
*/
const capitalize = str => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
/**
* @param {string} description
* @param {import('../iterateJsdoc.js').Report} reportOrig
* @param {import('eslint').Rule.Node} jsdocNode
* @param {string|RegExp} abbreviationsRegex
* @param {import('eslint').SourceCode} sourceCode
* @param {import('comment-parser').Spec|{
* line: import('../iterateJsdoc.js').Integer
* }} tag
* @param {boolean} newlineBeforeCapsAssumesBadSentenceEnd
* @returns {boolean}
*/
const validateDescription = (description, reportOrig, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd) => {
if (!description || /^\n+$/u.test(description)) {
return false;
}
const descriptionNoHeadings = description.replaceAll(/^\s*#[^\n]*(\n|$)/gm, '');
const paragraphs = extractParagraphs(descriptionNoHeadings).filter(Boolean);
return paragraphs.some((paragraph, parIdx) => {
const sentences = extractSentences(paragraph, abbreviationsRegex);
const fix = /** @type {import('eslint').Rule.ReportFixer} */fixer => {
let text = sourceCode.getText(jsdocNode);
if (!/[.:?!]$/u.test(paragraph)) {
const line = paragraph.split('\n').filter(Boolean).pop();
text = text.replace(new RegExp(`${(0, _escapeStringRegexp.default)( /** @type {string} */
line)}$`, 'mu'), `${line}.`);
}
for (const sentence of sentences.filter(sentence_ => {
return !/^\s*$/u.test(sentence_) && !isCapitalized(sentence_) && !isTable(sentence_);
})) {
const beginning = sentence.split('\n')[0];
if ('tag' in tag && tag.tag) {
const reg = new RegExp(`(@${(0, _escapeStringRegexp.default)(tag.tag)}.*)${(0, _escapeStringRegexp.default)(beginning)}`, 'u');
text = text.replace(reg, (_$0, $1) => {
return $1 + capitalize(beginning);
});
} else {
text = text.replace(new RegExp('((?:[.?!]|\\*|\\})\\s*)' + (0, _escapeStringRegexp.default)(beginning), 'u'), '$1' + capitalize(beginning));
}
}
return fixer.replaceText(jsdocNode, text);
};
/**
* @param {string} msg
* @param {import('eslint').Rule.ReportFixer | null | undefined} fixer
* @param {{
* line?: number | undefined;
* column?: number | undefined;
* } | (import('comment-parser').Spec & {
* line?: number | undefined;
* column?: number | undefined;
* })} tagObj
* @returns {void}
*/
const report = (msg, fixer, tagObj) => {
if ('line' in tagObj) {
/**
* @type {{
* line: number;
* }}
*/
tagObj.line += parIdx * 2;
} else {
/** @type {import('comment-parser').Spec} */tagObj.source[0].number += parIdx * 2;
}
// Avoid errors if old column doesn't exist here
tagObj.column = 0;
reportOrig(msg, fixer, tagObj);
};
if (sentences.some(sentence => {
return /^[.?!]$/u.test(sentence);
})) {
report('Sentences must be more than punctuation.', null, tag);
}
if (sentences.some(sentence => {
return !/^\s*$/u.test(sentence) && !isCapitalized(sentence) && !isTable(sentence);
})) {
report('Sentences should start with an uppercase character.', fix, tag);
}
const paragraphNoAbbreviations = paragraph.replace(abbreviationsRegex, '');
if (!/(?:[.?!|]|```)\s*$/u.test(paragraphNoAbbreviations)) {
report('Sentences must end with a period.', fix, tag);
return true;
}
if (newlineBeforeCapsAssumesBadSentenceEnd && !isNewLinePrecededByAPeriod(paragraphNoAbbreviations)) {
report('A line of text is started with an uppercase character, but the preceding line does not end the sentence.', null, tag);
return true;
}
return false;
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
context,
jsdoc,
report,
jsdocNode,
utils
}) => {
const /** @type {{abbreviations: string[], newlineBeforeCapsAssumesBadSentenceEnd: boolean}} */{
abbreviations = [],
newlineBeforeCapsAssumesBadSentenceEnd = false
} = context.options[0] || {};
const abbreviationsRegex = abbreviations.length ? new RegExp('\\b' + abbreviations.map(abbreviation => {
return (0, _escapeStringRegexp.default)(abbreviation.replaceAll(/\.$/ug, '') + '.');
}).join('|') + '(?:$|\\s)', 'gu') : '';
let {
description
} = utils.getDescription();
const indices = [...description.matchAll(/```[\s\S]*```/gu)].map(match => {
const {
index
} = match;
const [{
length
}] = match;
return {
index,
length
};
}).reverse();
for (const {
index,
length
} of indices) {
description = description.slice(0, index) + description.slice( /** @type {import('../iterateJsdoc.js').Integer} */index + length);
}
if (validateDescription(description, report, jsdocNode, abbreviationsRegex, sourceCode, {
line: jsdoc.source[0].number + 1
}, newlineBeforeCapsAssumesBadSentenceEnd)) {
return;
}
utils.forEachPreferredTag('description', matchingJsdocTag => {
const desc = `${matchingJsdocTag.name} ${utils.getTagDescription(matchingJsdocTag)}`.trim();
validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, matchingJsdocTag, newlineBeforeCapsAssumesBadSentenceEnd);
}, true);
const {
tagsWithNames
} = utils.getTagsByType(jsdoc.tags);
const tagsWithoutNames = utils.filterTags(({
tag: tagName
}) => {
return otherDescriptiveTags.has(tagName) || utils.hasOptionTag(tagName) && !tagsWithNames.some(({
tag
}) => {
// If user accidentally adds tags with names (or like `returns`
// get parsed as having names), do not add to this list
return tag === tagName;
});
});
tagsWithNames.some(tag => {
const desc = /** @type {string} */utils.getTagDescription(tag).replace(/^- /u, '').trimEnd();
return validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd);
});
tagsWithoutNames.some(tag => {
const desc = `${tag.name} ${utils.getTagDescription(tag)}`.trim();
return validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd);
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that block description, explicit `@description`, and `@param`/`@returns` tag descriptions are written in complete sentences.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-description-complete-sentence.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
abbreviations: {
items: {
type: 'string'
},
type: 'array'
},
newlineBeforeCapsAssumesBadSentenceEnd: {
type: 'boolean'
},
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireDescriptionCompleteSentence.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
utils
}) => {
if (utils.avoidDocs()) {
return;
}
const {
enableFixer = true,
exemptNoArguments = false
} = context.options[0] || {};
const targetTagName = 'example';
const functionExamples = jsdoc.tags.filter(({
tag
}) => {
return tag === targetTagName;
});
if (!functionExamples.length) {
if (exemptNoArguments && utils.isIteratingFunction() && !utils.hasParams()) {
return;
}
utils.reportJSDoc(`Missing JSDoc @${targetTagName} declaration.`, null, () => {
if (enableFixer) {
utils.addTag(targetTagName);
}
});
return;
}
for (const example of functionExamples) {
const exampleContent = `${example.name} ${utils.getTagDescription(example)}`.trim().split('\n').filter(Boolean);
if (!exampleContent.length) {
report(`Missing JSDoc @${targetTagName} description.`, null, example);
}
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that all functions have examples.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-example.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
checkConstructors: {
default: true,
type: 'boolean'
},
checkGetters: {
default: false,
type: 'boolean'
},
checkSetters: {
default: false,
type: 'boolean'
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
default: true,
type: 'boolean'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
},
exemptNoArguments: {
default: false,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireExample.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultTags = {
file: {
initialCommentsOnly: true,
mustExist: true,
preventDuplicates: true
}
};
/**
* @param {import('../iterateJsdoc.js').StateObject} state
* @returns {void}
*/
const setDefaults = state => {
// First iteration
if (!state.globalTags) {
state.globalTags = {};
state.hasDuplicates = {};
state.hasTag = {};
state.hasNonCommentBeforeTag = {};
}
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdocNode,
state,
utils,
context
}) => {
const {
tags = defaultTags
} = context.options[0] || {};
setDefaults(state);
for (const tagName of Object.keys(tags)) {
const targetTagName = /** @type {string} */utils.getPreferredTagName({
tagName
});
const hasTag = Boolean(targetTagName && utils.hasTag(targetTagName));
state.hasTag[tagName] = hasTag || state.hasTag[tagName];
const hasDuplicate = state.hasDuplicates[tagName];
if (hasDuplicate === false) {
// Was marked before, so if a tag now, is a dupe
state.hasDuplicates[tagName] = hasTag;
} else if (!hasDuplicate && hasTag) {
// No dupes set before, but has first tag, so change state
// from `undefined` to `false` so can detect next time
state.hasDuplicates[tagName] = false;
state.hasNonCommentBeforeTag[tagName] = state.hasNonComment && state.hasNonComment < jsdocNode.range[0];
}
}
}, {
exit({
context,
state,
utils
}) {
setDefaults(state);
const {
tags = defaultTags
} = context.options[0] || {};
for (const [tagName, {
mustExist = false,
preventDuplicates = false,
initialCommentsOnly = false
}] of Object.entries(tags)) {
const obj = utils.getPreferredTagNameObject({
tagName
});
if (obj && typeof obj === 'object' && 'blocked' in obj) {
utils.reportSettings(`\`settings.jsdoc.tagNamePreference\` cannot block @${obj.tagName} ` + 'for the `require-file-overview` rule');
} else {
const targetTagName = obj && typeof obj === 'object' && obj.replacement || obj;
if (mustExist && !state.hasTag[tagName]) {
utils.reportSettings(`Missing @${targetTagName}`);
}
if (preventDuplicates && state.hasDuplicates[tagName]) {
utils.reportSettings(`Duplicate @${targetTagName}`);
}
if (initialCommentsOnly && state.hasNonCommentBeforeTag[tagName]) {
utils.reportSettings(`@${targetTagName} should be at the beginning of the file`);
}
}
}
},
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that all files have one `@file`, `@fileoverview`, or `@overview` tag at the beginning of the file.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-file-overview.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
tags: {
patternProperties: {
'.*': {
additionalProperties: false,
properties: {
initialCommentsOnly: {
type: 'boolean'
},
mustExist: {
type: 'boolean'
},
preventDuplicates: {
type: 'boolean'
}
},
type: 'object'
}
},
type: 'object'
}
},
type: 'object'
}],
type: 'suggestion'
},
nonComment({
state,
node
}) {
if (!state.hasNonComment) {
state.hasNonComment = node.range[0];
}
}
});
module.exports = exports.default;
//# sourceMappingURL=requireFileOverview.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
utils,
report,
context,
jsdoc,
jsdocNode
}) => {
const [mainCircumstance, {
tags = null
} = {}] = context.options;
const tgs =
/**
* @type {null|"any"|{[key: string]: "always"|"never"}}
*/
tags;
/**
* @param {import('@es-joy/jsdoccomment').JsdocTagWithInline} jsdocTag
* @param {string} targetTagName
* @param {"always"|"never"} [circumstance]
* @returns {void}
*/
const checkHyphens = (jsdocTag, targetTagName, circumstance = mainCircumstance) => {
const always = !circumstance || circumstance === 'always';
const desc = /** @type {string} */utils.getTagDescription(jsdocTag);
if (!desc.trim()) {
return;
}
const startsWithHyphen = /^\s*-/u.test(desc);
if (always) {
if (!startsWithHyphen) {
report(`There must be a hyphen before @${targetTagName} description.`, fixer => {
const lineIndex = /** @type {import('../iterateJsdoc.js').Integer} */
jsdocTag.line;
const sourceLines = sourceCode.getText(jsdocNode).split('\n');
// Get start index of description, accounting for multi-line descriptions
const description = desc.split('\n')[0];
const descriptionIndex = sourceLines[lineIndex].lastIndexOf(description);
const replacementLine = sourceLines[lineIndex].slice(0, descriptionIndex) + '- ' + description;
sourceLines.splice(lineIndex, 1, replacementLine);
const replacement = sourceLines.join('\n');
return fixer.replaceText(jsdocNode, replacement);
}, jsdocTag);
}
} else if (startsWithHyphen) {
let lines = 0;
for (const {
tokens
} of jsdocTag.source) {
if (tokens.description) {
break;
}
lines++;
}
utils.reportJSDoc(`There must be no hyphen before @${targetTagName} description.`, {
line: jsdocTag.source[0].number + lines
}, () => {
for (const {
tokens
} of jsdocTag.source) {
if (tokens.description) {
tokens.description = tokens.description.replace(/^\s*-\s*/u, '');
break;
}
}
}, true);
}
};
utils.forEachPreferredTag('param', checkHyphens);
if (tgs) {
const tagEntries = Object.entries(tgs);
for (const [tagName, circumstance] of tagEntries) {
if (tagName === '*') {
const preferredParamTag = utils.getPreferredTagName({
tagName: 'param'
});
for (const {
tag
} of jsdoc.tags) {
if (tag === preferredParamTag || tagEntries.some(([tagNme]) => {
return tagNme !== '*' && tagNme === tag;
})) {
continue;
}
utils.forEachPreferredTag(tag, (jsdocTag, targetTagName) => {
checkHyphens(jsdocTag, targetTagName, /** @type {"always"|"never"} */circumstance);
});
}
continue;
}
utils.forEachPreferredTag(tagName, (jsdocTag, targetTagName) => {
checkHyphens(jsdocTag, targetTagName, /** @type {"always"|"never"} */circumstance);
});
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires a hyphen before the `@param` description.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-hyphen-before-param-description.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
enum: ['always', 'never'],
type: 'string'
}, {
additionalProperties: false,
properties: {
tags: {
anyOf: [{
patternProperties: {
'.*': {
enum: ['always', 'never'],
type: 'string'
}
},
type: 'object'
}, {
enum: ['any'],
type: 'string'
}]
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireHyphenBeforeParamDescription.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,507 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _exportParser = _interopRequireDefault(require("../exportParser.cjs"));
var _iterateJsdoc = require("../iterateJsdoc.cjs");
var _jsdocUtils = require("../jsdocUtils.cjs");
var _jsdoccomment = require("@es-joy/jsdoccomment");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @typedef {{
* ancestorsOnly: boolean,
* esm: boolean,
* initModuleExports: boolean,
* initWindow: boolean
* }} RequireJsdocOpts
*/
/**
* @typedef {import('eslint').Rule.Node|
* import('@typescript-eslint/types').TSESTree.Node} ESLintOrTSNode
*/
/** @type {import('json-schema').JSONSchema4} */
const OPTIONS_SCHEMA = {
additionalProperties: false,
properties: {
checkConstructors: {
default: true,
type: 'boolean'
},
checkGetters: {
anyOf: [{
type: 'boolean'
}, {
enum: ['no-setter'],
type: 'string'
}],
default: true
},
checkSetters: {
anyOf: [{
type: 'boolean'
}, {
enum: ['no-getter'],
type: 'string'
}],
default: true
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
},
minLineCount: {
type: 'integer'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
default: true,
type: 'boolean'
},
exemptEmptyConstructors: {
default: false,
type: 'boolean'
},
exemptEmptyFunctions: {
default: false,
type: 'boolean'
},
fixerMessage: {
default: '',
type: 'string'
},
minLineCount: {
type: 'integer'
},
publicOnly: {
oneOf: [{
default: false,
type: 'boolean'
}, {
additionalProperties: false,
default: {},
properties: {
ancestorsOnly: {
type: 'boolean'
},
cjs: {
type: 'boolean'
},
esm: {
type: 'boolean'
},
window: {
type: 'boolean'
}
},
type: 'object'
}]
},
require: {
additionalProperties: false,
default: {},
properties: {
ArrowFunctionExpression: {
default: false,
type: 'boolean'
},
ClassDeclaration: {
default: false,
type: 'boolean'
},
ClassExpression: {
default: false,
type: 'boolean'
},
FunctionDeclaration: {
default: true,
type: 'boolean'
},
FunctionExpression: {
default: false,
type: 'boolean'
},
MethodDefinition: {
default: false,
type: 'boolean'
}
},
type: 'object'
}
},
type: 'object'
};
/**
* @param {import('eslint').Rule.RuleContext} context
* @param {import('json-schema').JSONSchema4Object} baseObject
* @param {string} option
* @param {string} key
* @returns {boolean|undefined}
*/
const getOption = (context, baseObject, option, key) => {
if (context.options[0] && option in context.options[0] && (
// Todo: boolean shouldn't be returning property, but
// tests currently require
typeof context.options[0][option] === 'boolean' || key in context.options[0][option])) {
return context.options[0][option][key];
}
return /** @type {{[key: string]: {default?: boolean|undefined}}} */baseObject.properties[key].default;
};
/**
* @param {import('eslint').Rule.RuleContext} context
* @param {import('../iterateJsdoc.js').Settings} settings
* @returns {{
* contexts: (string|{
* context: string,
* inlineCommentBlock: boolean,
* minLineCount: import('../iterateJsdoc.js').Integer
* })[],
* enableFixer: boolean,
* exemptEmptyConstructors: boolean,
* exemptEmptyFunctions: boolean,
* fixerMessage: string,
* minLineCount: undefined|import('../iterateJsdoc.js').Integer,
* publicOnly: boolean|{[key: string]: boolean|undefined}
* require: {[key: string]: boolean|undefined}
* }}
*/
const getOptions = (context, settings) => {
const {
publicOnly,
contexts = settings.contexts || [],
exemptEmptyConstructors = true,
exemptEmptyFunctions = false,
enableFixer = true,
fixerMessage = '',
minLineCount = undefined
} = context.options[0] || {};
return {
contexts,
enableFixer,
exemptEmptyConstructors,
exemptEmptyFunctions,
fixerMessage,
minLineCount,
publicOnly: (baseObj => {
if (!publicOnly) {
return false;
}
/** @type {{[key: string]: boolean|undefined}} */
const properties = {};
for (const prop of Object.keys( /** @type {import('json-schema').JSONSchema4Object} */
/** @type {import('json-schema').JSONSchema4Object} */baseObj.properties)) {
const opt = getOption(context, /** @type {import('json-schema').JSONSchema4Object} */baseObj, 'publicOnly', prop);
properties[prop] = opt;
}
return properties;
})( /** @type {import('json-schema').JSONSchema4Object} */
( /** @type {import('json-schema').JSONSchema4Object} */
( /** @type {import('json-schema').JSONSchema4Object} */
OPTIONS_SCHEMA.properties.publicOnly).oneOf)[1]),
require: (baseObj => {
/** @type {{[key: string]: boolean|undefined}} */
const properties = {};
for (const prop of Object.keys( /** @type {import('json-schema').JSONSchema4Object} */
/** @type {import('json-schema').JSONSchema4Object} */baseObj.properties)) {
const opt = getOption(context, /** @type {import('json-schema').JSONSchema4Object} */
baseObj, 'require', prop);
properties[prop] = opt;
}
return properties;
})( /** @type {import('json-schema').JSONSchema4Object} */
OPTIONS_SCHEMA.properties.require)
};
};
/** @type {import('eslint').Rule.RuleModule} */
var _default = exports.default = {
create(context) {
/* c8 ignore next -- Fallback to deprecated method */
const {
sourceCode = context.getSourceCode()
} = context;
const settings = (0, _iterateJsdoc.getSettings)(context);
if (!settings) {
return {};
}
const opts = getOptions(context, settings);
const {
require: requireOption,
contexts,
exemptEmptyFunctions,
exemptEmptyConstructors,
enableFixer,
fixerMessage,
minLineCount
} = opts;
const publicOnly =
/**
* @type {{
* [key: string]: boolean | undefined;
* }}
*/
opts.publicOnly;
/**
* @type {import('../iterateJsdoc.js').CheckJsdoc}
*/
const checkJsDoc = (info, _handler, node) => {
if (
// Optimize
minLineCount !== undefined || contexts.some(ctxt => {
if (typeof ctxt === 'string') {
return false;
}
const {
minLineCount: count
} = ctxt;
return count !== undefined;
})) {
/**
* @param {undefined|import('../iterateJsdoc.js').Integer} count
*/
const underMinLine = count => {
var _sourceCode$getText$m;
return count !== undefined && count > (((_sourceCode$getText$m = sourceCode.getText(node).match(/\n/gu)) === null || _sourceCode$getText$m === void 0 ? void 0 : _sourceCode$getText$m.length) ?? 0) + 1;
};
if (underMinLine(minLineCount)) {
return;
}
const {
minLineCount: contextMinLineCount
} =
/**
* @type {{
* context: string;
* inlineCommentBlock: boolean;
* minLineCount: number;
* }}
*/
contexts.find(ctxt => {
if (typeof ctxt === 'string') {
return false;
}
const {
context: ctx
} = ctxt;
return ctx === (info.selector || node.type);
}) || {};
if (underMinLine(contextMinLineCount)) {
return;
}
}
const jsDocNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, node, settings);
if (jsDocNode) {
return;
}
// For those who have options configured against ANY constructors (or
// setters or getters) being reported
if ((0, _jsdocUtils.exemptSpeciaMethods)({
description: '',
inlineTags: [],
problems: [],
source: [],
tags: []
}, node, context, [OPTIONS_SCHEMA])) {
return;
}
if (
// Avoid reporting param-less, return-less functions (when
// `exemptEmptyFunctions` option is set)
exemptEmptyFunctions && info.isFunctionContext ||
// Avoid reporting param-less, return-less constructor methods (when
// `exemptEmptyConstructors` option is set)
exemptEmptyConstructors && (0, _jsdocUtils.isConstructor)(node)) {
const functionParameterNames = (0, _jsdocUtils.getFunctionParameterNames)(node);
if (!functionParameterNames.length && !(0, _jsdocUtils.hasReturnValue)(node)) {
return;
}
}
const fix = /** @type {import('eslint').Rule.ReportFixer} */fixer => {
// Default to one line break if the `minLines`/`maxLines` settings allow
const lines = settings.minLines === 0 && settings.maxLines >= 1 ? 1 : settings.minLines;
/** @type {ESLintOrTSNode|import('@typescript-eslint/types').TSESTree.Decorator} */
let baseNode = (0, _jsdoccomment.getReducedASTNode)(node, sourceCode);
const decorator = (0, _jsdoccomment.getDecorator)( /** @type {import('eslint').Rule.Node} */
baseNode);
if (decorator) {
baseNode = decorator;
}
const indent = (0, _jsdocUtils.getIndent)({
text: sourceCode.getText( /** @type {import('eslint').Rule.Node} */baseNode, /** @type {import('eslint').AST.SourceLocation} */
( /** @type {import('eslint').Rule.Node} */baseNode.loc).start.column)
});
const {
inlineCommentBlock
} =
/**
* @type {{
* context: string,
* inlineCommentBlock: boolean,
* minLineCount: import('../iterateJsdoc.js').Integer
* }}
*/
contexts.find(contxt => {
if (typeof contxt === 'string') {
return false;
}
const {
context: ctxt
} = contxt;
return ctxt === node.type;
}) || {};
const insertion = (inlineCommentBlock ? `/** ${fixerMessage}` : `/**\n${indent}*${fixerMessage}\n${indent}`) + `*/${'\n'.repeat(lines)}${indent.slice(0, -1)}`;
return fixer.insertTextBefore( /** @type {import('eslint').Rule.Node} */
baseNode, insertion);
};
const report = () => {
const {
start
} = /** @type {import('eslint').AST.SourceLocation} */node.loc;
const loc = {
end: {
column: 0,
line: start.line + 1
},
start
};
context.report({
fix: enableFixer ? fix : null,
loc,
messageId: 'missingJsDoc',
node
});
};
if (publicOnly) {
/** @type {RequireJsdocOpts} */
const opt = {
ancestorsOnly: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.ancestorsOnly) ?? false),
esm: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.esm) ?? true),
initModuleExports: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.cjs) ?? true),
initWindow: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.window) ?? false)
};
const exported = _exportParser.default.isUncommentedExport(node, sourceCode, opt, settings);
if (exported) {
report();
}
} else {
report();
}
};
/**
* @param {string} prop
* @returns {boolean}
*/
const hasOption = prop => {
return requireOption[prop] || contexts.some(ctxt => {
return typeof ctxt === 'object' ? ctxt.context === prop : ctxt === prop;
});
};
return {
...(0, _jsdocUtils.getContextObject)((0, _jsdocUtils.enforcedContexts)(context, [], settings), checkJsDoc),
ArrowFunctionExpression(node) {
if (!hasOption('ArrowFunctionExpression')) {
return;
}
if (['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) || ['Property', 'ObjectProperty', 'ClassProperty', 'PropertyDefinition'].includes(node.parent.type) && node ===
/**
* @type {import('@typescript-eslint/types').TSESTree.Property|
* import('@typescript-eslint/types').TSESTree.PropertyDefinition
* }
*/
node.parent.value) {
checkJsDoc({
isFunctionContext: true
}, null, node);
}
},
ClassDeclaration(node) {
if (!hasOption('ClassDeclaration')) {
return;
}
checkJsDoc({
isFunctionContext: false
}, null, node);
},
ClassExpression(node) {
if (!hasOption('ClassExpression')) {
return;
}
checkJsDoc({
isFunctionContext: false
}, null, node);
},
FunctionDeclaration(node) {
if (!hasOption('FunctionDeclaration')) {
return;
}
checkJsDoc({
isFunctionContext: true
}, null, node);
},
FunctionExpression(node) {
if (!hasOption('FunctionExpression')) {
return;
}
if (['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) || ['Property', 'ObjectProperty', 'ClassProperty', 'PropertyDefinition'].includes(node.parent.type) && node ===
/**
* @type {import('@typescript-eslint/types').TSESTree.Property|
* import('@typescript-eslint/types').TSESTree.PropertyDefinition
* }
*/
node.parent.value) {
checkJsDoc({
isFunctionContext: true
}, null, node);
}
},
MethodDefinition(node) {
if (!hasOption('MethodDefinition')) {
return;
}
checkJsDoc({
isFunctionContext: true,
selector: 'MethodDefinition'
}, null, /** @type {import('eslint').Rule.Node} */node.value);
}
};
},
meta: {
docs: {
category: 'Stylistic Issues',
description: 'Require JSDoc comments',
recommended: true,
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-jsdoc.md#repos-sticky-header'
},
fixable: 'code',
messages: {
missingJsDoc: 'Missing JSDoc comment.'
},
schema: [OPTIONS_SCHEMA],
type: 'suggestion'
}
};
module.exports = exports.default;
//# sourceMappingURL=requireJsdoc.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,527 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @typedef {[string, boolean, () => RootNamerReturn]} RootNamerReturn
*/
/**
* @param {string[]} desiredRoots
* @param {number} currentIndex
* @returns {RootNamerReturn}
*/
const rootNamer = (desiredRoots, currentIndex) => {
/** @type {string} */
let name;
let idx = currentIndex;
const incremented = desiredRoots.length <= 1;
if (incremented) {
const base = desiredRoots[0];
const suffix = idx++;
name = `${base}${suffix}`;
} else {
name = /** @type {string} */desiredRoots.shift();
}
return [name, incremented, () => {
return rootNamer(desiredRoots, idx);
}];
};
/* eslint-disable complexity -- Temporary */
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
utils,
context
}) => {
/* eslint-enable complexity -- Temporary */
if (utils.avoidDocs()) {
return;
}
// Param type is specified by type in @type
if (utils.hasTag('type')) {
return;
}
const {
autoIncrementBase = 0,
checkRestProperty = false,
checkDestructured = true,
checkDestructuredRoots = true,
checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
enableFixer = true,
enableRootFixer = true,
enableRestElementFixer = true,
unnamedRootBase = ['root'],
useDefaultObjectProperties = false
} = context.options[0] || {};
const preferredTagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'param'
});
if (!preferredTagName) {
return;
}
const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties);
if (!functionParameterNames.length) {
return;
}
const jsdocParameterNames =
/**
* @type {{
* idx: import('../iterateJsdoc.js').Integer;
* name: string;
* type: string;
* }[]}
*/
utils.getJsdocTagsDeep(preferredTagName);
const shallowJsdocParameterNames = jsdocParameterNames.filter(tag => {
return !tag.name.includes('.');
}).map((tag, idx) => {
return {
...tag,
idx
};
});
const checkTypesRegex = utils.getRegexFromString(checkTypesPattern);
/**
* @type {{
* functionParameterIdx: import('../iterateJsdoc.js').Integer,
* functionParameterName: string,
* inc: boolean|undefined,
* remove?: true,
* type?: string|undefined
* }[]}
*/
const missingTags = [];
const flattenedRoots = utils.flattenRoots(functionParameterNames).names;
/**
* @type {{
* [key: string]: import('../iterateJsdoc.js').Integer
* }}
*/
const paramIndex = {};
/**
* @param {string} cur
* @returns {boolean}
*/
const hasParamIndex = cur => {
return utils.dropPathSegmentQuotes(String(cur)) in paramIndex;
};
/**
*
* @param {string|number|undefined} cur
* @returns {import('../iterateJsdoc.js').Integer}
*/
const getParamIndex = cur => {
return paramIndex[utils.dropPathSegmentQuotes(String(cur))];
};
/**
*
* @param {string} cur
* @param {import('../iterateJsdoc.js').Integer} idx
* @returns {void}
*/
const setParamIndex = (cur, idx) => {
paramIndex[utils.dropPathSegmentQuotes(String(cur))] = idx;
};
for (const [idx, cur] of flattenedRoots.entries()) {
setParamIndex(cur, idx);
}
/**
*
* @param {(import('@es-joy/jsdoccomment').JsdocTagWithInline & {
* newAdd?: boolean
* })[]} jsdocTags
* @param {import('../iterateJsdoc.js').Integer} indexAtFunctionParams
* @returns {import('../iterateJsdoc.js').Integer}
*/
const findExpectedIndex = (jsdocTags, indexAtFunctionParams) => {
const remainingRoots = functionParameterNames.slice(indexAtFunctionParams || 0);
const foundIndex = jsdocTags.findIndex(({
name,
newAdd
}) => {
return !newAdd && remainingRoots.some(remainingRoot => {
if (Array.isArray(remainingRoot)) {
return (
/**
* @type {import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string|undefined;
* }}
*/
remainingRoot[1].names.includes(name)
);
}
if (typeof remainingRoot === 'object') {
return name === remainingRoot.name;
}
return name === remainingRoot;
});
});
const tags = foundIndex > -1 ? jsdocTags.slice(0, foundIndex) : jsdocTags.filter(({
tag
}) => {
return tag === preferredTagName;
});
let tagLineCount = 0;
for (const {
source
} of tags) {
for (const {
tokens: {
end
}
} of source) {
if (!end) {
tagLineCount++;
}
}
}
return tagLineCount;
};
let [nextRootName, incremented, namer] = rootNamer([...unnamedRootBase], autoIncrementBase);
const thisOffset = functionParameterNames[0] === 'this' ? 1 : 0;
for (const [functionParameterIdx, functionParameterName] of functionParameterNames.entries()) {
let inc;
if (Array.isArray(functionParameterName)) {
const matchedJsdoc = shallowJsdocParameterNames[functionParameterIdx - thisOffset];
/** @type {string} */
let rootName;
if (functionParameterName[0]) {
rootName = functionParameterName[0];
} else if (matchedJsdoc && matchedJsdoc.name) {
rootName = matchedJsdoc.name;
if (matchedJsdoc.type && matchedJsdoc.type.search(checkTypesRegex) === -1) {
continue;
}
} else {
rootName = nextRootName;
inc = incremented;
}
[nextRootName, incremented, namer] = namer();
const {
hasRestElement,
hasPropertyRest,
rests,
names
} =
/**
* @type {import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string | undefined;
* }}
*/
functionParameterName[1];
const notCheckingNames = [];
if (!enableRestElementFixer && hasRestElement) {
continue;
}
if (!checkDestructuredRoots) {
continue;
}
for (const [idx, paramName] of names.entries()) {
// Add root if the root name is not in the docs (and is not already
// in the tags to be fixed)
if (!jsdocParameterNames.find(({
name
}) => {
return name === rootName;
}) && !missingTags.find(({
functionParameterName: fpn
}) => {
return fpn === rootName;
})) {
const emptyParamIdx = jsdocParameterNames.findIndex(({
name
}) => {
return !name;
});
if (emptyParamIdx > -1) {
missingTags.push({
functionParameterIdx: emptyParamIdx,
functionParameterName: rootName,
inc,
remove: true
});
} else {
missingTags.push({
functionParameterIdx: hasParamIndex(rootName) ? getParamIndex(rootName) : getParamIndex(paramName),
functionParameterName: rootName,
inc
});
}
}
if (!checkDestructured) {
continue;
}
if (!checkRestProperty && rests[idx]) {
continue;
}
const fullParamName = `${rootName}.${paramName}`;
const notCheckingName = jsdocParameterNames.find(({
name,
type: paramType
}) => {
return utils.comparePaths(name)(fullParamName) && paramType.search(checkTypesRegex) === -1 && paramType !== '';
});
if (notCheckingName !== undefined) {
notCheckingNames.push(notCheckingName.name);
}
if (notCheckingNames.find(name => {
return fullParamName.startsWith(name);
})) {
continue;
}
if (jsdocParameterNames && !jsdocParameterNames.find(({
name
}) => {
return utils.comparePaths(name)(fullParamName);
})) {
missingTags.push({
functionParameterIdx: getParamIndex(functionParameterName[0] ? fullParamName : paramName),
functionParameterName: fullParamName,
inc,
type: hasRestElement && !hasPropertyRest ? '{...any}' : undefined
});
}
}
continue;
}
/** @type {string} */
let funcParamName;
let type;
if (typeof functionParameterName === 'object') {
if (!enableRestElementFixer && functionParameterName.restElement) {
continue;
}
funcParamName = /** @type {string} */functionParameterName.name;
type = '{...any}';
} else {
funcParamName = /** @type {string} */functionParameterName;
}
if (jsdocParameterNames && !jsdocParameterNames.find(({
name
}) => {
return name === funcParamName;
}) && funcParamName !== 'this') {
missingTags.push({
functionParameterIdx: getParamIndex(funcParamName),
functionParameterName: funcParamName,
inc,
type
});
}
}
/**
*
* @param {{
* functionParameterIdx: import('../iterateJsdoc.js').Integer,
* functionParameterName: string,
* remove?: true,
* inc?: boolean,
* type?: string
* }} cfg
*/
const fix = ({
functionParameterIdx,
functionParameterName,
remove,
inc,
type
}) => {
if (inc && !enableRootFixer) {
return;
}
/**
*
* @param {import('../iterateJsdoc.js').Integer} tagIndex
* @param {import('../iterateJsdoc.js').Integer} sourceIndex
* @param {import('../iterateJsdoc.js').Integer} spliceCount
* @returns {void}
*/
const createTokens = (tagIndex, sourceIndex, spliceCount) => {
// console.log(sourceIndex, tagIndex, jsdoc.tags, jsdoc.source);
const tokens = {
number: sourceIndex + 1,
source: '',
tokens: {
delimiter: '*',
description: '',
end: '',
lineEnd: '',
name: functionParameterName,
newAdd: true,
postDelimiter: ' ',
postName: '',
postTag: ' ',
postType: type ? ' ' : '',
start: jsdoc.source[sourceIndex].tokens.start,
tag: `@${preferredTagName}`,
type: type ?? ''
}
};
/**
* @type {(import('@es-joy/jsdoccomment').JsdocTagWithInline & {
* newAdd?: true
* })[]}
*/
jsdoc.tags.splice(tagIndex, spliceCount, {
description: '',
inlineTags: [],
name: functionParameterName,
newAdd: true,
optional: false,
problems: [],
source: [tokens],
tag: preferredTagName,
type: type ?? ''
});
const firstNumber = jsdoc.source[0].number;
jsdoc.source.splice(sourceIndex, spliceCount, tokens);
for (const [idx, src] of jsdoc.source.slice(sourceIndex).entries()) {
src.number = firstNumber + sourceIndex + idx;
}
};
const offset = jsdoc.source.findIndex(({
tokens: {
tag,
end
}
}) => {
return tag || end;
});
if (remove) {
createTokens(functionParameterIdx, offset + functionParameterIdx, 1);
} else {
const expectedIdx = findExpectedIndex(jsdoc.tags, functionParameterIdx);
createTokens(expectedIdx, offset + expectedIdx, 0);
}
};
/**
* @returns {void}
*/
const fixer = () => {
for (const missingTag of missingTags) {
fix(missingTag);
}
};
if (missingTags.length && jsdoc.source.length === 1) {
utils.makeMultiline();
}
for (const {
functionParameterName
} of missingTags) {
utils.reportJSDoc(`Missing JSDoc @${preferredTagName} "${functionParameterName}" declaration.`, null, enableFixer ? fixer : null);
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that all function parameters are documented.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
autoIncrementBase: {
default: 0,
type: 'integer'
},
checkConstructors: {
default: true,
type: 'boolean'
},
checkDestructured: {
default: true,
type: 'boolean'
},
checkDestructuredRoots: {
default: true,
type: 'boolean'
},
checkGetters: {
default: false,
type: 'boolean'
},
checkRestProperty: {
default: false,
type: 'boolean'
},
checkSetters: {
default: false,
type: 'boolean'
},
checkTypesPattern: {
type: 'string'
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
type: 'boolean'
},
enableRestElementFixer: {
type: 'boolean'
},
enableRootFixer: {
type: 'boolean'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
},
unnamedRootBase: {
items: {
type: 'string'
},
type: 'array'
},
useDefaultObjectProperties: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
},
// We cannot cache comment nodes as the contexts may recur with the
// same comment node but a different JS node, and we may need the different
// JS node to ensure we iterate its context
noTracking: true
});
module.exports = exports.default;
//# sourceMappingURL=requireParam.cjs.map

Some files were not shown because too many files have changed in this diff Show More