Flask html response minifier

Overview

Flask-HTMLmin

PyPI version Supported Python Versions License tests codecov

Minify flask text/html mime type responses. Just add MINIFY_HTML = True to your deployment config to minify HTML and text responses of your flask application.

Installation

To install Flask-HTMLmin, simply use pip:

pip install Flask-HTMLmin

Or use pipenv:

pipenv install Flask-HTMLmin

Or use poetry:

poetry add Flask-HTMLmin

Or alternatively, you can download the repository and install it manually by doing:

git clone [email protected]:hamidfzm/Flask-HTMLmin.git
cd Flask-HTMLmin
python setup.py install

Example

from flask import Flask, render_template
from flask_htmlmin import HTMLMIN
    
app = Flask(__name__)
app.config['MINIFY_HTML'] = True

htmlmin = HTMLMIN(app)
# or you can use HTMLMIN.init_app(app)
# pass additional parameters to htmlmin
# HTMLMIN(app, **kwargs)
# example:
# htmlmin = HTMLMIN(app, remove_comments=False, remove_empty_space=True, disable_css_min=True)


@app.route('/')
def main():
    # index.html will be minimized !!!
    return render_template('index.html')


@app.route('/exempt')
@htmlmin.exempt
def exempted_route():
    # index.html will be exempted and not blessed by holy htmlmin !!!
    return render_template('index.html')


if __name__ == '__main__':
    app.run()

TODO

  • Test cases
  • Route (or URL rule) exemption
  • Caching (in progress)
  • Minify inline CSS
  • Minify inline Javascript
  • Type hints
