Sith/sith/storage.py

74 lines
2.6 KiB
Python

import logging
import subprocess
import warnings
import sass
from django.conf import settings
from django.contrib.staticfiles.storage import (
ManifestStaticFilesStorage,
)
from django.core.files.storage import Storage
class SithStorage(ManifestStaticFilesStorage):
def _compile_scss(self):
to_exec = list(settings.STATIC_ROOT.rglob("*.scss"))
if len(to_exec) == 0:
return
for file in to_exec:
# remove existing css files that will be replaced
# keeping them while compiling the scss would break
# import statements resolution
css_file = file.with_suffix(".css")
if css_file.exists():
css_file.unlink()
scss_paths = [p.resolve() for p in to_exec if p.suffix == ".scss"]
base_args = {"output_style": "compressed", "precision": settings.SASS_PRECISION}
compiled_files = {
p: sass.compile(filename=str(p), **base_args) for p in scss_paths
}
for file, scss in compiled_files.items():
file.replace(file.with_suffix(".css")).write_text(scss)
# once the files are compiled, the manifest must be updated
# to have the right suffix
new_entries = {
k.replace(".scss", ".css"): self.hashed_files.pop(k).replace(
".scss", ".css"
)
for k in list(self.hashed_files.keys())
if k.endswith(".scss")
}
self.hashed_files.update(new_entries)
self.save_manifest()
@staticmethod
def _minify_js():
try:
subprocess.run(["uglifyjs", "-v"])
except FileNotFoundError:
warnings.warn(
"Couldn't minify JS files. Make sure UglifyJs is installed.",
stacklevel=1,
)
return
to_exec = [
p for p in settings.STATIC_ROOT.rglob("*.js") if ".min" not in p.suffixes
]
for path in to_exec:
p = path.resolve()
subprocess.run(["uglifyjs", p, "-o", p])
logging.getLogger("main").info(f"Minified {path}")
def post_process(
self, paths: dict[str, tuple[Storage, str]], *, dry_run: bool = False
):
# Whether we get the files that were processed by ManifestFilesMixin
# by calling super() or whether we get them from the manifest file
# makes no difference - we have to open the manifest file anyway
# because we need to update the paths stored inside it.
yield from super().post_process(paths, dry_run)
self._compile_scss()
self._minify_js()