report.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. 'use strict';
  2. const _ = require('lodash');
  3. /** @typedef {{
  4. ruleName: string,
  5. result: import('stylelint').PostcssResult,
  6. message: string,
  7. node: import('postcss').Node & {
  8. positionBy(opts: { index?: number, word?: string }): { line: number, column: number }
  9. },
  10. index?: number,
  11. word?: string,
  12. line?: number
  13. }} Violation */
  14. /**
  15. * Report a violation.
  16. *
  17. * This function accounts for `disabledRanges` attached to the result.
  18. * That is, if the reported violation is within a disabledRange,
  19. * it is ignored. Otherwise, it is attached to the result as a
  20. * postcss warning.
  21. *
  22. * It also accounts for the rule's severity.
  23. *
  24. * You *must* pass *either* a node or a line number.
  25. * @param {Violation} violation
  26. */
  27. module.exports = function (violation) {
  28. const ruleName = violation.ruleName;
  29. const result = violation.result;
  30. const message = violation.message;
  31. const line = violation.line;
  32. const node = violation.node;
  33. const index = violation.index;
  34. const word = violation.word;
  35. result.stylelint = result.stylelint || {
  36. ruleSeverities: {},
  37. customMessages: {},
  38. };
  39. // In quiet mode, mere warnings are ignored
  40. if (result.stylelint.quiet && result.stylelint.ruleSeverities[ruleName] !== 'error') {
  41. return;
  42. }
  43. // If a line is not passed, use the node.positionBy method to get the
  44. // line number that the complaint pertains to
  45. const startLine = line || node.positionBy({ index }).line;
  46. if (
  47. result.stylelint.disabledRanges &&
  48. (!result.stylelint.ignoreDisables || result.stylelint.reportNeedlessDisables)
  49. ) {
  50. const ranges = result.stylelint.disabledRanges[ruleName] || result.stylelint.disabledRanges.all;
  51. for (const range of ranges) {
  52. if (
  53. // If the violation is within a disabledRange,
  54. // and that disabledRange's rules include this one,
  55. // do not register a warning
  56. range.start <= startLine &&
  57. (range.end === undefined || range.end >= startLine) &&
  58. (!range.rules || range.rules.includes(ruleName))
  59. ) {
  60. if (result.stylelint.reportNeedlessDisables) {
  61. // Collect disabled warnings
  62. // Used to report `needlessDisables` in subsequent processing.
  63. const disabledWarnings =
  64. result.stylelint.disabledWarnings || (result.stylelint.disabledWarnings = []);
  65. disabledWarnings.push({
  66. rule: ruleName,
  67. line: startLine,
  68. });
  69. if (!result.stylelint.ignoreDisables) {
  70. return;
  71. }
  72. break;
  73. } else {
  74. return;
  75. }
  76. }
  77. }
  78. }
  79. /** @type {string} */
  80. const severity = _.get(result.stylelint, ['ruleSeverities', ruleName], 'ignore');
  81. if (!result.stylelint.stylelintError && severity === 'error') {
  82. result.stylelint.stylelintError = true;
  83. }
  84. /** @type {import('stylelint').StylelintWarningOptions} */
  85. const warningProperties = {
  86. severity,
  87. rule: ruleName,
  88. };
  89. if (node) {
  90. warningProperties.node = node;
  91. }
  92. if (index) {
  93. warningProperties.index = index;
  94. }
  95. if (word) {
  96. warningProperties.word = word;
  97. }
  98. const warningMessage = _.get(result.stylelint, ['customMessages', ruleName], message);
  99. result.warn(warningMessage, warningProperties);
  100. };