index.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. 'use strict';
  2. const atRuleParamIndex = require('../../utils/atRuleParamIndex');
  3. const mediaFeatureColonSpaceChecker = require('../mediaFeatureColonSpaceChecker');
  4. const ruleMessages = require('../../utils/ruleMessages');
  5. const validateOptions = require('../../utils/validateOptions');
  6. const whitespaceChecker = require('../../utils/whitespaceChecker');
  7. const ruleName = 'media-feature-colon-space-after';
  8. const messages = ruleMessages(ruleName, {
  9. expectedAfter: () => 'Expected single space after ":"',
  10. rejectedAfter: () => 'Unexpected whitespace after ":"',
  11. });
  12. const meta = {
  13. url: 'https://stylelint.io/user-guide/rules/media-feature-colon-space-after',
  14. fixable: true,
  15. };
  16. /** @type {import('stylelint').Rule} */
  17. const rule = (primary, _secondaryOptions, context) => {
  18. const checker = whitespaceChecker('space', primary, messages);
  19. return (root, result) => {
  20. const validOptions = validateOptions(result, ruleName, {
  21. actual: primary,
  22. possible: ['always', 'never'],
  23. });
  24. if (!validOptions) {
  25. return;
  26. }
  27. /** @type {Map<import('postcss').AtRule, number[]> | undefined} */
  28. let fixData;
  29. mediaFeatureColonSpaceChecker({
  30. root,
  31. result,
  32. locationChecker: checker.after,
  33. checkedRuleName: ruleName,
  34. fix: context.fix
  35. ? (atRule, index) => {
  36. const paramColonIndex = index - atRuleParamIndex(atRule);
  37. fixData = fixData || new Map();
  38. const colonIndices = fixData.get(atRule) || [];
  39. colonIndices.push(paramColonIndex);
  40. fixData.set(atRule, colonIndices);
  41. return true;
  42. }
  43. : null,
  44. });
  45. if (fixData) {
  46. for (const [atRule, colonIndices] of fixData.entries()) {
  47. let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params;
  48. for (const index of colonIndices.sort((a, b) => b - a)) {
  49. const beforeColon = params.slice(0, index + 1);
  50. const afterColon = params.slice(index + 1);
  51. if (primary === 'always') {
  52. params = beforeColon + afterColon.replace(/^\s*/, ' ');
  53. } else if (primary === 'never') {
  54. params = beforeColon + afterColon.replace(/^\s*/, '');
  55. }
  56. }
  57. if (atRule.raws.params) {
  58. atRule.raws.params.raw = params;
  59. } else {
  60. atRule.params = params;
  61. }
  62. }
  63. }
  64. };
  65. };
  66. rule.ruleName = ruleName;
  67. rule.messages = messages;
  68. rule.meta = meta;
  69. module.exports = rule;