summaryrefslogtreecommitdiff
path: root/django_pyscss/scss.py
diff options
context:
space:
mode:
Diffstat (limited to 'django_pyscss/scss.py')
-rw-r--r--django_pyscss/scss.py223
1 files changed, 0 insertions, 223 deletions
diff --git a/django_pyscss/scss.py b/django_pyscss/scss.py
deleted file mode 100644
index b4c5981..0000000
--- a/django_pyscss/scss.py
+++ /dev/null
@@ -1,223 +0,0 @@
-from __future__ import absolute_import, unicode_literals
-
-import os
-from itertools import product
-
-from django.contrib.staticfiles.storage import staticfiles_storage
-from django.conf import settings
-
-from scss import (
- Scss, dequote, log, SourceFile, SassRule, config,
-)
-
-from django_pyscss.utils import find_all_files
-
-
-# TODO: It's really gross to modify this global settings variable.
-# This is where PyScss is supposed to find the image files for making sprites.
-config.STATIC_ROOT = find_all_files
-config.STATIC_URL = staticfiles_storage.url('scss/')
-
-# This is where PyScss places the sprite files.
-config.ASSETS_ROOT = os.path.join(settings.STATIC_ROOT, 'scss', 'assets')
-# PyScss expects a trailing slash.
-config.ASSETS_URL = staticfiles_storage.url('scss/assets/')
-
-
-class DjangoScss(Scss):
- """
- A subclass of the Scss compiler that uses the storages API for accessing
- files.
- """
- supported_extensions = ['.scss', '.sass', '.css']
-
- def get_file_from_storage(self, filename):
- try:
- filename = staticfiles_storage.path(filename)
- except NotImplementedError:
- # remote storages don't implement path
- pass
- if staticfiles_storage.exists(filename):
- return filename, staticfiles_storage
- else:
- return None, None
-
- def get_file_from_finders(self, filename):
- for file_and_storage in find_all_files(filename):
- return file_and_storage
- return None, None
-
- def get_file_and_storage(self, filename):
- # TODO: the switch probably shouldn't be on DEBUG
- if settings.DEBUG:
- return self.get_file_from_finders(filename)
- else:
- return self.get_file_from_storage(filename)
-
- def get_possible_import_paths(self, path, relative_to=None):
- """
- Returns an iterable of possible paths for an import.
-
- relative_to is None in the case that the SCSS is being rendered from a
- string or if it is the first file.
- """
- paths = []
-
- if path.startswith('/'): # absolute import
- path = path[1:]
- elif relative_to: # relative import
- path = os.path.join(relative_to, path)
-
- dirname, filename = os.path.split(path)
- name, ext = os.path.splitext(filename)
- if ext:
- search_exts = [ext]
- else:
- search_exts = self.supported_extensions
- for prefix, suffix in product(('_', ''), search_exts):
- paths.append(os.path.join(dirname, prefix + name + suffix))
- paths.append(path)
- return paths
-
- def _find_source_file(self, filename, relative_to=None):
- paths = self.get_possible_import_paths(filename, relative_to)
- log.debug('Searching for %s in %s', filename, paths)
- for name in paths:
- full_filename, storage = self.get_file_and_storage(name)
- if full_filename:
- if full_filename not in self.source_file_index:
- with storage.open(full_filename) as f:
- source = f.read()
-
- source_file = SourceFile(
- full_filename,
- source,
- )
- # SourceFile.__init__ calls os.path.realpath on this, we don't want
- # that, we want them to remain relative.
- source_file.parent_dir = os.path.dirname(name)
- self.source_files.append(source_file)
- self.source_file_index[full_filename] = source_file
- return self.source_file_index[full_filename]
-
- def _do_import(self, rule, scope, block):
- """
- Implements @import using the django storages API.
- """
- # Protect against going to prohibited places...
- if any(scary_token in block.argument for scary_token in ('..', '://', 'url(')):
- rule.properties.append((block.prop, None))
- return
-
- full_filename = None
- names = block.argument.split(',')
- for name in names:
- name = dequote(name.strip())
-
- relative_to = rule.source_file.parent_dir
- source_file = self._find_source_file(name, relative_to)
-
- if source_file is None:
- i_codestr = self._do_magic_import(rule, scope, block)
-
- if i_codestr is not None:
- source_file = SourceFile.from_string(i_codestr)
- self.source_files.append(source_file)
- self.source_file_index[full_filename] = source_file
-
- if source_file is None:
- log.warn("File to import not found or unreadable: '%s' (%s)", name, rule.file_and_line)
- continue
-
- import_key = (name, source_file.parent_dir)
- if rule.namespace.has_import(import_key):
- # If already imported in this scope, skip
- continue
-
- _rule = SassRule(
- source_file=source_file,
- lineno=block.lineno,
- import_key=import_key,
- unparsed_contents=source_file.contents,
-
- # rule
- options=rule.options,
- properties=rule.properties,
- extends_selectors=rule.extends_selectors,
- ancestry=rule.ancestry,
- namespace=rule.namespace,
- )
- rule.namespace.add_import(import_key, rule.import_key, rule.file_and_line)
- self.manage_children(_rule, scope)
-
- def Compilation(self, scss_string=None, scss_file=None, super_selector=None,
- filename=None, is_sass=None, line_numbers=True,
- relative_to=None):
- """
- Overwritten to call _find_source_file instead of
- SourceFile.from_filename. Also added the relative_to option.
- """
- if not os.path.exists(config.ASSETS_ROOT):
- os.makedirs(config.ASSETS_ROOT)
- if super_selector:
- self.super_selector = super_selector + ' '
- self.reset()
-
- source_file = None
- if scss_string is not None:
- source_file = SourceFile.from_string(scss_string, filename, is_sass, line_numbers)
- # Set the parent_dir to be something meaningful instead of the
- # current working directory, which is never correct for DjangoScss.
- source_file.parent_dir = relative_to
- elif scss_file is not None:
- # Call _find_source_file instead of SourceFile.from_filename
- source_file = self._find_source_file(scss_file)
-
- if source_file is not None:
- # Clear the existing list of files
- self.source_files = []
- self.source_file_index = dict()
-
- self.source_files.append(source_file)
- self.source_file_index[source_file.filename] = source_file
-
- # this will compile and manage rule: child objects inside of a node
- self.parse_children()
-
- # this will manage @extends
- self.apply_extends()
-
- rules_by_file, css_files = self.parse_properties()
-
- all_rules = 0
- all_selectors = 0
- exceeded = ''
- final_cont = ''
- files = len(css_files)
- for source_file in css_files:
- rules = rules_by_file[source_file]
- fcont, total_rules, total_selectors = self.create_css(rules)
- all_rules += total_rules
- all_selectors += total_selectors
- if not exceeded and all_selectors > 4095:
- exceeded = " (IE exceeded!)"
- log.error("Maximum number of supported selectors in Internet Explorer (4095) exceeded!")
- if files > 1 and self.scss_opts.get('debug_info', False):
- if source_file.is_string:
- final_cont += "/* %s %s generated add up to a total of %s %s accumulated%s */\n" % (
- total_selectors,
- 'selector' if total_selectors == 1 else 'selectors',
- all_selectors,
- 'selector' if all_selectors == 1 else 'selectors',
- exceeded)
- else:
- final_cont += "/* %s %s generated from '%s' add up to a total of %s %s accumulated%s */\n" % (
- total_selectors,
- 'selector' if total_selectors == 1 else 'selectors',
- source_file.filename,
- all_selectors,
- 'selector' if all_selectors == 1 else 'selectors',
- exceeded)
- final_cont += fcont
-
- return final_cont