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