-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
111 lines (103 loc) · 4.56 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import plugin from 'tailwindcss/plugin.js';
export default plugin(({ matchVariant }) => {
matchVariant('pattern', (pattern_selector) => {
const [pattern, selector = '*', extraneous] = pattern_selector.split(';').map((str) => str.trim());
if (!pattern) throw new Error(`No pattern provided in Tailwind CSS selector pattern '${pattern_selector}'`);
const optionalSelector = selector === '*' ? '' : selector;
if (extraneous)
throw new Error(
`Found more than 2 semicolon-delimited (;) arguments in Tailwind CSS selector pattern '${pattern_selector}'`
);
const combinator = pattern[0];
const validCombinatorSymbols = ['+', '-', '%', '>', '<', '^'];
if (!combinator || !validCombinatorSymbols.includes(combinator))
throw new Error(
`Combinator used '${combinator}' in Tailwind CSS selector pattern '${pattern_selector}' is not one of the valid combinators: ${validCombinatorSymbols.join(
', '
)}`
);
const isDoubleCombinator = pattern[1] === combinator;
if (!isDoubleCombinator && validCombinatorSymbols.includes(pattern[1] as unknown as string))
throw new Error(
`Second character in Tailwind CSS selector pattern '${pattern_selector}' ('${pattern[1]}') is a valid combinator but does not match the first combinator used ('${combinator}')`
);
const nthIndex_dir = isDoubleCombinator ? pattern.slice(2) : pattern.slice(1);
if (isDoubleCombinator && nthIndex_dir)
throw new Error(
`Double combinator '${combinator.repeat(
2
)}' in Tailwind CSS selector pattern '${pattern_selector}' can only be followed by an optional selector argument, delimited by a semicolon; instead found '${nthIndex_dir}'`
);
const validDirSymbols = ['<', '>'];
const hasDir = !isDoubleCombinator && validDirSymbols.includes(nthIndex_dir.slice(-1));
const [_nthIndex = '1', dir] = !isDoubleCombinator
? hasDir
? [nthIndex_dir.slice(0, -1), nthIndex_dir.slice(-1)]
: nthIndex_dir
? [nthIndex_dir]
: []
: [];
const nthIndex = Number(_nthIndex);
console.log({
pattern,
hasDir,
_nthIndex,
dir,
nthIndex,
});
if (!Number.isFinite(nthIndex))
throw new Error(`Invalid nth-index value '${_nthIndex}' in Tailwind CSS selector pattern '${pattern_selector}'`);
if (!(nthIndex > 0))
throw new Error(
`nth-index value '${nthIndex}' in Tailwind CSS selector pattern '${pattern_selector}' must be greater than 0`
);
let result = '';
if (combinator === '+' || combinator === '%') {
if (isDoubleCombinator) {
result += `& ~ ${selector}`;
} else if (!dir) {
result += `& + ${'* + '.repeat(nthIndex - 1)}${selector}`;
} else if (dir === '<') {
result += [...Array(nthIndex)].map((_, i) => `& + ${'* + '.repeat(i)}${selector}`).join(', ');
} else if (dir === '>') {
result += `& ${'+ * '.repeat(nthIndex - 1)}~ ${selector}`;
}
}
if (combinator === '%') result += `, `;
if (combinator === '-' || combinator === '%') {
if (isDoubleCombinator) {
result += `${optionalSelector}:has(~ &)`;
} else if (!dir) {
result += `${optionalSelector}:has(${'+ * '.repeat(nthIndex - 1)}+ &)`;
} else if (dir === '<') {
result += `${optionalSelector}:has(${[...Array(nthIndex)].map((_, i) => `+ ${'* + '.repeat(i)}&`).join(', ')})`;
} else if (dir === '>') {
result += `${optionalSelector}:has(~${' * +'.repeat(nthIndex - 1)} &)`;
}
}
if (combinator === '>' || combinator === '^') {
if (isDoubleCombinator) {
result += `& ${selector}`;
} else if (!dir) {
result += `& ${'> * '.repeat(nthIndex - 1)}> ${selector}`;
} else if (dir === '<') {
result += [...Array(nthIndex)].map((_, i) => `& > ${'* > '.repeat(i)}${selector}`).join(', ');
} else if (dir === '>') {
result += `& ${'> * '.repeat(nthIndex - 1)}${selector}`;
}
}
if (combinator === '^') result += `, `;
if (combinator === '<' || combinator === '^') {
if (isDoubleCombinator) {
result += `${optionalSelector}:has(&)`;
} else if (!dir) {
result += `${optionalSelector}:has(${'> * '.repeat(nthIndex - 1)}> &)`;
} else if (dir === '<') {
result += `${optionalSelector}:has(${[...Array(nthIndex)].map((_, i) => `${'> * '.repeat(i)}> &`).join(', ')})`;
} else if (dir === '>') {
result += `${optionalSelector}:has(${'* > '.repeat(nthIndex - 1)}&)`;
}
}
return `:is(${result})`;
});
});