django-sass-processor-0.5.4/0000755000076500000240000000000013053557767016212 5ustar jriefstaff00000000000000django-sass-processor-0.5.4/django_sass_processor.egg-info/0000755000076500000240000000000013053557767024276 5ustar jriefstaff00000000000000django-sass-processor-0.5.4/django_sass_processor.egg-info/dependency_links.txt0000644000076500000240000000000113053557767030344 0ustar jriefstaff00000000000000 django-sass-processor-0.5.4/django_sass_processor.egg-info/not-zip-safe0000644000076500000240000000000112604774424026514 0ustar jriefstaff00000000000000 django-sass-processor-0.5.4/django_sass_processor.egg-info/PKG-INFO0000644000076500000240000004233413053557767025401 0ustar jriefstaff00000000000000Metadata-Version: 1.1 Name: django-sass-processor Version: 0.5.4 Summary: SASS processor to compile SCSS files into *.css, while rendering, or offline. Home-page: https://github.com/jrief/django-sass-processor Author: Jacob Rief Author-email: jacob.rief@gmail.com License: LICENSE-MIT Description: django-sass-processor ===================== Processor to compile files from markup languages such as SASS/SCSS. **django-sass-processor** converts ``*.scss`` or ``*.sass`` files into ``*.css`` while rendering templates. For performance reasons this is done only once, since the preprocessor keeps track on the timestamps and only recompiles, if any of the imported SASS/SCSS files is younger than the corresponding generated CSS file. Introduction ------------ This Django app provides a templatetag ``{% sass_src 'path/to/file.scss' %}``, which can be used instead of the built-in templatetag ``static``. Since version 0.3.4 this also works for Jinja2 templates. If SASS/SCSS files shall be referenced through the ``Media`` class, or ``media`` property, the SASS processor can be used directly. Additionally, **django-sass-processor** is shipped with a management command, which can convert the content of all occurrences inside the templatetag ``sass_src`` as an offline operation. Hence the **libsass** compiler is not required in a production environment. During development, a `sourcemap `__ is generated along side with the compiled ``*.css`` file. This allows to debug style sheet errors much easier. With this tool, you can safely remove your Ruby installations "Compass" and "SASS" from your Django projects. You neither need any directory "watching" daemons based on node.js. Project's Home -------------- On GitHub: https://github.com/jrief/django-sass-processor Please use the issue tracker to report bugs or propose new features. Installation ------------ :: pip install libsass django-compressor django-sass-processor ``django-compressor`` is required only for offline compilation, when using the command ``manage.py compilescss``. ``libsass`` is not required on the production environment, if SASS/SCSS files have been precompiled and deployed using offline compilation. Configuration ------------- In ``settings.py`` add to: .. code:: python INSTALLED_APPS = [ ... 'sass_processor', ... ] Optionally, add a list of additional search paths, the SASS compiler may examine when using the ``@import "...";`` statement in SASS/SCSS files: .. code:: python import os SASS_PROCESSOR_INCLUDE_DIRS = [ os.path.join(PROJECT_PATH, 'extra-styles/scss'), os.path.join(PROJECT_PATH, 'node_modules'), ] Additionally, **django-sass-processor** will traverse all installed Django apps (``INSTALLED_APPS``) and look into their static folders. If any of them contain a file matching the regular expression pattern ``^_.+\.(scss|sass)$`` (read: filename starts with an underscore and is of type ``scss`` or ``sass``), then that app specific static folder is added to the **libsass** include dirs. This feature can be disabled in your settings with .. code:: python SASS_PROCESSOR_AUTO_INCLUDE = False If inside of your SASS/SCSS files you also want to import (using ``@import "path/to/scssfile";``) files which do not start with an underscore, then you can configure another pattern in your settings, for instance .. code:: python SASS_PROCESSOR_INCLUDE_FILE_PATTERN = r'^.+\.scss$' will look for all files of type ``scss``. Remember that SASS/SCSS files which start with an underscore are intended to be imported by other SASS/SCSS files, while files starting with a letter are intended to be included by the HTML tag ````. During development, or when ``SASS_PROCESSOR_ENABLED = True``, the compiled file is placed into the folder referenced by ``SASS_PROCESSOR_ROOT`` (if unset, this setting defaults to ``STATIC_ROOT``). Having a location outside of the working directory prevents to pollute your local ``static/css/...`` directories with auto-generated files. Therefore assure, that this directory is writable by the Django runserver. **django-sass-processor** is shipped with a special finder, to locate the generated ``*.css`` files in the directory referred by ``SASS_PROCESSOR_ROOT`` (or, if unset ``STATIC_ROOT``). Just add it to your ``settings.py``. If there is no ``STATICFILES_FINDERS`` in your ``settings.py`` don't forget to include the **Django** `default finders `__. .. code:: python STATICFILES_FINDERS = [ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'sass_processor.finders.CssFinder', ... ] Fine tune SASS compiler parameters in ``settings.py``. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Integer ``SASS_PRECISION`` sets floating point precision for output css. libsass' default is ``5``. Note: **bootstrap-sass** requires ``8``, otherwise various layout problems *will* occur. :: SASS_PRECISION = 8 ``SASS_OUTPUT_STYLE`` sets coding style of the compiled result, one of ``compact``, ``compressed``, ``expanded``, or ``nested``. Default is ``nested`` for ``DEBUG`` and ``compressed`` in production. Note: **libsass-python** 0.8.3 has `problem encoding result while saving on Windows `__, the issue is already fixed and will be included in future ``pip`` package release, in the meanwhile avoid ``compressed`` output style. :: SASS_OUTPUT_STYLE = 'compact' Jinja2 support ~~~~~~~~~~~~~~ ``sass_processor.jinja2.ext.SassSrc`` is a Jinja2 extension. Add it to your Jinja2 environment to enable the tag ``sass_src``, there is no need for a ``load`` tag. Example of how to add your Jinja2 environment to Django: In ``settings.py``: .. code:: python TEMPLATES = [{ 'BACKEND': 'django.template.backends.jinja2.Jinja2', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'environment': 'yourapp.jinja2.environment' }, ... }] Make sure to add the default template backend, if you're still using Django templates elsewhere. This is covered in the `Upgrading templates documentation `__. In ``yourapp/jinja2.py``: .. code:: python from jinja2 import Environment def environment(**kwargs): extensions = [] if 'extensions' not in kwargs else kwargs['extensions'] extensions.append('sass_processor.jinja2.ext.SassSrc') kwargs['extensions'] = extensions return Environment(**kwargs) Usage ----- In your Django templates ~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: django {% load sass_tags %} The above template code will be rendered as HTML .. code:: html You can safely use this templatetag inside a Sekizai's ``{% addtoblock "css" %}`` statement. In Media classes or properties ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In Python code, you can access the API of the SASS processor directly. This for instance is useful in Django's admin or form framework. .. code:: python from sass_processor.processor import sass_processor class SomeAdminOrFormClass(...): ... class Media: css = { 'all': (sass_processor('myapp/css/mystyle.scss'),) } Offline compilation ------------------- If you want to precompile all occurrences of your SASS/SCSS files for the whole project, on the command line invoke: :: ./manage.py compilescss This is useful for preparing production environments, where SASS/SCSS files can't be compiled on the fly. To simplify the deployment, the compiled ``*.css`` files are stored side-by-side with their corresponding SASS/SCSS files; just run :: ./manage.py collectstatic afterwards. In case you don't want to expose the SASS/SCSS files in a production environment, deploy with :: ./manage.py collectstatic --ignore=.scss In case you want to get rid of the compiled ``*.css`` files in your local static directories, simply reverse the above command: :: ./manage.py compilescss --delete-files This will remove all occurrences of previously generated ``*.css`` files. Or you may direct compile results to the ``SASS_PROCESSOR_ROOT`` directory (if not specified - to ``STATIC_ROOT``): :: ./manage.py compilescss --use-processor-root Combine with ``--delete-files`` switch to purge results from there. If you use an alternative templating engine set its name in ``--engine`` argument. Currently ``django`` and ``jinja2`` are supported, see `django-compressor documentation `__ on how to set up ``COMPRESS_JINJA2_GET_ENVIRONMENT`` to configure jinja2 engine support. During offline compilation **django-sass-processor** parses all Python files and looks for invokations of ``sass_processor('path/to/sassfile.scss')``. Therefore the string specifying the filename must be hard coded and shall not be concatenated or being somehow generated. Alternative templates ~~~~~~~~~~~~~~~~~~~~~ By default, **django-sass-processor** will locate SASS/SCSS files from .html templates, but you can extend or override this behavior in your settings with: .. code:: python SASS_TEMPLATE_EXTS = ['.html','.jade'] Configure SASS variables through settings.py -------------------------------------------- In SASS, a nasty problem is to set the correct include paths for icons and fonts. Normally this is done through a ``_variables.scss`` file, but this inhibits a configuration through your projects ``settings.py``. To avoid the need for duplicate configuration settings, **django-sass-processor** offers a SASS function to fetch any arbitrary configuration from the project's ``settings.py``. This is specially handy for setting the include path of your Glyphicons font directory. Assume, Bootstrap-SASS has been installed using: :: npm install bootstrap-sass then locate the directory named ``node_modules`` and add it to your settings, so that your fonts are accessible through the Django's ``django.contrib.staticfiles.finders.FileSystemFinder``: .. code:: python STATICFILES_DIRS = [ ... ('node_modules', '/path/to/your/project/node_modules/'), ... ] NODE_MODULES_URL = STATIC_URL + 'node_modules/' With the SASS function ``get-setting``, you now can override any SASS variable with a configurable value. For the Glyphicons font search path, add this to your ``_variables.scss``: :: $icon-font-path: unquote(get-setting(NODE_MODULES_URL) + "bootstrap-sass/assets/fonts/bootstrap/"); and ``@import "variables";`` whenever you need Glyphicons. You then can safely remove any font references, such as ```` from you HTML templates. Changelog --------- - 0.5.3 - Fixed compilescss: Did not find calls of sass\_processor within a dict, list or tuple - 0.5.2 - Fixed Python 3 incompatibility. Open files as binaries, since they may contain unicode characters. - 0.5.1 - Add ``APPS_INCLUDE_DIRS`` to the SASS include path. - 0.5.0 - SASS/SCSS files can also be referenced in pure Python files, for instance in ``Media`` class or ``media`` property definitions. - The SASS processor will look for potential include directories, so that the ``@import "..."`` statement also works for SASS files located in other Django apps. - 0.4.0 - 0.4.4 - Refactored the sass processor into a self-contained class ``SassProcessor``, which can be accessed through an API, the Jinja2 template engine and the existing templatetag. - 0.3.5 - Added Jinja2 support, see `Jinja2 support <#jinja2-support>`__. - 0.3.4 - Fixed: ``get_template_sources()`` in Django-1.9 returns Objects rather than strings. - In command, use ``ArgumentParser`` rather than ``OptionParser``. - 0.3.1...0.3.3 - Changed the build process in ``setup.py``. - 0.3.0 - Compatible with Django 1.8+. - bootstrap3-sass ready: appropriate floating point precision (8) can be set in ``settings.py``. - Offline compilation results may optionally be stored in ``SASS_PROCESSOR_ROOT``. - 0.2.6 - Hotfix: added SASS function ``get-setting`` also to offline compiler. - 0.2.5 - Compatible with Python3 - Replaced ``SortedDict`` with ``OrderedDict`` to be prepared for Django-1.9 - Raise a ``TemplateSyntax`` error, if a SASS ``@include "..."`` fails to find the file. - Added SASS function ``get-setting`` to fetch configuration directives from ``settings.py``. - 0.2.4 - Forcing compiled unicode to bytes, since 'Font Awesome' uses Unicode Private Use Area (PUA) and hence implicit conversion on ``fh.write()`` failed. - 0.2.3 - Allow for setting template extensions and output style. - Force Django to calculate template\_source\_loaders from TEMPLATE\_LOADERS settings, by asking to find a dummy template. - 0.2.0 - Removed dependency to **django-sekizai** and **django-classy-tags**. It now can operate in stand-alone mode. Therefore the project has been renamed to **django-sass-processor**. - 0.1.0 - Initial revision named **django-sekizai-processors**, based on a preprocessor for the Sekizai template tags ``{% addtoblock %}``. Platform: OS Independent Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Framework :: Django Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 django-sass-processor-0.5.4/django_sass_processor.egg-info/requires.txt0000644000076500000240000000001013053557767026665 0ustar jriefstaff00000000000000libsass django-sass-processor-0.5.4/django_sass_processor.egg-info/SOURCES.txt0000644000076500000240000000214413053557767026163 0ustar jriefstaff00000000000000LICENSE-MIT MANIFEST.in README.md setup.py django_sass_processor.egg-info/PKG-INFO django_sass_processor.egg-info/SOURCES.txt django_sass_processor.egg-info/dependency_links.txt django_sass_processor.egg-info/not-zip-safe django_sass_processor.egg-info/requires.txt django_sass_processor.egg-info/top_level.txt sass_processor/__init__.py sass_processor/__init__.pyc sass_processor/apps.py sass_processor/apps.pyc sass_processor/finders.py sass_processor/finders.pyc sass_processor/processor.py sass_processor/processor.pyc sass_processor/storage.py sass_processor/storage.pyc sass_processor/utils.py sass_processor/utils.pyc sass_processor/jinja2/__init__.py sass_processor/jinja2/ext.py sass_processor/management/__init__.py sass_processor/management/__init__.pyc sass_processor/management/commands/__init__.py sass_processor/management/commands/__init__.pyc sass_processor/management/commands/compilescss.py sass_processor/management/commands/compilescss.pyc sass_processor/templatetags/__init__.py sass_processor/templatetags/__init__.pyc sass_processor/templatetags/sass_tags.py sass_processor/templatetags/sass_tags.pycdjango-sass-processor-0.5.4/django_sass_processor.egg-info/top_level.txt0000644000076500000240000000001713053557767027026 0ustar jriefstaff00000000000000sass_processor django-sass-processor-0.5.4/LICENSE-MIT0000644000076500000240000000206612604774407017643 0ustar jriefstaff00000000000000The MIT License (MIT) Copyright (c) 2015 Jacob Rief Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. django-sass-processor-0.5.4/MANIFEST.in0000644000076500000240000000011112604774407017732 0ustar jriefstaff00000000000000include LICENSE-MIT include README.md recursive-include sass_processor * django-sass-processor-0.5.4/PKG-INFO0000644000076500000240000004233413053557767017315 0ustar jriefstaff00000000000000Metadata-Version: 1.1 Name: django-sass-processor Version: 0.5.4 Summary: SASS processor to compile SCSS files into *.css, while rendering, or offline. Home-page: https://github.com/jrief/django-sass-processor Author: Jacob Rief Author-email: jacob.rief@gmail.com License: LICENSE-MIT Description: django-sass-processor ===================== Processor to compile files from markup languages such as SASS/SCSS. **django-sass-processor** converts ``*.scss`` or ``*.sass`` files into ``*.css`` while rendering templates. For performance reasons this is done only once, since the preprocessor keeps track on the timestamps and only recompiles, if any of the imported SASS/SCSS files is younger than the corresponding generated CSS file. Introduction ------------ This Django app provides a templatetag ``{% sass_src 'path/to/file.scss' %}``, which can be used instead of the built-in templatetag ``static``. Since version 0.3.4 this also works for Jinja2 templates. If SASS/SCSS files shall be referenced through the ``Media`` class, or ``media`` property, the SASS processor can be used directly. Additionally, **django-sass-processor** is shipped with a management command, which can convert the content of all occurrences inside the templatetag ``sass_src`` as an offline operation. Hence the **libsass** compiler is not required in a production environment. During development, a `sourcemap `__ is generated along side with the compiled ``*.css`` file. This allows to debug style sheet errors much easier. With this tool, you can safely remove your Ruby installations "Compass" and "SASS" from your Django projects. You neither need any directory "watching" daemons based on node.js. Project's Home -------------- On GitHub: https://github.com/jrief/django-sass-processor Please use the issue tracker to report bugs or propose new features. Installation ------------ :: pip install libsass django-compressor django-sass-processor ``django-compressor`` is required only for offline compilation, when using the command ``manage.py compilescss``. ``libsass`` is not required on the production environment, if SASS/SCSS files have been precompiled and deployed using offline compilation. Configuration ------------- In ``settings.py`` add to: .. code:: python INSTALLED_APPS = [ ... 'sass_processor', ... ] Optionally, add a list of additional search paths, the SASS compiler may examine when using the ``@import "...";`` statement in SASS/SCSS files: .. code:: python import os SASS_PROCESSOR_INCLUDE_DIRS = [ os.path.join(PROJECT_PATH, 'extra-styles/scss'), os.path.join(PROJECT_PATH, 'node_modules'), ] Additionally, **django-sass-processor** will traverse all installed Django apps (``INSTALLED_APPS``) and look into their static folders. If any of them contain a file matching the regular expression pattern ``^_.+\.(scss|sass)$`` (read: filename starts with an underscore and is of type ``scss`` or ``sass``), then that app specific static folder is added to the **libsass** include dirs. This feature can be disabled in your settings with .. code:: python SASS_PROCESSOR_AUTO_INCLUDE = False If inside of your SASS/SCSS files you also want to import (using ``@import "path/to/scssfile";``) files which do not start with an underscore, then you can configure another pattern in your settings, for instance .. code:: python SASS_PROCESSOR_INCLUDE_FILE_PATTERN = r'^.+\.scss$' will look for all files of type ``scss``. Remember that SASS/SCSS files which start with an underscore are intended to be imported by other SASS/SCSS files, while files starting with a letter are intended to be included by the HTML tag ````. During development, or when ``SASS_PROCESSOR_ENABLED = True``, the compiled file is placed into the folder referenced by ``SASS_PROCESSOR_ROOT`` (if unset, this setting defaults to ``STATIC_ROOT``). Having a location outside of the working directory prevents to pollute your local ``static/css/...`` directories with auto-generated files. Therefore assure, that this directory is writable by the Django runserver. **django-sass-processor** is shipped with a special finder, to locate the generated ``*.css`` files in the directory referred by ``SASS_PROCESSOR_ROOT`` (or, if unset ``STATIC_ROOT``). Just add it to your ``settings.py``. If there is no ``STATICFILES_FINDERS`` in your ``settings.py`` don't forget to include the **Django** `default finders `__. .. code:: python STATICFILES_FINDERS = [ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'sass_processor.finders.CssFinder', ... ] Fine tune SASS compiler parameters in ``settings.py``. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Integer ``SASS_PRECISION`` sets floating point precision for output css. libsass' default is ``5``. Note: **bootstrap-sass** requires ``8``, otherwise various layout problems *will* occur. :: SASS_PRECISION = 8 ``SASS_OUTPUT_STYLE`` sets coding style of the compiled result, one of ``compact``, ``compressed``, ``expanded``, or ``nested``. Default is ``nested`` for ``DEBUG`` and ``compressed`` in production. Note: **libsass-python** 0.8.3 has `problem encoding result while saving on Windows `__, the issue is already fixed and will be included in future ``pip`` package release, in the meanwhile avoid ``compressed`` output style. :: SASS_OUTPUT_STYLE = 'compact' Jinja2 support ~~~~~~~~~~~~~~ ``sass_processor.jinja2.ext.SassSrc`` is a Jinja2 extension. Add it to your Jinja2 environment to enable the tag ``sass_src``, there is no need for a ``load`` tag. Example of how to add your Jinja2 environment to Django: In ``settings.py``: .. code:: python TEMPLATES = [{ 'BACKEND': 'django.template.backends.jinja2.Jinja2', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'environment': 'yourapp.jinja2.environment' }, ... }] Make sure to add the default template backend, if you're still using Django templates elsewhere. This is covered in the `Upgrading templates documentation `__. In ``yourapp/jinja2.py``: .. code:: python from jinja2 import Environment def environment(**kwargs): extensions = [] if 'extensions' not in kwargs else kwargs['extensions'] extensions.append('sass_processor.jinja2.ext.SassSrc') kwargs['extensions'] = extensions return Environment(**kwargs) Usage ----- In your Django templates ~~~~~~~~~~~~~~~~~~~~~~~~ .. code:: django {% load sass_tags %} The above template code will be rendered as HTML .. code:: html You can safely use this templatetag inside a Sekizai's ``{% addtoblock "css" %}`` statement. In Media classes or properties ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In Python code, you can access the API of the SASS processor directly. This for instance is useful in Django's admin or form framework. .. code:: python from sass_processor.processor import sass_processor class SomeAdminOrFormClass(...): ... class Media: css = { 'all': (sass_processor('myapp/css/mystyle.scss'),) } Offline compilation ------------------- If you want to precompile all occurrences of your SASS/SCSS files for the whole project, on the command line invoke: :: ./manage.py compilescss This is useful for preparing production environments, where SASS/SCSS files can't be compiled on the fly. To simplify the deployment, the compiled ``*.css`` files are stored side-by-side with their corresponding SASS/SCSS files; just run :: ./manage.py collectstatic afterwards. In case you don't want to expose the SASS/SCSS files in a production environment, deploy with :: ./manage.py collectstatic --ignore=.scss In case you want to get rid of the compiled ``*.css`` files in your local static directories, simply reverse the above command: :: ./manage.py compilescss --delete-files This will remove all occurrences of previously generated ``*.css`` files. Or you may direct compile results to the ``SASS_PROCESSOR_ROOT`` directory (if not specified - to ``STATIC_ROOT``): :: ./manage.py compilescss --use-processor-root Combine with ``--delete-files`` switch to purge results from there. If you use an alternative templating engine set its name in ``--engine`` argument. Currently ``django`` and ``jinja2`` are supported, see `django-compressor documentation `__ on how to set up ``COMPRESS_JINJA2_GET_ENVIRONMENT`` to configure jinja2 engine support. During offline compilation **django-sass-processor** parses all Python files and looks for invokations of ``sass_processor('path/to/sassfile.scss')``. Therefore the string specifying the filename must be hard coded and shall not be concatenated or being somehow generated. Alternative templates ~~~~~~~~~~~~~~~~~~~~~ By default, **django-sass-processor** will locate SASS/SCSS files from .html templates, but you can extend or override this behavior in your settings with: .. code:: python SASS_TEMPLATE_EXTS = ['.html','.jade'] Configure SASS variables through settings.py -------------------------------------------- In SASS, a nasty problem is to set the correct include paths for icons and fonts. Normally this is done through a ``_variables.scss`` file, but this inhibits a configuration through your projects ``settings.py``. To avoid the need for duplicate configuration settings, **django-sass-processor** offers a SASS function to fetch any arbitrary configuration from the project's ``settings.py``. This is specially handy for setting the include path of your Glyphicons font directory. Assume, Bootstrap-SASS has been installed using: :: npm install bootstrap-sass then locate the directory named ``node_modules`` and add it to your settings, so that your fonts are accessible through the Django's ``django.contrib.staticfiles.finders.FileSystemFinder``: .. code:: python STATICFILES_DIRS = [ ... ('node_modules', '/path/to/your/project/node_modules/'), ... ] NODE_MODULES_URL = STATIC_URL + 'node_modules/' With the SASS function ``get-setting``, you now can override any SASS variable with a configurable value. For the Glyphicons font search path, add this to your ``_variables.scss``: :: $icon-font-path: unquote(get-setting(NODE_MODULES_URL) + "bootstrap-sass/assets/fonts/bootstrap/"); and ``@import "variables";`` whenever you need Glyphicons. You then can safely remove any font references, such as ```` from you HTML templates. Changelog --------- - 0.5.3 - Fixed compilescss: Did not find calls of sass\_processor within a dict, list or tuple - 0.5.2 - Fixed Python 3 incompatibility. Open files as binaries, since they may contain unicode characters. - 0.5.1 - Add ``APPS_INCLUDE_DIRS`` to the SASS include path. - 0.5.0 - SASS/SCSS files can also be referenced in pure Python files, for instance in ``Media`` class or ``media`` property definitions. - The SASS processor will look for potential include directories, so that the ``@import "..."`` statement also works for SASS files located in other Django apps. - 0.4.0 - 0.4.4 - Refactored the sass processor into a self-contained class ``SassProcessor``, which can be accessed through an API, the Jinja2 template engine and the existing templatetag. - 0.3.5 - Added Jinja2 support, see `Jinja2 support <#jinja2-support>`__. - 0.3.4 - Fixed: ``get_template_sources()`` in Django-1.9 returns Objects rather than strings. - In command, use ``ArgumentParser`` rather than ``OptionParser``. - 0.3.1...0.3.3 - Changed the build process in ``setup.py``. - 0.3.0 - Compatible with Django 1.8+. - bootstrap3-sass ready: appropriate floating point precision (8) can be set in ``settings.py``. - Offline compilation results may optionally be stored in ``SASS_PROCESSOR_ROOT``. - 0.2.6 - Hotfix: added SASS function ``get-setting`` also to offline compiler. - 0.2.5 - Compatible with Python3 - Replaced ``SortedDict`` with ``OrderedDict`` to be prepared for Django-1.9 - Raise a ``TemplateSyntax`` error, if a SASS ``@include "..."`` fails to find the file. - Added SASS function ``get-setting`` to fetch configuration directives from ``settings.py``. - 0.2.4 - Forcing compiled unicode to bytes, since 'Font Awesome' uses Unicode Private Use Area (PUA) and hence implicit conversion on ``fh.write()`` failed. - 0.2.3 - Allow for setting template extensions and output style. - Force Django to calculate template\_source\_loaders from TEMPLATE\_LOADERS settings, by asking to find a dummy template. - 0.2.0 - Removed dependency to **django-sekizai** and **django-classy-tags**. It now can operate in stand-alone mode. Therefore the project has been renamed to **django-sass-processor**. - 0.1.0 - Initial revision named **django-sekizai-processors**, based on a preprocessor for the Sekizai template tags ``{% addtoblock %}``. Platform: OS Independent Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Framework :: Django Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 django-sass-processor-0.5.4/README.md0000644000076500000240000003101113023136060017435 0ustar jriefstaff00000000000000# django-sass-processor Processor to compile files from markup languages such as SASS/SCSS. **django-sass-processor** converts ``*.scss`` or ``*.sass`` files into ``*.css`` while rendering templates. For performance reasons this is done only once, since the preprocessor keeps track on the timestamps and only recompiles, if any of the imported SASS/SCSS files is younger than the corresponding generated CSS file. ## Introduction This Django app provides a templatetag ``{% sass_src 'path/to/file.scss' %}``, which can be used instead of the built-in templatetag ``static``. Since version 0.3.4 this also works for Jinja2 templates. If SASS/SCSS files shall be referenced through the ``Media`` class, or ``media`` property, the SASS processor can be used directly. Additionally, **django-sass-processor** is shipped with a management command, which can convert the content of all occurrences inside the templatetag ``sass_src`` as an offline operation. Hence the **libsass** compiler is not required in a production environment. During development, a [sourcemap](https://developer.chrome.com/devtools/docs/css-preprocessors) is generated along side with the compiled ``*.css`` file. This allows to debug style sheet errors much easier. With this tool, you can safely remove your Ruby installations "Compass" and "SASS" from your Django projects. You neither need any directory "watching" daemons based on node.js. ## Project's Home On GitHub: https://github.com/jrief/django-sass-processor Please use the issue tracker to report bugs or propose new features. ## Installation ``` pip install libsass django-compressor django-sass-processor ``` ``django-compressor`` is required only for offline compilation, when using the command ``manage.py compilescss``. ``libsass`` is not required on the production environment, if SASS/SCSS files have been precompiled and deployed using offline compilation. ## Configuration In ``settings.py`` add to: ```python INSTALLED_APPS = [ ... 'sass_processor', ... ] ``` Optionally, add a list of additional search paths, the SASS compiler may examine when using the ``@import "...";`` statement in SASS/SCSS files: ```python import os SASS_PROCESSOR_INCLUDE_DIRS = [ os.path.join(PROJECT_PATH, 'extra-styles/scss'), os.path.join(PROJECT_PATH, 'node_modules'), ] ``` Additionally, **django-sass-processor** will traverse all installed Django apps (``INSTALLED_APPS``) and look into their static folders. If any of them contain a file matching the regular expression pattern ``^_.+\.(scss|sass)$`` (read: filename starts with an underscore and is of type ``scss`` or ``sass``), then that app specific static folder is added to the **libsass** include dirs. This feature can be disabled in your settings with ```python SASS_PROCESSOR_AUTO_INCLUDE = False ``` If inside of your SASS/SCSS files you also want to import (using ``@import "path/to/scssfile";``) files which do not start with an underscore, then you can configure another pattern in your settings, for instance ```python SASS_PROCESSOR_INCLUDE_FILE_PATTERN = r'^.+\.scss$' ``` will look for all files of type ``scss``. Remember that SASS/SCSS files which start with an underscore are intended to be imported by other SASS/SCSS files, while files starting with a letter are intended to be included by the HTML tag ````. During development, or when ``SASS_PROCESSOR_ENABLED = True``, the compiled file is placed into the folder referenced by ``SASS_PROCESSOR_ROOT`` (if unset, this setting defaults to ``STATIC_ROOT``). Having a location outside of the working directory prevents to pollute your local ``static/css/...`` directories with auto-generated files. Therefore assure, that this directory is writable by the Django runserver. **django-sass-processor** is shipped with a special finder, to locate the generated ``*.css`` files in the directory referred by ``SASS_PROCESSOR_ROOT`` (or, if unset ``STATIC_ROOT``). Just add it to your ``settings.py``. If there is no ``STATICFILES_FINDERS`` in your ``settings.py`` don't forget to include the **Django** [default finders](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-STATICFILES_FINDERS). ```python STATICFILES_FINDERS = [ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'sass_processor.finders.CssFinder', ... ] ``` #### Fine tune SASS compiler parameters in ``settings.py``. Integer `SASS_PRECISION` sets floating point precision for output css. libsass' default is ``5``. Note: **bootstrap-sass** requires ``8``, otherwise various layout problems _will_ occur. ``` SASS_PRECISION = 8 ``` `SASS_OUTPUT_STYLE` sets coding style of the compiled result, one of ``compact``, ``compressed``, ``expanded``, or ``nested``. Default is ``nested`` for ``DEBUG`` and ``compressed`` in production. Note: **libsass-python** 0.8.3 has [problem encoding result while saving on Windows](https://github.com/dahlia/libsass-python/pull/82), the issue is already fixed and will be included in future `pip` package release, in the meanwhile avoid ``compressed`` output style. ``` SASS_OUTPUT_STYLE = 'compact' ``` ### Jinja2 support `sass_processor.jinja2.ext.SassSrc` is a Jinja2 extension. Add it to your Jinja2 environment to enable the tag `sass_src`, there is no need for a `load` tag. Example of how to add your Jinja2 environment to Django: In `settings.py`: ```python TEMPLATES = [{ 'BACKEND': 'django.template.backends.jinja2.Jinja2', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'environment': 'yourapp.jinja2.environment' }, ... }] ``` Make sure to add the default template backend, if you're still using Django templates elsewhere. This is covered in the [Upgrading templates documentation](https://docs.djangoproject.com/en/stable/ref/templates/upgrading/). In `yourapp/jinja2.py`: ```python from jinja2 import Environment def environment(**kwargs): extensions = [] if 'extensions' not in kwargs else kwargs['extensions'] extensions.append('sass_processor.jinja2.ext.SassSrc') kwargs['extensions'] = extensions return Environment(**kwargs) ``` ## Usage ### In your Django templates ```django {% load sass_tags %} ``` The above template code will be rendered as HTML ```html ``` You can safely use this templatetag inside a Sekizai's ``{% addtoblock "css" %}`` statement. ### In Media classes or properties In Python code, you can access the API of the SASS processor directly. This for instance is useful in Django's admin or form framework. ```python from sass_processor.processor import sass_processor class SomeAdminOrFormClass(...): ... class Media: css = { 'all': (sass_processor('myapp/css/mystyle.scss'),) } ``` ## Offline compilation If you want to precompile all occurrences of your SASS/SCSS files for the whole project, on the command line invoke: ``` ./manage.py compilescss ``` This is useful for preparing production environments, where SASS/SCSS files can't be compiled on the fly. To simplify the deployment, the compiled ``*.css`` files are stored side-by-side with their corresponding SASS/SCSS files; just run ``` ./manage.py collectstatic ``` afterwards. In case you don't want to expose the SASS/SCSS files in a production environment, deploy with ``` ./manage.py collectstatic --ignore=.scss ``` In case you want to get rid of the compiled ``*.css`` files in your local static directories, simply reverse the above command: ``` ./manage.py compilescss --delete-files ``` This will remove all occurrences of previously generated ``*.css`` files. Or you may direct compile results to the ``SASS_PROCESSOR_ROOT`` directory (if not specified - to ``STATIC_ROOT``): ``` ./manage.py compilescss --use-processor-root ``` Combine with ``--delete-files`` switch to purge results from there. If you use an alternative templating engine set its name in ``--engine`` argument. Currently ``django`` and ``jinja2`` are supported, see [django-compressor documentation](http://django-compressor.readthedocs.org/en/latest/) on how to set up ``COMPRESS_JINJA2_GET_ENVIRONMENT`` to configure jinja2 engine support. During offline compilation **django-sass-processor** parses all Python files and looks for invokations of ``sass_processor('path/to/sassfile.scss')``. Therefore the string specifying the filename must be hard coded and shall not be concatenated or being somehow generated. ### Alternative templates By default, **django-sass-processor** will locate SASS/SCSS files from .html templates, but you can extend or override this behavior in your settings with: ```python SASS_TEMPLATE_EXTS = ['.html','.jade'] ``` ## Configure SASS variables through settings.py In SASS, a nasty problem is to set the correct include paths for icons and fonts. Normally this is done through a ``_variables.scss`` file, but this inhibits a configuration through your projects ``settings.py``. To avoid the need for duplicate configuration settings, **django-sass-processor** offers a SASS function to fetch any arbitrary configuration from the project's ``settings.py``. This is specially handy for setting the include path of your Glyphicons font directory. Assume, Bootstrap-SASS has been installed using: ``` npm install bootstrap-sass ``` then locate the directory named ``node_modules`` and add it to your settings, so that your fonts are accessible through the Django's ``django.contrib.staticfiles.finders.FileSystemFinder``: ```python STATICFILES_DIRS = [ ... ('node_modules', '/path/to/your/project/node_modules/'), ... ] NODE_MODULES_URL = STATIC_URL + 'node_modules/' ``` With the SASS function ``get-setting``, you now can override any SASS variable with a configurable value. For the Glyphicons font search path, add this to your ``_variables.scss``: ``` $icon-font-path: unquote(get-setting(NODE_MODULES_URL) + "bootstrap-sass/assets/fonts/bootstrap/"); ``` and ``@import "variables";`` whenever you need Glyphicons. You then can safely remove any font references, such as ```` from you HTML templates. ## Changelog * 0.5.3 - Fixed compilescss: Did not find calls of sass_processor within a dict, list or tuple * 0.5.2 - Fixed Python 3 incompatibility. Open files as binaries, since they may contain unicode characters. * 0.5.1 - Add ``APPS_INCLUDE_DIRS`` to the SASS include path. * 0.5.0 - SASS/SCSS files can also be referenced in pure Python files, for instance in ``Media`` class or ``media`` property definitions. - The SASS processor will look for potential include directories, so that the ``@import "..."`` statement also works for SASS files located in other Django apps. * 0.4.0 - 0.4.4 - Refactored the sass processor into a self-contained class ``SassProcessor``, which can be accessed through an API, the Jinja2 template engine and the existing templatetag. * 0.3.5 - Added Jinja2 support, see [Jinja2 support](#jinja2-support). * 0.3.4 - Fixed: ``get_template_sources()`` in Django-1.9 returns Objects rather than strings. - In command, use ``ArgumentParser`` rather than ``OptionParser``. * 0.3.1...0.3.3 - Changed the build process in ``setup.py``. * 0.3.0 - Compatible with Django 1.8+. - bootstrap3-sass ready: appropriate floating point precision (8) can be set in ``settings.py``. - Offline compilation results may optionally be stored in ``SASS_PROCESSOR_ROOT``. * 0.2.6 - Hotfix: added SASS function ``get-setting`` also to offline compiler. * 0.2.5 - Compatible with Python3 - Replaced ``SortedDict`` with ``OrderedDict`` to be prepared for Django-1.9 - Raise a ``TemplateSyntax`` error, if a SASS ``@include "..."`` fails to find the file. - Added SASS function ``get-setting`` to fetch configuration directives from ``settings.py``. * 0.2.4 - Forcing compiled unicode to bytes, since 'Font Awesome' uses Unicode Private Use Area (PUA) and hence implicit conversion on ``fh.write()`` failed. * 0.2.3 - Allow for setting template extensions and output style. - Force Django to calculate template_source_loaders from TEMPLATE_LOADERS settings, by asking to find a dummy template. * 0.2.0 - Removed dependency to **django-sekizai** and **django-classy-tags**. It now can operate in stand-alone mode. Therefore the project has been renamed to **django-sass-processor**. * 0.1.0 - Initial revision named **django-sekizai-processors**, based on a preprocessor for the Sekizai template tags ``{% addtoblock %}``. django-sass-processor-0.5.4/sass_processor/0000755000076500000240000000000013053557767021262 5ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/__init__.py0000644000076500000240000000137313053557723023367 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals """ See PEP 386 (https://www.python.org/dev/peps/pep-0386/) Release logic: 1. Remove ".devX" from __version__ (below) 2. Remove ".devX" latest version in README.md / Changelog 3. git add sass_processor/__init__.py 4. git commit -m 'Bump to ' 5. git push 6. (assure that all tests pass) 7. git tag 8. git push --tags 9. python setup.py sdist upload 10. bump the version, append ".dev0" to __version__ 11. Add a new heading to README.md / Changelog, named ".dev" 12. git add sass_processor/__init__.py README.md 12. git commit -m 'Start with ' 13. git push """ __version__ = '0.5.4' default_app_config = 'sass_processor.apps.SassProcessorConfig' django-sass-processor-0.5.4/sass_processor/__init__.pyc0000644000076500000240000000053113053557767023535 0ustar jriefstaff00000000000000ó Óß®Xc@s ddlmZdZdZdS(iÿÿÿÿ(tunicode_literalsu0.5.4u'sass_processor.apps.SassProcessorConfigN(t __future__Rt __version__tdefault_app_config(((sR/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/__init__.pytsdjango-sass-processor-0.5.4/sass_processor/apps.py0000644000076500000240000000244712773235417022577 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import re import os from django.apps import apps, AppConfig from django.conf import settings from django.core.files.storage import get_storage_class APPS_INCLUDE_DIRS = [] class SassProcessorConfig(AppConfig): name = 'sass_processor' verbose_name = "Sass Processor" _storage = get_storage_class(import_path=settings.STATICFILES_STORAGE)() _auto_include = getattr(settings, 'SASS_PROCESSOR_AUTO_INCLUDE', True) _pattern = re.compile(getattr(settings, 'SASS_PROCESSOR_INCLUDE_FILE_PATTERN', r'^_.+\.(scss|sass)$')) def ready(self): if self._auto_include: app_configs = apps.get_app_configs() for app_config in app_configs: static_dir = os.path.join(app_config.path, self._storage.base_url.strip(os.path.sep)) if os.path.isdir(static_dir): self.traverse_tree(static_dir) @classmethod def traverse_tree(cls, static_dir): """traverse the static folders an look for at least one file ending in .scss/.sass""" for root, dirs, files in os.walk(static_dir): for filename in files: if cls._pattern.match(filename): APPS_INCLUDE_DIRS.append(static_dir) return django-sass-processor-0.5.4/sass_processor/apps.pyc0000644000076500000240000000403013004474316022717 0ustar jriefstaff00000000000000ó ;íWc@s~ddlmZddlZddlZddlmZmZddlmZddl m Z gZ defd„ƒYZ dS(iÿÿÿÿ(tunicode_literalsN(tappst AppConfig(tsettings(tget_storage_classtSassProcessorConfigcBsneZdZdZedejƒƒZeede ƒZ e j eeddƒƒZ d„Zed„ƒZRS(usass_processoruSass Processort import_pathuSASS_PROCESSOR_AUTO_INCLUDEu#SASS_PROCESSOR_INCLUDE_FILE_PATTERNu^_.+\.(scss|sass)$cCs||jrxtjƒ}x`|D]U}tjj|j|jjjtjj ƒƒ}tjj |ƒr|j |ƒqqWndS(N( t _auto_includeRtget_app_configstostpathtjoint_storagetbase_urltstriptseptisdirt traverse_tree(tselft app_configst app_configt static_dir((sN/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/apps.pytreadys    -cCs[xTtj|ƒD]C\}}}x1|D])}|jj|ƒr&tj|ƒdSq&WqWdS(uOtraverse the static folders an look for at least one file ending in .scss/.sassN(R twalkt_patterntmatchtAPPS_INCLUDE_DIRStappend(tclsRtroottdirstfilestfilename((sN/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/apps.pyRs   (t__name__t __module__tnamet verbose_nameRRtSTATICFILES_STORAGER tgetattrtTrueRtretcompileRRt classmethodR(((sN/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/apps.pyR s ( t __future__RR(R t django.appsRRt django.confRtdjango.core.files.storageRRR(((sN/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/apps.pyts  django-sass-processor-0.5.4/sass_processor/finders.py0000644000076500000240000000206312605201406023241 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- import os from collections import OrderedDict from django.conf import settings from django.contrib.staticfiles.finders import FileSystemFinder from django.core.files.storage import FileSystemStorage class CssFinder(FileSystemFinder): """ Find static *.css files compiled on the fly using templatetag `{% sass_src "" %}` and stored below `SASS_PROCESSOR_ROOT`. """ locations = [] def __init__(self, apps=None, *args, **kwargs): location = getattr(settings, 'SASS_PROCESSOR_ROOT', settings.STATIC_ROOT) if not os.path.isdir(location): return self.locations = [ ('', location), ] self.storages = OrderedDict() filesystem_storage = FileSystemStorage(location=location) filesystem_storage.prefix = self.locations[0][0] self.storages[location] = filesystem_storage def find(self, path, all=False): if path.endswith('.css') or path.endswith('.css.map'): return super(CssFinder, self).find(path, all) return [] django-sass-processor-0.5.4/sass_processor/finders.pyc0000644000076500000240000000331313004667473023421 0ustar jriefstaff00000000000000ó Vc@sfddlZddlmZddlmZddlmZddlmZdefd„ƒYZ dS(iÿÿÿÿN(t OrderedDict(tsettings(tFileSystemFinder(tFileSystemStoraget CssFindercBs,eZdZgZdd„Zed„ZRS(s‡ Find static *.css files compiled on the fly using templatetag `{% sass_src "" %}` and stored below `SASS_PROCESSOR_ROOT`. cOs}ttdtjƒ}tjj|ƒs+dSd|fg|_tƒ|_t d|ƒ}|jdd|_ ||j|s django-sass-processor-0.5.4/sass_processor/jinja2/0000755000076500000240000000000013053557767022437 5ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/jinja2/__init__.py0000644000076500000240000000000012712133326024514 0ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/jinja2/ext.py0000644000076500000240000000146212741254443023600 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals from jinja2 import lexer, nodes from jinja2.ext import Extension from sass_processor.processor import SassProcessor class SassSrc(Extension): tags = set(['sass_src']) def parse(self, parser): lineno = next(parser.stream).lineno token = parser.stream.expect( lexer.TOKEN_STRING ) path = nodes.Const(token.value) call = self.call_method( '_sass_src_support', [ path, nodes.Const(parser.filename) ] ) return nodes.Output( [call], lineno=lineno ) def _sass_src_support(self, path, source_file): sass_processor = SassProcessor(source_file) return sass_processor(path) django-sass-processor-0.5.4/sass_processor/management/0000755000076500000240000000000013053557767023376 5ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/management/__init__.py0000644000076500000240000000000012604774407025466 0ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/management/__init__.pyc0000644000076500000240000000026413004474317025635 0ustar jriefstaff00000000000000ó ùVc@sdS(N((((s]/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/__init__.pytsdjango-sass-processor-0.5.4/sass_processor/management/commands/0000755000076500000240000000000013053557767025177 5ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/management/commands/__init__.py0000644000076500000240000000000012604774407027267 0ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/management/commands/__init__.pyc0000644000076500000240000000027513012665563027444 0ustar jriefstaff00000000000000ó ùVc@sdS(N((((sf/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/__init__.pytsdjango-sass-processor-0.5.4/sass_processor/management/commands/compilescss.py0000644000076500000240000003331313023134320030045 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import os import ast import django import sass from django.apps import apps from django.conf import settings from django.core.management.base import BaseCommand, CommandError from django.template.loader import get_template # noqa Leave this in to preload template locations from importlib import import_module from django.template.base import Origin from django.utils.encoding import force_bytes from django.utils.translation import gettext_lazy as _ from compressor.exceptions import TemplateDoesNotExist, TemplateSyntaxError from sass_processor.apps import APPS_INCLUDE_DIRS from sass_processor.templatetags.sass_tags import SassSrcNode from sass_processor.processor import SassProcessor from sass_processor.storage import find_file from sass_processor.utils import get_setting class FuncCallVisitor(ast.NodeVisitor): def __init__(self, func_name): self.func_name = func_name self.sass_files = [] def visit_Call(self, node): try: if node.func.id == self.func_name: arg0 = dict((a, b) for a, b in ast.iter_fields(node))['args'][0] self.sass_files.append(getattr(arg0, arg0._fields[0])) except AttributeError: pass self.generic_visit(node) class Command(BaseCommand): help = "Compile SASS/SCSS into CSS outside of the request/response cycle" def __init__(self): self.parser = None self.template_exts = getattr(settings, 'SASS_TEMPLATE_EXTS', ['.html']) self.sass_output_style = getattr(settings, 'SASS_OUTPUT_STYLE', 'nested' if settings.DEBUG else 'compressed') self.use_static_root = False self.static_root = '' super(Command, self).__init__() def add_arguments(self, parser): parser.add_argument( '--delete-files', action='store_true', dest='delete_files', default=False, help=_("Delete generated `*.css` files instead of creating them.") ) parser.add_argument( '--use-processor-root', action='store_true', dest='use_processor_root', default=False, help=_("Store resulting .css in settings.SASS_PROCESSOR_ROOT folder. " "Default: store each css side-by-side with .scss.") ) parser.add_argument( '--engine', dest='engine', default='django', help=_("Set templating engine used (django, jinja2). Default: django.") ) parser.add_argument( '--sass-precision', dest='sass_precision', type=int, help=_("Set the precision for numeric computations in the SASS processor. Default: settings.SASS_PRECISION.") ) def handle(self, *args, **options): self.verbosity = int(options['verbosity']) self.delete_files = options['delete_files'] self.use_static_root = options['use_processor_root'] if self.use_static_root: self.static_root = getattr(settings, 'SASS_PROCESSOR_ROOT', settings.STATIC_ROOT) self.parser = self.get_parser(options['engine']) try: self.sass_precision = int(options['sass_precision'] or settings.SASS_PRECISION) except (AttributeError, TypeError, ValueError): self.sass_precision = None self.processed_files = [] # find all Python files making up this project; They might invoke `sass_processor` for py_source in self.find_sources(): self.parse_source(py_source) if self.verbosity > 0: self.stdout.write(".", ending="") # find all Django/Jinja2 templates making up this project; They might invoke `sass_src` templates = self.find_templates() for template_name in templates: self.parse_template(template_name) if self.verbosity > 0: self.stdout.write(".", ending="") # summarize what has been done if self.verbosity > 0: self.stdout.write("") if self.delete_files: msg = "Successfully deleted {0} previously generated `*.css` files." self.stdout.write(msg.format(len(self.processed_files))) else: msg = "Successfully compiled {0} referred SASS/SCSS files." self.stdout.write(msg.format(len(self.processed_files))) def get_parser(self, engine): if engine == "jinja2": from compressor.offline.jinja2 import Jinja2Parser env = settings.COMPRESS_JINJA2_GET_ENVIRONMENT() parser = Jinja2Parser(charset=settings.FILE_CHARSET, env=env) elif engine == "django": from compressor.offline.django import DjangoParser parser = DjangoParser(charset=settings.FILE_CHARSET) else: raise CommandError("Invalid templating engine '{}' specified.".format(engine)) return parser def find_sources(self): """ Look for Python sources available for the current configuration. """ app_configs = apps.get_app_configs() for app_config in app_configs: ignore_dirs = [] for root, dirs, files in os.walk(app_config.path): if [True for idir in ignore_dirs if root.startswith(idir)]: continue if '__init__.py' not in files: ignore_dirs.append(root) continue for filename in files: basename, ext = os.path.splitext(filename) if ext != '.py': continue yield os.path.abspath(os.path.join(root, filename)) def parse_source(self, filename): """ Extract the statements from the given file, look for function calls `sass_processor(scss_file)` and compile the filename into CSS. """ callvisitor = FuncCallVisitor('sass_processor') tree = ast.parse(open(filename, 'rb').read()) callvisitor.visit(tree) for sass_file in callvisitor.sass_files: sass_filename = find_file(sass_file) if not sass_filename or sass_filename in self.processed_files: continue if self.delete_files: self.delete_file(sass_filename) else: self.compile_sass(sass_filename) def find_templates(self): """ Look for templates and extract the nodes containing the SASS file. """ paths = set() for loader in self.get_loaders(): try: module = import_module(loader.__module__) get_template_sources = getattr(module, 'get_template_sources', loader.get_template_sources) template_sources = get_template_sources('') paths.update([t.name if isinstance(t, Origin) else t for t in template_sources]) except (ImportError, AttributeError): pass if not paths: raise CommandError("No template paths found. None of the configured template loaders provided template paths") templates = set() for path in paths: for root, _, files in os.walk(str(path)): templates.update(os.path.join(root, name) for name in files if not name.startswith('.') and any(name.endswith(ext) for ext in self.template_exts)) if not templates: raise CommandError("No templates found. Make sure your TEMPLATE_LOADERS and TEMPLATE_DIRS settings are correct.") return templates def get_loaders(self): if django.VERSION < (1, 8): from django.template.base import TemplateDoesNotExist as DjangoTemplateDoesNotExist from django.template.loader import template_source_loaders if template_source_loaders is None: try: from django.template.loader import ( find_template as finder_func) except ImportError: from django.template.loader import ( find_template_source as finder_func) # noqa try: # Force django to calculate template_source_loaders from # TEMPLATE_LOADERS settings, by asking to find a dummy template source, name = finder_func('test') except DjangoTemplateDoesNotExist: pass # Reload template_source_loaders now that it has been calculated ; # it should contain the list of valid, instanciated template loaders # to use. from django.template.loader import template_source_loaders else: from django.template import engines template_source_loaders = [] for e in engines.all(): template_source_loaders.extend(e.engine.get_template_loaders(e.engine.loaders)) loaders = [] # If template loader is CachedTemplateLoader, return the loaders # that it wraps around. So if we have # TEMPLATE_LOADERS = ( # ('django.template.loaders.cached.Loader', ( # 'django.template.loaders.filesystem.Loader', # 'django.template.loaders.app_directories.Loader', # )), # ) # The loaders will return django.template.loaders.filesystem.Loader # and django.template.loaders.app_directories.Loader # The cached Loader and similar ones include a 'loaders' attribute # so we look for that. for loader in template_source_loaders: if hasattr(loader, 'loaders'): loaders.extend(loader.loaders) else: loaders.append(loader) return loaders def parse_template(self, template_name): try: template = self.parser.parse(template_name) except IOError: # unreadable file -> ignore if self.verbosity > 0: self.stderr.write("\nUnreadable template at: {}".format(template_name)) return except TemplateSyntaxError as e: # broken template -> ignore if self.verbosity > 0: self.stderr.write("\nInvalid template {}: {}".format(template_name, e)) return except TemplateDoesNotExist: # non existent template -> ignore if self.verbosity > 0: self.stderr.write("\nNon-existent template at: {}".format(template_name)) return except UnicodeDecodeError: if self.verbosity > 0: self.stderr.write("\nUnicodeDecodeError while trying to read template {}".format(template_name)) try: nodes = list(self.walk_nodes(template, original=template)) except Exception as e: # Could be an error in some base template if self.verbosity > 0: self.stderr.write("\nError parsing template {}: {}".format(template_name, e)) else: for node in nodes: sass_filename = find_file(node.path) if not sass_filename or sass_filename in self.processed_files: continue if self.delete_files: self.delete_file(sass_filename) else: self.compile_sass(sass_filename) def compile_sass(self, sass_filename): """ Compile the given SASS file into CSS """ # add a functions to be used from inside SASS custom_functions = {'get-setting': get_setting} compile_kwargs = { 'filename': sass_filename, 'include_paths': SassProcessor.include_paths + APPS_INCLUDE_DIRS, 'custom_functions': custom_functions, } if self.sass_precision: compile_kwargs['precision'] = self.sass_precision if self.sass_output_style: compile_kwargs['output_style'] = self.sass_output_style content = sass.compile(**compile_kwargs) destpath = self.get_destination(sass_filename) with open(destpath, 'wb') as fh: fh.write(force_bytes(content)) self.processed_files.append(sass_filename) if self.verbosity > 1: self.stdout.write("Compiled SASS/SCSS file: '{0}'\n".format(sass_filename)) def delete_file(self, sass_filename): """ Delete a *.css file, but only if it has been generated through a SASS/SCSS file. """ destpath = self.get_destination(sass_filename) if os.path.isfile(destpath): os.remove(destpath) self.processed_files.append(sass_filename) if self.verbosity > 1: self.stdout.write("Deleted '{0}'\n".format(destpath)) def get_destination(self, source): if not self.use_static_root: basename, _ = os.path.splitext(source) destpath = basename + '.css' else: basename, _ = os.path.splitext(os.path.basename(source)) destpath = os.path.join(self.static_root, basename + '.css') return destpath def walk_nodes(self, node, original): """ Iterate over the nodes recursively yielding the templatetag 'sass_src' """ try: # try with django-compressor<2.1 nodelist = self.parser.get_nodelist(node, original=original) except TypeError: nodelist = self.parser.get_nodelist(node, original=original, context=None) for node in nodelist: if isinstance(node, SassSrcNode): if node.is_sass: yield node else: for node in self.walk_nodes(node, original=original): yield node django-sass-processor-0.5.4/sass_processor/management/commands/compilescss.pyc0000644000076500000240000003360013023136323030214 0ustar jriefstaff00000000000000ó иLXc@s_ddlmZddlZddlZddlZddlZddlmZddlm Z ddl m Z m Z ddl mZddlmZddlmZdd lmZdd lmZdd lmZmZdd lmZdd lmZddlm Z ddl!m"Z"ddl#m$Z$dej%fd„ƒYZ&de fd„ƒYZ'dS(iÿÿÿÿ(tunicode_literalsN(tapps(tsettings(t BaseCommandt CommandError(t get_template(t import_module(tOrigin(t force_bytes(t gettext_lazy(tTemplateDoesNotExisttTemplateSyntaxError(tAPPS_INCLUDE_DIRS(t SassSrcNode(t SassProcessor(t find_file(t get_settingtFuncCallVisitorcBseZd„Zd„ZRS(cCs||_g|_dS(N(t func_namet sass_files(tselfR((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyt__init__s cCsˆyc|jj|jkrbtd„tj|ƒDƒƒdd}|jjt||j dƒƒnWnt k rvnX|j |ƒdS(Ncss!|]\}}||fVqdS(N((t.0tatb((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pys suargsi( tfunctidRtdicttastt iter_fieldsRtappendtgetattrt_fieldstAttributeErrort generic_visit(Rtnodetarg0((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyt visit_Calls'' (t__name__t __module__RR%(((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyRs tCommandcBsƒeZdZd„Zd„Zd„Zd„Zd„Zd„Zd„Z d„Z d „Z d „Z d „Z d „Zd „ZRS(u@Compile SASS/SCSS into CSS outside of the request/response cyclecCsnd|_ttddgƒ|_ttdtjr9dndƒ|_t|_d|_ t t |ƒj ƒdS(NuSASS_TEMPLATE_EXTSu.htmluSASS_OUTPUT_STYLEunestedu compressedu( tNonetparserRRt template_extstDEBUGtsass_output_styletFalsetuse_static_roott static_roottsuperR(R(R((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyR*s    c Cs¤|jddddddtdtdƒƒ|jd dddd dtdtd ƒƒ|jd dd dddtdƒƒ|jddddtdtdƒƒdS(Nu--delete-filestactionu store_truetdestu delete_filestdefaultthelpu8Delete generated `*.css` files instead of creating them.u--use-processor-rootuuse_processor_rootumStore resulting .css in settings.SASS_PROCESSOR_ROOT folder. Default: store each css side-by-side with .scss.u--engineuengineudjangou=Set templating engine used (django, jinja2). Default: django.u--sass-precisionusass_precisionttypeucSet the precision for numeric computations in the SASS processor. Default: settings.SASS_PRECISION.(t add_argumentR.t_tint(RR*((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyt add_arguments3s,   cOsÖt|dƒ|_|d|_|d|_|jrQttdtjƒ|_n|j|dƒ|_ y t|dp}tj ƒ|_ Wn#t t tfk r¬d|_ nXg|_xI|jƒD];}|j|ƒ|jdkrÃ|jjdd d ƒqÃqÃW|jƒ}xC|D];}|j|ƒ|jdkr|jjdd d ƒqqW|jdkrÒ|jjd ƒ|jr§d }|jj|jt|jƒƒƒqÒd }|jj|jt|jƒƒƒndS( Nu verbosityu delete_filesuuse_processor_rootuSASS_PROCESSOR_ROOTuengineusass_precisioniu.tendinguu<Successfully deleted {0} previously generated `*.css` files.u3Successfully compiled {0} referred SASS/SCSS files.(R9t verbosityt delete_filesR/RRt STATIC_ROOTR0t get_parserR*tSASS_PRECISIONtsass_precisionR!t TypeErrort ValueErrorR)tprocessed_filest find_sourcest parse_sourcetstdouttwritetfind_templatestparse_templatetformattlen(Rtargstoptionst py_sourcet templatest template_nametmsg((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pythandlePs6           %cCs|dkrCddlm}tjƒ}|dtjd|ƒ}nF|dkrtddlm}|dtjƒ}ntdj|ƒƒ‚|S( Nujinja2iÿÿÿÿ(t Jinja2Parsertcharsettenvudjango(t DjangoParseru)Invalid templating engine '{}' specified.( tcompressor.offline.jinja2RTRtCOMPRESS_JINJA2_GET_ENVIRONMENTt FILE_CHARSETtcompressor.offline.djangoRWRRK(RtengineRTRVR*RW((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyR?us   c csõtjƒ}xâ|D]Ú}g}xËtj|jƒD]·\}}}g|D]}|j|ƒrHt^qHroq2nd|krŽ|j|ƒq2nxX|D]P}tjj|ƒ\} } | dkrÅq•ntjj tjj ||ƒƒVq•Wq2WqWdS(uR Look for Python sources available for the current configuration. u __init__.pyu.pyN( Rtget_app_configstostwalktpatht startswithtTrueRtsplitexttabspathtjoin( Rt app_configst app_configt ignore_dirstroottdirstfilestidirtfilenametbasenametext((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyRE‚s  "(    cCstdƒ}tjt|dƒjƒƒ}|j|ƒx_|jD]T}t|ƒ}| sA||jkroqAn|j rˆ|j |ƒqA|j |ƒqAWdS(uœ Extract the statements from the given file, look for function calls `sass_processor(scss_file)` and compile the filename into CSS. usass_processorurbN( RRtparsetopentreadtvisitRRRDR=t delete_filet compile_sass(RRmt callvisitorttreet sass_filet sass_filename((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyRF•s    c s7tƒ}xšˆjƒD]Œ}ylt|jƒ}t|d|jƒ}|dƒ}|jg|D]$}t|tƒrz|j n|^q\ƒWqt t fk r¡qXqW|s»t dƒ‚ntƒ}xW|D]O}xFt jt|ƒƒD]/\‰} } |j‡‡fd†| DƒƒqçWqËW|s3t dƒ‚n|S(uT Look for templates and extract the nodes containing the SASS file. uget_template_sourcesuuXNo template paths found. None of the configured template loaders provided template pathsc3sS|]I‰ˆjdƒ rt‡fd†ˆjDƒƒrtjjˆˆƒVqdS(u.c3s|]}ˆj|ƒVqdS(N(tendswith(RRo(tname(si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pys ºsN(RatanyR+R^R`Re(R(RiR(R{si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pys ¸su[No templates found. Make sure your TEMPLATE_LOADERS and TEMPLATE_DIRS settings are correct.(tsett get_loadersRR'Rtget_template_sourcestupdatet isinstanceRR{t ImportErrorR!RR^R_tstr( RtpathstloadertmoduleRttemplate_sourcesttRPR`R8Rk((RiRsi/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyRI¦s&  <  %c CsItjd kr³ddlm}ddlm}|dkrÿyddlm}Wn!tk rrddlm }nXy|dƒ\}}Wn|k rœnXddlm}qÿnLdd l m }g}x3|j ƒD]%}|j |jj|jjƒƒqÖWg}x=|D]5} t| d ƒr4|j | jƒq |j| ƒq W|S( Niiiÿÿÿÿ(R (ttemplate_source_loaders(t find_template(tfind_template_sourceutest(tenginesuloaders(ii(tdjangotVERSIONtdjango.template.baseR tdjango.template.loaderR‰R)RŠR‚R‹tdjango.templateRŒtalltextendR\tget_template_loaderstloadersthasattrR( RtDjangoTemplateDoesNotExistR‰t finder_functsourceR{RŒteR•R…((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyR~¿s.   # cCs×y|jj|ƒ}Wnõtk rU|jdkrQ|jjdj|ƒƒndStk r–}|jdkr’|jjdj||ƒƒndStk rÒ|jdkrÎ|jjdj|ƒƒndSt k r |jdkr|jjdj|ƒƒqnXyt |j |d|ƒƒ}WnAt k rp}|jdkrÓ|jjdj||ƒƒqÓncXx_|D]W}t |jƒ}| sx||jkr©qxn|jrÂ|j|ƒqx|j|ƒqxWdS(Niu Unreadable template at: {}u Invalid template {}: {}u Non-existent template at: {}u4 UnicodeDecodeError while trying to read template {}toriginalu Error parsing template {}: {}(R*RptIOErrorR<tstderrRHRKR R tUnicodeDecodeErrortlistt walk_nodest ExceptionRR`RDR=RtRu(RRQttemplateRštnodesR#Ry((si/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/management/commands/compilescss.pyRJís:    #  cCséitd6}i|d6tjtd6|d6}|jrH|j|ds(    django-sass-processor-0.5.4/sass_processor/processor.py0000644000076500000240000001116313053557337023646 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals import os import json from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.files.base import ContentFile from django.template import Context from django.utils.encoding import force_bytes, iri_to_uri from django.utils.six.moves.urllib.parse import urljoin from sass_processor.utils import get_setting from .storage import SassFileStorage, find_file from .apps import APPS_INCLUDE_DIRS try: import sass except ImportError: sass = None try: FileNotFoundError except NameError: FileNotFoundError = IOError class SassProcessor(object): storage = SassFileStorage() include_paths = list(getattr(settings, 'SASS_PROCESSOR_INCLUDE_DIRS', [])) prefix = iri_to_uri(getattr(settings, 'STATIC_URL', '')) try: sass_precision = int(settings.SASS_PRECISION) except (AttributeError, TypeError, ValueError): sass_precision = None sass_output_style = getattr( settings, 'SASS_OUTPUT_STYLE', 'nested' if settings.DEBUG else 'compressed') processor_enabled = getattr(settings, 'SASS_PROCESSOR_ENABLED', settings.DEBUG) sass_extensions = ('.scss', '.sass') def __init__(self, path=None): self._path = path def __call__(self, path): basename, ext = os.path.splitext(path) filename = find_file(path) if filename is None: raise FileNotFoundError("Unable to locate file {path}".format(path=path)) if ext not in self.sass_extensions: # return the given path, since it ends neither in `.scss` nor in `.sass` return urljoin(self.prefix, path) # compare timestamp of sourcemap file with all its dependencies, and check if we must recompile css_filename = basename + '.css' url = urljoin(self.prefix, css_filename) if not self.processor_enabled: return url sourcemap_filename = css_filename + '.map' if find_file(css_filename) and self.is_latest(sourcemap_filename): return url # with offline compilation, raise an error, if css file could not be found. if sass is None: msg = "Offline compiled file `{}` is missing and libsass has not been installed." raise ImproperlyConfigured(msg.format(css_filename)) # add a function to be used from inside SASS custom_functions = {'get-setting': get_setting} # otherwise compile the SASS/SCSS file into .css and store it sourcemap_url = self.storage.url(sourcemap_filename) compile_kwargs = { 'filename': filename, 'source_map_filename': sourcemap_url, 'include_paths': self.include_paths + APPS_INCLUDE_DIRS, 'custom_functions': custom_functions, } if self.sass_precision: compile_kwargs['precision'] = self.sass_precision if self.sass_output_style: compile_kwargs['output_style'] = self.sass_output_style content, sourcemap = sass.compile(**compile_kwargs) content = force_bytes(content) sourcemap = force_bytes(sourcemap) if self.storage.exists(css_filename): self.storage.delete(css_filename) self.storage.save(css_filename, ContentFile(content)) if self.storage.exists(sourcemap_filename): self.storage.delete(sourcemap_filename) self.storage.save(sourcemap_filename, ContentFile(sourcemap)) return url def resolve_path(self, context=None): if context is None: context = Context() return self._path.resolve(context) def is_sass(self): _, ext = os.path.splitext(self.resolve_path()) return ext in self.sass_extensions def is_latest(self, sourcemap_filename): sourcemap_file = find_file(sourcemap_filename) if not sourcemap_file or not os.path.isfile(sourcemap_file): return False sourcemap_mtime = os.stat(sourcemap_file).st_mtime with open(sourcemap_file, 'r') as fp: sourcemap = json.load(fp) for srcfilename in sourcemap.get('sources'): components = os.path.normpath(srcfilename).split(os.path.sep) srcfilename = ''.join([os.path.sep + c for c in components if c != os.path.pardir]) if not os.path.isfile(srcfilename) or os.stat(srcfilename).st_mtime > sourcemap_mtime: # at least one of the source is younger that the sourcemap referring it return False return True _sass_processor = SassProcessor() def sass_processor(filename): return _sass_processor(filename) django-sass-processor-0.5.4/sass_processor/processor.pyc0000644000076500000240000001172013004474316023777 0ustar jriefstaff00000000000000ó ;íWc@s<ddlmZddlZddlZddlmZddlmZddlm Z ddl m Z ddl m Z mZddlmZdd lmZd d lmZmZd d lmZyddlZWnek rídZnXyeWnek reZnXd efd„ƒYZeƒZ d„Z!dS(iÿÿÿÿ(tunicode_literalsN(tsettings(tImproperlyConfigured(t ContentFile(tContext(t force_bytest iri_to_uri(turljoin(t get_settingi(tSassFileStoraget find_file(tAPPS_INCLUDE_DIRSt SassProcessorcBsæeZeƒZeeedgƒƒZeeeddƒƒZ ye ej ƒZ Wn e eefk rtdZ nXeedejrdndƒZeedejƒZdZdd „Zd „Zdd „Zd „Zd „ZRS(uSASS_PROCESSOR_INCLUDE_DIRSu STATIC_URLuuSASS_OUTPUT_STYLEunestedu compresseduSASS_PROCESSOR_ENABLEDu.scssu.sasscCs ||_dS(N(t_path(tselftpath((sS/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/processor.pyt__init__+scCstjj|ƒ\}}t|ƒ}|dkrKtdjd|ƒƒ‚n||jkrjt|j |ƒS|d}t|j |ƒ}|j s“|S|d}|j |ƒr°|St dkrÚd}t |j|ƒƒ‚nitd6} |jj|ƒ} i|d6| d6|jtd 6| d 6} |jr;|j| d +N(u.scssu.sass(t__name__t __module__R RtlisttgetattrRRRRtinttSASS_PRECISIONRtAttributeErrort TypeErrort ValueErrorRtDEBUGRRRRR/R2R4R(((sS/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/processor.pyR s$    2  cCs t|ƒS(N(t_sass_processor(R&((sS/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/processor.pytsass_processorzs("t __future__RRR:t django.confRtdjango.core.exceptionsRtdjango.core.files.baseRtdjango.templateRtdjango.utils.encodingRRt#django.utils.six.moves.urllib.parseRtsass_processor.utilsRRR R tappsR Rt ImportErrorRRt NameErrortIOErrortobjectR RSRT(((sS/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/processor.pyts,      ] django-sass-processor-0.5.4/sass_processor/storage.py0000644000076500000240000000126512604774407023275 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from django.conf import settings from django.contrib.staticfiles.finders import get_finders from django.core.files.storage import FileSystemStorage class SassFileStorage(FileSystemStorage): def __init__(self, location=None, base_url=None, *args, **kwargs): if location is None: location = getattr(settings, 'SASS_PROCESSOR_ROOT', settings.STATIC_ROOT) if base_url is None: base_url = settings.STATIC_URL super(SassFileStorage, self).__init__(location, base_url, *args, **kwargs) def find_file(path): for finder in get_finders(): result = finder.find(path) if result: return result django-sass-processor-0.5.4/sass_processor/storage.pyc0000644000076500000240000000247713004474316023435 0ustar jriefstaff00000000000000ó ùVc@sSddlmZddlmZddlmZdefd„ƒYZd„ZdS(iÿÿÿÿ(tsettings(t get_finders(tFileSystemStoragetSassFileStoragecBseZddd„ZRS(cOs_|dkr$ttdtjƒ}n|dkr<tj}ntt|ƒj||||ŽdS(NtSASS_PROCESSOR_ROOT(tNonetgetattrRt STATIC_ROOTt STATIC_URLtsuperRt__init__(tselftlocationtbase_urltargstkwargs((sQ/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/storage.pyR s    N(t__name__t __module__RR (((sQ/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/storage.pyRscCs1x*tƒD]}|j|ƒ}|r |Sq WdS(N(Rtfind(tpathtfindertresult((sQ/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/storage.pyt find_filesN(t django.confRt"django.contrib.staticfiles.findersRtdjango.core.files.storageRRR(((sQ/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/storage.pyts django-sass-processor-0.5.4/sass_processor/templatetags/0000755000076500000240000000000013053557767023754 5ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/templatetags/__init__.py0000644000076500000240000000000012604774407026044 0ustar jriefstaff00000000000000django-sass-processor-0.5.4/sass_processor/templatetags/__init__.pyc0000644000076500000240000000026613004474316026214 0ustar jriefstaff00000000000000ó ùVc@sdS(N((((s_/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/__init__.pytsdjango-sass-processor-0.5.4/sass_processor/templatetags/sass_tags.py0000644000076500000240000000303412773232037026301 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.template import Library from django.template.base import Node, TemplateSyntaxError from sass_processor.processor import SassProcessor try: FileNotFoundError except NameError: FileNotFoundError = IOError register = Library() class SassSrcNode(Node): def __init__(self, path): self.sass_processor = SassProcessor(path) @classmethod def handle_token(cls, parser, token): bits = token.split_contents() if len(bits) != 2: raise TemplateSyntaxError("'{0}' takes a URL to a CSS file as its only argument".format(*bits)) path = parser.compile_filter(bits[1]) return cls(path) @property def path(self): return self.sass_processor.resolve_path() @property def is_sass(self): return self.sass_processor.is_sass() def render(self, context): try: path = self.sass_processor.resolve_path(context) url = self.sass_processor(path) except AttributeError: msg = "No sass/scss file specified while rendering tag 'sass_src' in template {}" raise TemplateSyntaxError(msg.format(context.template_name)) except FileNotFoundError as e: msg = str(e) + " while rendering tag 'sass_src' in template {}" raise TemplateSyntaxError(msg.format(context.template_name)) return url @register.tag(name='sass_src') def render_sass_src(parser, token): return SassSrcNode.handle_token(parser, token) django-sass-processor-0.5.4/sass_processor/templatetags/sass_tags.pyc0000644000076500000240000000553213004474316026445 0ustar jriefstaff00000000000000ó 4íWc@s¦ddlmZddlmZddlmZmZddlmZye Wne k rge Z nXeƒZ defd„ƒYZ e jddƒd „ƒZd S( iÿÿÿÿ(tunicode_literals(tLibrary(tNodetTemplateSyntaxError(t SassProcessort SassSrcNodecBsGeZd„Zed„ƒZed„ƒZed„ƒZd„ZRS(cCst|ƒ|_dS(N(Rtsass_processor(tselftpath((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pyt__init__scCsS|jƒ}t|ƒdkr6tdj|Œƒ‚n|j|dƒ}||ƒS(Niu4'{0}' takes a URL to a CSS file as its only argumenti(tsplit_contentstlenRtformattcompile_filter(tclstparserttokentbitsR((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pyt handle_tokens  cCs |jjƒS(N(Rt resolve_path(R((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pyRscCs |jjƒS(N(Rtis_sass(R((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pyR scCs•y%|jj|ƒ}|j|ƒ}Wnitk rVd}t|j|jƒƒ‚n;tk r}t|ƒd}t|j|jƒƒ‚nX|S(NuINo sass/scss file specified while rendering tag 'sass_src' in template {}u. while rendering tag 'sass_src' in template {}(RRtAttributeErrorRR t template_nametFileNotFoundErrortstr(RtcontextRturltmsgte((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pytrender$s ( t__name__t __module__R t classmethodRtpropertyRRR(((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pyRs  tnameusass_srccCstj||ƒS(N(RR(RR((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pytrender_sass_src0sN(t __future__Rtdjango.templateRtdjango.template.baseRRtsass_processor.processorRRt NameErrortIOErrortregisterRttagR#(((s`/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/templatetags/sass_tags.pyts    django-sass-processor-0.5.4/sass_processor/utils.py0000644000076500000240000000037512754322404022762 0ustar jriefstaff00000000000000# -*- coding: utf-8 -*- from django.conf import settings from django.template import TemplateSyntaxError def get_setting(key): try: return getattr(settings, key) except AttributeError as e: raise TemplateSyntaxError(e.message) django-sass-processor-0.5.4/sass_processor/utils.pyc0000644000076500000240000000113413004474316023116 0ustar jriefstaff00000000000000ó ¥±Wc@s-ddlmZddlmZd„ZdS(iÿÿÿÿ(tsettings(tTemplateSyntaxErrorcCs:ytt|ƒSWn"tk r5}t|jƒ‚nXdS(N(tgetattrRtAttributeErrorRtmessage(tkeyte((sO/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/utils.pyt get_settingsN(t django.confRtdjango.templateRR(((sO/Users/jrief/Workspace/djangoSHOP/django-sass-processor/sass_processor/utils.pytsdjango-sass-processor-0.5.4/setup.cfg0000644000076500000240000000007313053557767020033 0ustar jriefstaff00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 django-sass-processor-0.5.4/setup.py0000644000076500000240000000247012744724731017720 0ustar jriefstaff00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import unicode_literals from setuptools import setup, find_packages from sass_processor import __version__ try: from pypandoc import convert except ImportError: import io def convert(filename, fmt): with io.open(filename, encoding='utf-8') as fd: return fd.read() CLASSIFIERS = [ 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Framework :: Django', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', ] setup( name='django-sass-processor', version=__version__, description='SASS processor to compile SCSS files into *.css, while rendering, or offline.', author='Jacob Rief', author_email='jacob.rief@gmail.com', url='https://github.com/jrief/django-sass-processor', packages=find_packages(), install_requires=['libsass'], license='LICENSE-MIT', platforms=['OS Independent'], classifiers=CLASSIFIERS, long_description=convert('README.md', 'rst'), include_package_data=True, zip_safe=False, )