Comments
  • utf8 crash

    utf8 crash

    Hello

    Tried out the module .. ran into an error. [2018-08-01 11:14:04 +0000] [2320] [INFO] Starting gunicorn 19.9.0 [2018-08-01 11:14:04 +0000] [2320] [INFO] Listening at: http://0.0.0.0:5000 (2320) [2018-08-01 11:14:04 +0000] [2320] [INFO] Using worker: gevent [2018-08-01 11:14:04 +0000] [2324] [INFO] Booting worker with pid: 2324 [2018-08-01 11:14:04 +0000] [2325] [INFO] Booting worker with pid: 2325 [2018-08-01 11:14:09 +0000] [2325] [ERROR] Error handling request / Traceback (most recent call last): File "/home/anon/miniconda2/lib/python2.7/site-packages/gunicorn/workers/base_async.py", line 56, in handle self.handle_request(listener_name, req, client, addr) File "/home/anon/miniconda2/lib/python2.7/site-packages/gunicorn/workers/ggevent.py", line 160, in handle_request addr) File "/home/anon/miniconda2/lib/python2.7/site-packages/gunicorn/workers/base_async.py", line 107, in handle_request respiter = self.wsgi(environ, resp.start_response) File "/home/anon/miniconda2/lib/python2.7/site-packages/flask/app.py", line 2309, in call return self.wsgi_app(environ, start_response) File "/home/anon/miniconda2/lib/python2.7/site-packages/flask/app.py", line 2295, in wsgi_app response = self.handle_exception(e) File "/home/anon/miniconda2/lib/python2.7/site-packages/flask/app.py", line 1741, in handle_exception reraise(exc_type, exc_value, tb) File "/home/anon/miniconda2/lib/python2.7/site-packages/flask/app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "/home/anon/miniconda2/lib/python2.7/site-packages/flask/app.py", line 1816, in full_dispatch_request return self.finalize_request(rv) File "/home/anon/miniconda2/lib/python2.7/site-packages/flask/app.py", line 1833, in finalize_request response = self.process_response(response) File "/home/anon/miniconda2/lib/python2.7/site-packages/flask/app.py", line 2112, in process_response response = handler(response) File "/home/anon/miniconda2/lib/python2.7/site-packages/flask_htmlmin/init.py", line 35, in response_minify self.html_minify.minify(response.get_data(as_text=True)) File "/home/anon/miniconda2/lib/python2.7/site-packages/werkzeug/wrappers.py", line 989, in get_data rv = rv.decode(self.charset) File "/home/anon/miniconda2/lib/python2.7/encodings/utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0x8b in position 1: invalid start byte

    wontfix 
    opened by ra-esmith 18
  • OpenTagNotFoundError() redirect code 302

    OpenTagNotFoundError() redirect code 302

    https://github.com/hamidfzm/Flask-HTMLmin/blob/82f828bc6a39d2672bfd152db353e0ee563b48c1/flask_htmlmin.py#L32

    if you use flask.redirect, this redirection with code 302 and the response: https://github.com/pallets/werkzeug/blob/4397e61daf66ad43bd5668741c5d876de116a71f/werkzeug/utils.py#L373

    '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'
    '<title>Redirecting...</title>\n'
    '<h1>Redirecting...</h1>\n'
    '<p>You should be redirected automatically to target URL: '
    '<a href="%s">%s</a>. If not click the link.'
    

    for htmlmin.parser is not valid: https://github.com/mankyd/htmlmin/blob/dff1163a1ec25fe94aeaeefe702377b5a9e912b3/htmlmin/parser.py#L261

    that gives an error OpenTagNotFoundError()

    bug 
    opened by citijk 11
  • unexpected call to parse_endtag

    unexpected call to parse_endtag

    Hi. Getting a sporadic error 'unexpected call to parse_endtag". I haven't been able to replicate the issue reliably.

    Occurs here in parse.py file in htmlmin. assert rawdata[i:i+2] == "</", "unexpected call to parse_endtag"

    However as a suggestion, perhaps a try except AssertionError should be added to the reponse_minify method. This way even if the error does occur, the final webpage is still rendered as the original unminified response is returned.

    wontfix 
    opened by arcane99 4
  • Stop using pytest-runner

    Stop using pytest-runner

    setup_requires and tests_requires are firmly deprecated by setuptools upstream, and pytest-runner similarly, since it makes use of functionality that setuptools would like to remove. Stop setting {setup,test}_requires in setup.py, and remove pytest-runner from Pipfile.

    Fixes #29

    opened by s-t-e-v-e-n-k 3
  • Can we read htmlmin options from the flask config file?

    Can we read htmlmin options from the flask config file?

    Hi, thanks for the tool!

    What do you think about allowing these settings to be set in the app.config?

    default_options = {
                'remove_comments': True,
                'reduce_empty_attributes': True,
                'remove_optional_attribute_quotes': False
            }
    default_options.update(kwargs)
    

    As well as the other options for htmlmin from https://htmlmin.readthedocs.io/en/latest/reference.html?

    Personally, I'd really like to add the "remove_empty_space". Somehow my output has whitespace between all tags, for example the closing tags on my homepage look like this -

    </div> </div> </div> </body> </html>
    
    opened by christopherpickering 2
  • Example not working

    Example not working

    I'm testing the example provided in README:

    from flask import Flask, render_template
    from flask_htmlmin import HTMLMIN
        
    app = Flask(__name__)
    app.config['MINIFY_PAGE'] = True
    
    htmlmin = HTMLMIN(app)
    # or you can use HTMLMIN.init_app(app)
    # pass additional parameters to htmlmin
    # HTMLMIN(app, **kwargs)
    
    @app.route('/')
    def main():
        # index.html will be minimized !!!
        return render_template('index.html')
    
    
    @app.route('/exempt')
    @htmlmin.exempt
    def exempted_route():
        # index.html will be exempted and not blessed by holy htmlmin !!!
        return render_template('index.html')
    
    
    if __name__ == '__main__':
        app.run()
    

    And this is my templates/index.html

    <html>
      <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
      </head>
    
      <body>
        <div>
          Hello
        </div>
        <div>
          World
        </div>
      </body>
    </html>
    

    I'm using python 3.7.2 and there is no minified output.

    opened by wiltonsr 2
  • Example not working

    Example not working

    I don't know exactly why, but the example doesn't work in my environment. No minify output.

    However your other answer works fine.

    http://stackoverflow.com/a/26139704/564979

    ty

    enhancement 
    opened by ar-anvd 2
  • disable_css_min argument leads to error in initialization

    disable_css_min argument leads to error in initialization

    Using the example I get this:

    htmlmin = HTMLMIN(app, remove_comments=False, remove_empty_space=True, disable_css_min=True)

    TypeError: unexpected keyword argument 'disable_css_min'

    Also, when I install via pip, I get this: Using legacy setup.py install for Flask-HTMLmin, since package 'wheel' is not installed.

    bug 
    opened by akcode47 1
  • Bump urllib3 from 1.26.4 to 1.26.5

    Bump urllib3 from 1.26.4 to 1.26.5

    Bumps urllib3 from 1.26.4 to 1.26.5.

    Release notes

    Sourced from urllib3's releases.

    1.26.5

    :warning: IMPORTANT: urllib3 v2.0 will drop support for Python 2: Read more in the v2.0 Roadmap

    • Fixed deprecation warnings emitted in Python 3.10.
    • Updated vendored six library to 1.16.0.
    • Improved performance of URL parser when splitting the authority component.

    If you or your organization rely on urllib3 consider supporting us via GitHub Sponsors

    Changelog

    Sourced from urllib3's changelog.

    1.26.5 (2021-05-26)

    • Fixed deprecation warnings emitted in Python 3.10.
    • Updated vendored six library to 1.16.0.
    • Improved performance of URL parser when splitting the authority component.
    Commits
    • d161647 Release 1.26.5
    • 2d4a3fe Improve performance of sub-authority splitting in URL
    • 2698537 Update vendored six to 1.16.0
    • 07bed79 Fix deprecation warnings for Python 3.10 ssl module
    • d725a9b Add Python 3.10 to GitHub Actions
    • 339ad34 Use pytest==6.2.4 on Python 3.10+
    • f271c9c Apply latest Black formatting
    • 1884878 [1.26] Properly proxy EOF on the SSLTransport test suite
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • Adding test cases

    Adding test cases

    Hi @hamidfzm thanks for the extension. I'm adding test cases with pytest and 100% coverage tested on py2.7 and py.3.6 to run test python setup.py test

    opened by mrf345 1
  • Ignore OpenTagNotFoundError errors from htmlmin

    Ignore OpenTagNotFoundError errors from htmlmin

    htmlmin raises OpenTagNotFoundError in some cases (origin unclear). Catch the exception and pass the input through un-minified.

    Works around #10, mankyd/htmlmin#46.

    opened by df7cb 1
