Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions django/contrib/staticfiles/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class HashedFilesMixin:
r"""(?P<matched>@import\s*["']\s*(?P<url>.*?)["'])""",
"""@import url("%(url)s")""",
),
(
r'(?m)(?P<matched>)^(/\*# (?-i:sourceMappingURL)=(?P<url>.*) \*/)$',
'/*# sourceMappingURL=%(url)s */',
),
)),
('*.js', (
(
Expand Down
8 changes: 6 additions & 2 deletions docs/ref/contrib/staticfiles.txt
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ method). The regular expressions used to find those paths
(``django.contrib.staticfiles.storage.HashedFilesMixin.patterns``) cover:

* The `@import`_ rule and `url()`_ statement of `Cascading Style Sheets`_.
* The `source map`_ comment in JavaScript.
* `Source map`_ comments in CSS and JavaScript files.

For example, the ``'css/styles.css'`` file with this content:

Expand Down Expand Up @@ -327,10 +327,14 @@ argument. For example::

.. versionchanged:: 4.0

Support for finding paths in the source map comments was added.
Support for finding paths in JavaScript source map comments was added.

The ``manifest_storage`` argument was added.

.. versionchanged:: 4.1

Support for finding paths in CSS source map comments was added.

.. attribute:: storage.ManifestStaticFilesStorage.max_post_process_passes

Since static files might reference other static files that need to have their
Expand Down
3 changes: 2 additions & 1 deletion docs/releases/4.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ Minor features
:mod:`django.contrib.staticfiles`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* ...
* :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now
replaces paths to CSS source map references with their hashed counterparts.

:mod:`django.contrib.syndication`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* {outline: 1px solid red;}
/*# sOuRcEMaPpInGURL=source_map.css.map */
24 changes: 24 additions & 0 deletions tests/staticfiles_tests/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,30 @@ def test_css_import_case_insensitive(self):
self.assertIn(b"other.d41d8cd98f00.css", content)
self.assertPostCondition()

def test_css_source_map(self):
relpath = self.hashed_file_path('cached/source_map.css')
self.assertEqual(relpath, 'cached/source_map.b2fceaf426aa.css')
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
self.assertNotIn(b'/*# sourceMappingURL=source_map.css.map */', content)
self.assertIn(
b'/*# sourceMappingURL=source_map.css.99914b932bd3.map */',
content,
)
self.assertPostCondition()

def test_css_source_map_sensitive(self):
relpath = self.hashed_file_path('cached/source_map_sensitive.css')
self.assertEqual(relpath, 'cached/source_map_sensitive.456683f2106f.css')
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
self.assertIn(b'/*# sOuRcEMaPpInGURL=source_map.css.map */', content)
self.assertNotIn(
b'/*# sourceMappingURL=source_map.css.99914b932bd3.map */',
content,
)
self.assertPostCondition()

def test_js_source_map(self):
relpath = self.hashed_file_path('cached/source_map.js')
self.assertEqual(relpath, 'cached/source_map.cd45b8534a87.js')
Expand Down