Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new confinfiguration option HTML_COMPRESSOR and implemented new #833

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion docs/compressors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ css-html-js-minify compressor
=============================

The css-html-js-minify is full Python compressor using `css-html-js-minify <https://github.com/ciotto/css-html-js-minify>`_
for compressing javascript and stylesheets.
for compressing javascript, stylesheets and HTML.

To use it for your stylesheets add this to your ``PIPELINE['CSS_COMPRESSOR']`` ::

Expand All @@ -251,11 +251,49 @@ To use it for your javascripts add this to your ``PIPELINE['JS_COMPRESSOR']`` ::

PIPELINE['JS_COMPRESSOR'] = 'pipeline.compressors.csshtmljsminify.CssHtmlJsMinifyCompressor'

To use it for your HTML add this to your ``PIPELINE['HTML_COMPRESSOR']`` ::

PIPELINE['HTML_COMPRESSOR'] = 'pipeline.compressors.csshtmljsminify.CssHtmlJsMinifyCompressor'

Install the css-html-js-minify library with your favorite Python package manager ::

pip install css-html-js-minify


minify-html compressor
======================

The minify-html is a Rust HTML minifier with binding to Python
`minify-html <https://github.com/wilsonzlin/minify-html>`_
for compressing HTML.

To use it for your HTML add this to your ``PIPELINE['HTML_COMPRESSOR']`` ::

PIPELINE['HTML_COMPRESSOR'] = 'pipeline.compressors.minifyhtml.MinifyHtmlCompressor'

Install the minify-html library with your favorite Python package manager ::

pip install minify-html

``MINIFYHTML_PARAMS``
---------------------

Additional parameters to use when ``minify_html.minify()`` is called.

Defaults to ``{'do_not_minify_doctype': True, 'ensure_spec_compliant_unquoted_attribute_values': True, 'keep_spaces_between_attributes': True, 'minify_css': True, 'minify_js': True}``


Django HTML compressor
======================

Django's ``strip_spaces_between_tags()`` from ``django.utils.html`` to simply
strip spaces between HTML tags.

To use it for your HTML add this to your ``PIPELINE['HTML_COMPRESSOR']`` ::

PIPELINE['HTML_COMPRESSOR'] = 'pipeline.compressors.djangohtml.DjangoHtmlCompressor'


No-Op Compressors
=================

Expand All @@ -266,6 +304,7 @@ To use it, add this to your settings ::

PIPELINE['CSS_COMPRESSOR'] = 'pipeline.compressors.NoopCompressor'
PIPELINE['JS_COMPRESSOR'] = 'pipeline.compressors.NoopCompressor'
PIPELINE['HTML_COMPRESSOR'] = 'pipeline.compressors.NoopCompressor'


Write your own compressor class
Expand Down
9 changes: 9 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,15 @@ Defaults to ``'pipeline.compressors.yuglify.YuglifyCompressor'``

Please note that in order to use Yuglify compressor, you need to install Yuglify (see :doc:`installation` for more details).

``HTML_COMPRESSOR``
...................

Compressor class to be applied to HTML responses.

If empty or ``None``, HTML responses won't be compressed.

Defaults to ``'pipeline.compressors.djangohtml.DjangoHtmlCompressor'``

``TEMPLATE_NAMESPACE``
......................

Expand Down
14 changes: 14 additions & 0 deletions pipeline/compressors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ def js_compressor(self):
def css_compressor(self):
return to_class(settings.CSS_COMPRESSOR)

@property
def html_compressor(self):
return to_class(settings.HTML_COMPRESSOR)

def compress_js(
self,
paths: Sequence[str],
Expand Down Expand Up @@ -157,6 +161,13 @@ def compress_css(self, paths, output_filename, variant=None, **kwargs):
else:
raise CompressorError(f'"{variant}" is not a valid variant')

def compress_html(self, html, **kwargs):
"""Minify HTML response"""
compressor = self.html_compressor
if compressor:
html = getattr(compressor(verbose=self.verbose), "compress_html")(html)
return html

def compile_templates(self, paths):
compiled = []
if not paths:
Expand Down Expand Up @@ -441,3 +452,6 @@ def compress_js(self, js):

def compress_css(self, css):
return css

def compress_html(self, html):
return html
5 changes: 5 additions & 0 deletions pipeline/compressors/csshtmljsminify.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ def compress_js(self, js):
from css_html_js_minify import js_minify

return js_minify(js)

def compress_html(self, html):
from css_html_js_minify import html_minify

return html_minify(html)
12 changes: 12 additions & 0 deletions pipeline/compressors/djangohtml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from pipeline.compressors import CompressorBase


class DjangoHtmlCompressor(CompressorBase):
"""
Simple Django HTML minifier using 'django.utils.html.strip_spaces_between_tags()'
"""

def compress_html(self, html):
from django.utils.html import strip_spaces_between_tags as minify_html

return minify_html(html.strip())
14 changes: 14 additions & 0 deletions pipeline/compressors/minifyhtml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pipeline.compressors import CompressorBase
from pipeline.conf import settings


class MinifyHtmlCompressor(CompressorBase):
"""
HTML compressor based on the Python library minify-html
(https://pypi.org/project/minify-html).
"""

def compress_html(self, html):
import minify_html

return minify_html.minify(html, **settings.MINIFYHTML_PARAMS)
8 changes: 8 additions & 0 deletions pipeline/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"SHOW_ERRORS_INLINE": _settings.DEBUG,
"CSS_COMPRESSOR": "pipeline.compressors.yuglify.YuglifyCompressor",
"JS_COMPRESSOR": "pipeline.compressors.yuglify.YuglifyCompressor",
"HTML_COMPRESSOR": "pipeline.compressors.djangohtml.DjangoHtmlCompressor",
"COMPILERS": [],
"STYLESHEETS": {},
"JAVASCRIPT": {},
Expand Down Expand Up @@ -53,6 +54,13 @@
"STYLUS_ARGUMENTS": "",
"LESS_BINARY": "/usr/bin/env lessc",
"LESS_ARGUMENTS": "",
"MINIFYHTML_PARAMS": {
"do_not_minify_doctype": True,
"ensure_spec_compliant_unquoted_attribute_values": True,
"keep_spaces_between_attributes": True,
"minify_css": True,
"minify_js": True,
},
"MIMETYPES": (
(("text/coffeescript"), (".coffee")),
(("text/less"), (".less")),
Expand Down
8 changes: 6 additions & 2 deletions pipeline/middleware.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from django.contrib.staticfiles.storage import staticfiles_storage
from django.core.exceptions import MiddlewareNotUsed
from django.utils.deprecation import MiddlewareMixin
from django.utils.encoding import DjangoUnicodeDecodeError
from django.utils.html import strip_spaces_between_tags as minify_html

from pipeline.compressors import Compressor
from pipeline.conf import settings


Expand All @@ -17,8 +18,11 @@ def process_response(self, request, response):
response.has_header("Content-Type")
and "text/html" in response["Content-Type"]
):
compressor = Compressor(storage=staticfiles_storage, verbose=False)
try:
response.content = minify_html(response.content.decode("utf-8").strip())
response.content = compressor.compress_html(
response.content.decode("utf-8")
)
response["Content-Length"] = str(len(response.content))
except DjangoUnicodeDecodeError:
pass
Expand Down