Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

requireDescriptionCompleteSentence.js 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _lodash = _interopRequireDefault(require("lodash"));
  7. var _mainUmd = require("regextras/dist/main-umd");
  8. var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
  9. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  10. const otherDescriptiveTags = new Set([// 'copyright' and 'see' might be good addition, but as the former may be
  11. // sensitive text, and the latter may have just a link, they are not
  12. // included by default
  13. 'summary', 'file', 'fileoverview', 'overview', 'classdesc', 'todo', 'deprecated', 'throws', 'exception', 'yields', 'yield']);
  14. const extractParagraphs = text => {
  15. return text.split(/(?<![;:])\n\n/u);
  16. };
  17. const extractSentences = (text, abbreviationsRegex) => {
  18. const txt = text // Remove all {} tags.
  19. .replace(/\{[\s\S]*?\}\s*/gu, '') // Remove custom abbreviations
  20. .replace(abbreviationsRegex, '');
  21. const sentenceEndGrouping = /([.?!])(?:\s+|$)/u;
  22. const puncts = (0, _mainUmd.RegExtras)(sentenceEndGrouping).map(txt, punct => {
  23. return punct;
  24. });
  25. return txt.split(/[.?!](?:\s+|$)/u) // Re-add the dot.
  26. .map((sentence, idx) => {
  27. return /^\s*$/u.test(sentence) ? sentence : `${sentence}${puncts[idx] || ''}`;
  28. });
  29. };
  30. const isNewLinePrecededByAPeriod = text => {
  31. let lastLineEndsSentence;
  32. const lines = text.split('\n');
  33. return !lines.some(line => {
  34. if (lastLineEndsSentence === false && /^[A-Z][a-z]/u.test(line)) {
  35. return true;
  36. }
  37. lastLineEndsSentence = /[.:?!|]$/u.test(line);
  38. return false;
  39. });
  40. };
  41. const isCapitalized = str => {
  42. return str[0] === str[0].toUpperCase();
  43. };
  44. const isTable = str => {
  45. return str.charAt() === '|';
  46. };
  47. const capitalize = str => {
  48. return str.charAt(0).toUpperCase() + str.slice(1);
  49. };
  50. const validateDescription = (description, reportOrig, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd) => {
  51. if (!description) {
  52. return false;
  53. }
  54. const paragraphs = extractParagraphs(description);
  55. return paragraphs.some((paragraph, parIdx) => {
  56. const sentences = extractSentences(paragraph, abbreviationsRegex);
  57. const fix = fixer => {
  58. let text = sourceCode.getText(jsdocNode);
  59. if (!/[.:?!]$/u.test(paragraph)) {
  60. const line = paragraph.split('\n').pop();
  61. text = text.replace(new RegExp(`${_lodash.default.escapeRegExp(line)}$`, 'mu'), `${line}.`);
  62. }
  63. for (const sentence of sentences.filter(sentence_ => {
  64. return !/^\s*$/u.test(sentence_) && !isCapitalized(sentence_) && !isTable(sentence_);
  65. })) {
  66. const beginning = sentence.split('\n')[0];
  67. if (tag.tag) {
  68. const reg = new RegExp(`(@${_lodash.default.escapeRegExp(tag.tag)}.*)${_lodash.default.escapeRegExp(beginning)}`, 'u');
  69. text = text.replace(reg, (_$0, $1) => {
  70. return $1 + capitalize(beginning);
  71. });
  72. } else {
  73. text = text.replace(new RegExp('((?:[.!?]|\\*|\\})\\s*)' + _lodash.default.escapeRegExp(beginning), 'u'), '$1' + capitalize(beginning));
  74. }
  75. }
  76. return fixer.replaceText(jsdocNode, text);
  77. };
  78. const report = (msg, fixer, tagObj) => {
  79. if ('line' in tagObj) {
  80. tagObj.line += parIdx * 2;
  81. } else {
  82. tagObj.source[0].number += parIdx * 2;
  83. } // Avoid errors if old column doesn't exist here
  84. tagObj.column = 0;
  85. reportOrig(msg, fixer, tagObj);
  86. };
  87. if (sentences.some(sentence => {
  88. return !/^\s*$/u.test(sentence) && !isCapitalized(sentence) && !isTable(sentence);
  89. })) {
  90. report('Sentence should start with an uppercase character.', fix, tag);
  91. }
  92. const paragraphNoAbbreviations = paragraph.replace(abbreviationsRegex, '');
  93. if (!/[.!?|]\s*$/u.test(paragraphNoAbbreviations)) {
  94. report('Sentence must end with a period.', fix, tag);
  95. return true;
  96. }
  97. if (newlineBeforeCapsAssumesBadSentenceEnd && !isNewLinePrecededByAPeriod(paragraphNoAbbreviations)) {
  98. report('A line of text is started with an uppercase character, but preceding line does not end the sentence.', null, tag);
  99. return true;
  100. }
  101. return false;
  102. });
  103. };
  104. var _default = (0, _iterateJsdoc.default)(({
  105. sourceCode,
  106. context,
  107. jsdoc,
  108. report,
  109. jsdocNode,
  110. utils
  111. }) => {
  112. const options = context.options[0] || {};
  113. const {
  114. abbreviations = [],
  115. newlineBeforeCapsAssumesBadSentenceEnd = false
  116. } = options;
  117. const abbreviationsRegex = abbreviations.length ? new RegExp('\\b' + abbreviations.map(abbreviation => {
  118. return _lodash.default.escapeRegExp(abbreviation.replace(/\.$/g, '') + '.');
  119. }).join('|') + '(?:$|\\s)', 'gu') : '';
  120. const {
  121. description
  122. } = utils.getDescription();
  123. if (validateDescription(description, report, jsdocNode, abbreviationsRegex, sourceCode, {
  124. line: jsdoc.source[0].number + 1
  125. }, newlineBeforeCapsAssumesBadSentenceEnd)) {
  126. return;
  127. }
  128. utils.forEachPreferredTag('description', matchingJsdocTag => {
  129. const desc = `${matchingJsdocTag.name} ${utils.getTagDescription(matchingJsdocTag)}`.trim();
  130. validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, matchingJsdocTag, newlineBeforeCapsAssumesBadSentenceEnd);
  131. }, true);
  132. const {
  133. tagsWithNames
  134. } = utils.getTagsByType(jsdoc.tags);
  135. const tagsWithoutNames = utils.filterTags(({
  136. tag: tagName
  137. }) => {
  138. return otherDescriptiveTags.has(tagName) || utils.hasOptionTag(tagName) && !tagsWithNames.some(({
  139. tag
  140. }) => {
  141. // If user accidentally adds tags with names (or like `returns`
  142. // get parsed as having names), do not add to this list
  143. return tag === tagName;
  144. });
  145. });
  146. tagsWithNames.some(tag => {
  147. const desc = _lodash.default.trimStart(utils.getTagDescription(tag), '- ').trimEnd();
  148. return validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd);
  149. });
  150. tagsWithoutNames.some(tag => {
  151. const desc = `${tag.name} ${utils.getTagDescription(tag)}`.trim();
  152. return validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd);
  153. });
  154. }, {
  155. iterateAllJsdocs: true,
  156. meta: {
  157. docs: {
  158. description: 'Requires that block description, explicit `@description`, and `@param`/`@returns` tag descriptions are written in complete sentences.',
  159. url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-description-complete-sentence'
  160. },
  161. fixable: 'code',
  162. schema: [{
  163. additionalProperties: false,
  164. properties: {
  165. abbreviations: {
  166. items: {
  167. type: 'string'
  168. },
  169. type: 'array'
  170. },
  171. newlineBeforeCapsAssumesBadSentenceEnd: {
  172. type: 'boolean'
  173. },
  174. tags: {
  175. items: {
  176. type: 'string'
  177. },
  178. type: 'array'
  179. }
  180. },
  181. type: 'object'
  182. }],
  183. type: 'suggestion'
  184. }
  185. });
  186. exports.default = _default;
  187. module.exports = exports.default;
  188. //# sourceMappingURL=requireDescriptionCompleteSentence.js.map