Fixed #32383 -- Added source map support to ManifestStaticFilesStorage.

This commit is contained in:
Adam Johnson 2021-01-26 23:10:00 +00:00 committed by Mariusz Felisiak
parent 9ee693bd6c
commit e32722d160
7 changed files with 48 additions and 9 deletions

View File

@ -49,6 +49,9 @@ class HashedFilesMixin:
r"""(url\(['"]{0,1}\s*(.*?)["']{0,1}\))""", r"""(url\(['"]{0,1}\s*(.*?)["']{0,1}\))""",
(r"""(@import\s*["']\s*(.*?)["'])""", """@import url("%s")"""), (r"""(@import\s*["']\s*(.*?)["'])""", """@import url("%s")"""),
)), )),
('*.js', (
(r'(?m)^(//# (?-i:sourceMappingURL)=(.*))$', '//# sourceMappingURL=%s'),
)),
) )
keep_intermediate_files = True keep_intermediate_files = True

View File

@ -291,24 +291,30 @@ The storage backend automatically replaces the paths found in the saved
files matching other saved files with the path of the cached copy (using files matching other saved files with the path of the cached copy (using
the :meth:`~django.contrib.staticfiles.storage.StaticFilesStorage.post_process` the :meth:`~django.contrib.staticfiles.storage.StaticFilesStorage.post_process`
method). The regular expressions used to find those paths method). The regular expressions used to find those paths
(``django.contrib.staticfiles.storage.HashedFilesMixin.patterns``) (``django.contrib.staticfiles.storage.HashedFilesMixin.patterns``) cover:
by default covers the `@import`_ rule and `url()`_ statement of `Cascading
Style Sheets`_. For example, the ``'css/styles.css'`` file with the * The `@import`_ rule and `url()`_ statement of `Cascading Style Sheets`_.
content * The `source map`_ comment in JavaScript.
For example, the ``'css/styles.css'`` file with this content:
.. code-block:: css .. code-block:: css
@import url("../admin/css/base.css"); @import url("../admin/css/base.css");
would be replaced by calling the :meth:`~django.core.files.storage.Storage.url` ...would be replaced by calling the
method of the ``ManifestStaticFilesStorage`` storage backend, ultimately :meth:`~django.core.files.storage.Storage.url` method of the
saving a ``'css/styles.55e7cbb9ba48.css'`` file with the following ``ManifestStaticFilesStorage`` storage backend, ultimately saving a
content: ``'css/styles.55e7cbb9ba48.css'`` file with the following content:
.. code-block:: css .. code-block:: css
@import url("../admin/css/base.27e20196a850.css"); @import url("../admin/css/base.27e20196a850.css");
.. versionchanged:: 4.0
Support for finding paths in the source map comments was added.
.. attribute:: storage.ManifestStaticFilesStorage.max_post_process_passes .. attribute:: storage.ManifestStaticFilesStorage.max_post_process_passes
Since static files might reference other static files that need to have their Since static files might reference other static files that need to have their
@ -361,6 +367,7 @@ hashing algorithm.
.. _`@import`: https://www.w3.org/TR/CSS2/cascade.html#at-import .. _`@import`: https://www.w3.org/TR/CSS2/cascade.html#at-import
.. _`url()`: https://www.w3.org/TR/CSS2/syndata.html#uri .. _`url()`: https://www.w3.org/TR/CSS2/syndata.html#uri
.. _`Cascading Style Sheets`: https://www.w3.org/Style/CSS/ .. _`Cascading Style Sheets`: https://www.w3.org/Style/CSS/
.. _`source map`: https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map
``ManifestFilesMixin`` ``ManifestFilesMixin``
---------------------- ----------------------

View File

@ -136,7 +136,9 @@ Minor features
:mod:`django.contrib.staticfiles` :mod:`django.contrib.staticfiles`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ... * :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` now
replaces paths to JavaScript source map references with their hashed
counterparts.
:mod:`django.contrib.syndication` :mod:`django.contrib.syndication`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1 @@
//# sourceMappingURL=source_map.js.map

View File

@ -0,0 +1 @@
//# sOuRcEMaPpInGURL=source_map.js.map

View File

@ -216,6 +216,30 @@ class TestHashedFiles:
self.assertIn(b"other.d41d8cd98f00.css", content) self.assertIn(b"other.d41d8cd98f00.css", content)
self.assertPostCondition() self.assertPostCondition()
def test_js_source_map(self):
relpath = self.hashed_file_path('cached/source_map.js')
self.assertEqual(relpath, 'cached/source_map.9371cbb02a26.js')
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
self.assertNotIn(b'//# sourceMappingURL=source_map.js.map', content)
self.assertIn(
b'//# sourceMappingURL=source_map.js.99914b932bd3.map',
content,
)
self.assertPostCondition()
def test_js_source_map_sensitive(self):
relpath = self.hashed_file_path('cached/source_map_sensitive.js')
self.assertEqual(relpath, 'cached/source_map_sensitive.5da96fdd3cb3.js')
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
self.assertIn(b'//# sOuRcEMaPpInGURL=source_map.js.map', content)
self.assertNotIn(
b'//# sourceMappingURL=source_map.js.99914b932bd3.map',
content,
)
self.assertPostCondition()
@override_settings( @override_settings(
STATICFILES_DIRS=[os.path.join(TEST_ROOT, 'project', 'faulty')], STATICFILES_DIRS=[os.path.join(TEST_ROOT, 'project', 'faulty')],
STATICFILES_FINDERS=['django.contrib.staticfiles.finders.FileSystemFinder'], STATICFILES_FINDERS=['django.contrib.staticfiles.finders.FileSystemFinder'],