index.js 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports["default"] = rule;
  6. exports.ruleName = exports.meta = exports.messages = void 0;
  7. var _postcssResolveNestedSelector = _interopRequireDefault(require("postcss-resolve-nested-selector"));
  8. var _stylelint = require("stylelint");
  9. var _utils = require("../../utils");
  10. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  11. var ruleName = (0, _utils.namespace)("percent-placeholder-pattern");
  12. exports.ruleName = ruleName;
  13. var messages = _stylelint.utils.ruleMessages(ruleName, {
  14. expected: function expected(placeholder) {
  15. return "Expected %-placeholder \"%".concat(placeholder, "\" to match specified pattern");
  16. }
  17. });
  18. exports.messages = messages;
  19. var meta = {
  20. url: (0, _utils.ruleUrl)(ruleName)
  21. };
  22. exports.meta = meta;
  23. function rule(pattern) {
  24. return function (root, result) {
  25. var validOptions = _stylelint.utils.validateOptions(result, ruleName, {
  26. actual: pattern,
  27. possible: [_utils.isRegExp, _utils.isString]
  28. });
  29. if (!validOptions) {
  30. return;
  31. }
  32. var placeholderPattern = (0, _utils.isString)(pattern) ? new RegExp(pattern) : pattern;
  33. // Checking placeholder definitions (looking among regular rules)
  34. root.walkRules(function (rule) {
  35. var selector = rule.selector;
  36. // Just a shorthand for calling `parseSelector`
  37. function parse(selector) {
  38. (0, _utils.parseSelector)(selector, result, rule, function (s) {
  39. return checkSelector(s, rule);
  40. });
  41. }
  42. // If it's a custom prop or a less mixin
  43. if (!(0, _utils.isStandardRule)(rule)) {
  44. return;
  45. }
  46. // If the selector has interpolation
  47. if (!(0, _utils.isStandardSelector)(selector)) {
  48. return;
  49. }
  50. // Nested selectors are processed in steps, as nesting levels are resolved.
  51. // Here we skip processing intermediate parts of selectors (to process only fully resolved selectors)
  52. // if (rule.nodes.some(node => node.type === "rule" || node.type === "atrule")) { return }
  53. // Only resolve selectors that have an interpolating "&"
  54. if ((0, _utils.hasInterpolatingAmpersand)(selector)) {
  55. (0, _postcssResolveNestedSelector["default"])(selector, rule).forEach(parse);
  56. } else {
  57. parse(selector);
  58. }
  59. });
  60. function checkSelector(fullSelector, rule) {
  61. // postcss-selector-parser gives %placeholders' nodes a "tag" type
  62. fullSelector.walkTags(function (compoundSelector) {
  63. var value = compoundSelector.value,
  64. sourceIndex = compoundSelector.sourceIndex;
  65. if (value[0] !== "%") {
  66. return;
  67. }
  68. var placeholder = value.slice(1);
  69. if (placeholderPattern.test(placeholder)) {
  70. return;
  71. }
  72. _stylelint.utils.report({
  73. result: result,
  74. ruleName: ruleName,
  75. message: messages.expected(placeholder),
  76. node: rule,
  77. index: sourceIndex
  78. });
  79. });
  80. }
  81. };
  82. }
  83. rule.ruleName = ruleName;
  84. rule.messages = messages;
  85. rule.meta = meta;