UNPKG

1.6 kBJavaScriptView Raw
1let matchingBrackets = new Map([
2 ['{', '}'],
3 ['[', ']'],
4 ['(', ')'],
5])
6let inverseMatchingBrackets = new Map(
7 Array.from(matchingBrackets.entries()).map(([k, v]) => [v, k])
8)
9
10let quotes = new Set(['"', "'", '`'])
11
12// Arbitrary values must contain balanced brackets (), [] and {}. Escaped
13// values don't count, and brackets inside quotes also don't count.
14//
15// E.g.: w-[this-is]w-[weird-and-invalid]
16// E.g.: w-[this-is\\]w-\\[weird-but-valid]
17// E.g.: content-['this-is-also-valid]-weirdly-enough']
18export default function isValidArbitraryValue(value) {
19 let stack = []
20 let inQuotes = false
21
22 for (let i = 0; i < value.length; i++) {
23 let char = value[i]
24
25 if (char === ':' && !inQuotes && stack.length === 0) {
26 return false
27 }
28
29 // Non-escaped quotes allow us to "allow" anything in between
30 if (quotes.has(char) && value[i - 1] !== '\\') {
31 inQuotes = !inQuotes
32 }
33
34 if (inQuotes) continue
35 if (value[i - 1] === '\\') continue // Escaped
36
37 if (matchingBrackets.has(char)) {
38 stack.push(char)
39 } else if (inverseMatchingBrackets.has(char)) {
40 let inverse = inverseMatchingBrackets.get(char)
41
42 // Nothing to pop from, therefore it is unbalanced
43 if (stack.length <= 0) {
44 return false
45 }
46
47 // Popped value must match the inverse value, otherwise it is unbalanced
48 if (stack.pop() !== inverse) {
49 return false
50 }
51 }
52 }
53
54 // If there is still something on the stack, it is also unbalanced
55 if (stack.length > 0) {
56 return false
57 }
58
59 // All good, totally balanced!
60 return true
61}