Releases(v2.2.1)
  • v2.2.1(Oct 24, 2022)

    What's Changed

    • Stop using pytest-runner by @s-t-e-v-e-n-k in https://github.com/hamidfzm/Flask-HTMLmin/pull/31
    • Fix documentation error in README by @bfontaine in https://github.com/hamidfzm/Flask-HTMLmin/pull/32
    • Fix https://github.com/hamidfzm/Flask-HTMLmin/issues/30 by @hamidfzm

    New Contributors

    • @s-t-e-v-e-n-k made their first contribution in https://github.com/hamidfzm/Flask-HTMLmin/pull/31
    • @bfontaine made their first contribution in https://github.com/hamidfzm/Flask-HTMLmin/pull/32

    Full Changelog: https://github.com/hamidfzm/Flask-HTMLmin/compare/v2.2.0...v2.2.1

    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Oct 18, 2021)

  • v2.1.0(Feb 10, 2021)

  • v2.0.3(Feb 10, 2021)

  • v2.0.2(Mar 30, 2020)

  • v2.0.1(Mar 30, 2020)

  • v2.0.0(Mar 30, 2020)

    This release comes in the midst of a global pandemic. Wish you a healthy life with lots of success.

    • Dropped support for Python 2.7 (setuptools stopped supporting it so basically you can't install this project in Python 2.7)
    • Migrate from Travis CI to Github Actions
    • Migrate from Coveralls to Codecov
    • Update README
    • Update PyPI description
    • Fix comments typo (@timgates42)
    Source code(tar.gz)
    Source code(zip)
  • v1.5.2(Oct 24, 2019)

    • Fix setup.py issues
    • Update setup.py categories
    • Fix tests
    • Change MINIFY_PAGE to MINIFY_HTML
    • Add deprecation warning for old config

    I'm going to implement a caching solution for minified HTML. Any suggestions would be greatly appreciated.

    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Oct 20, 2018)

    • Add Route (or URL rule) exemption (@hamidfzm)
    • Update tests (@hamidfzm)
    • Add python 3.7 support (@hamidfzm)
    • Update README (@hamidfzm)
      • Example
      • Badges
    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Jul 22, 2018)

  • v1.3.2(Mar 18, 2018)

  • v1.3.1(Oct 7, 2017)

  • v1.3.0(Oct 5, 2017)

  • v1.2.1(Jul 17, 2017)

  • v1.2(Jun 30, 2016)

  • v1.1(Jan 14, 2016)

Owner
Hamid Feizabadi
Web Developer, Python, Go
Hamid Feizabadi
Domoticz-hyundai-kia - Domoticz Hyundai-Kia plugin for Domoticz home automation system

Domoticz Hyundai-Kia plugin Author: Creasol https://www.creasol.it/domotics For

