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
Курс "Искусственный интеллект и машинное обучение"

Искусственный интеллект и машинное обучение О курсе Данный репозиторий содержит в себе сопроводительный учебный материал для курса "Искусственный инте

Dmitry Aladin 19 Dec 04, 2022
Identifies the faulty wafer before it can be used for the fabrication of integrated circuits and, in photovoltaics, to manufacture solar cells.

Identifies the faulty wafer before it can be used for the fabrication of integrated circuits and, in photovoltaics, to manufacture solar cells. The project retrains itself after every prediction, mak

Arun Singh Babal 2 Jul 01, 2022
Aim of the project is to reduce phishing victims. 😇

Sites: For more details visit our Blog. How to use 😀 : You just have to paste the url in the ENTER THE SUSPECTED URL section and SELECT THE RESEMBELI

0 May 19, 2022
Social reading and reviewing, decentralized with ActivityPub

BookWyrm Social reading and reviewing, decentralized with ActivityPub Contents Joining BookWyrm Contributing About BookWyrm What it is and isn't The r

BookWyrm 1.4k Jan 08, 2023
Build your own Etherscan with web3.py

Build your own Etherscan with web3.py Video Tutorial: Run it pip3 install -r requirements.txt export FLASK_APP=app export FLASK_ENV=development flask

35 Jan 02, 2023
thonny plugin for gitonic

thonny-gitonic thonny plugin for gitonic open gitonic in thonny by pressing Control+Shift+g, or via tools menu press ESC key to minimize gitonic windo

karl 1 Apr 12, 2022
Python version of RocketLeague-Dropshot-Calculated-shot

Python version of RocketLeague-Dropshot-Calculated-shot. This is just to demo around and a tool I used to develop the actual plugin.

JareBear 1 Jan 14, 2022
A python script that fetches the grades of a student from a WAEC result in pdf format.

About waec-result-analyzer A python script that fetches the grades of a student from a WAEC result in pdf format. Built for federal government college

Oshodi Kolapo 2 Dec 04, 2021
pythonOS: An operating system kernel made in python and assembly

pythonOS An operating system kernel made in python and assembly Wait what? It uses a custom compiler called snek that implements a part of python3.9 (

Abbix 69 Dec 23, 2022
Why write code when you can import it directly from GitHub Copilot?

Copilot Importer Why write code when you can import it directly from GitHub Copilot? What is Copilot Importer? The copilot python module will dynamica

Mythic 41 Jan 04, 2023
Djangoblog - A blogging site where people can make their accout and write blogs and read other author's blogs

This a blogging site where people can make their accout and write blogs and read other author's blogs.

1 Jan 26, 2022
calculadora financiera hecha en python

Calculadora financiera Calculadora de factores financieros basicos, puede calcular tanto factores como expresiones algebraicas en funcion de dichos fa

crudo 5 Nov 10, 2021
Python dictionaries with advanced dot notation access

from box import Box movie_box = Box({ "Robin Hood: Men in Tights": { "imdb stars": 6.7, "length": 104 } }) movie_box.Robin_Hood_Men_in_Tights.imdb_s

Chris Griffith 2.1k Dec 28, 2022
A collection of design patterns and idioms in Python (With tests!).

Python Patterns Help the project financially: Donate: https://smartlegion.github.io/donate/ Yandex Money: https://yoomoney.ru/to/4100115206129186 PayP

5 Sep 12, 2021
CoreSE - basic of social Engineering tool

Core Social Engineering basic of social Engineering tool. just for fun :) About First of all, I must say that I wrote such a project because of my int

Hamed Mohammadvand 7 Jun 10, 2022
All exercises done during the Python 3 course in the Video Course (World 1, 2 and 3)

Python3-cursoemvideo-exercises - All exercises done during the Python 3 course in the Video Course (World 1, 2 and 3)

Renan Barbosa 3 Jan 17, 2022
A repository for all ZenML projects that are specific production use-cases.

ZenFiles Original Image source: https://www.goodfon.com/wallpaper/x-files-sekretnye-materialy.html And naturally, all credits to the awesome X-Files s

ZenML 66 Jan 06, 2023
Find virtual hosts (vhosts) from IP addresses and hostnames

Features Enumerate vhosts from a list of IP addresses and domain names. Virtual Hosts are enumerated using the following process: Supplied domains are

3 Jul 09, 2022
An example project which contains the Unity components necessary to complete Navigation2's SLAM tutorial with a Turtlebot3, using a custom Unity environment in place of Gazebo.

Navigation 2 SLAM Example This example provides a Unity Project and a colcon workspace that, when used together, allows a user to substitute Unity as

Unity Technologies 183 Jan 04, 2023