Source code for djangofloor.templatetags.pipeline

"""Emulate django-pipeline templatetags
====================================

Allows you to use the same `javascript` and `stylesheet` template tags if `django-pipeline` is not installed.
If you add `django-pipeline` to your `settings.INSTALLED_APPS`, these versions are ignored, using the original ones.
If you keep the default settings, `django-pipeline` is automatically detected and added, so you have nothing to do.

"""
import os
import subprocess
import warnings
from pathlib import Path

from django import template
from django.conf import settings
from django.utils.safestring import mark_safe

from djangofloor.utils import RemovedInDjangoFloor200Warning

if settings.USE_PIPELINE:
    # noinspection PyPackageRequirements
    import pipeline.templatetags.pipeline as pipe

    # noinspection PyPackageRequirements
    from pipeline.compressors import CompressorBase

    # noinspection PyPackageRequirements
    from pipeline.compilers import CompilerBase
else:
    pipe = None
    CompressorBase = object
    CompilerBase = object

__author__ = "Matthieu Gallet"

register = template.Library()
_deprecated_files = {
    "bootstrap3/css/bootstrap.css",
    "bootstrap3/css/bootstrap.css.map",
    "bootstrap3/css/bootstrap.min.css",
    "bootstrap3/css/bootstrap.min.css.map",
    "bootstrap3/css/bootswatch.less",
    "bootstrap3/css/variables.less",
    "bootstrap3/fonts/glyphicons-halflings-regular.eot",
    "bootstrap3/fonts/glyphicons-halflings-regular.svg",
    "bootstrap3/fonts/glyphicons-halflings-regular.ttf",
    "bootstrap3/fonts/glyphicons-halflings-regular.woff",
    "bootstrap3/fonts/glyphicons-halflings-regular.woff2",
    "bootstrap3/js/bootstrap.js",
    "bootstrap3/js/bootstrap.min.js",
    "css/bootstrap-select.css",
    "css/bootstrap-select.min.css",
    "css/djangofloor.css",
    "css/font-awesome.css",
    "css/font-awesome.min.css",
    "fonts/FontAwesome.otf",
    "fonts/fontawesome-webfont.eot",
    "fonts/fontawesome-webfont.svg",
    "fonts/fontawesome-webfont.ttf",
    "fonts/fontawesome-webfont.woff",
    "fonts/glyphicons-halflings-regular.eot",
    "fonts/glyphicons-halflings-regular.svg",
    "fonts/glyphicons-halflings-regular.ttf",
    "fonts/glyphicons-halflings-regular.woff",
    "fonts/glyphicons-halflings-regular.woff2",
    "images/favicon.ico",
    "images/favicon.png",
    "js/bootstrap-notify.js",
    "js/bootstrap-notify.min.js",
    "js/bootstrap-select.js",
    "js/bootstrap-select.min.js",
    "js/djangofloor.js",
    "js/html5shiv.js",
    "js/jquery-1.10.2.js",
    "js/jquery-1.10.2.min.map",
    "js/jquery.min.js",
    "js/respond.min.js",
}
_warned_files = set()


[docs]@register.simple_tag def javascript(key): """insert all javascript files corresponding to the given key""" if pipe and settings.PIPELINE["PIPELINE_ENABLED"] and not settings.DEBUG: node = pipe.JavascriptNode(key) return node.render({key: key}) filenames = settings.PIPELINE["JAVASCRIPT"][key]["source_filenames"] context = {} # The type attribute is unnecessary for JavaScript resources. context.update(settings.PIPELINE["JAVASCRIPT"][key].get("extra_context", {})) extra = " ".join('%s="%s"' % x for x in context.items()) def fmt(filename): if filename in _deprecated_files and filename not in _warned_files: warnings.warn( "%s is deprecated" % filename, RemovedInDjangoFloor200Warning, stacklevel=2, ) _warned_files.add(filename) return '<script src="%s%s" %s></script>' % ( settings.STATIC_URL, filename, extra, ) node = "\n".join([fmt(x) for x in filenames]) return mark_safe(node)
[docs]@register.simple_tag def stylesheet(key): """insert all javascript files corresponding to the given key""" if pipe and settings.PIPELINE["PIPELINE_ENABLED"]: node = pipe.StylesheetNode(key) return node.render({key: key}) filenames = settings.PIPELINE["STYLESHEETS"][key]["source_filenames"] context = {"type": "text/css", "rel": "stylesheet"} context.update(settings.PIPELINE["STYLESHEETS"][key].get("extra_context", {})) extra = " ".join('%s="%s"' % x for x in context.items()) def fmt(filename): return '<link href="%s%s" %s/>' % (settings.STATIC_URL, filename, extra) result = "\n".join([fmt(x) for x in filenames]) return mark_safe(result)
# noinspection PyClassHasNoInit,PyAbstractClass
[docs]class RcssCompressor(CompressorBase): """ JS compressor based on the Python library slimit (http://pypi.python.org/pypi/slimit/ ). """ # noinspection PyMethodMayBeStatic
[docs] def compress_css(self, css): # noinspection PyUnresolvedReferences,PyPackageRequirements from rcssmin import cssmin return cssmin(css)
# noinspection PyClassHasNoInit
[docs]class PyScssCompiler(CompilerBase): """ SASS (.scss) compiler based on the Python library pyScss. (http://pyscss.readthedocs.io/en/latest/ ). However, this compiler is limited to SASS 3.2 and cannot compile modern projets like Bootstrap 4. Please use :class:`pipeline.compilers.sass.SASSCompiler` if you use modern SCSS files. """ output_extension = "css"
[docs] def match_file(self, filename): return filename.endswith(".scss") or filename.endswith(".sass")
[docs] def compile_file(self, infile, outfile, outdated=False, force=False): # noinspection PyUnresolvedReferences,PyUnresolvedReferences,PyPackageRequirements from scss import Compiler root = Path(os.path.abspath(settings.STATIC_ROOT)) compiler = Compiler(root=root, search_path=("./",)) css_content = compiler.compile(infile) with open(outfile, "w") as fd: fd.write(css_content) if self.verbose: print(css_content)
# noinspection PyClassHasNoInit
[docs]class TypescriptCompiler(CompilerBase): """ TypeScript (.ts) compiler using "tsc". (https://www.typescriptlang.org ). """ output_extension = "js"
[docs] def match_file(self, filename): return filename.endswith(".ts")
[docs] def compile_file(self, infile, outfile, outdated=False, force=False): # noinspection PyPackageRequirements from pipeline.exceptions import CompilerError command = ( [settings.TYPESCRIPT_BINARY] + settings.TYPESCRIPT_ARGUMENTS + ["-out", outfile, infile] ) try: p = subprocess.Popen( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) stdout, __ = p.communicate(b"") if p.returncode != 0: raise CompilerError( "Unable to execute TypeScript", command=command, error_output=stdout.decode(), ) except Exception as e: raise CompilerError(e, command=command, error_output=str(e))