index.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. 'use strict';
  2. const ruleMessages = require('../../utils/ruleMessages');
  3. const selectorAttributeOperatorSpaceChecker = require('../selectorAttributeOperatorSpaceChecker');
  4. const validateOptions = require('../../utils/validateOptions');
  5. const whitespaceChecker = require('../../utils/whitespaceChecker');
  6. const ruleName = 'selector-attribute-operator-space-after';
  7. const messages = ruleMessages(ruleName, {
  8. expectedAfter: (operator) => `Expected single space after "${operator}"`,
  9. rejectedAfter: (operator) => `Unexpected whitespace after "${operator}"`,
  10. });
  11. const meta = {
  12. url: 'https://stylelint.io/user-guide/rules/selector-attribute-operator-space-after',
  13. fixable: true,
  14. deprecated: true,
  15. };
  16. /** @type {import('stylelint').Rule} */
  17. const rule = (primary, _secondaryOptions, context) => {
  18. return (root, result) => {
  19. const checker = whitespaceChecker('space', primary, messages);
  20. const validOptions = validateOptions(result, ruleName, {
  21. actual: primary,
  22. possible: ['always', 'never'],
  23. });
  24. if (!validOptions) {
  25. return;
  26. }
  27. selectorAttributeOperatorSpaceChecker({
  28. root,
  29. result,
  30. locationChecker: checker.after,
  31. checkedRuleName: ruleName,
  32. checkBeforeOperator: false,
  33. fix: context.fix
  34. ? (attributeNode) => {
  35. /** @type {{ operatorAfter: string, setOperatorAfter: (fixed: string) => void }} */
  36. const { operatorAfter, setOperatorAfter } = (() => {
  37. const rawOperator = attributeNode.raws.operator;
  38. if (rawOperator) {
  39. return {
  40. operatorAfter: rawOperator.slice(
  41. attributeNode.operator ? attributeNode.operator.length : 0,
  42. ),
  43. setOperatorAfter(fixed) {
  44. delete attributeNode.raws.operator;
  45. if (!attributeNode.raws.spaces) attributeNode.raws.spaces = {};
  46. if (!attributeNode.raws.spaces.operator)
  47. attributeNode.raws.spaces.operator = {};
  48. attributeNode.raws.spaces.operator.after = fixed;
  49. },
  50. };
  51. }
  52. const rawSpacesOperator =
  53. attributeNode.raws.spaces && attributeNode.raws.spaces.operator;
  54. const rawOperatorAfter = rawSpacesOperator && rawSpacesOperator.after;
  55. if (rawOperatorAfter) {
  56. return {
  57. operatorAfter: rawOperatorAfter,
  58. setOperatorAfter(fixed) {
  59. rawSpacesOperator.after = fixed;
  60. },
  61. };
  62. }
  63. return {
  64. operatorAfter:
  65. (attributeNode.spaces.operator && attributeNode.spaces.operator.after) || '',
  66. setOperatorAfter(fixed) {
  67. if (!attributeNode.spaces.operator) attributeNode.spaces.operator = {};
  68. attributeNode.spaces.operator.after = fixed;
  69. },
  70. };
  71. })();
  72. if (primary === 'always') {
  73. setOperatorAfter(operatorAfter.replace(/^\s*/, ' '));
  74. return true;
  75. }
  76. if (primary === 'never') {
  77. setOperatorAfter(operatorAfter.replace(/^\s*/, ''));
  78. return true;
  79. }
  80. return false;
  81. }
  82. : null,
  83. });
  84. };
  85. };
  86. rule.ruleName = ruleName;
  87. rule.messages = messages;
  88. rule.meta = meta;
  89. module.exports = rule;