blob: c95b99cd0e55e2e9b9d080b231a949a42363dfd7 [file] [log] [blame]
{"version":3,"sources":["../../src/rules/requireDescriptionCompleteSentence.js"],"names":["otherDescriptiveTags","extractParagraphs","text","reverse","join","split","map","par","extractSentences","abbreviationsRegex","txt","replace","sentenceEndGrouping","puncts","punct","sentence","idx","test","isNewLinePrecededByAPeriod","lastLineEndsSentence","lines","some","line","isCapitalized","str","toUpperCase","isTable","charAt","capitalize","slice","validateDescription","description","reportOrig","jsdocNode","sourceCode","tag","paragraphs","paragraph","parIdx","sentences","fix","fixer","getText","_","last","RegExp","escapeRegExp","filter","sentence_","beginning","reg","$0","$1","replaceText","report","msg","tagObj","column","paragraphNoAbbreviations","context","jsdoc","utils","options","abbreviations","length","abbreviation","tags","forEachPreferredTag","matchingJsdocTag","name","trim","getTagsByType","tagsWithNames","tagsWithoutNames","filterTags","tagName","includes","hasOptionTag","trimStart","iterateAllJsdocs","meta","fixable","schema","additionalProperties","properties","items","type"],"mappings":"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","sourcesContent":["import _ from 'lodash';\nimport {RegExtras} from 'regextras/dist/main-umd';\nimport iterateJsdoc from '../iterateJsdoc';\n\nconst otherDescriptiveTags = [\n // 'copyright' and 'see' might be good addition, but as the former may be\n // sensitive text, and the latter may have just a link, they are not\n // included by default\n 'summary', 'file', 'fileoverview', 'overview', 'classdesc', 'todo',\n 'deprecated', 'throws', 'exception', 'yields', 'yield',\n];\n\nconst extractParagraphs = (text) => {\n // Todo [engine:node@>8.11.0]: Uncomment following line with neg. lookbehind instead\n // return text.split(/(?<![;:])\\n\\n/u);\n return [...text].reverse().join('').split(/\\n\\n(?![;:])/u).map((par) => {\n return [...par].reverse().join('');\n }).reverse();\n};\n\nconst extractSentences = (text, abbreviationsRegex) => {\n const txt = text\n\n // Remove all {} tags.\n .replace(/\\{[\\s\\S]*?\\}\\s*/gu, '')\n\n // Remove custom abbreviations\n .replace(abbreviationsRegex, '');\n\n const sentenceEndGrouping = /([.?!])(?:\\s+|$)/u;\n const puncts = RegExtras(sentenceEndGrouping).map(txt, (punct) => {\n return punct;\n });\n\n return txt\n\n .split(/[.?!](?:\\s+|$)/u)\n\n // Re-add the dot.\n .map((sentence, idx) => {\n return /^\\s*$/u.test(sentence) ? sentence : `${sentence}${puncts[idx] || ''}`;\n });\n};\n\nconst isNewLinePrecededByAPeriod = (text) => {\n let lastLineEndsSentence;\n\n const lines = text.split('\\n');\n\n return !lines.some((line) => {\n if (lastLineEndsSentence === false && /^[A-Z][a-z]/u.test(line)) {\n return true;\n }\n\n lastLineEndsSentence = /[.:?!|]$/u.test(line);\n\n return false;\n });\n};\n\nconst isCapitalized = (str) => {\n return str[0] === str[0].toUpperCase();\n};\n\nconst isTable = (str) => {\n return str.charAt() === '|';\n};\n\nconst capitalize = (str) => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nconst validateDescription = (description, reportOrig, jsdocNode, abbreviationsRegex, sourceCode, tag) => {\n if (!description) {\n return false;\n }\n\n const paragraphs = extractParagraphs(description);\n\n return paragraphs.some((paragraph, parIdx) => {\n const sentences = extractSentences(paragraph, abbreviationsRegex);\n\n const fix = (fixer) => {\n let text = sourceCode.getText(jsdocNode);\n\n if (!/[.:?!]$/u.test(paragraph)) {\n const line = _.last(paragraph.split('\\n'));\n\n text = text.replace(new RegExp(`${_.escapeRegExp(line)}$`, 'mu'), `${line}.`);\n }\n\n for (const sentence of sentences.filter((sentence_) => {\n return !(/^\\s*$/u).test(sentence_) && !isCapitalized(sentence_) &&\n !isTable(sentence_);\n })) {\n const beginning = sentence.split('\\n')[0];\n\n if (tag.tag) {\n const reg = new RegExp(`(@${_.escapeRegExp(tag.tag)}.*)${_.escapeRegExp(beginning)}`, 'u');\n\n text = text.replace(reg, ($0, $1) => {\n return $1 + capitalize(beginning);\n });\n } else {\n text = text.replace(beginning, capitalize(beginning));\n }\n }\n\n return fixer.replaceText(jsdocNode, text);\n };\n\n const report = (msg, fixer, tagObj) => {\n tagObj.line += parIdx * 2;\n\n // Avoid errors if old column doesn't exist here\n tagObj.column = 0;\n reportOrig(msg, fixer, tagObj);\n };\n\n if (sentences.some((sentence) => {\n return !(/^\\s*$/u).test(sentence) && !isCapitalized(sentence) && !isTable(sentence);\n })) {\n report('Sentence should start with an uppercase character.', fix, tag);\n }\n\n const paragraphNoAbbreviations = paragraph.replace(abbreviationsRegex, '');\n\n if (!/[.!?|]$/u.test(paragraphNoAbbreviations)) {\n report('Sentence must end with a period.', fix, tag);\n\n return true;\n }\n\n if (!isNewLinePrecededByAPeriod(paragraphNoAbbreviations)) {\n report('A line of text is started with an uppercase character, but preceding line does not end the sentence.', null, tag);\n\n return true;\n }\n\n return false;\n });\n};\n\nexport default iterateJsdoc(({\n sourceCode,\n context,\n jsdoc,\n report,\n jsdocNode,\n utils,\n}) => {\n const options = context.options[0] || {};\n const {\n abbreviations = [],\n } = options;\n\n const abbreviationsRegex = abbreviations.length ?\n new RegExp('\\\\b' + abbreviations.map((abbreviation) => {\n return _.escapeRegExp(abbreviation.replace(/\\.$/g, '') + '.');\n }).join('|') + '(?:$|\\\\s)', 'gu') :\n '';\n\n if (!jsdoc.tags ||\n validateDescription(jsdoc.description, report, jsdocNode, abbreviationsRegex, sourceCode, {\n line: jsdoc.line + 1,\n })\n ) {\n return;\n }\n\n utils.forEachPreferredTag('description', (matchingJsdocTag) => {\n const description = `${matchingJsdocTag.name} ${matchingJsdocTag.description}`.trim();\n validateDescription(description, report, jsdocNode, abbreviationsRegex, sourceCode, matchingJsdocTag);\n }, true);\n\n const {tagsWithNames} = utils.getTagsByType(jsdoc.tags);\n const tagsWithoutNames = utils.filterTags(({tag: tagName}) => {\n return otherDescriptiveTags.includes(tagName) ||\n utils.hasOptionTag(tagName) && !tagsWithNames.some(({tag}) => {\n // If user accidentally adds tags with names (or like `returns`\n // get parsed as having names), do not add to this list\n return tag === tagName;\n });\n });\n\n tagsWithNames.some((tag) => {\n const description = _.trimStart(tag.description, '- ');\n\n return validateDescription(description, report, jsdocNode, abbreviationsRegex, sourceCode, tag);\n });\n\n tagsWithoutNames.some((tag) => {\n const description = `${tag.name} ${tag.description}`.trim();\n\n return validateDescription(description, report, jsdocNode, abbreviationsRegex, sourceCode, tag);\n });\n}, {\n iterateAllJsdocs: true,\n meta: {\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n abbreviations: {\n items: {\n type: 'string',\n },\n type: 'array',\n },\n tags: {\n items: {\n type: 'string',\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"file":"requireDescriptionCompleteSentence.js"}