index.cjs.js 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. 'use strict';
  2. function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
  3. var postcss = _interopDefault(require('postcss'));
  4. var selectorParser = _interopDefault(require('postcss-selector-parser'));
  5. var index = postcss.plugin('postcss-dir-pseudo-class', opts => {
  6. const dir = Object(opts).dir;
  7. const preserve = Boolean(Object(opts).preserve);
  8. return root => {
  9. // walk rules using the :dir pseudo-class
  10. root.walkRules(/:dir\([^\)]*\)/, rule => {
  11. let currentRule = rule; // conditionally preserve the original rule
  12. if (preserve) {
  13. currentRule = rule.cloneBefore();
  14. } // update the rule selector
  15. currentRule.selector = selectorParser(selectors => {
  16. // for each (comma separated) selector
  17. selectors.nodes.forEach(selector => {
  18. // walk all selector nodes that are :dir pseudo-classes
  19. selector.walk(node => {
  20. if ('pseudo' === node.type && ':dir' === node.value) {
  21. // previous and next selector nodes
  22. const prev = node.prev();
  23. const next = node.next();
  24. const prevIsSpaceCombinator = prev && prev.type && 'combinator' === prev.type && ' ' === prev.value;
  25. const nextIsSpaceCombinator = next && next.type && 'combinator' === next.type && ' ' === next.value; // preserve the selector tree
  26. if (prevIsSpaceCombinator && (nextIsSpaceCombinator || !next)) {
  27. node.replaceWith(selectorParser.universal());
  28. } else {
  29. node.remove();
  30. } // conditionally prepend a combinator before inserting the [dir] attribute
  31. const first = selector.nodes[0];
  32. const firstIsSpaceCombinator = first && 'combinator' === first.type && ' ' === first.value;
  33. const firstIsHtml = first && 'tag' === first.type && 'html' === first.value;
  34. const firstIsRoot = first && 'pseudo' === first.type && ':root' === first.value;
  35. if (first && !firstIsHtml && !firstIsRoot && !firstIsSpaceCombinator) {
  36. selector.prepend(selectorParser.combinator({
  37. value: ' '
  38. }));
  39. } // value of the :dir pseudo-class
  40. const value = node.nodes.toString(); // whether :dir matches the presumed direction
  41. const isdir = dir === value; // [dir] attribute
  42. const dirAttr = selectorParser.attribute({
  43. attribute: 'dir',
  44. operator: '=',
  45. quoteMark: '"',
  46. value: `"${value}"`
  47. }); // not[dir] attribute
  48. const notDirAttr = selectorParser.pseudo({
  49. value: `${firstIsHtml || firstIsRoot ? '' : 'html'}:not`
  50. });
  51. notDirAttr.append(selectorParser.attribute({
  52. attribute: 'dir',
  53. operator: '=',
  54. quoteMark: '"',
  55. value: `"${'ltr' === value ? 'rtl' : 'ltr'}"`
  56. }));
  57. if (isdir) {
  58. // if the direction is presumed
  59. if (firstIsHtml) {
  60. // insert :root after html tag
  61. selector.insertAfter(first, notDirAttr);
  62. } else {
  63. // prepend :root
  64. selector.prepend(notDirAttr);
  65. }
  66. } else if (firstIsHtml) {
  67. // otherwise, insert dir attribute after html tag
  68. selector.insertAfter(first, dirAttr);
  69. } else {
  70. // otherwise, prepend the dir attribute
  71. selector.prepend(dirAttr);
  72. }
  73. }
  74. });
  75. });
  76. }).processSync(currentRule.selector);
  77. });
  78. };
  79. });
  80. module.exports = index;
  81. //# sourceMappingURL=index.cjs.js.map