(str, isString)
| 131 | * @returns {string} normalized url |
| 132 | */ |
| 133 | const normalizeUrl = (str, isString) => { |
| 134 | // Fast paths: skip the regex engine for the common URL with no escape and |
| 135 | // no edge whitespace (e.g. `./img.png`). Each guard is equivalent to the |
| 136 | // regex being a no-op. |
| 137 | // Remove escaped newlines from a string-token url like `url("im\<newline>g.png")`. |
| 138 | if (isString && str.includes("\\")) { |
| 139 | str = str.replace(STRING_MULTILINE, ""); |
| 140 | } |
| 141 | |
| 142 | // Remove unnecessary spaces from `url(" img.png ")` |
| 143 | if ( |
| 144 | str.length !== 0 && |
| 145 | (isCssWhitespace(str.charCodeAt(0)) || |
| 146 | isCssWhitespace(str.charCodeAt(str.length - 1))) |
| 147 | ) { |
| 148 | str = str.replace(TRIM_WHITE_SPACES, ""); |
| 149 | } |
| 150 | |
| 151 | // Unescape |
| 152 | if (str.includes("\\")) { |
| 153 | str = str.replace(UNESCAPE, (match) => { |
| 154 | if (match.length > 2) { |
| 155 | return String.fromCharCode(Number.parseInt(match.slice(1).trim(), 16)); |
| 156 | } |
| 157 | return match[1]; |
| 158 | }); |
| 159 | } |
| 160 | |
| 161 | if (/^data:/i.test(str)) { |
| 162 | return str; |
| 163 | } |
| 164 | |
| 165 | if (str.includes("%")) { |
| 166 | // Convert `url('%2E/img.png')` -> `url('./img.png')` |
| 167 | try { |
| 168 | str = decodeURIComponent(str); |
| 169 | } catch (_err) { |
| 170 | // Ignore |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | return str; |
| 175 | }; |
| 176 | |
| 177 | // `escapeIdentifier` / `unescapeIdentifier` live in ./syntax.js; they're re-exported at the bottom for back-compat callers. |
| 178 |
no test coverage detected