def compile_sass(self, sass_filename, sass_fileurl):
     """
     Compile the given SASS file into CSS
     """
     compile_kwargs = {
         'filename': sass_filename,
         'include_paths': SassProcessor.include_paths + APPS_INCLUDE_DIRS,
         'custom_functions': get_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)
     self.save_to_destination(content, sass_filename, sass_fileurl)
     self.processed_files.append(sass_filename)
     if self.verbosity > 1:
         self.stdout.write("Compiled SASS/SCSS file: '{0}'\n".format(sass_filename))
예제 #2
0
    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 path

        # compare timestamp of sourcemap file with all its dependencies, and check if we must recompile
        css_filename = basename + '.css'
        if not self.processor_enabled:
            return css_filename
        sourcemap_filename = css_filename + '.map'
        base = os.path.dirname(filename)
        if find_file(css_filename) and self.is_latest(sourcemap_filename,
                                                      base):
            return css_filename

        # 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))

        # otherwise compile the SASS/SCSS file into .css and store it
        filename_map = filename.replace(ext, '.css.map')
        compile_kwargs = {
            'filename': filename,
            'source_map_filename': filename_map,
            'include_paths': self.include_paths + APPS_INCLUDE_DIRS,
            'custom_functions': get_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, sourcemap = force_bytes(content), force_bytes(sourcemap)

        # autoprefix CSS files using postcss in external JavaScript process
        if self.node_npx_path and os.path.isdir(self.node_modules_dir or ''):
            os.environ['NODE_PATH'] = self.node_modules_dir
            try:
                options = [
                    self.node_npx_path, 'postcss', '--use', 'autoprefixer'
                ]
                if not settings.DEBUG:
                    options.append('--no-map')
                proc = subprocess.Popen(options,
                                        stdin=subprocess.PIPE,
                                        stdout=subprocess.PIPE)
                proc.stdin.write(content)
                proc.stdin.close()
                autoprefixed_content = proc.stdout.read()
                proc.wait()
            except (FileNotFoundError, BrokenPipeError) as exc:
                logger.warning("Unable to postcss {}. Reason: {}".format(
                    filename, exc))
            else:
                if len(autoprefixed_content) >= len(content):
                    content = autoprefixed_content

        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 css_filename