Creasol 7 Aug 03, 2022
Small pip update helpers.

pipdate pipdate is a collection of small pip update helpers. The command pipdate # or python3.9 -m pipdate updates all your pip-installed packages. (O

Nico Schlömer 69 Dec 18, 2022
Fly DCS without a joystick

Intro Usage Delete all mouse view axis Install DCSEasyControlExports to your "Saved Games/DCS/" Path python DCSEasyControl/main.py Set DCS to F12 view

XuHao 36 Dec 27, 2022
The ROS package for Airbotics.

airbotics The ROS package for Airbotics: Developed for ROS 1 and Python 3.8. The package has not been officially released on ROS yet so manual install

Airbotics 19 Dec 25, 2022
Framework To Ease Operating with Quantum Computers

QType Framework To Ease Operating with Quantum Computers Concept # define an array of 15 cubits:

Antonio Párraga Navarro 2 Jun 06, 2022
Howell County, Missouri, COVID-19 data and (unofficial) estimates

COVID-19 in Howell County, Missouri This repository contains the daily data files used to generate my COVID-19 dashboard for Howell County, Missouri,

Jonathan Thornton 0 Jun 18, 2022
Auto-ropper is a tool that aims to automate the exploitation of ROP.

Auto-ropper is a tool that aims to automate the exploitation of ROP. Its goal is to become a tool that no longer requires user interaction.

Zerotistic 16 Nov 13, 2022
OnTime is a small python that you set a time and on that time, app will send you notification and also play an alarm.

OnTime Always be OnTime! What is OnTime? OnTime is a small python that you set a time and on that time, app will send you notification and also play a

AmirHossein Mohammadi 11 Jan 16, 2022
Create rangebased on lists or values of the range itself. Range any type. Can you imagine?

funcao-allrange-for-python3 Create rangebased on lists or values of the range itself. Range any type. Can you imagine? WARNING!!! THIS MODULE DID NOT

farioso-fernando 1 Feb 09, 2022
Deis v1, the CoreOS and Docker PaaS: Your PaaS. Your Rules.

This repository (deis/deis) is no longer developed or maintained. The Deis v1 PaaS based on CoreOS Container Linux and Fleet has been replaced by Deis

Deis 6.1k Jan 04, 2023
Dungeon Dice Rolls is an aplication that the user can roll dices (d4, d6, d8, d10, d12, d20 and d100) and store the results in one of the 6 arrays.

Dungeon Dice Rolls is an aplication that the user can roll dices (d4, d6, d8, d10, d12, d20 and d100) and store the results in one of the 6 arrays.

Bracero 1 Dec 31, 2021
More routines for operating on iterables, beyond itertools

More Itertools Python's itertools library is a gem - you can compose elegant solutions for a variety of problems with the functions it provides. In mo

2.8k Jan 02, 2023
This is a calculator of strike price distance for options.

Calculator-of-strike-price-distance-for-options This is a calculator of strike price distance for options. Options are a type of derivative. One strat

André Luís Lopes da Silva 4 Dec 30, 2022
Helps to arrange nodes

Relax brush for nodes, helps to arrange nodes easier.

336 Dec 15, 2022
dbt adapter for Firebolt

dbt-firebolt dbt adapter for Firebolt dbt-firebolt supports dbt 0.21 and newer Installation First, download the JDBC driver and place it wherever you'

23 Dec 14, 2022
NCAR/UCAR virtual Python Tutorial Seminar Series lesson on MetPy.

The Project Pythia Python Tutorial Seminar Series continues with a lesson on MetPy on Wednesday, 2 February 2022 at 1 PM Mountain Standard Time.

Project Pythia Tutorials 6 Oct 09, 2022
Weblate is a copylefted libre software web-based continuous localization system

Weblate is a copylefted libre software web-based continuous localization system, used by over 2500 libre projects and companies in more than 165 count

Weblate 7 Dec 15, 2022
Beginner Projects A couple of beginner projects here

Beginner Projects A couple of beginner projects here, listed from easiest to hardest :) selector.py: simply a random selector to tell me who to faceti

Kylie 272 Jan 07, 2023
Official repository for the BPF Performance Tools book

BPF Performance Tools This is the official repository of BPF (eBPF) tools from the book BPF Performance Tools: Linux and Application Observability. Th

Brendan Gregg 1.2k Dec 28, 2022
A class to draw curves expressed as L-System production rules

A class to draw curves expressed as L-System production rules

Juna Salviati 6 Sep 09, 2022