(input)
| 221 | * @returns {ParsedSource[]} url references |
| 222 | */ |
| 223 | const parseCssUrls = (input) => { |
| 224 | const ts = new TokenStream(input); |
| 225 | /** @type {ParsedSource[]} */ |
| 226 | const result = []; |
| 227 | for (;;) { |
| 228 | const t = ts.consume(); |
| 229 | if (t.type === TT_EOF) break; |
| 230 | if (t.type === TT_URL) { |
| 231 | if (t.contentEnd > t.contentStart) { |
| 232 | result.push([ |
| 233 | input.slice(t.contentStart, t.contentEnd), |
| 234 | t.contentStart, |
| 235 | t.contentEnd |
| 236 | ]); |
| 237 | } |
| 238 | } else if ( |
| 239 | t.type === TT_FUNCTION && |
| 240 | equalsLowerCase(input.slice(t.start, t.end - 1), "url") |
| 241 | ) { |
| 242 | let s = ts.consume(); |
| 243 | while (s.type === TT_WHITESPACE) s = ts.consume(); |
| 244 | if (s.type === TT_STRING) { |
| 245 | const quote = input.charCodeAt(s.start); |
| 246 | const innerStart = s.start + 1; |
| 247 | // Drop the closing quote, unless the string is unterminated at EOF. |
| 248 | const innerEnd = |
| 249 | input.charCodeAt(s.end - 1) === quote ? s.end - 1 : s.end; |
| 250 | if (innerEnd > innerStart) { |
| 251 | result.push([ |
| 252 | input.slice(innerStart, innerEnd), |
| 253 | innerStart, |
| 254 | innerEnd |
| 255 | ]); |
| 256 | } |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | return result; |
| 261 | }; |
| 262 | |
| 263 | /** |
| 264 | * @param {Map<string, string>} attributes attributes |
nothing calls this directly
no test coverage detected