123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.js"));
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- // 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.js.map
|