index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. 'use strict';
  2. const blockString = require('../../utils/blockString');
  3. const hasBlock = require('../../utils/hasBlock');
  4. const rawNodeString = require('../../utils/rawNodeString');
  5. const report = require('../../utils/report');
  6. const ruleMessages = require('../../utils/ruleMessages');
  7. const validateOptions = require('../../utils/validateOptions');
  8. const whitespaceChecker = require('../../utils/whitespaceChecker');
  9. const ruleName = 'block-closing-brace-space-after';
  10. const messages = ruleMessages(ruleName, {
  11. expectedAfter: () => 'Expected single space after "}"',
  12. rejectedAfter: () => 'Unexpected whitespace after "}"',
  13. expectedAfterSingleLine: () => 'Expected single space after "}" of a single-line block',
  14. rejectedAfterSingleLine: () => 'Unexpected whitespace after "}" of a single-line block',
  15. expectedAfterMultiLine: () => 'Expected single space after "}" of a multi-line block',
  16. rejectedAfterMultiLine: () => 'Unexpected whitespace after "}" of a multi-line block',
  17. });
  18. const meta = {
  19. url: 'https://stylelint.io/user-guide/rules/block-closing-brace-space-after',
  20. deprecated: true,
  21. };
  22. /** @type {import('stylelint').Rule} */
  23. const rule = (primary) => {
  24. const checker = whitespaceChecker('space', primary, messages);
  25. return (root, result) => {
  26. const validOptions = validateOptions(result, ruleName, {
  27. actual: primary,
  28. possible: [
  29. 'always',
  30. 'never',
  31. 'always-single-line',
  32. 'never-single-line',
  33. 'always-multi-line',
  34. 'never-multi-line',
  35. ],
  36. });
  37. if (!validOptions) {
  38. return;
  39. }
  40. // Check both kinds of statements: rules and at-rules
  41. root.walkRules(check);
  42. root.walkAtRules(check);
  43. /**
  44. * @param {import('postcss').Rule | import('postcss').AtRule} statement
  45. */
  46. function check(statement) {
  47. const nextNode = statement.next();
  48. if (!nextNode) {
  49. return;
  50. }
  51. if (!hasBlock(statement)) {
  52. return;
  53. }
  54. let reportIndex = statement.toString().length;
  55. let source = rawNodeString(nextNode);
  56. // Skip a semicolon at the beginning, if any
  57. if (source && source.startsWith(';')) {
  58. source = source.slice(1);
  59. reportIndex++;
  60. }
  61. checker.after({
  62. source,
  63. index: -1,
  64. lineCheckStr: blockString(statement),
  65. err: (msg) => {
  66. report({
  67. message: msg,
  68. node: statement,
  69. index: reportIndex,
  70. result,
  71. ruleName,
  72. });
  73. },
  74. });
  75. }
  76. };
  77. };
  78. rule.ruleName = ruleName;
  79. rule.messages = messages;
  80. rule.meta = meta;
  81. module.exports = rule;