|
1 | 1 | from __future__ import absolute_import, unicode_literals
|
2 | 2 |
|
| 3 | +import os |
3 | 4 | import fnmatch
|
4 | 5 |
|
5 | 6 | from django.contrib.staticfiles import finders
|
6 | 7 | from django.contrib.staticfiles.storage import staticfiles_storage
|
7 | 8 | from django.conf import settings
|
8 | 9 |
|
9 | 10 | from scss import (
|
10 |
| - Scss, dequote, log, spawn_rule, |
11 |
| - OPTIONS, PROPERTIES, |
| 11 | + Scss, dequote, log, SourceFile, SassRule, |
12 | 12 | )
|
13 | 13 |
|
14 | 14 |
|
@@ -42,53 +42,77 @@ def get_file_from_storage(self, filename):
|
42 | 42 | # remote storages don't implement path
|
43 | 43 | pass
|
44 | 44 | finally:
|
45 |
| - with staticfiles_storage.open(filename) as f: |
46 |
| - return f.read() |
| 45 | + return filename, staticfiles_storage |
47 | 46 |
|
48 | 47 | def get_file_from_finders(self, filename):
|
49 |
| - path, storage = find_one_file(filename) |
50 |
| - with storage.open(path) as f: |
51 |
| - return f.read() |
| 48 | + return find_one_file(filename) |
52 | 49 |
|
53 |
| - def get_file_contents(self, filename): |
| 50 | + def get_file_and_storage(self, filename): |
54 | 51 | # TODO: the switch probably shouldn't be on DEBUG
|
55 | 52 | if settings.DEBUG:
|
56 | 53 | return self.get_file_from_finders(filename)
|
57 | 54 | else:
|
58 | 55 | return self.get_file_from_storage(filename)
|
59 | 56 |
|
60 |
| - def _do_import(self, rule, p_selectors, p_parents, p_children, scope, media, c_lineno, c_property, c_codestr, code, name): |
| 57 | + def _find_source_file(self, name): |
| 58 | + full_filename, storage = self.get_file_and_storage(name) |
| 59 | + if name not in self.source_files: |
| 60 | + with storage.open(full_filename) as f: |
| 61 | + source = f.read() |
| 62 | + source_file = SourceFile( |
| 63 | + full_filename, |
| 64 | + source, |
| 65 | + parent_dir=os.path.realpath(os.path.dirname(full_filename)), |
| 66 | + ) |
| 67 | + self.source_files.append(source_file) |
| 68 | + self.source_file_index[full_filename] = source_file |
| 69 | + return self.source_file_index[full_filename] |
| 70 | + |
| 71 | + def _do_import(self, rule, scope, block): |
61 | 72 | """
|
62 | 73 | Implements @import using the django storages API.
|
63 | 74 | """
|
64 | 75 | # Protect against going to prohibited places...
|
65 |
| - if '..' in name or '://' in name or 'url(' in name: |
66 |
| - rule[PROPERTIES].append((c_lineno, c_property, None)) |
| 76 | + if any(scary_token in block.argument for scary_token in ('..', '://', 'url(')): |
| 77 | + rule.properties.append((block.prop, None)) |
67 | 78 | return
|
68 | 79 |
|
69 | 80 | full_filename = None
|
70 |
| - i_codestr = None |
71 |
| - names = name.split(',') |
72 |
| - for filename in names: |
73 |
| - filename = dequote(name.strip()) |
74 |
| - if '@import ' + filename in rule[OPTIONS]: |
| 81 | + names = block.argument.split(',') |
| 82 | + for name in names: |
| 83 | + name = dequote(name.strip()) |
| 84 | + |
| 85 | + source_file = self._find_source_file(name) |
| 86 | + |
| 87 | + if source_file is None: |
| 88 | + i_codestr = self._do_magic_import(rule, scope, block) |
| 89 | + |
| 90 | + if i_codestr is not None: |
| 91 | + source_file = SourceFile.from_string(i_codestr) |
| 92 | + self.source_files.append(source_file) |
| 93 | + self.source_file_index[full_filename] = source_file |
| 94 | + |
| 95 | + if source_file is None: |
| 96 | + log.warn("File to import not found or unreadable: '%s' (%s)", name, rule.file_and_line) |
| 97 | + continue |
| 98 | + |
| 99 | + import_key = (name, source_file.parent_dir) |
| 100 | + if rule.namespace.has_import(import_key): |
75 | 101 | # If already imported in this scope, skip
|
76 | 102 | continue
|
77 | 103 |
|
78 |
| - try: |
79 |
| - i_codestr = self.scss_files[filename] |
80 |
| - except KeyError: |
81 |
| - i_codestr = self.get_file_contents(filename) |
82 |
| - |
83 |
| - if i_codestr is None: |
84 |
| - i_codestr = self._do_magic_import(rule, p_selectors, p_parents, p_children, scope, media, c_lineno, c_property, c_codestr, code, name) |
85 |
| - if i_codestr is None: |
86 |
| - log.warn("I couldn't find this file (%s)." % filename) |
87 |
| - |
88 |
| - i_codestr = self.scss_files[name] = i_codestr and self.load_string(i_codestr, full_filename) |
89 |
| - if name not in self.scss_files: |
90 |
| - self._scss_files_order.append(name) |
91 |
| - if i_codestr is not None: |
92 |
| - _rule = spawn_rule(rule, codestr=i_codestr, path=full_filename, lineno=c_lineno) |
93 |
| - self.manage_children(_rule, p_selectors, p_parents, p_children, scope, media) |
94 |
| - rule[OPTIONS]['@import ' + name] = True |
| 104 | + _rule = SassRule( |
| 105 | + source_file=source_file, |
| 106 | + lineno=block.lineno, |
| 107 | + import_key=import_key, |
| 108 | + unparsed_contents=source_file.contents, |
| 109 | + |
| 110 | + # rule |
| 111 | + options=rule.options, |
| 112 | + properties=rule.properties, |
| 113 | + extends_selectors=rule.extends_selectors, |
| 114 | + ancestry=rule.ancestry, |
| 115 | + namespace=rule.namespace, |
| 116 | + ) |
| 117 | + rule.namespace.add_import(import_key, rule.import_key, rule.file_and_line) |
| 118 | + self.manage_children(_rule, scope) |
0 commit comments