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
Port of the OpenCascade library to JavaScript / WebAssembly using Emscripten

OpenCascade.js A port of the OpenCascade CAD library to JavaScript and WebAssembly via Emscripten. Explore the docs » Examples · Issues · Discuss Proj

Sebastian Alff 347 Jan 08, 2023
Absolute solvation free energy calculations with OpenFF and OpenMM

ABsolute SOLVantion Free Energy Calculations The absolv framework aims to offer a simple API for computing the change in free energy when transferring

7 Dec 07, 2022
Blender 3.1 Alpha (and later) PLY importer that correctly loads point clouds (and all PLY models as point clouds)

import-ply-as-verts Blender 3.1 Alpha (and later) PLY importer that correctly loads point clouds (and all PLY models as point clouds) Latest News Mand

Michael Prostka 82 Dec 20, 2022
This library is an ongoing effort towards bringing the data exchanging ability between Java/Scala and Python

PyJava This library is an ongoing effort towards bringing the data exchanging ability between Java/Scala and Python

Byzer 6 Oct 17, 2022
This library attempts to abstract the handling of Sigma rules in Python

This library attempts to abstract the handling of Sigma rules in Python. The rules are parsed using a schema defined with pydantic, and can be easily loaded from YAML files into a structured Python o

Caleb Stewart 44 Oct 29, 2022
Here You will Find CodeChef Challenge Solutions

Here You will Find CodeChef Challenge Solutions

kanishk kashyap 1 Sep 03, 2022
a url shortener with fastapi and tortoise-orm

fastapi-tortoise-orm-url-shortener a url shortener with fastapi and tortoise-orm

19 Aug 12, 2022
An extensive password manager built using Python, multiple implementations. Something to meet everyone's taste.

An awesome open-sourced password manager! Explore the docs » View Demo · Report Bug · Request Feature 🐍 Python Password Manager 🔐 An extensive passw

Sam R 7 Sep 28, 2021
Export transactions for an algorand wallet to a CSV file

algorand_txn_csv_exporter - (Algorand transaction CSV exporter) This script will export transactions for an algorand wallet to a CSV file. It is inten

TeneoPython01 5 Jun 19, 2022
Magenta: Music and Art Generation with Machine Intelligence

Magenta is a research project exploring the role of machine learning in the process of creating art and music. Primarily this involves developing new

Magenta 18.1k Jan 05, 2023
Daily knowledge pills to get better in Python.

Python daily pills Daily knowledge pills to get better Python code. Why Does your Python code suffers of any of this symptoms? Incorrect Indentation I

Jeferson Vaz dos Santos 35 Sep 19, 2022
For my Philips Airpurifier AC3259/10

Philips-Airpurifier For my Philips Airpurifier AC3259/10 I will try to keep this code

AcidSleeper 7 Feb 26, 2022
Liquid Rocket Engine Cooling Simulation

Liquid Rocket Engine Cooling Simulation NASA CEA The implemented class calls NASA CEA via RocketCEA. INSTALL GUIDE In progress install instructions fo

John Salib 1 Jan 30, 2022
MiniJVM is simple java virtual machine written by python language, it can load class file from file system and run it.

MiniJVM MiniJVM是一款使用python编写的简易JVM,能够从本地加载class文件并且执行绝大多数指令。 支持的功能 1.从本地磁盘加载class并解析 2.支持绝大多数指令集的执行 3.支持虚拟机内存分区以及对象的创建 4.支持方法的调用和参数传递 5.支持静态代码块的初始化 不支

keguoyu 60 Apr 01, 2022
Automated Changelog/release note generation

Quickly generate changelogs and release notes by analysing your git history. A tool written in python, but works on any language.

Documatic 95 Jan 03, 2023
Free version of Okuru selfbot, okuru.xyz

Indigo Selfbot Free OpenSource selfbot, Premium version can be found at https://okuru.xyz (5$.) Usage python[3] main.py Installation To install you ca

Dimitri Demarkus 31 Aug 07, 2022
Python binding to rust zw-fast-quantile

zw_fast_quantile_py zw-fast-quantile python binding Installation pip install zw_fast_quantile_py Usage import zw_fast_quantile_py

Paul Meng 1 Dec 30, 2021
CountdownTimer - Countdown Timer For Python

Countdown Timer This python script asks for the user time (input) in seconds, an

Arinzechukwu Okoye 1 Jan 01, 2022
Beancount: Double-Entry Accounting from Text Files.

beancount: Double-Entry Accounting from Text Files Contents Description Documentation Download & Installation Versions Filing Bugs Copyright and Licen

2.3k Dec 28, 2022
Simple rofi script to choose player for playerctl to execute its command

rofi-playerctl-switcher simple rofi script to choose player for playerctl to execute its command Usage copy playerSwitch.py and playerctl.sh to ~/.con

2 Jan 03, 2022