(input: string, keepEmpty = false)
| 49 | const RE_SINGLE = /^[A-Za-z]$/ |
| 50 | |
| 51 | export function splitByTopLevelComma(input: string, keepEmpty = false): string[] { |
| 52 | if (!input) return [] |
| 53 | |
| 54 | const out: string[] = [] |
| 55 | let depth = 0 |
| 56 | let quote: "'" | '"' | null = null |
| 57 | let buf = '' |
| 58 | |
| 59 | for (let i = 0; i < input.length; i++) { |
| 60 | const ch = input[i] |
| 61 | |
| 62 | if (quote) { |
| 63 | if (ch === '\\') { |
| 64 | buf += ch |
| 65 | i++ |
| 66 | if (i < input.length) buf += input[i] |
| 67 | continue |
| 68 | } |
| 69 | if (ch === quote) quote = null |
| 70 | buf += ch |
| 71 | continue |
| 72 | } |
| 73 | |
| 74 | if (ch === '"' || ch === "'") { |
| 75 | quote = ch |
| 76 | buf += ch |
| 77 | continue |
| 78 | } |
| 79 | |
| 80 | if (ch === '(') depth++ |
| 81 | else if (ch === ')') depth = Math.max(0, depth - 1) |
| 82 | else if (ch === ',' && depth === 0) { |
| 83 | const segment = buf.trim() |
| 84 | if (segment || keepEmpty) out.push(segment) |
| 85 | buf = '' |
| 86 | continue |
| 87 | } |
| 88 | |
| 89 | buf += ch |
| 90 | } |
| 91 | |
| 92 | const tail = buf.trim() |
| 93 | if (tail || keepEmpty) { |
| 94 | out.push(tail) |
| 95 | } |
| 96 | |
| 97 | return out |
| 98 | } |
| 99 | |
| 100 | function hasTopLevelComma(value: string): boolean { |
| 101 | return splitByTopLevelComma(value, true).length > 1 |
no outgoing calls
no test coverage detected