@@ -23,6 +23,21 @@ class PipelineManifestStorage(PipelineMixin, ManifestFilesMixin, StaticFilesStor
2323 imports in comments. Ref: https://code.djangoproject.com/ticket/21080
2424 """
2525
26+ # Skip map files
27+ # https://code.djangoproject.com/ticket/33353#comment:13
28+ patterns = (
29+ (
30+ "*.css" ,
31+ (
32+ "(?P<matched>url\\ (['\" ]{0,1}\\ s*(?P<url>.*?)[\" ']{0,1}\\ ))" ,
33+ (
34+ "(?P<matched>@import\\ s*[\" ']\\ s*(?P<url>.*?)[\" '])" ,
35+ '@import url("%(url)s")' ,
36+ ),
37+ ),
38+ ),
39+ )
40+
2641 def get_comment_blocks (self , content ):
2742 """
2843 Return a list of (start, end) tuples for each comment block.
@@ -32,73 +47,85 @@ def get_comment_blocks(self, content):
3247 for match in re .finditer (r'\/\*.*?\*\/' , content , flags = re .DOTALL )
3348 ]
3449
35- def url_converter (self , name , hashed_files , template = None , comment_blocks = None ):
50+
51+ def is_in_comment (self , pos , comments ):
52+ for start , end in comments :
53+ if start < pos and pos < end :
54+ return True
55+ if pos < start :
56+ return False
57+ return False
58+
59+
60+ def url_converter (self , name , hashed_files , template = None , comment_blocks = []):
3661 """
3762 Return the custom URL converter for the given file name.
3863 """
39- if comment_blocks is None :
40- comment_blocks = []
41-
4264 if template is None :
4365 template = self .default_template
4466
4567 def converter (matchobj ):
4668 """
4769 Convert the matched URL to a normalized and hashed URL.
70+
4871 This requires figuring out which files the matched URL resolves
4972 to and calling the url() method of the storage.
5073 """
51- matched , url = matchobj .groups ()
74+ matches = matchobj .groupdict ()
75+ matched = matches ["matched" ]
76+ url = matches ["url" ]
5277
5378 # Ignore URLs in comments.
5479 if self .is_in_comment (matchobj .start (), comment_blocks ):
5580 return matched
5681
5782 # Ignore absolute/protocol-relative and data-uri URLs.
58- if re .match (r' ^[a-z]+:' , url ):
83+ if re .match (r" ^[a-z]+:" , url ):
5984 return matched
6085
6186 # Ignore absolute URLs that don't point to a static file (dynamic
6287 # CSS / JS?). Note that STATIC_URL cannot be empty.
63- if url .startswith ('/' ) and not url .startswith (settings .STATIC_URL ):
88+ if url .startswith ("/" ) and not url .startswith (settings .STATIC_URL ):
6489 return matched
6590
6691 # Strip off the fragment so a path-like fragment won't interfere.
6792 url_path , fragment = urldefrag (url )
6893
69- if url_path .startswith ('/' ):
94+ # Ignore URLs without a path
95+ if not url_path :
96+ return matched
97+
98+ if url_path .startswith ("/" ):
7099 # Otherwise the condition above would have returned prematurely.
71100 assert url_path .startswith (settings .STATIC_URL )
72- target_name = url_path [len (settings .STATIC_URL ):]
101+ target_name = url_path [len (settings .STATIC_URL ) :]
73102 else :
74103 # We're using the posixpath module to mix paths and URLs conveniently.
75- source_name = name if os .sep == '/' else name .replace (os .sep , '/' )
104+ source_name = name if os .sep == "/" else name .replace (os .sep , "/" )
76105 target_name = posixpath .join (posixpath .dirname (source_name ), url_path )
77106
78107 # Determine the hashed name of the target file with the storage backend.
79108 hashed_url = self ._url (
80- self ._stored_name , unquote (target_name ),
81- force = True , hashed_files = hashed_files ,
109+ self ._stored_name ,
110+ unquote (target_name ),
111+ force = True ,
112+ hashed_files = hashed_files ,
82113 )
83114
84- transformed_url = '/' .join (url_path .split ('/' )[:- 1 ] + hashed_url .split ('/' )[- 1 :])
115+ transformed_url = "/" .join (
116+ url_path .split ("/" )[:- 1 ] + hashed_url .split ("/" )[- 1 :]
117+ )
85118
86119 # Restore the fragment that was stripped off earlier.
87120 if fragment :
88- transformed_url += ('?#' if '?#' in url else '#' ) + fragment
121+ transformed_url += ("?#" if "?#" in url else "#" ) + fragment
89122
90123 # Return the hashed version to the file
91- return template % unquote (transformed_url )
124+ matches ["url" ] = unquote (transformed_url )
125+ return template % matches
92126
93127 return converter
94128
95- def is_in_comment (self , pos , comments ):
96- for start , end in comments :
97- if start < pos and pos < end :
98- return True
99- if pos < start :
100- return False
101- return False
102129
103130 def _post_process (self , paths , adjustable_paths , hashed_files ):
104131 # Sort the files by directory level
@@ -122,7 +149,7 @@ def path_level(name):
122149 hashed_name = hashed_files [hash_key ]
123150
124151 # then get the original's file content..
125- if hasattr (original_file , ' seek' ):
152+ if hasattr (original_file , " seek" ):
126153 original_file .seek (0 )
127154
128155 hashed_file_exists = self .exists (hashed_name )
@@ -131,12 +158,14 @@ def path_level(name):
131158 # ..to apply each replacement pattern to the content
132159 if name in adjustable_paths :
133160 old_hashed_name = hashed_name
134- content = original_file .read ().decode (settings . FILE_CHARSET )
161+ content = original_file .read ().decode ("utf-8" )
135162 for extension , patterns in self ._patterns .items ():
136163 if matches_patterns (path , (extension ,)):
137164 comment_blocks = self .get_comment_blocks (content )
138165 for pattern , template in patterns :
139- converter = self .url_converter (name , hashed_files , template , comment_blocks )
166+ converter = self .url_converter (
167+ name , hashed_files , template , comment_blocks
168+ )
140169 try :
141170 content = pattern .sub (converter , content )
142171 except ValueError as exc :
@@ -145,8 +174,9 @@ def path_level(name):
145174 self .delete (hashed_name )
146175 # then save the processed result
147176 content_file = ContentFile (content .encode ())
148- # Save intermediate file for reference
149- saved_name = self ._save (hashed_name , content_file )
177+ if self .keep_intermediate_files :
178+ # Save intermediate file for reference
179+ self ._save (hashed_name , content_file )
150180 hashed_name = self .hashed_name (name , content_file )
151181
152182 if self .exists (hashed_name ):
0 commit comments