diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 935a2680..c3edead2 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -14,6 +14,6 @@ limitations under the License. */ module.exports = { - extends: ['@jsdoc', 'plugin:prettier/recommended'], + extends: ['@jsdoc'], root: true, }; diff --git a/package-lock.json b/package-lock.json index 61629371..aa0d3438 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,9 +40,6 @@ "ajv": "^8.12.0", "c8": "^8.0.1", "eslint": "^8.54.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-simple-import-sort": "^10.0.0", "execa": "^8.0.1", "hereby": "^1.8.8", "jasmine": "^5.1.0", @@ -12274,13 +12271,16 @@ "license": "Apache-2.0", "dependencies": { "@babel/eslint-parser": "^7.23.3", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-simple-import-sort": "^10.0.0" }, "engines": { "node": ">=v18.12.0" }, "peerDependencies": { - "eslint": ">= 8.54.0" + "eslint": ">= 8.54.0", + "prettier": ">= 3.1.0" } }, "packages/jsdoc-parse": { diff --git a/package.json b/package.json index a846e8de..4a82e22a 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,6 @@ "ajv": "^8.12.0", "c8": "^8.0.1", "eslint": "^8.54.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-simple-import-sort": "^10.0.0", "execa": "^8.0.1", "hereby": "^1.8.8", "jasmine": "^5.1.0", diff --git a/packages/jsdoc-doclet/lib/doclet-store.js b/packages/jsdoc-doclet/lib/doclet-store.js index 4e5e29a6..0c253a01 100644 --- a/packages/jsdoc-doclet/lib/doclet-store.js +++ b/packages/jsdoc-doclet/lib/doclet-store.js @@ -62,16 +62,12 @@ export class DocletStore { static #propertiesWithMaps = ['kind', 'longname', 'memberof']; static #propertyToMapName = new Map( - DocletStore.#propertiesWithMaps.map((prop) => { - return [prop, 'docletsBy' + _.capitalize(prop)]; - }) + DocletStore.#propertiesWithMaps.map((prop) => [prop, 'docletsBy' + _.capitalize(prop)]) ); static #propertiesWithSets = ['augments', 'borrowed', 'implements', 'mixes']; static #propertyToSetName = new Map( - DocletStore.#propertiesWithSets.map((prop) => { - return [prop, 'docletsWith' + _.capitalize(prop)]; - }) + DocletStore.#propertiesWithSets.map((prop) => [prop, 'docletsWith' + _.capitalize(prop)]) ); constructor(dependencies) { @@ -113,9 +109,8 @@ export class DocletStore { const isVisible = doclet.isVisible(); const newDoclet = opts.newDoclet ?? false; const wasVisible = newDoclet ? false : this.doclets.has(doclet); - const visibilityChanged = (() => { - return newDoclet || (!wasVisible && isVisible) || (wasVisible && !isVisible); - })(); + const visibilityChanged = (() => + newDoclet || (!wasVisible && isVisible) || (wasVisible && !isVisible))(); const docletInfo = { isGlobal: doclet.isGlobal(), isVisible, diff --git a/packages/jsdoc-eslint-config/index.js b/packages/jsdoc-eslint-config/index.js index 9e9f7552..1398b83d 100644 --- a/packages/jsdoc-eslint-config/index.js +++ b/packages/jsdoc-eslint-config/index.js @@ -14,6 +14,8 @@ limitations under the License. */ module.exports = { + extends: ['plugin:prettier/recommended'], + env: { es6: true, jasmine: true, @@ -26,7 +28,7 @@ module.exports = { requireConfigFile: false, sourceType: 'module', }, - plugins: ['simple-import-sort'], + plugins: ['prettier', 'simple-import-sort'], rules: { // Possible errors @@ -238,5 +240,8 @@ module.exports = { // https://github.com/lydell/eslint-plugin-simple-import-sort 'simple-import-sort/imports': 'error', 'simple-import-sort/exports': 'error', + + // https://github.com/prettier/eslint-plugin-prettier + 'prettier/prettier': 'error', }, }; diff --git a/packages/jsdoc-eslint-config/package.json b/packages/jsdoc-eslint-config/package.json index bb4ed76f..6421690f 100644 --- a/packages/jsdoc-eslint-config/package.json +++ b/packages/jsdoc-eslint-config/package.json @@ -12,10 +12,13 @@ "main": "index.js", "dependencies": { "@babel/eslint-parser": "^7.23.3", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-simple-import-sort": "^10.0.0" }, "peerDependencies": { - "eslint": ">= 8.54.0" + "eslint": ">= 8.54.0", + "prettier": ">= 3.1.0" }, "publishConfig": { "access": "public" diff --git a/packages/jsdoc-parse/lib/parser.js b/packages/jsdoc-parse/lib/parser.js index f8b2ae32..40636d8e 100644 --- a/packages/jsdoc-parse/lib/parser.js +++ b/packages/jsdoc-parse/lib/parser.js @@ -53,6 +53,7 @@ function getLastValue(set) { let value; if (set) { + // eslint-disable-next-line curly for (value of set); } diff --git a/packages/jsdoc-salty/index.js b/packages/jsdoc-salty/index.js index d32c4cab..b274cbb4 100644 --- a/packages/jsdoc-salty/index.js +++ b/packages/jsdoc-salty/index.js @@ -16,7 +16,5 @@ const Salty = require('./lib/salty'); module.exports = { - taffy: (items) => { - return new Salty(items); - }, + taffy: (items) => new Salty(items), }; diff --git a/packages/jsdoc-tag/lib/definitions/core.js b/packages/jsdoc-tag/lib/definitions/core.js index 39b1e080..460d97d5 100644 --- a/packages/jsdoc-tag/lib/definitions/core.js +++ b/packages/jsdoc-tag/lib/definitions/core.js @@ -29,593 +29,587 @@ function stripModuleNamespace(docletName) { } // Core JSDoc tags that are shared with other tag dictionaries. -export const getTags = (deps) => { - return { - abstract: { - mustNotHaveValue: true, - onTagged(doclet) { - // we call this `virtual` because `abstract` is a reserved word - doclet.virtual = true; - }, - synonyms: ['virtual'], +export const getTags = (deps) => ({ + abstract: { + mustNotHaveValue: true, + onTagged(doclet) { + // we call this `virtual` because `abstract` is a reserved word + doclet.virtual = true; }, - access: { - mustHaveValue: true, - onTagged(doclet, { value }) { - // only valid values are package, private, protected and public - if (/^(package|private|protected|public)$/i.test(value)) { - doclet.access = value.toLowerCase(); - } else { - doclet.access = undefined; - } - }, + synonyms: ['virtual'], + }, + access: { + mustHaveValue: true, + onTagged(doclet, { value }) { + // only valid values are package, private, protected and public + if (/^(package|private|protected|public)$/i.test(value)) { + doclet.access = value.toLowerCase(); + } else { + doclet.access = undefined; + } }, - alias: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.alias = value; - }, + }, + alias: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.alias = value; }, - async: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.async = true; - }, + }, + async: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.async = true; }, - augments: { - mustHaveValue: true, - // Allow augments value to be specified as a normal type, e.g. {Type} - onTagText: util.parseTypeText, - onTagged(doclet, { value }) { - doclet.augment(util.firstWordOf(value)); - }, - synonyms: ['extends'], + }, + augments: { + mustHaveValue: true, + // Allow augments value to be specified as a normal type, e.g. {Type} + onTagText: util.parseTypeText, + onTagged(doclet, { value }) { + doclet.augment(util.firstWordOf(value)); }, - author: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.author ??= []; - doclet.author.push(value); - }, + synonyms: ['extends'], + }, + author: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.author ??= []; + doclet.author.push(value); }, - // This symbol has a member that should use the same docs as another symbol. - borrows: { - mustHaveValue: true, - onTagged(doclet, tag) { - const parsed = util.parseBorrows(doclet, tag); + }, + // This symbol has a member that should use the same docs as another symbol. + borrows: { + mustHaveValue: true, + onTagged(doclet, tag) { + const parsed = util.parseBorrows(doclet, tag); - doclet.borrow(parsed.target, parsed.source); - }, + doclet.borrow(parsed.target, parsed.source); }, - class: { - onTagged(doclet, tag) { - let looksLikeDesc; + }, + class: { + onTagged(doclet, tag) { + let looksLikeDesc; - doclet.addTag('kind', 'class'); + doclet.addTag('kind', 'class'); - // handle special case where both @class and @constructor tags exist in same doclet - if (tag.originalTitle === 'class') { - // multiple words after @class? - looksLikeDesc = (tag.value || '').match(/\S+\s+\S+/); - if ( - (looksLikeDesc || /@construct(s|or)\b/i.test(doclet.comment)) && - !/@classdesc\b/i.test(doclet.comment) - ) { - // treat the @class tag as a @classdesc tag instead - doclet.classdesc = tag.value; - - return; - } - } - - util.setDocletNameToValue(doclet, tag); - }, - synonyms: ['constructor'], - }, - classdesc: { - onTagged(doclet, { value }) { - doclet.classdesc = value; - }, - }, - constant: { - canHaveType: true, - canHaveName: true, - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); - util.setDocletNameToValueName(doclet, tag); - util.setDocletTypeToValueType(doclet, tag); - }, - synonyms: ['const'], - }, - constructs: { - onTagged(doclet, { value }) { - let ownerClassName; - - if (!value) { - // this can be resolved later in the handlers - ownerClassName = '{@thisClass}'; - } else { - ownerClassName = util.firstWordOf(value); - } - doclet.addTag('alias', ownerClassName); - doclet.addTag('kind', 'class'); - }, - }, - copyright: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.copyright = value; - }, - }, - default: { - onTagged(doclet, { value }) { - if (value) { - doclet.defaultvalue = value; - } else if ( - doclet.meta && - doclet.meta.code && - typeof doclet.meta.code.value !== 'undefined' + // handle special case where both @class and @constructor tags exist in same doclet + if (tag.originalTitle === 'class') { + // multiple words after @class? + looksLikeDesc = (tag.value || '').match(/\S+\s+\S+/); + if ( + (looksLikeDesc || /@construct(s|or)\b/i.test(doclet.comment)) && + !/@classdesc\b/i.test(doclet.comment) ) { - switch (doclet.meta.code.type) { - case Syntax.ArrayExpression: - doclet.defaultvalue = astNode.nodeToValue(doclet.meta.code.node); - doclet.defaultvaluetype = 'array'; - break; + // treat the @class tag as a @classdesc tag instead + doclet.classdesc = tag.value; - case Syntax.Literal: - doclet.defaultvalue = doclet.meta.code.value; - break; - - case Syntax.ObjectExpression: - doclet.defaultvalue = astNode.nodeToValue(doclet.meta.code.node); - doclet.defaultvaluetype = 'object'; - break; - - default: - // do nothing - break; - } + return; } - }, - synonyms: ['defaultvalue'], + } + + util.setDocletNameToValue(doclet, tag); }, - deprecated: { - // value is optional - onTagged(doclet, { value }) { - doclet.deprecated = value ?? true; - }, + synonyms: ['constructor'], + }, + classdesc: { + onTagged(doclet, { value }) { + doclet.classdesc = value; }, - enum: { - canHaveType: true, - onTagged(doclet, tag) { - doclet.kind ??= 'member'; - doclet.isEnum = true; + }, + constant: { + canHaveType: true, + canHaveName: true, + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + util.setDocletNameToValueName(doclet, tag); + util.setDocletTypeToValueType(doclet, tag); + }, + synonyms: ['const'], + }, + constructs: { + onTagged(doclet, { value }) { + let ownerClassName; + + if (!value) { + // this can be resolved later in the handlers + ownerClassName = '{@thisClass}'; + } else { + ownerClassName = util.firstWordOf(value); + } + doclet.addTag('alias', ownerClassName); + doclet.addTag('kind', 'class'); + }, + }, + copyright: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.copyright = value; + }, + }, + default: { + onTagged(doclet, { value }) { + if (value) { + doclet.defaultvalue = value; + } else if (doclet.meta && doclet.meta.code && typeof doclet.meta.code.value !== 'undefined') { + switch (doclet.meta.code.type) { + case Syntax.ArrayExpression: + doclet.defaultvalue = astNode.nodeToValue(doclet.meta.code.node); + doclet.defaultvaluetype = 'array'; + break; + + case Syntax.Literal: + doclet.defaultvalue = doclet.meta.code.value; + break; + + case Syntax.ObjectExpression: + doclet.defaultvalue = astNode.nodeToValue(doclet.meta.code.node); + doclet.defaultvaluetype = 'object'; + break; + + default: + // do nothing + break; + } + } + }, + synonyms: ['defaultvalue'], + }, + deprecated: { + // value is optional + onTagged(doclet, { value }) { + doclet.deprecated = value ?? true; + }, + }, + enum: { + canHaveType: true, + onTagged(doclet, tag) { + doclet.kind ??= 'member'; + doclet.isEnum = true; + util.setDocletTypeToValueType(doclet, tag); + }, + }, + event: { + isNamespace: true, + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + util.setDocletNameToValue(doclet, tag); + }, + }, + example: { + keepsWhitespace: true, + removesIndent: true, + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.examples ??= []; + doclet.examples.push(value); + }, + }, + exports: { + mustHaveValue: true, + onTagged(doclet, { value }) { + const modName = util.firstWordOf(value); + + // in case the user wrote something like `/** @exports module:foo */`: + doclet.addTag('alias', stripModuleNamespace(modName)); + doclet.addTag('kind', 'module'); + }, + }, + external: { + canHaveType: true, + isNamespace: true, + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + if (tag.value && tag.value.type) { util.setDocletTypeToValueType(doclet, tag); - }, - }, - event: { - isNamespace: true, - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); + doclet.addTag('name', doclet.type.names[0]); + } else { util.setDocletNameToValue(doclet, tag); - }, + } }, - example: { - keepsWhitespace: true, - removesIndent: true, - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.examples ??= []; - doclet.examples.push(value); - }, - }, - exports: { - mustHaveValue: true, - onTagged(doclet, { value }) { - const modName = util.firstWordOf(value); + synonyms: ['host'], + }, + file: { + onTagged(doclet, tag) { + util.setNameToFile(doclet); + util.setDocletKindToTitle(doclet, tag); + util.setDocletDescriptionToValue(doclet, tag); - // in case the user wrote something like `/** @exports module:foo */`: - doclet.addTag('alias', stripModuleNamespace(modName)); - doclet.addTag('kind', 'module'); - }, + doclet.preserveName = true; }, - external: { - canHaveType: true, - isNamespace: true, - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); - if (tag.value && tag.value.type) { - util.setDocletTypeToValueType(doclet, tag); - doclet.addTag('name', doclet.type.names[0]); - } else { - util.setDocletNameToValue(doclet, tag); - } - }, - synonyms: ['host'], + synonyms: ['fileoverview', 'overview'], + }, + fires: { + mustHaveValue: true, + onTagged(doclet, tag) { + doclet.fires ??= []; + util.applyNamespaceToTag('event', tag); + doclet.fires.push(tag.value); }, - file: { - onTagged(doclet, tag) { - util.setNameToFile(doclet); - util.setDocletKindToTitle(doclet, tag); - util.setDocletDescriptionToValue(doclet, tag); - - doclet.preserveName = true; - }, - synonyms: ['fileoverview', 'overview'], + synonyms: ['emits'], + }, + function: { + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + util.setDocletNameToValue(doclet, tag); }, - fires: { - mustHaveValue: true, - onTagged(doclet, tag) { - doclet.fires ??= []; - util.applyNamespaceToTag('event', tag); - doclet.fires.push(tag.value); - }, - synonyms: ['emits'], + synonyms: ['func', 'method'], + }, + generator: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.generator = true; }, - function: { - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); - util.setDocletNameToValue(doclet, tag); - }, - synonyms: ['func', 'method'], + }, + global: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.scope = SCOPE.NAMES.GLOBAL; + doclet.memberof = undefined; }, - generator: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.generator = true; - }, + }, + hideconstructor: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.hideconstructor = true; }, - global: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.scope = SCOPE.NAMES.GLOBAL; - doclet.memberof = undefined; - }, + }, + ignore: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.ignore = true; }, - hideconstructor: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.hideconstructor = true; - }, + }, + implements: { + mustHaveValue: true, + onTagText: util.parseTypeText, + onTagged(doclet, { value }) { + doclet.implements ??= []; + doclet.implements.push(value); }, - ignore: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.ignore = true; - }, + }, + inheritdoc: { + mustNotHaveValue: true, + onTagged(doclet) { + // Use an empty string so JSDoc can support `@inheritdoc Foo#bar` in the future. + doclet.inheritdoc = ''; }, - implements: { - mustHaveValue: true, - onTagText: util.parseTypeText, - onTagged(doclet, { value }) { - doclet.implements ??= []; - doclet.implements.push(value); - }, + }, + inner: { + onTagged(doclet, tag) { + util.setDocletScopeToTitle(doclet, tag, deps); }, - inheritdoc: { - mustNotHaveValue: true, - onTagged(doclet) { - // Use an empty string so JSDoc can support `@inheritdoc Foo#bar` in the future. - doclet.inheritdoc = ''; - }, + }, + instance: { + onTagged(doclet, tag) { + util.setDocletScopeToTitle(doclet, tag, deps); }, - inner: { - onTagged(doclet, tag) { - util.setDocletScopeToTitle(doclet, tag, deps); - }, - }, - instance: { - onTagged(doclet, tag) { - util.setDocletScopeToTitle(doclet, tag, deps); - }, - }, - interface: { - canHaveName: true, - onTagged(doclet, tag) { - doclet.addTag('kind', 'interface'); - if (tag.value) { - util.setDocletNameToValueName(doclet, tag); - } - }, - }, - lends: { - onTagged(doclet, { value }) { - doclet.alias = value ?? LONGNAMES.GLOBAL; - doclet.addTag('undocumented'); - }, - }, - license: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.license = value; - }, - }, - listens: { - mustHaveValue: true, - onTagged(doclet, tag) { - doclet.listens ??= []; - util.applyNamespaceToTag('event', tag); - doclet.listens.push(tag.value); - }, - }, - member: { - canHaveType: true, - canHaveName: true, - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); + }, + interface: { + canHaveName: true, + onTagged(doclet, tag) { + doclet.addTag('kind', 'interface'); + if (tag.value) { util.setDocletNameToValueName(doclet, tag); + } + }, + }, + lends: { + onTagged(doclet, { value }) { + doclet.alias = value ?? LONGNAMES.GLOBAL; + doclet.addTag('undocumented'); + }, + }, + license: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.license = value; + }, + }, + listens: { + mustHaveValue: true, + onTagged(doclet, tag) { + doclet.listens ??= []; + util.applyNamespaceToTag('event', tag); + doclet.listens.push(tag.value); + }, + }, + member: { + canHaveType: true, + canHaveName: true, + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + util.setDocletNameToValueName(doclet, tag); + util.setDocletTypeToValueType(doclet, tag); + }, + synonyms: ['var'], + }, + memberof: { + mustHaveValue: true, + onTagged(doclet, tag) { + if (tag.originalTitle === 'memberof!') { + doclet.forceMemberof = true; + if (tag.value === LONGNAMES.GLOBAL) { + doclet.addTag('global'); + doclet.memberof = undefined; + } + } + util.setDocletMemberof(doclet, tag); + }, + synonyms: ['memberof!'], + }, + mixes: { + mustHaveValue: true, + onTagged(doclet, { value }) { + const source = util.firstWordOf(value); + + doclet.mix(source); + }, + }, + mixin: { + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + util.setDocletNameToValue(doclet, tag); + }, + }, + modifies: { + canHaveType: true, + onTagged(doclet, { value }) { + doclet.modifies ??= []; + doclet.modifies.push(value); + }, + }, + module: { + canHaveType: true, + isNamespace: true, + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + util.setDocletNameToValue(doclet, tag); + if (!doclet.name) { + util.setDocletNameToFilename(doclet); + } + // in case the user wrote something like `/** @module module:foo */`: + doclet.name = stripModuleNamespace(doclet.name); + + util.setDocletTypeToValueType(doclet, tag); + }, + }, + namespace: { + canHaveType: true, + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); + util.setDocletNameToValue(doclet, tag); + util.setDocletTypeToValueType(doclet, tag); + }, + }, + package: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.access = 'package'; + }, + }, + param: { + canHaveType: true, + canHaveName: true, + onTagged(doclet, { value }) { + doclet.params ??= []; + doclet.params.push(value ?? {}); + }, + synonyms: ['arg', 'argument'], + }, + private: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.access = 'private'; + }, + }, + property: { + mustHaveValue: true, + canHaveType: true, + canHaveName: true, + onTagged(doclet, { value }) { + doclet.properties ??= []; + doclet.properties.push(value); + }, + synonyms: ['prop'], + }, + protected: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.access = 'protected'; + }, + }, + public: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.access = 'public'; + }, + }, + readonly: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.readonly = true; + }, + }, + requires: { + mustHaveValue: true, + onTagged(doclet, { value }) { + let requiresName; + + // Inline link tags are passed through as-is so that `@requires {@link foo}` works. + if (isInlineTag(value, 'link\\S*')) { + requiresName = value; + } + // Otherwise, assume it's a module. + else { + requiresName = util.firstWordOf(value); + if (!requiresName.match(MODULE_NAMESPACE_REGEXP)) { + requiresName = MODULE_NAMESPACE + requiresName; + } + } + + doclet.requires ??= []; + doclet.requires.push(requiresName); + }, + }, + returns: { + mustHaveValue: true, + canHaveType: true, + onTagged(doclet, { value }) { + doclet.returns ??= []; + doclet.returns.push(value); + }, + synonyms: ['return'], + }, + see: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.see ??= []; + doclet.see.push(value); + }, + }, + since: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.since = value; + }, + }, + static: { + onTagged(doclet, tag) { + util.setDocletScopeToTitle(doclet, tag, deps); + }, + }, + summary: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.summary = value; + }, + }, + this: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.this = util.firstWordOf(value); + }, + }, + throws: { + mustHaveValue: true, + canHaveType: true, + onTagged(doclet, { value }) { + doclet.exceptions ??= []; + doclet.exceptions.push(value); + }, + synonyms: ['exception'], + }, + todo: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.todo ??= []; + doclet.todo.push(value); + }, + }, + type: { + mustHaveValue: true, + mustNotHaveDescription: true, + canHaveType: true, + onTagText(text) { + let closeIdx; + let openIdx; + + const OPEN_BRACE = '{'; + const CLOSE_BRACE = '}'; + + // Remove line breaks. + text = text.replace(/[\f\n\r]/g, ''); + + // Text must be a type expression; for backwards compatibility, we add braces if they're + // missing. But do NOT add braces to things like `@type {string} some pointless text`. + openIdx = text.indexOf(OPEN_BRACE); + closeIdx = text.indexOf(CLOSE_BRACE); + + // A type expression is at least one character long. + if (openIdx !== 0 || closeIdx <= openIdx + 1) { + text = OPEN_BRACE + text + CLOSE_BRACE; + } + + return text; + }, + onTagged(doclet, tag) { + if (tag.value && tag.value.type) { util.setDocletTypeToValueType(doclet, tag); - }, - synonyms: ['var'], - }, - memberof: { - mustHaveValue: true, - onTagged(doclet, tag) { - if (tag.originalTitle === 'memberof!') { - doclet.forceMemberof = true; - if (tag.value === LONGNAMES.GLOBAL) { - doclet.addTag('global'); - doclet.memberof = undefined; - } + + // For backwards compatibility, we interpret `@type` for functions as the return type. + if (doclet.kind === 'function') { + doclet.addTag('returns', tag.text); } - util.setDocletMemberof(doclet, tag); - }, - synonyms: ['memberof!'], + } }, - mixes: { - mustHaveValue: true, - onTagged(doclet, { value }) { - const source = util.firstWordOf(value); + }, + typedef: { + canHaveType: true, + canHaveName: true, + onTagged(doclet, tag) { + util.setDocletKindToTitle(doclet, tag); - doclet.mix(source); - }, - }, - mixin: { - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); - util.setDocletNameToValue(doclet, tag); - }, - }, - modifies: { - canHaveType: true, - onTagged(doclet, { value }) { - doclet.modifies ??= []; - doclet.modifies.push(value); - }, - }, - module: { - canHaveType: true, - isNamespace: true, - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); - util.setDocletNameToValue(doclet, tag); - if (!doclet.name) { - util.setDocletNameToFilename(doclet); - } - // in case the user wrote something like `/** @module module:foo */`: - doclet.name = stripModuleNamespace(doclet.name); + if (tag.value) { + util.setDocletNameToValueName(doclet, tag); - util.setDocletTypeToValueType(doclet, tag); - }, - }, - namespace: { - canHaveType: true, - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); - util.setDocletNameToValue(doclet, tag); - util.setDocletTypeToValueType(doclet, tag); - }, - }, - package: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.access = 'package'; - }, - }, - param: { - canHaveType: true, - canHaveName: true, - onTagged(doclet, { value }) { - doclet.params ??= []; - doclet.params.push(value ?? {}); - }, - synonyms: ['arg', 'argument'], - }, - private: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.access = 'private'; - }, - }, - property: { - mustHaveValue: true, - canHaveType: true, - canHaveName: true, - onTagged(doclet, { value }) { - doclet.properties ??= []; - doclet.properties.push(value); - }, - synonyms: ['prop'], - }, - protected: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.access = 'protected'; - }, - }, - public: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.access = 'public'; - }, - }, - readonly: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.readonly = true; - }, - }, - requires: { - mustHaveValue: true, - onTagged(doclet, { value }) { - let requiresName; - - // Inline link tags are passed through as-is so that `@requires {@link foo}` works. - if (isInlineTag(value, 'link\\S*')) { - requiresName = value; - } - // Otherwise, assume it's a module. - else { - requiresName = util.firstWordOf(value); - if (!requiresName.match(MODULE_NAMESPACE_REGEXP)) { - requiresName = MODULE_NAMESPACE + requiresName; - } - } - - doclet.requires ??= []; - doclet.requires.push(requiresName); - }, - }, - returns: { - mustHaveValue: true, - canHaveType: true, - onTagged(doclet, { value }) { - doclet.returns ??= []; - doclet.returns.push(value); - }, - synonyms: ['return'], - }, - see: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.see ??= []; - doclet.see.push(value); - }, - }, - since: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.since = value; - }, - }, - static: { - onTagged(doclet, tag) { - util.setDocletScopeToTitle(doclet, tag, deps); - }, - }, - summary: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.summary = value; - }, - }, - this: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.this = util.firstWordOf(value); - }, - }, - throws: { - mustHaveValue: true, - canHaveType: true, - onTagged(doclet, { value }) { - doclet.exceptions ??= []; - doclet.exceptions.push(value); - }, - synonyms: ['exception'], - }, - todo: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.todo ??= []; - doclet.todo.push(value); - }, - }, - type: { - mustHaveValue: true, - mustNotHaveDescription: true, - canHaveType: true, - onTagText(text) { - let closeIdx; - let openIdx; - - const OPEN_BRACE = '{'; - const CLOSE_BRACE = '}'; - - // Remove line breaks. - text = text.replace(/[\f\n\r]/g, ''); - - // Text must be a type expression; for backwards compatibility, we add braces if they're - // missing. But do NOT add braces to things like `@type {string} some pointless text`. - openIdx = text.indexOf(OPEN_BRACE); - closeIdx = text.indexOf(CLOSE_BRACE); - - // A type expression is at least one character long. - if (openIdx !== 0 || closeIdx <= openIdx + 1) { - text = OPEN_BRACE + text + CLOSE_BRACE; - } - - return text; - }, - onTagged(doclet, tag) { - if (tag.value && tag.value.type) { + // Callbacks are always type {function}. + if (tag.originalTitle === 'callback') { + doclet.type = { + names: ['function'], + }; + } else { util.setDocletTypeToValueType(doclet, tag); - - // For backwards compatibility, we interpret `@type` for functions as the return type. - if (doclet.kind === 'function') { - doclet.addTag('returns', tag.text); - } } - }, + } }, - typedef: { - canHaveType: true, - canHaveName: true, - onTagged(doclet, tag) { - util.setDocletKindToTitle(doclet, tag); + synonyms: ['callback'], + }, + variation: { + mustHaveValue: true, + onTagged(doclet, tag) { + let value = tag.value; + const match = value.match(VARIATION_VALUE_REGEXP); - if (tag.value) { - util.setDocletNameToValueName(doclet, tag); + if (match) { + value = match[1]; + } - // Callbacks are always type {function}. - if (tag.originalTitle === 'callback') { - doclet.type = { - names: ['function'], - }; - } else { - util.setDocletTypeToValueType(doclet, tag); - } - } - }, - synonyms: ['callback'], + doclet.variation = value; }, - variation: { - mustHaveValue: true, - onTagged(doclet, tag) { - let value = tag.value; - const match = value.match(VARIATION_VALUE_REGEXP); - - if (match) { - value = match[1]; - } - - doclet.variation = value; - }, + }, + version: { + mustHaveValue: true, + onTagged(doclet, { value }) { + doclet.version = value; }, - version: { - mustHaveValue: true, - onTagged(doclet, { value }) { - doclet.version = value; - }, + }, + yields: { + mustHaveValue: true, + canHaveType: true, + onTagged(doclet, { value }) { + doclet.yields ??= []; + doclet.yields.push(value); }, - yields: { - mustHaveValue: true, - canHaveType: true, - onTagged(doclet, { value }) { - doclet.yields ??= []; - doclet.yields.push(value); - }, - synonyms: ['yield'], - }, - }; -}; + synonyms: ['yield'], + }, +}); diff --git a/packages/jsdoc-tag/lib/definitions/internal.js b/packages/jsdoc-tag/lib/definitions/internal.js index 8806919e..57f3133f 100644 --- a/packages/jsdoc-tag/lib/definitions/internal.js +++ b/packages/jsdoc-tag/lib/definitions/internal.js @@ -15,49 +15,47 @@ */ // Tags that JSDoc uses internally, and that must always be defined. -export const getTags = () => { - return { - // Special separator tag indicating that multiple doclets should be generated for the same - // comment. Used internally (and by some JSDoc users, although it's not officially supported). - // - // In the following example, the parser will replace `//**` with an `@also` tag: - // /** - // * Foo. - // *//** - // * Foo with a param. - // * @param {string} bar - // */ - // function foo(bar) {} - also: { - onTagged() { - // Let the parser handle it. We define the tag here to avoid "not a known tag" errors. - }, +export const getTags = () => ({ + // Special separator tag indicating that multiple doclets should be generated for the same + // comment. Used internally (and by some JSDoc users, although it's not officially supported). + // + // In the following example, the parser will replace `//**` with an `@also` tag: + // /** + // * Foo. + // *//** + // * Foo with a param. + // * @param {string} bar + // */ + // function foo(bar) {} + also: { + onTagged() { + // Let the parser handle it. We define the tag here to avoid "not a known tag" errors. }, - description: { - mustHaveValue: true, - onTagged: (doclet, { value }) => { - doclet.description = value; - }, - synonyms: ['desc'], + }, + description: { + mustHaveValue: true, + onTagged: (doclet, { value }) => { + doclet.description = value; }, - kind: { - mustHaveValue: true, - onTagged: (doclet, { value }) => { - doclet.kind = value; - }, + synonyms: ['desc'], + }, + kind: { + mustHaveValue: true, + onTagged: (doclet, { value }) => { + doclet.kind = value; }, - name: { - mustHaveValue: true, - onTagged: (doclet, { value }) => { - doclet.name = value; - }, + }, + name: { + mustHaveValue: true, + onTagged: (doclet, { value }) => { + doclet.name = value; }, - undocumented: { - mustNotHaveValue: true, - onTagged(doclet) { - doclet.undocumented = true; - doclet.comment = ''; - }, + }, + undocumented: { + mustNotHaveValue: true, + onTagged(doclet) { + doclet.undocumented = true; + doclet.comment = ''; }, - }; -}; + }, +}); diff --git a/packages/jsdoc-test-matchers/index.js b/packages/jsdoc-test-matchers/index.js index 0da92180..62f7308b 100644 --- a/packages/jsdoc-test-matchers/index.js +++ b/packages/jsdoc-test-matchers/index.js @@ -60,9 +60,7 @@ function matchmaker(name, checker) { } const matcherFuncs = { - toBeArray: (actual) => { - return _.isArray(actual); - }, + toBeArray: (actual) => _.isArray(actual), toBeArrayOfSize: (actual, expected) => { if (_.isArray(actual) && actual.length === expected) { return true; @@ -77,76 +75,31 @@ const matcherFuncs = { return !actual.some((item) => !_.isString(item)); }, - toBeArrayOfObjects: (actual) => { - return _.isArray(actual) && !actual.some((item) => !_.isObject(item)); - }, - toBeBoolean: (actual) => { - return _.isBoolean(actual); - }, - toBeEmptyArray: (actual) => { - return _.isArray(actual) && actual.length === 0; - }, - toBeEmptyMap: (actual) => { - return _.isMap(actual) && actual.size === 0; - }, - toBeEmptyObject: (actual) => { - return _.isObject(actual) && !Object.keys(actual).length; - }, - toBeEmptySet: (actual) => { - return _.isSet(actual) && actual.size === 0; - }, - toBeEmptyString: (actual) => { - return actual === ''; - }, - toBeError: (actual) => { - return actual instanceof Error; - }, - toBeErrorOfType: (actual, expected) => { - return actual instanceof Error && actual.name === expected; - }, - toBeFunction: (actual) => { - return _.isFunction(actual); - }, + toBeArrayOfObjects: (actual) => _.isArray(actual) && !actual.some((item) => !_.isObject(item)), + toBeBoolean: (actual) => _.isBoolean(actual), + toBeEmptyArray: (actual) => _.isArray(actual) && actual.length === 0, + toBeEmptyMap: (actual) => _.isMap(actual) && actual.size === 0, + toBeEmptyObject: (actual) => _.isObject(actual) && !Object.keys(actual).length, + toBeEmptySet: (actual) => _.isSet(actual) && actual.size === 0, + toBeEmptyString: (actual) => actual === '', + toBeError: (actual) => actual instanceof Error, + toBeErrorOfType: (actual, expected) => actual instanceof Error && actual.name === expected, + toBeFunction: (actual) => _.isFunction(actual), toBeInstanceOf: isInstanceOf, - toBeLessThanOrEqualTo: (actual, expected) => { - return actual <= expected; - }, - toBeMap: (actual) => { - return _.isMap(actual); - }, - toBeNonEmptyObject: (actual) => { - return _.isObject(actual) && Object.keys(actual).length; - }, - toBeNonEmptyString: (actual) => { - return _.isString(actual) && actual.length > 0; - }, - toBeNumber: (actual) => { - return _.isNumber(actual); - }, - toBeObject: (actual) => { - return _.isObject(actual); - }, - toBeSet: (actual) => { - return _.isSet(actual); - }, - toBeString: (actual) => { - return _.isString(actual); - }, - toBeWholeNumber: (actual) => { - return Number.isInteger(actual); - }, - toEndWith: (actual, expected) => { - return _.isString(actual) && _.isString(expected) && actual.endsWith(expected); - }, - toHave: (actual, expected) => { - return (_.isMap(actual) || _.isSet(actual)) && actual.has(expected); - }, - toHaveMethod: (actual, expected) => { - return _.isObject(actual) && _.isFunction(actual[expected]); - }, - toHaveOwnProperty: (actual, expected) => { - return Object.hasOwn(actual, expected); - }, + toBeLessThanOrEqualTo: (actual, expected) => actual <= expected, + toBeMap: (actual) => _.isMap(actual), + toBeNonEmptyObject: (actual) => _.isObject(actual) && Object.keys(actual).length, + toBeNonEmptyString: (actual) => _.isString(actual) && actual.length > 0, + toBeNumber: (actual) => _.isNumber(actual), + toBeObject: (actual) => _.isObject(actual), + toBeSet: (actual) => _.isSet(actual), + toBeString: (actual) => _.isString(actual), + toBeWholeNumber: (actual) => Number.isInteger(actual), + toEndWith: (actual, expected) => + _.isString(actual) && _.isString(expected) && actual.endsWith(expected), + toHave: (actual, expected) => (_.isMap(actual) || _.isSet(actual)) && actual.has(expected), + toHaveMethod: (actual, expected) => _.isObject(actual) && _.isFunction(actual[expected]), + toHaveOwnProperty: (actual, expected) => Object.hasOwn(actual, expected), // The objects in `actual` must have all of the keys and values from the corresponding objects in // `expected`. The object in `actual` can have additional properties as well. For example, if // `expected[0]` is `{ a: 1 }`, and `actual[0]` is `{ a: 1, b: 2 }`, then the objects match. @@ -176,9 +129,7 @@ const matcherFuncs = { // The `actual` object must have all of the keys and values from the `expected` object. The // `actual` object can have additional properties as well. For example, if `expected` is // `{ a: 1 }`, and `actual` is `{ a: 1, b: 2 }`, then the objects match. - toMatchObject: (actual, expected) => { - return _.isMatch(actual, expected); - }, + toMatchObject: (actual, expected) => _.isMatch(actual, expected), toThrowErrorOfType: (actual, expected) => { let error;