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