source: frontend/node_modules/tailwindcss/lib/util/pseudoElements.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/** @typedef {import('postcss-selector-parser').Root} Root */ /** @typedef {import('postcss-selector-parser').Selector} Selector */ /** @typedef {import('postcss-selector-parser').Pseudo} Pseudo */ /** @typedef {import('postcss-selector-parser').Node} Node */ // There are some pseudo-elements that may or may not be:
2// **Actionable**
3// Zero or more user-action pseudo-classes may be attached to the pseudo-element itself
4// structural-pseudo-classes are NOT allowed but we don't make
5// The spec is not clear on whether this is allowed or not — but in practice it is.
6// **Terminal**
7// It MUST be placed at the end of a selector
8//
9// This is the required in the spec. However, some pseudo elements are not "terminal" because
10// they represent a "boundary piercing" that is compiled out by a build step.
11// **Jumpable**
12// Any terminal element may "jump" over combinators when moving to the end of the selector
13//
14// This is a backwards-compat quirk of pseudo element variants from earlier versions of Tailwind CSS.
15/** @typedef {'terminal' | 'actionable' | 'jumpable'} PseudoProperty */ /** @type {Record<string, PseudoProperty[]>} */ "use strict";
16Object.defineProperty(exports, "__esModule", {
17 value: true
18});
19Object.defineProperty(exports, "movePseudos", {
20 enumerable: true,
21 get: function() {
22 return movePseudos;
23 }
24});
25let elementProperties = {
26 // Pseudo elements from the spec
27 "::after": [
28 "terminal",
29 "jumpable"
30 ],
31 "::backdrop": [
32 "terminal",
33 "jumpable"
34 ],
35 "::before": [
36 "terminal",
37 "jumpable"
38 ],
39 "::cue": [
40 "terminal"
41 ],
42 "::cue-region": [
43 "terminal"
44 ],
45 "::first-letter": [
46 "terminal",
47 "jumpable"
48 ],
49 "::first-line": [
50 "terminal",
51 "jumpable"
52 ],
53 "::grammar-error": [
54 "terminal"
55 ],
56 "::marker": [
57 "terminal",
58 "jumpable"
59 ],
60 "::part": [
61 "terminal",
62 "actionable"
63 ],
64 "::placeholder": [
65 "terminal",
66 "jumpable"
67 ],
68 "::selection": [
69 "terminal",
70 "jumpable"
71 ],
72 "::slotted": [
73 "terminal"
74 ],
75 "::spelling-error": [
76 "terminal"
77 ],
78 "::target-text": [
79 "terminal"
80 ],
81 // Pseudo elements from the spec with special rules
82 "::file-selector-button": [
83 "terminal",
84 "actionable"
85 ],
86 // Library-specific pseudo elements used by component libraries
87 // These are Shadow DOM-like
88 "::deep": [
89 "actionable"
90 ],
91 "::v-deep": [
92 "actionable"
93 ],
94 "::ng-deep": [
95 "actionable"
96 ],
97 // Note: As a rule, double colons (::) should be used instead of a single colon
98 // (:). This distinguishes pseudo-classes from pseudo-elements. However, since
99 // this distinction was not present in older versions of the W3C spec, most
100 // browsers support both syntaxes for the original pseudo-elements.
101 ":after": [
102 "terminal",
103 "jumpable"
104 ],
105 ":before": [
106 "terminal",
107 "jumpable"
108 ],
109 ":first-letter": [
110 "terminal",
111 "jumpable"
112 ],
113 ":first-line": [
114 "terminal",
115 "jumpable"
116 ],
117 ":where": [],
118 ":is": [],
119 ":has": [],
120 // The default value is used when the pseudo-element is not recognized
121 // Because it's not recognized, we don't know if it's terminal or not
122 // So we assume it can be moved AND can have user-action pseudo classes attached to it
123 __default__: [
124 "terminal",
125 "actionable"
126 ]
127};
128function movePseudos(sel) {
129 let [pseudos] = movablePseudos(sel);
130 // Remove all pseudo elements from their respective selectors
131 pseudos.forEach(([sel, pseudo])=>sel.removeChild(pseudo));
132 // Re-add them to the end of the selector in the correct order.
133 // This moves terminal pseudo elements to the end of the
134 // selector otherwise the selector will not be valid.
135 //
136 // Examples:
137 // - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
138 // - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
139 //
140 // The selector `::before:hover` does not work but we
141 // can make it work for you by flipping the order.
142 sel.nodes.push(...pseudos.map(([, pseudo])=>pseudo));
143 return sel;
144}
145/** @typedef {[sel: Selector, pseudo: Pseudo, attachedTo: Pseudo | null]} MovablePseudo */ /** @typedef {[pseudos: MovablePseudo[], lastSeenElement: Pseudo | null]} MovablePseudosResult */ /**
146 * @param {Selector} sel
147 * @returns {MovablePseudosResult}
148 */ function movablePseudos(sel) {
149 /** @type {MovablePseudo[]} */ let buffer = [];
150 /** @type {Pseudo | null} */ let lastSeenElement = null;
151 for (let node of sel.nodes){
152 if (node.type === "combinator") {
153 buffer = buffer.filter(([, node])=>propertiesForPseudo(node).includes("jumpable"));
154 lastSeenElement = null;
155 } else if (node.type === "pseudo") {
156 if (isMovablePseudoElement(node)) {
157 lastSeenElement = node;
158 buffer.push([
159 sel,
160 node,
161 null
162 ]);
163 } else if (lastSeenElement && isAttachablePseudoClass(node, lastSeenElement)) {
164 buffer.push([
165 sel,
166 node,
167 lastSeenElement
168 ]);
169 } else {
170 lastSeenElement = null;
171 }
172 var _node_nodes;
173 for (let sub of (_node_nodes = node.nodes) !== null && _node_nodes !== void 0 ? _node_nodes : []){
174 let [movable, lastSeenElementInSub] = movablePseudos(sub);
175 lastSeenElement = lastSeenElementInSub || lastSeenElement;
176 buffer.push(...movable);
177 }
178 }
179 }
180 return [
181 buffer,
182 lastSeenElement
183 ];
184}
185/**
186 * @param {Node} node
187 * @returns {boolean}
188 */ function isPseudoElement(node) {
189 return node.value.startsWith("::") || elementProperties[node.value] !== undefined;
190}
191/**
192 * @param {Node} node
193 * @returns {boolean}
194 */ function isMovablePseudoElement(node) {
195 return isPseudoElement(node) && propertiesForPseudo(node).includes("terminal");
196}
197/**
198 * @param {Node} node
199 * @param {Pseudo} pseudo
200 * @returns {boolean}
201 */ function isAttachablePseudoClass(node, pseudo) {
202 if (node.type !== "pseudo") return false;
203 if (isPseudoElement(node)) return false;
204 return propertiesForPseudo(pseudo).includes("actionable");
205}
206/**
207 * @param {Pseudo} pseudo
208 * @returns {PseudoProperty[]}
209 */ function propertiesForPseudo(pseudo) {
210 var _elementProperties_pseudo_value;
211 return (_elementProperties_pseudo_value = elementProperties[pseudo.value]) !== null && _elementProperties_pseudo_value !== void 0 ? _elementProperties_pseudo_value : elementProperties.__default__;
212}
Note: See TracBrowser for help on using the repository browser.