index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. 'use strict';
  2. const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
  3. const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector');
  4. const keywordSets = require('../../reference/keywordSets');
  5. const parseSelector = require('../../utils/parseSelector');
  6. const report = require('../../utils/report');
  7. const ruleMessages = require('../../utils/ruleMessages');
  8. const validateOptions = require('../../utils/validateOptions');
  9. const ruleName = 'selector-pseudo-class-case';
  10. const messages = ruleMessages(ruleName, {
  11. expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`,
  12. });
  13. const meta = {
  14. url: 'https://stylelint.io/user-guide/rules/list/selector-pseudo-class-case',
  15. };
  16. /** @type {import('stylelint').Rule} */
  17. const rule = (primary, _secondaryOptions, context) => {
  18. return (root, result) => {
  19. const validOptions = validateOptions(result, ruleName, {
  20. actual: primary,
  21. possible: ['lower', 'upper'],
  22. });
  23. if (!validOptions) {
  24. return;
  25. }
  26. root.walkRules((ruleNode) => {
  27. if (!isStandardSyntaxRule(ruleNode)) {
  28. return;
  29. }
  30. const selector = ruleNode.selector;
  31. if (!selector.includes(':')) {
  32. return;
  33. }
  34. const fixedSelector = parseSelector(
  35. ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector,
  36. result,
  37. ruleNode,
  38. (selectorTree) => {
  39. selectorTree.walkPseudos((pseudoNode) => {
  40. const pseudo = pseudoNode.value;
  41. if (!isStandardSyntaxSelector(pseudo)) {
  42. return;
  43. }
  44. if (
  45. pseudo.includes('::') ||
  46. keywordSets.levelOneAndTwoPseudoElements.has(pseudo.toLowerCase().slice(1))
  47. ) {
  48. return;
  49. }
  50. const expectedPseudo =
  51. primary === 'lower' ? pseudo.toLowerCase() : pseudo.toUpperCase();
  52. if (pseudo === expectedPseudo) {
  53. return;
  54. }
  55. if (context.fix) {
  56. pseudoNode.value = expectedPseudo;
  57. return;
  58. }
  59. report({
  60. message: messages.expected(pseudo, expectedPseudo),
  61. node: ruleNode,
  62. index: pseudoNode.sourceIndex,
  63. ruleName,
  64. result,
  65. });
  66. });
  67. },
  68. );
  69. if (context.fix && fixedSelector) {
  70. if (ruleNode.raws.selector) {
  71. ruleNode.raws.selector.raw = fixedSelector;
  72. } else {
  73. ruleNode.selector = fixedSelector;
  74. }
  75. }
  76. });
  77. };
  78. };
  79. rule.ruleName = ruleName;
  80. rule.messages = messages;
  81. rule.meta = meta;
  82. module.exports = rule;