@@ -23,6 +23,21 @@ class PipelineManifestStorage(PipelineMixin, ManifestFilesMixin, StaticFilesStor
23
23
imports in comments. Ref: https://code.djangoproject.com/ticket/21080
24
24
"""
25
25
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
+
26
41
def get_comment_blocks (self , content ):
27
42
"""
28
43
Return a list of (start, end) tuples for each comment block.
@@ -32,73 +47,85 @@ def get_comment_blocks(self, content):
32
47
for match in re .finditer (r'\/\*.*?\*\/' , content , flags = re .DOTALL )
33
48
]
34
49
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 = []):
36
61
"""
37
62
Return the custom URL converter for the given file name.
38
63
"""
39
- if comment_blocks is None :
40
- comment_blocks = []
41
-
42
64
if template is None :
43
65
template = self .default_template
44
66
45
67
def converter (matchobj ):
46
68
"""
47
69
Convert the matched URL to a normalized and hashed URL.
70
+
48
71
This requires figuring out which files the matched URL resolves
49
72
to and calling the url() method of the storage.
50
73
"""
51
- matched , url = matchobj .groups ()
74
+ matches = matchobj .groupdict ()
75
+ matched = matches ["matched" ]
76
+ url = matches ["url" ]
52
77
53
78
# Ignore URLs in comments.
54
79
if self .is_in_comment (matchobj .start (), comment_blocks ):
55
80
return matched
56
81
57
82
# Ignore absolute/protocol-relative and data-uri URLs.
58
- if re .match (r' ^[a-z]+:' , url ):
83
+ if re .match (r" ^[a-z]+:" , url ):
59
84
return matched
60
85
61
86
# Ignore absolute URLs that don't point to a static file (dynamic
62
87
# 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 ):
64
89
return matched
65
90
66
91
# Strip off the fragment so a path-like fragment won't interfere.
67
92
url_path , fragment = urldefrag (url )
68
93
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 ("/" ):
70
99
# Otherwise the condition above would have returned prematurely.
71
100
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 ) :]
73
102
else :
74
103
# 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 , "/" )
76
105
target_name = posixpath .join (posixpath .dirname (source_name ), url_path )
77
106
78
107
# Determine the hashed name of the target file with the storage backend.
79
108
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 ,
82
113
)
83
114
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
+ )
85
118
86
119
# Restore the fragment that was stripped off earlier.
87
120
if fragment :
88
- transformed_url += ('?#' if '?#' in url else '#' ) + fragment
121
+ transformed_url += ("?#" if "?#" in url else "#" ) + fragment
89
122
90
123
# Return the hashed version to the file
91
- return template % unquote (transformed_url )
124
+ matches ["url" ] = unquote (transformed_url )
125
+ return template % matches
92
126
93
127
return converter
94
128
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
102
129
103
130
def _post_process (self , paths , adjustable_paths , hashed_files ):
104
131
# Sort the files by directory level
@@ -122,7 +149,7 @@ def path_level(name):
122
149
hashed_name = hashed_files [hash_key ]
123
150
124
151
# then get the original's file content..
125
- if hasattr (original_file , ' seek' ):
152
+ if hasattr (original_file , " seek" ):
126
153
original_file .seek (0 )
127
154
128
155
hashed_file_exists = self .exists (hashed_name )
@@ -131,12 +158,14 @@ def path_level(name):
131
158
# ..to apply each replacement pattern to the content
132
159
if name in adjustable_paths :
133
160
old_hashed_name = hashed_name
134
- content = original_file .read ().decode (settings . FILE_CHARSET )
161
+ content = original_file .read ().decode ("utf-8" )
135
162
for extension , patterns in self ._patterns .items ():
136
163
if matches_patterns (path , (extension ,)):
137
164
comment_blocks = self .get_comment_blocks (content )
138
165
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
+ )
140
169
try :
141
170
content = pattern .sub (converter , content )
142
171
except ValueError as exc :
@@ -145,8 +174,9 @@ def path_level(name):
145
174
self .delete (hashed_name )
146
175
# then save the processed result
147
176
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 )
150
180
hashed_name = self .hashed_name (name , content_file )
151
181
152
182
if self .exists (hashed_name ):
0 commit comments