diff --git django/contrib/staticfiles/storage.py django/contrib/staticfiles/storage.py
index b3ee32e665..9f5077edad 100644
|
|
def url(self, name, force=False):
|
194 | 194 | """ |
195 | 195 | return self._url(self.stored_name, name, force) |
196 | 196 | |
197 | | def url_converter(self, name, hashed_files, template=None): |
| 197 | def url_converter(self, name, hashed_files, template, commented_regions): |
198 | 198 | """ |
199 | 199 | Return the custom URL converter for the given file name. |
200 | 200 | """ |
… |
… |
def converter(matchobj):
|
212 | 212 | matched = matches["matched"] |
213 | 213 | url = matches["url"] |
214 | 214 | |
| 215 | from bisect import bisect |
| 216 | |
| 217 | if len(commented_regions): |
| 218 | m_start, m_end = span = matchobj.span() |
| 219 | comment_index = bisect(commented_regions, span) |
| 220 | if comment_index != 0: |
| 221 | c_start, c_end = commented_regions[comment_index - 1] |
| 222 | # If match lies within commented region |
| 223 | if c_start <= m_start and m_end <= c_end: |
| 224 | return matched |
| 225 | |
215 | 226 | # Ignore absolute/protocol-relative and data-uri URLs. |
216 | 227 | if re.match(r"^[a-z]+:", url): |
217 | 228 | return matched |
… |
… |
def path_level(name):
|
356 | 367 | content = original_file.read().decode("utf-8") |
357 | 368 | for extension, patterns in self._patterns.items(): |
358 | 369 | if matches_patterns(path, (extension,)): |
| 370 | commented_regions = self._parse_commented_regions( |
| 371 | extension, content |
| 372 | ) |
359 | 373 | for pattern, template in patterns: |
360 | 374 | converter = self.url_converter( |
361 | | name, hashed_files, template |
| 375 | name, hashed_files, template, commented_regions |
362 | 376 | ) |
363 | 377 | try: |
364 | 378 | content = pattern.sub(converter, content) |
… |
… |
def path_level(name):
|
396 | 410 | |
397 | 411 | yield name, hashed_name, processed, substitutions |
398 | 412 | |
| 413 | def _parse_commented_regions(self, extension, content): |
| 414 | if extension == "*.js": |
| 415 | js_region_re = re.compile( |
| 416 | r""" |
| 417 | ( |
| 418 | # single-quoted strings |
| 419 | '([^'\\]|(\\.))*?' |
| 420 | # double-quoted strings |
| 421 | |"([^"\\]|(\\.))*?" |
| 422 | # template literals |
| 423 | |`.*?` |
| 424 | # single line comments |
| 425 | |//.*?\n |
| 426 | # multi-line comments |
| 427 | |/\*.*?\*/ |
| 428 | ) |
| 429 | """, |
| 430 | re.VERBOSE | re.DOTALL, |
| 431 | ) |
| 432 | return [m.span() for m in js_region_re.finditer(content)] |
| 433 | else: |
| 434 | return [] |
| 435 | |
399 | 436 | def clean_name(self, name): |
400 | 437 | return name.replace("\\", "/") |
401 | 438 | |