| "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]*[.?!`\\p{RGI_Emoji}]\\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)(({ |
| context, |
| jsdoc, |
| report, |
| 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.hasOwn(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) && !/.+/v.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(/^[\- ]*/v, '').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: { |
| description: `Set this to an array of strings representing the AST context (or an object with |
| optional \`context\` and \`comment\` properties) where you wish the rule to be applied (e.g., |
| \`ClassDeclaration\` for ES6 classes). |
| |
| \`context\` defaults to \`any\` and \`comment\` defaults to no specific comment context. |
| |
| Overrides the default contexts (\`ArrowFunctionExpression\`, \`FunctionDeclaration\`, |
| \`FunctionExpression\`). Set to \`"any"\` if you want the rule to apply to any |
| JSDoc block throughout your files. |
| |
| See the ["AST and Selectors"](../#advanced-ast-and-selectors) |
| section of our Advanced docs for more on the expected format. |
| `, |
| items: { |
| anyOf: [{ |
| type: 'string' |
| }, { |
| additionalProperties: false, |
| properties: { |
| comment: { |
| type: 'string' |
| }, |
| context: { |
| type: 'string' |
| } |
| }, |
| type: 'object' |
| }] |
| }, |
| type: 'array' |
| }, |
| mainDescription: { |
| description: `If you wish to override the main block description without changing the |
| default \`match-description\` (which can cascade to the \`tags\` with \`true\`), |
| you may use \`mainDescription\`: |
| |
| \`\`\`js |
| { |
| 'jsdoc/match-description': ['error', { |
| mainDescription: '[A-Z].*\\\\.', |
| tags: { |
| param: true, |
| returns: true |
| } |
| }] |
| } |
| \`\`\` |
| |
| There is no need to add \`mainDescription: true\`, as by default, the main |
| block description (and only the main block description) is linted, though you |
| may disable checking it by setting it to \`false\`. |
| |
| You may also provide an object with \`message\`: |
| |
| \`\`\`js |
| { |
| 'jsdoc/match-description': ['error', { |
| mainDescription: { |
| message: 'Capitalize first word of JSDoc block descriptions', |
| match: '[A-Z].*\\\\.' |
| }, |
| tags: { |
| param: true, |
| returns: true |
| } |
| }] |
| } |
| \`\`\``, |
| oneOf: [{ |
| format: 'regex', |
| type: 'string' |
| }, { |
| type: 'boolean' |
| }, { |
| additionalProperties: false, |
| properties: { |
| match: { |
| oneOf: [{ |
| format: 'regex', |
| type: 'string' |
| }, { |
| type: 'boolean' |
| }] |
| }, |
| message: { |
| type: 'string' |
| } |
| }, |
| type: 'object' |
| }] |
| }, |
| matchDescription: { |
| description: `You can supply your own expression to override the default, passing a |
| \`matchDescription\` string on the options object. |
| |
| Defaults to using (only) the \`v\` flag, so |
| to add your own flags, encapsulate your expression as a string, but like a |
| literal, e.g., \`/[A-Z].*\\./vi\`. |
| |
| \`\`\`js |
| { |
| 'jsdoc/match-description': ['error', {matchDescription: '[A-Z].*\\\\.'}] |
| } |
| \`\`\``, |
| format: 'regex', |
| type: 'string' |
| }, |
| message: { |
| description: `You may provide a custom default message by using the following format: |
| |
| \`\`\`js |
| { |
| 'jsdoc/match-description': ['error', { |
| message: 'The default description should begin with a capital letter.' |
| }] |
| } |
| \`\`\` |
| |
| This can be overridden per tag or for the main block description by setting |
| \`message\` within \`tags\` or \`mainDescription\`, respectively. |
| `, |
| type: 'string' |
| }, |
| nonemptyTags: { |
| description: `If not set to \`false\`, will enforce that the following tags have at least |
| some content: |
| |
| - \`@copyright\` |
| - \`@example\` |
| - \`@see\` |
| - \`@todo\` |
| |
| If you supply your own tag description for any of the above tags in \`tags\`, |
| your description will take precedence.`, |
| type: 'boolean' |
| }, |
| tags: { |
| description: `If you want different regular expressions to apply to tags, you may use |
| the \`tags\` option object: |
| |
| \`\`\`js |
| { |
| 'jsdoc/match-description': ['error', {tags: { |
| param: '\\\\- [A-Z].*\\\\.', |
| returns: '[A-Z].*\\\\.' |
| }}] |
| } |
| \`\`\` |
| |
| In place of a string, you can also add \`true\` to indicate that a particular |
| tag should be linted with the \`matchDescription\` value (or the default). |
| |
| \`\`\`js |
| { |
| 'jsdoc/match-description': ['error', {tags: { |
| param: true, |
| returns: true |
| }}] |
| } |
| \`\`\` |
| |
| Alternatively, you may supply an object with a \`message\` property to indicate |
| the error message for that tag. |
| |
| \`\`\`js |
| { |
| 'jsdoc/match-description': ['error', {tags: { |
| param: {message: 'Begin with a hyphen', match: '\\\\- [A-Z].*\\\\.'}, |
| returns: {message: 'Capitalize for returns (the default)', match: true} |
| }}] |
| } |
| \`\`\` |
| |
| The tags \`@param\`/\`@arg\`/\`@argument\` and \`@property\`/\`@prop\` will be properly |
| parsed to ensure that the matched "description" text includes only the text |
| after the name. |
| |
| All other tags will treat the text following the tag name, a space, and |
| an optional curly-bracketed type expression (and another space) as part of |
| its "description" (e.g., for \`@returns {someType} some description\`, the |
| description is \`some description\` while for \`@some-tag xyz\`, the description |
| is \`xyz\`).`, |
| 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 |