@es-joy/jsdoccomment
Advanced tools
Comparing version 0.38.0 to 0.39.0
# CHANGES for `@es-joy/jsdoccomment` | ||
## 0.39.0 | ||
- feat: types for test files and emit declaration files | ||
- fix(estreeToString): add `JsdodInlineTag` stringify support | ||
- refactor: lint | ||
- docs: add `JsdocInlineTag` to README | ||
- chore: update devDeps. | ||
## 0.38.0 | ||
@@ -4,0 +12,0 @@ |
{ | ||
"name": "@es-joy/jsdoccomment", | ||
"version": "0.38.0", | ||
"version": "0.39.0", | ||
"author": "Brett Zamir <brettz9@yahoo.com>", | ||
@@ -13,2 +13,3 @@ "contributors": [], | ||
"type": "module", | ||
"types": "./dist/index.d.ts", | ||
"main": "./dist/index.cjs.cjs", | ||
@@ -50,11 +51,18 @@ "exports": { | ||
"devDependencies": { | ||
"@babel/core": "^7.21.4", | ||
"@babel/core": "^7.21.8", | ||
"@babel/plugin-syntax-class-properties": "^7.12.13", | ||
"@babel/preset-env": "^7.21.4", | ||
"@babel/preset-env": "^7.21.5", | ||
"@brettz9/eslint-plugin": "^1.0.4", | ||
"@rollup/plugin-babel": "^6.0.3", | ||
"@types/chai": "^4.3.5", | ||
"@types/eslint": "^8.37.0", | ||
"@types/esquery": "^1.0.2", | ||
"@types/estraverse": "^5.1.2", | ||
"@types/estree": "^1.0.1", | ||
"@types/mocha": "^10.0.1", | ||
"@typescript-eslint/types": "^5.59.5", | ||
"c8": "^7.13.0", | ||
"chai": "^4.3.7", | ||
"eslint": "^8.38.0", | ||
"eslint-config-ash-nazg": "34.11.1", | ||
"eslint": "^8.40.0", | ||
"eslint-config-ash-nazg": "34.12.0", | ||
"eslint-config-standard": "^17.0.0", | ||
@@ -66,3 +74,3 @@ "eslint-plugin-array-func": "^3.1.8", | ||
"eslint-plugin-import": "^2.27.5", | ||
"eslint-plugin-jsdoc": "^43.0.5", | ||
"eslint-plugin-jsdoc": "^44.2.2", | ||
"eslint-plugin-markdown": "^3.0.0", | ||
@@ -74,10 +82,13 @@ "eslint-plugin-n": "^15.7.0", | ||
"eslint-plugin-sonarjs": "^0.19.0", | ||
"eslint-plugin-unicorn": "^46.0.0", | ||
"espree": "^9.5.1", | ||
"eslint-plugin-unicorn": "^47.0.0", | ||
"espree": "^9.5.2", | ||
"estraverse": "^5.3.0", | ||
"mocha": "^10.2.0", | ||
"rollup": "^3.20.6" | ||
"rollup": "^3.21.6", | ||
"typescript": "^5.0.4" | ||
}, | ||
"scripts": { | ||
"tsc": "tsc", | ||
"open": "open ./coverage/lcov-report/index.html", | ||
"build": "npm run rollup && tsc -p tsconfig-prod.json", | ||
"rollup": "rollup -c", | ||
@@ -88,4 +99,4 @@ "eslint": "eslint --ext=js,cjs,md,html .", | ||
"c8": "c8 npm run mocha", | ||
"test": "npm run lint && npm run rollup && npm run c8" | ||
"test": "npm run lint && npm run build && npm run c8" | ||
} | ||
} |
@@ -97,7 +97,8 @@ # @es-joy/jsdoccomment | ||
Has two visitable properties: | ||
Has the following visitable properties: | ||
1. `tags` (an array of `JsdocTag`; see below) | ||
2. `descriptionLines` (an array of `JsdocDescriptionLine` for multiline | ||
1. `descriptionLines` (an array of `JsdocDescriptionLine` for multiline | ||
descriptions). | ||
2. `tags` (an array of `JsdocTag`; see below) | ||
3. `inlineTags` (an array of `JsdocInlineTag`; see below) | ||
@@ -128,9 +129,10 @@ Has the following custom non-visitable property: | ||
Has three visitable properties: | ||
Has the following visitable properties: | ||
1. `parsedType` (the `jsdoc-type-pratt-parser` AST representation of the tag's | ||
type (see the `jsdoc-type-pratt-parser` section below)). | ||
2. `descriptionLines` (an array of `JsdocDescriptionLine` for multiline | ||
2. `typeLines` (an array of `JsdocTypeLine` for multiline type strings) | ||
3. `descriptionLines` (an array of `JsdocDescriptionLine` for multiline | ||
descriptions) | ||
3. `typeLines` (an array of `JsdocTypeLine` for multiline type strings) | ||
4. `inlineTags` (an array of `JsdocInlineTag`) | ||
@@ -182,2 +184,17 @@ May also have the following non-visitable properties from `comment-parser` | ||
### `JsdocInlineTag` | ||
No visitable properties. | ||
Has the following non-visitable properties: | ||
1. `format`: 'pipe' | 'plain' | 'prefix' | 'space'. These follow the styles of [link](https://jsdoc.app/tags-inline-link.html) or [tutorial](https://jsdoc.app/tags-inline-tutorial.html). | ||
1. `pipe`: `{@link namepathOrURL|link text}` | ||
2. `plain`: `{@link namepathOrURL}` | ||
3. `prefix`: `[link text]{@link namepathOrURL}` | ||
4. `space`: `{@link namepathOrURL link text (after the first space)}` | ||
2. `namepathOrURL`: string | ||
3. `tag`: string. The standard allows `tutorial` or `link` | ||
4. `text`: string | ||
## ESLint AST produced for `jsdoc-type-pratt-parser` | ||
@@ -184,0 +201,0 @@ |
@@ -14,3 +14,5 @@ import esquery from 'esquery'; | ||
* @param {string} commentSelector | ||
* @param {Node} jsdoc | ||
* @param {import('comment-parser').Block & { | ||
* inlineTags: import('./commentParserToESTree.js').JsdocInlineTagNoType[] | ||
* }} jsdoc | ||
* @returns {boolean} | ||
@@ -20,3 +22,3 @@ */ | ||
/** | ||
* @param {Settings} settings | ||
* @param {{[name: string]: any}} settings | ||
* @returns {CommentHandler} | ||
@@ -35,3 +37,7 @@ */ | ||
return esquery.matches(ast, selector, null, { | ||
const _ast = /** @type {unknown} */ (ast); | ||
return esquery.matches(/** @type {import('estree').Node} */ ( | ||
_ast | ||
), selector, null, { | ||
visitorKeys: { | ||
@@ -38,0 +44,0 @@ ...jsdocTypePrattParserVisitorKeys, |
@@ -6,3 +6,3 @@ import {parse as jsdocTypePrattParse} from 'jsdoc-type-pratt-parser'; | ||
* @param {JsdocTypeLine[]|JsdocTag} container | ||
* @param {boolean} isArr | ||
* @param {boolean} [isArr] | ||
* @returns {void} | ||
@@ -12,3 +12,3 @@ */ | ||
if (isArr) { | ||
const firstItem = container[0]; | ||
const firstItem = /** @type {JsdocTypeLine[]} */ (container)[0]; | ||
firstItem.rawType = firstItem.rawType.replace( | ||
@@ -18,3 +18,7 @@ /^\{/u, '' | ||
const lastItem = container[container.length - 1]; | ||
const lastItem = /** @type {JsdocTypeLine} */ ( | ||
/** @type {JsdocTypeLine[]} */ ( | ||
container | ||
).at(-1) | ||
); | ||
lastItem.rawType = lastItem.rawType.replace(/\}$/u, ''); | ||
@@ -24,16 +28,9 @@ | ||
} | ||
container.rawType = container.rawType.replace( | ||
/^\{/u, '' | ||
).replace(/\}$/u, ''); | ||
/** @type {JsdocTag} */ (container).rawType = | ||
/** @type {JsdocTag} */ (container).rawType.replace( | ||
/^\{/u, '' | ||
).replace(/\}$/u, ''); | ||
}; | ||
/** | ||
* @external CommentParserJsdoc | ||
*/ | ||
/** | ||
* @external JsdocTypePrattParserMode | ||
*/ | ||
/** | ||
* @typedef {{ | ||
@@ -64,2 +61,6 @@ * delimiter: string, | ||
* text: string, | ||
* }} JsdocInlineTagNoType | ||
*/ | ||
/** | ||
* @typedef {JsdocInlineTagNoType & { | ||
* type: "JsdocInlineTag" | ||
@@ -76,8 +77,11 @@ * }} JsdocInlineTag | ||
* inlineTags: JsdocInlineTag[] | ||
* name: string, | ||
* postDelimiter: string, | ||
* postName: string, | ||
* postTag: string, | ||
* postType: string, | ||
* rawType: string, | ||
* parsedType: import('jsdoc-type-pratt-parser').RootResult|null | ||
* tag: string, | ||
* terminal: string, | ||
* type: "JsdocTag", | ||
* type: string, | ||
* typeLines: JsdocTypeLine[], | ||
@@ -88,9 +92,18 @@ * }} JsdocTag | ||
/** | ||
* @typedef {number} Integer | ||
*/ | ||
/** | ||
* @typedef {{ | ||
* delimiter: string, | ||
* description: string, | ||
* descriptionEndLine?: Integer, | ||
* descriptionLines: JsdocDescriptionLine[], | ||
* descriptionStartLine?: Integer, | ||
* hasPreterminalDescription: 0|1, | ||
* hasPreterminalTagDescription?: 1, | ||
* initial: string, | ||
* inlineTags: JsdocInlineTag[] | ||
* lastDescriptionLine: Integer, | ||
* lastDescriptionLine?: Integer, | ||
* endLine: Integer, | ||
* lineEnd: string, | ||
@@ -104,2 +117,10 @@ * postDelimiter: string, | ||
/** | ||
* @param {object} cfg | ||
* @param {string} cfg.text | ||
* @param {string} cfg.tag | ||
* @param {'pipe' | 'plain' | 'prefix' | 'space'} cfg.format | ||
* @param {string} cfg.namepathOrURL | ||
* @returns {JsdocInlineTag} | ||
*/ | ||
const inlineTagToAST = ({text, tag, format, namepathOrURL}) => ({ | ||
@@ -115,6 +136,8 @@ text, | ||
* Converts comment parser AST to ESTree format. | ||
* @param {external:CommentParserJsdoc} jsdoc | ||
* @param {external:JsdocTypePrattParserMode} mode | ||
* @param {PlainObject} opts | ||
* @param {throwOnTypeParsingErrors} [opts.throwOnTypeParsingErrors=false] | ||
* @param {import('comment-parser').Block & { | ||
* inlineTags: JsdocInlineTagNoType[] | ||
* }} jsdoc | ||
* @param {import('jsdoc-type-pratt-parser').ParseMode} mode | ||
* @param {object} opts | ||
* @param {boolean} [opts.throwOnTypeParsingErrors=false] | ||
* @returns {JsdocBlock} | ||
@@ -146,4 +169,7 @@ */ | ||
if (lastTag.rawType && throwOnTypeParsingErrors) { | ||
err.message = `Tag @${lastTag.tag} with raw type ` + | ||
`\`${lastTag.rawType}\` had parsing error: ${err.message}`; | ||
/** @type {Error} */ ( | ||
err | ||
).message = `Tag @${lastTag.tag} with raw type ` + | ||
`\`${lastTag.rawType}\` had parsing error: ${ | ||
/** @type {Error} */ (err).message}`; | ||
throw err; | ||
@@ -167,2 +193,4 @@ } | ||
const endLine = source.length - 1; | ||
/** @type {JsdocBlock} */ | ||
const ast = { | ||
@@ -176,2 +204,3 @@ delimiter: delimiterRoot, | ||
initial: startRoot, | ||
tags: [], | ||
// `terminal` will be overwritten if there are other entries | ||
@@ -187,5 +216,13 @@ terminal: endRoot, | ||
/** | ||
* @type {JsdocTag[]} | ||
*/ | ||
const tags = []; | ||
/** @type {Integer|undefined} */ | ||
let lastDescriptionLine; | ||
/** @type {JsdocTag|null} */ | ||
let lastTag = null; | ||
let descLineStateOpen = true; | ||
@@ -278,2 +315,5 @@ | ||
/** | ||
* @type {JsdocInlineTag[]} | ||
*/ | ||
let tagInlineTags = []; | ||
@@ -283,7 +323,15 @@ if (tag) { | ||
// we can use the `tags` length as index into the parser result tags. | ||
tagInlineTags = jsdoc.tags[tags.length].inlineTags.map( | ||
(t) => inlineTagToAST(t) | ||
); | ||
tagInlineTags = | ||
/** | ||
* @type {import('comment-parser').Spec & { | ||
* inlineTags: JsdocInlineTagNoType[] | ||
* }} | ||
*/ ( | ||
jsdoc.tags[tags.length] | ||
).inlineTags.map( | ||
(t) => inlineTagToAST(t) | ||
); | ||
} | ||
/** @type {JsdocTag} */ | ||
const tagObj = { | ||
@@ -296,2 +344,3 @@ ...tkns, | ||
inlineTags: tagInlineTags, | ||
parsedType: null, | ||
rawType: '', | ||
@@ -310,4 +359,4 @@ type: 'JsdocTag', | ||
// Will strip rawType brackets after this tag | ||
lastTag.typeLines.push( | ||
lastTag.typeLines.length | ||
/** @type {JsdocTag} */ (lastTag).typeLines.push( | ||
/** @type {JsdocTag} */ (lastTag).typeLines.length | ||
? { | ||
@@ -328,3 +377,7 @@ delimiter, | ||
); | ||
lastTag.rawType += lastTag.rawType ? '\n' + rawType : rawType; | ||
/** @type {JsdocTag} */ (lastTag).rawType += /** @type {JsdocTag} */ ( | ||
lastTag | ||
).rawType | ||
? '\n' + rawType | ||
: rawType; | ||
} | ||
@@ -372,3 +425,3 @@ | ||
cleanUpLastTag(lastTag); | ||
cleanUpLastTag(/** @type {JsdocTag} */ (lastTag)); | ||
} | ||
@@ -375,0 +428,0 @@ }); |
@@ -8,3 +8,14 @@ import { | ||
/** | ||
* @typedef {{preferRawType?: boolean}} ESTreeToStringOptions | ||
*/ | ||
const stringifiers = { | ||
/** | ||
* @param {import('./commentParserToESTree.js').JsdocBlock} node | ||
* @param {ESTreeToStringOptions} opts | ||
* @param {string[]} descriptionLines | ||
* @param {string[]} tags | ||
* @returns {string} | ||
*/ | ||
JsdocBlock ({ | ||
@@ -15,4 +26,4 @@ delimiter, postDelimiter, lineEnd, initial, terminal, endLine | ||
(descriptionLines.length && !tags.length && | ||
descriptionLines[descriptionLines.length - 1].endsWith('\n')) || | ||
(tags.length && tags[tags.length - 1].endsWith('\n')); | ||
descriptionLines.at(-1)?.endsWith('\n')) || | ||
(tags.length && tags.at(-1)?.endsWith('\n')); | ||
return `${initial}${delimiter}${postDelimiter}${endLine | ||
@@ -36,2 +47,7 @@ ? ` | ||
}, | ||
/** | ||
* @param {import('./commentParserToESTree.js').JsdocDescriptionLine} node | ||
* @returns {string} | ||
*/ | ||
JsdocDescriptionLine ({ | ||
@@ -42,7 +58,35 @@ initial, delimiter, postDelimiter, description | ||
}, | ||
/** | ||
* @param {import('./commentParserToESTree.js').JsdocTypeLine} node | ||
* @returns {string} | ||
*/ | ||
JsdocTypeLine ({ | ||
initial, delimiter, postDelimiter, rawType, parsedType | ||
initial, delimiter, postDelimiter, rawType | ||
}) { | ||
return `${initial}${delimiter}${postDelimiter}${rawType}`; | ||
}, | ||
/** | ||
* @param {import('./commentParserToESTree.js').JsdocInlineTag} node | ||
*/ | ||
JsdocInlineTag ({format, namepathOrURL, tag, text}) { | ||
return format === 'pipe' | ||
? `{@${tag} ${namepathOrURL}|${text}}` | ||
: format === 'plain' | ||
? `{@${tag} ${namepathOrURL}}` | ||
: format === 'prefix' | ||
? `[${text}]{@${tag} ${namepathOrURL}}` | ||
// "space" | ||
: `{@${tag} ${namepathOrURL} ${text}}`; | ||
}, | ||
/** | ||
* @param {import('./commentParserToESTree.js').JsdocTag} node | ||
* @param {ESTreeToStringOptions} opts | ||
* @param {string} parsedType | ||
* @param {string[]} typeLines | ||
* @param {string[]} descriptionLines | ||
* @returns {string} | ||
*/ | ||
JsdocTag (node, opts, parsedType, typeLines, descriptionLines) { | ||
@@ -76,4 +120,10 @@ const { | ||
* custom entries?). | ||
* @param {Node} node | ||
* @param {{preferRawType: boolean}} opts | ||
* @param {import('./commentParserToESTree.js').JsdocBlock| | ||
* import('./commentParserToESTree.js').JsdocDescriptionLine| | ||
* import('./commentParserToESTree.js').JsdocTypeLine| | ||
* import('./commentParserToESTree.js').JsdocTag| | ||
* import('./commentParserToESTree.js').JsdocInlineTag| | ||
* import('jsdoc-type-pratt-parser').RootResult | ||
* } node | ||
* @param {ESTreeToStringOptions} opts | ||
* @throws {Error} | ||
@@ -86,12 +136,42 @@ * @returns {string} | ||
const args = childNodeOrArray.map((key) => { | ||
return Array.isArray(node[key]) | ||
? node[key].map((item) => { | ||
return estreeToString(item, opts); | ||
}) | ||
: (node[key] === undefined || node[key] === null | ||
? null | ||
: estreeToString(node[key], opts)); | ||
}); | ||
return stringifiers[node.type](node, opts, ...args); | ||
const args = /** @type {(string[]|string|null)[]} */ ( | ||
childNodeOrArray.map((key) => { | ||
// @ts-expect-error | ||
return Array.isArray(node[key]) | ||
// @ts-expect-error | ||
? node[key].map( | ||
( | ||
/** | ||
* @type {import('./commentParserToESTree.js').JsdocBlock| | ||
* import('./commentParserToESTree.js').JsdocDescriptionLine| | ||
* import('./commentParserToESTree.js').JsdocTypeLine| | ||
* import('./commentParserToESTree.js').JsdocTag| | ||
* import('./commentParserToESTree.js').JsdocInlineTag} | ||
*/ | ||
item | ||
) => { | ||
return estreeToString(item, opts); | ||
} | ||
) | ||
// @ts-expect-error | ||
: (node[key] === undefined || node[key] === null | ||
? null | ||
// @ts-expect-error | ||
: estreeToString(node[key], opts)); | ||
}) | ||
); | ||
return stringifiers[ | ||
/** | ||
* @type {import('./commentParserToESTree.js').JsdocBlock| | ||
* import('./commentParserToESTree.js').JsdocDescriptionLine| | ||
* import('./commentParserToESTree.js').JsdocTypeLine| | ||
* import('./commentParserToESTree.js').JsdocTag} | ||
*/ | ||
(node).type | ||
]( | ||
node, | ||
opts, | ||
// @ts-expect-error | ||
...args | ||
); | ||
} | ||
@@ -101,3 +181,9 @@ | ||
if (node.type.startsWith('JsdocType')) { | ||
return opts.preferRawType ? '' : `{${stringify(node)}}`; | ||
return opts.preferRawType | ||
? '' | ||
: `{${stringify( | ||
/** @type {import('jsdoc-type-pratt-parser').RootResult} */ ( | ||
node | ||
) | ||
)}}`; | ||
} | ||
@@ -104,0 +190,0 @@ |
@@ -8,2 +8,18 @@ /** | ||
/** | ||
* @typedef {import('eslint').AST.Token | import('estree').Comment | { | ||
* type: import('eslint').AST.TokenType|"Line"|"Block"|"Shebang", | ||
* value: string | ||
* }} Token | ||
*/ | ||
/** | ||
* @typedef {import('eslint').Rule.Node| | ||
* import('@typescript-eslint/types').TSESTree.Node} ESLintOrTSNode | ||
*/ | ||
/** | ||
* @typedef {number} int | ||
*/ | ||
/** | ||
* Checks if the given token is a comment token or not. | ||
@@ -20,4 +36,10 @@ * | ||
/** | ||
* @param {AST} node | ||
* @returns {boolean} | ||
* @param {(import('estree').Comment|import('eslint').Rule.Node) & { | ||
* declaration?: any, | ||
* decorators?: any[], | ||
* parent?: import('eslint').Rule.Node & { | ||
* decorators?: any[] | ||
* } | ||
* }} node | ||
* @returns {import('@typescript-eslint/types').TSESTree.Decorator|undefined} | ||
*/ | ||
@@ -32,3 +54,3 @@ const getDecorator = (node) => { | ||
* | ||
* @param {ASTNode} astNode An AST node. | ||
* @param {import('eslint').Rule.Node} astNode An AST node. | ||
* @returns {boolean} whether the given node represents an export declaration. | ||
@@ -45,8 +67,16 @@ * @private | ||
/** | ||
* @param {AST} astNode | ||
* @returns {AST} | ||
* @param {import('eslint').Rule.Node} astNode | ||
* @returns {import('eslint').Rule.Node} | ||
*/ | ||
const getTSFunctionComment = function (astNode) { | ||
const {parent} = astNode; | ||
/* c8 ignore next 3 */ | ||
if (!parent) { | ||
return astNode; | ||
} | ||
const grandparent = parent.parent; | ||
/* c8 ignore next 3 */ | ||
if (!grandparent) { | ||
return astNode; | ||
} | ||
const greatGrandparent = grandparent.parent; | ||
@@ -56,9 +86,9 @@ const greatGreatGrandparent = greatGrandparent && greatGrandparent.parent; | ||
// istanbul ignore if | ||
if (parent.type !== 'TSTypeAnnotation') { | ||
if (/** @type {ESLintOrTSNode} */ (parent).type !== 'TSTypeAnnotation') { | ||
return astNode; | ||
} | ||
switch (grandparent.type) { | ||
case 'PropertyDefinition': | ||
case 'ClassProperty': | ||
switch (/** @type {ESLintOrTSNode} */ (grandparent).type) { | ||
// @ts-expect-error | ||
case 'PropertyDefinition': case 'ClassProperty': | ||
case 'TSDeclareFunction': | ||
@@ -69,2 +99,6 @@ case 'TSMethodSignature': | ||
case 'ArrowFunctionExpression': | ||
/* c8 ignore next 3 */ | ||
if (!greatGrandparent) { | ||
return astNode; | ||
} | ||
// istanbul ignore else | ||
@@ -76,2 +110,6 @@ if ( | ||
) { | ||
/* c8 ignore next 3 */ | ||
if (!greatGreatGrandparent || !greatGreatGrandparent.parent) { | ||
return astNode; | ||
} | ||
return greatGreatGrandparent.parent; | ||
@@ -83,2 +121,6 @@ } | ||
case 'FunctionExpression': | ||
/* c8 ignore next 3 */ | ||
if (!greatGreatGrandparent) { | ||
return astNode; | ||
} | ||
// istanbul ignore else | ||
@@ -98,2 +140,7 @@ if (greatGrandparent.type === 'MethodDefinition') { | ||
/* c8 ignore next 3 */ | ||
if (!greatGreatGrandparent) { | ||
return astNode; | ||
} | ||
// istanbul ignore next | ||
@@ -147,6 +194,6 @@ switch (greatGrandparent.type) { | ||
* | ||
* @param {ASTNode} node An AST node. | ||
* @param {SourceCode} sourceCode The ESLint SourceCode. | ||
* @returns {ASTNode} The AST node that can be evaluated for appropriate | ||
* JSDoc comments. | ||
* @param {import('eslint').Rule.Node} node An AST node. | ||
* @param {import('eslint').SourceCode} sourceCode The ESLint SourceCode. | ||
* @returns {import('eslint').Rule.Node} The AST node that | ||
* can be evaluated for appropriate JSDoc comments. | ||
*/ | ||
@@ -156,3 +203,3 @@ const getReducedASTNode = function (node, sourceCode) { | ||
switch (node.type) { | ||
switch (/** @type {ESLintOrTSNode} */ (node).type) { | ||
case 'TSFunctionType': | ||
@@ -165,2 +212,6 @@ return getTSFunctionComment(node); | ||
case 'FunctionDeclaration': | ||
/* c8 ignore next 3 */ | ||
if (!parent) { | ||
return node; | ||
} | ||
return looksLikeExport(parent) ? parent : node; | ||
@@ -174,8 +225,20 @@ | ||
case 'FunctionExpression': | ||
/* c8 ignore next 3 */ | ||
if (!parent) { | ||
return node; | ||
} | ||
if ( | ||
!invokedExpression.has(parent.type) | ||
) { | ||
/** | ||
* @type {import('eslint').Rule.Node|Token|null} | ||
*/ | ||
let token = node; | ||
do { | ||
token = sourceCode.getTokenBefore(token, {includeComments: true}); | ||
token = sourceCode.getTokenBefore( | ||
/** @type {import('eslint').Rule.Node|import('eslint').AST.Token} */ ( | ||
token | ||
), | ||
{includeComments: true} | ||
); | ||
} while (token && token.type === 'Punctuator' && token.value === '('); | ||
@@ -223,5 +286,6 @@ | ||
* | ||
* @param {ASTNode} astNode The AST node to get the comment for. | ||
* @param {SourceCode} sourceCode | ||
* @param {{maxLines: Integer, minLines: Integer}} settings | ||
* @param {import('eslint').Rule.Node} astNode The AST node to get | ||
* the comment for. | ||
* @param {import('eslint').SourceCode} sourceCode | ||
* @param {{maxLines: int, minLines: int}} settings | ||
* @returns {Token|null} The Block comment token containing the JSDoc comment | ||
@@ -233,2 +297,4 @@ * for the given node or null if not found. | ||
const {minLines, maxLines} = settings; | ||
/** @type {import('eslint').Rule.Node|import('estree').Comment} */ | ||
let currentNode = astNode; | ||
@@ -240,3 +306,4 @@ let tokenBefore = null; | ||
if (decorator) { | ||
currentNode = decorator; | ||
const dec = /** @type {unknown} */ (decorator); | ||
currentNode = /** @type {import('eslint').Rule.Node} */ (dec); | ||
} | ||
@@ -265,2 +332,7 @@ tokenBefore = sourceCode.getTokenBefore( | ||
/* c8 ignore next 3 */ | ||
if (!tokenBefore || !currentNode.loc || !tokenBefore.loc) { | ||
return null; | ||
} | ||
if ( | ||
@@ -281,7 +353,10 @@ tokenBefore.type === 'Block' && | ||
* | ||
* @param {SourceCode} sourceCode The ESLint SourceCode | ||
* @param {ASTNode} node The AST node to get the comment for. | ||
* @param {PlainObject} settings The settings in context | ||
* @returns {Token|null} The Block comment token containing the JSDoc comment | ||
* for the given node or null if not found. | ||
* @param {import('eslint').SourceCode} sourceCode The ESLint SourceCode | ||
* @param {import('eslint').Rule.Node} node The AST node to get | ||
* the comment for. | ||
* @param {{maxLines: int, minLines: int}} settings The | ||
* settings in context | ||
* @returns {Token|null} The Block comment | ||
* token containing the JSDoc comment for the given node or | ||
* null if not found. | ||
* @public | ||
@@ -288,0 +363,0 @@ */ |
@@ -16,2 +16,6 @@ /* eslint-disable prefer-named-capture-group -- Temporary */ | ||
/** | ||
* @param {import('comment-parser').Spec} spec | ||
* @returns {boolean} | ||
*/ | ||
export const hasSeeWithLink = (spec) => { | ||
@@ -54,3 +58,7 @@ return spec.tag === 'see' && (/\{@link.+?\}/u).test(spec.source[0].source); | ||
// Type | ||
/** | ||
* Type tokenizer. | ||
* @param {import('comment-parser').Spec} spec | ||
* @returns {import('comment-parser').Spec} | ||
*/ | ||
(spec) => { | ||
@@ -64,3 +72,7 @@ if (noTypes.includes(spec.tag)) { | ||
// Name | ||
/** | ||
* Name tokenizer. | ||
* @param {import('comment-parser').Spec} spec | ||
* @returns {import('comment-parser').Spec} | ||
*/ | ||
(spec) => { | ||
@@ -77,7 +89,13 @@ if (spec.tag === 'template') { | ||
if (pos > -1) { | ||
[, postName, description, lineEnd] = extra.match(/(\s*)([^\r]*)(\r)?/u); | ||
[, postName, description, lineEnd] = /** @type {RegExpMatchArray} */ ( | ||
extra.match(/(\s*)([^\r]*)(\r)?/u) | ||
); | ||
} | ||
if (optionalBrackets.test(name)) { | ||
name = name.match(optionalBrackets)?.groups?.name; | ||
name = /** @type {string} */ ( | ||
/** @type {RegExpMatchArray} */ ( | ||
name.match(optionalBrackets) | ||
)?.groups?.name | ||
); | ||
spec.optional = true; | ||
@@ -105,3 +123,7 @@ } else { | ||
// Description | ||
/** | ||
* Description tokenizer. | ||
* @param {import('comment-parser').Spec} spec | ||
* @returns {import('comment-parser').Spec} | ||
*/ | ||
(spec) => { | ||
@@ -115,5 +137,7 @@ return preserveDescriptionTokenizer(spec); | ||
* Accepts a comment token and converts it into `comment-parser` AST. | ||
* @param {PlainObject} commentNode | ||
* @param {{value: string}} commentNode | ||
* @param {string} [indent=""] Whitespace | ||
* @returns {PlainObject} | ||
* @returns {import('comment-parser').Block & { | ||
* inlineTags: import('./parseInlineTags.js').InlineTag[] | ||
* }} | ||
*/ | ||
@@ -120,0 +144,0 @@ const parseComment = (commentNode, indent = '') => { |
/** | ||
* @param {RegExpMatchArray} match An inline tag regexp match. | ||
* @returns {string} | ||
* @param {RegExpMatchArray & { | ||
* indices: { | ||
* groups: { | ||
* [key: string]: [number, number] | ||
* } | ||
* } | ||
* groups: {[key: string]: string} | ||
* }} match An inline tag regexp match. | ||
* @returns {'pipe' | 'plain' | 'prefix' | 'space'} | ||
*/ | ||
@@ -21,2 +28,13 @@ function determineFormat (match) { | ||
/** | ||
* @typedef {{ | ||
* format: 'pipe' | 'plain' | 'prefix' | 'space', | ||
* namepathOrURL: string, | ||
* tag: string, | ||
* text: string, | ||
* start: number, | ||
* end: number, | ||
* }} InlineTag | ||
*/ | ||
/** | ||
* Extracts inline tags from a description. | ||
@@ -27,2 +45,3 @@ * @param {string} description | ||
function parseDescription (description) { | ||
/** @type {InlineTag[]} */ | ||
const result = []; | ||
@@ -45,3 +64,15 @@ | ||
for (const match of matches) { | ||
for (const mtch of matches) { | ||
const match = /** | ||
* @type {RegExpMatchArray & { | ||
* indices: { | ||
* groups: { | ||
* [key: string]: [number, number] | ||
* } | ||
* } | ||
* groups: {[key: string]: string} | ||
* }} | ||
*/ ( | ||
mtch | ||
); | ||
const {tag, namepathOrURL, text} = match.groups; | ||
@@ -67,3 +98,8 @@ const [start, end] = match.indices[0]; | ||
* into the `inlineTags` tokens, and populates `spec.inlineTags` | ||
* @param {Block} block | ||
* @param {import('comment-parser').Block & { | ||
* inlineTags?: InlineTag[] | ||
* }} block | ||
* @returns {import('comment-parser').Block & { | ||
* inlineTags: InlineTag[] | ||
* }} | ||
*/ | ||
@@ -73,5 +109,15 @@ export default function parseInlineTags (block) { | ||
for (const tag of block.tags) { | ||
tag.inlineTags = parseDescription(tag.description); | ||
/** | ||
* @type {import('comment-parser').Spec & { | ||
* inlineTags: InlineTag[] | ||
* }} | ||
*/ (tag).inlineTags = parseDescription(tag.description); | ||
} | ||
return block; | ||
return ( | ||
/** | ||
* @type {import('comment-parser').Block & { | ||
* inlineTags: InlineTag[] | ||
* }} | ||
*/ (block) | ||
); | ||
} |
@@ -0,5 +1,9 @@ | ||
/** | ||
* @param {string} str | ||
* @returns {string} | ||
*/ | ||
const toCamelCase = (str) => { | ||
return str.toLowerCase().replace(/^[a-z]/gu, (init) => { | ||
return str.toLowerCase().replaceAll(/^[a-z]/gu, (init) => { | ||
return init.toUpperCase(); | ||
}).replace(/_(?<wordInit>[a-z])/gu, (_, n1, o, s, {wordInit}) => { | ||
}).replaceAll(/_(?<wordInit>[a-z])/gu, (_, n1, o, s, {wordInit}) => { | ||
return wordInit.toUpperCase(); | ||
@@ -6,0 +10,0 @@ }); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
109494
36
2604
238
35