New Upstream Release - flask-htmlmin

Ready changes

Summary

Merged new upstream version: 2.2.1 (was: 1.3.2).

Resulting package

Built on 2022-12-07T10:54 (took 8m54s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases python3-flask-htmlmin

Lintian Result

Diff

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index bcee5c2..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.idea/
-env/
-.DS_Store
diff --git a/Flask_HTMLmin.egg-info/PKG-INFO b/Flask_HTMLmin.egg-info/PKG-INFO
new file mode 100644
index 0000000..beb92a7
--- /dev/null
+++ b/Flask_HTMLmin.egg-info/PKG-INFO
@@ -0,0 +1,102 @@
+Metadata-Version: 2.1
+Name: Flask-HTMLmin
+Version: 2.2.1
+Summary: Minify flask text/html mime type responses
+Home-page: https://github.com/hamidfzm/Flask-HTMLmin
+Author: Hamid FzM
+Author-email: hamidfzm@gmail.com
+License: BSD-3-Clause
+Platform: any
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Text Processing :: Markup :: HTML
+Requires-Python: >=3.6
+Description-Content-Type: text/markdown
+License-File: LICENSE
+
+
+Flask-HTMLmin
+=============
+[![PyPI version](https://badge.fury.io/py/Flask-HTMLmin.svg)](https://badge.fury.io/py/Flask-HTMLmin)
+![Supported Python Versions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue.svg)
+[![License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](LICENSE)
+![tests](https://github.com/hamidfzm/Flask-HTMLmin/workflows/tests/badge.svg)
+[![codecov](https://codecov.io/gh/hamidfzm/Flask-HTMLmin/branch/master/graph/badge.svg)](https://codecov.io/gh/hamidfzm/Flask-HTMLmin)
+
+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 git@github.com:hamidfzm/Flask-HTMLmin.git
+    cd Flask-HTMLmin
+    python setup.py install
+
+
+Example
+-------
+```python
+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
+----
+- [x] Test cases
+- [x] Route (or URL rule) exemption
+- [x] Caching (in progress)
+- [x] Minify inline CSS
+- [ ] Minify inline Javascript
+- [ ] Type hints
diff --git a/Flask_HTMLmin.egg-info/SOURCES.txt b/Flask_HTMLmin.egg-info/SOURCES.txt
new file mode 100644
index 0000000..8de105d
--- /dev/null
+++ b/Flask_HTMLmin.egg-info/SOURCES.txt
@@ -0,0 +1,12 @@
+LICENSE
+MANIFEST.in
+README.md
+setup.cfg
+setup.py
+Flask_HTMLmin.egg-info/PKG-INFO
+Flask_HTMLmin.egg-info/SOURCES.txt
+Flask_HTMLmin.egg-info/dependency_links.txt
+Flask_HTMLmin.egg-info/not-zip-safe
+Flask_HTMLmin.egg-info/requires.txt
+Flask_HTMLmin.egg-info/top_level.txt
+flask_htmlmin/__init__.py
\ No newline at end of file
diff --git a/Flask_HTMLmin.egg-info/dependency_links.txt b/Flask_HTMLmin.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Flask_HTMLmin.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/Flask_HTMLmin.egg-info/not-zip-safe b/Flask_HTMLmin.egg-info/not-zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Flask_HTMLmin.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
diff --git a/Flask_HTMLmin.egg-info/requires.txt b/Flask_HTMLmin.egg-info/requires.txt
new file mode 100644
index 0000000..d7bc694
--- /dev/null
+++ b/Flask_HTMLmin.egg-info/requires.txt
@@ -0,0 +1,3 @@
+Flask
+cssmin
+htmlmin
diff --git a/Flask_HTMLmin.egg-info/top_level.txt b/Flask_HTMLmin.egg-info/top_level.txt
new file mode 100644
index 0000000..3940595
--- /dev/null
+++ b/Flask_HTMLmin.egg-info/top_level.txt
@@ -0,0 +1,2 @@
+HTMLMIN
+flask_htmlmin
diff --git a/LICENSE b/LICENSE
index d956996..21902a6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2015, Hamid Feizabadi
+Copyright (c) 2015-2022, Hamid Feizabadi
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -21,4 +21,4 @@ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..beb92a7
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,102 @@
+Metadata-Version: 2.1
+Name: Flask-HTMLmin
+Version: 2.2.1
+Summary: Minify flask text/html mime type responses
+Home-page: https://github.com/hamidfzm/Flask-HTMLmin
+Author: Hamid FzM
+Author-email: hamidfzm@gmail.com
+License: BSD-3-Clause
+Platform: any
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Text Processing :: Markup :: HTML
+Requires-Python: >=3.6
+Description-Content-Type: text/markdown
+License-File: LICENSE
+
+
+Flask-HTMLmin
+=============
+[![PyPI version](https://badge.fury.io/py/Flask-HTMLmin.svg)](https://badge.fury.io/py/Flask-HTMLmin)
+![Supported Python Versions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue.svg)
+[![License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](LICENSE)
+![tests](https://github.com/hamidfzm/Flask-HTMLmin/workflows/tests/badge.svg)
+[![codecov](https://codecov.io/gh/hamidfzm/Flask-HTMLmin/branch/master/graph/badge.svg)](https://codecov.io/gh/hamidfzm/Flask-HTMLmin)
+
+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 git@github.com:hamidfzm/Flask-HTMLmin.git
+    cd Flask-HTMLmin
+    python setup.py install
+
+
+Example
+-------
+```python
+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
+----
+- [x] Test cases
+- [x] Route (or URL rule) exemption
+- [x] Caching (in progress)
+- [x] Minify inline CSS
+- [ ] Minify inline Javascript
+- [ ] Type hints
diff --git a/README.md b/README.md
index 267d0b3..f830ad8 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,31 @@
+
 Flask-HTMLmin
 =============
+[![PyPI version](https://badge.fury.io/py/Flask-HTMLmin.svg)](https://badge.fury.io/py/Flask-HTMLmin)
+![Supported Python Versions](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8%20%7C%203.9-blue.svg)
+[![License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](LICENSE)
+![tests](https://github.com/hamidfzm/Flask-HTMLmin/workflows/tests/badge.svg)
+[![codecov](https://codecov.io/gh/hamidfzm/Flask-HTMLmin/branch/master/graph/badge.svg)](https://codecov.io/gh/hamidfzm/Flask-HTMLmin)
 
-Minify flask `text/html` mime types responses.
-Just add `MINIFY_PAGE = True` to your deployment config to minify html and text responses of your flask application.
+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:
+To install Flask-HTMLmin, simply use pip:
 
     pip install Flask-HTMLmin
 
-Or alternatively, you can download the repository and install manually by doing:
+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 git@github.com:hamidfzm/Flask-HTMLmin.git
     cd Flask-HTMLmin
@@ -20,27 +34,43 @@ Or alternatively, you can download the repository and install manually by doing:
 
 Example
 -------
-
-    from flask import Flask, render_template
-    from flask_htmlmin import HTMLMIN
-    
-    app = Flask(__name__)
-    app.config['MINIFY_PAGE'] = True
-    
-    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')
+```python
+from flask import Flask, render_template
+from flask_htmlmin import HTMLMIN
     
-    if __name__ == '__main__':
-        app.run()
-        
+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
+- [x] Test cases
+- [x] Route (or URL rule) exemption
+- [x] Caching (in progress)
+- [x] Minify inline CSS
+- [ ] Minify inline Javascript
+- [ ] Type hints
diff --git a/debian/changelog b/debian/changelog
index 290e9cb..a7a4ae8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+flask-htmlmin (2.2.1-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Wed, 07 Dec 2022 10:47:16 -0000
+
 flask-htmlmin (1.3.2-4) unstable; urgency=medium
 
   [ Debian Janitor ]
diff --git a/flask_htmlmin.py b/flask_htmlmin.py
deleted file mode 100644
index e1cdaff..0000000
--- a/flask_htmlmin.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from htmlmin import Minifier
-
-__author__ = 'Hamid FzM'
-
-
-class HTMLMIN(object):
-    def __init__(self, app=None, **kwargs):
-        self.app = app
-        if app is not None:
-            self.init_app(app)
-
-        default_options = {
-            'remove_comments': True,
-            'reduce_empty_attributes': True,
-            'remove_optional_attribute_quotes': False
-        }
-        default_options.update(kwargs)
-
-        self.html_minify = Minifier(
-            **default_options)
-
-    def init_app(self, app):
-        app.config.setdefault('MINIFY_PAGE', False)
-
-        if app.config['MINIFY_PAGE']:
-            app.after_request(self.response_minify)
-
-    def response_minify(self, response):
-        """
-        minify response html to decrease traffic
-        """
-        if response.content_type == u'text/html; charset=utf-8':
-            response.direct_passthrough = False
-            response.set_data(
-                self.html_minify.minify(response.get_data(as_text=True))
-            )
-
-            return response
-        return response
diff --git a/flask_htmlmin/__init__.py b/flask_htmlmin/__init__.py
new file mode 100644
index 0000000..3a5774e
--- /dev/null
+++ b/flask_htmlmin/__init__.py
@@ -0,0 +1,132 @@
+from functools import wraps
+from htmlmin import Minifier
+from flask import request, current_app
+import warnings
+import cssmin
+import re
+
+
+class HTMLMIN(object):
+    def __init__(self, app=None, **kwargs):
+        self.app = app
+        if app is not None:
+            self.init_app(app)
+
+        default_options = {
+            'remove_comments': True,
+            'reduce_empty_attributes': True,
+            'remove_optional_attribute_quotes': False
+        }
+
+        self.disable_css_min = kwargs.pop('disable_css_min', False)
+        default_options.update(kwargs)
+        self.opts = default_options
+
+        self._exempt_routes = set()
+        self._html_minify = Minifier(
+            **default_options)
+
+    def init_app(self, app):
+        app.config.setdefault('MINIFY_HTML', False)
+
+        if 'MINIFY_PAGE' in app.config:
+            app.config['MINIFY_HTML'] = app.config['MINIFY_PAGE']
+            warnings.warn(
+                'MINIFY_PAGE is deprecated, use MINIFY_HTML instead',
+                DeprecationWarning,
+                stacklevel=2
+            )
+
+        if app.config['MINIFY_HTML']:
+            app.after_request(self.response_minify)
+
+    def response_minify(self, response):
+        """
+        minify response html to decrease traffic
+        """
+
+        if response.content_type == u'text/html; charset=utf-8':
+            endpoint = request.endpoint or ''
+            view_func = current_app.view_functions.get(endpoint, None)
+            name = (
+                '%s.%s' % (view_func.__module__, view_func.__name__)
+                if view_func else ''
+            )
+            if name in self._exempt_routes:
+                return response
+
+            response.direct_passthrough = False
+            if self.disable_css_min:
+                response.set_data(
+                    self._html_minify.minify(response.get_data(as_text=True))
+                )
+            else:
+                response.set_data(
+                    self._css_minify(
+                      self._html_minify.minify(
+                           response.get_data(as_text=True)
+                       )
+                     )
+                )
+
+            return response
+        return response
+
+    def _css_minify(self, response):
+        """
+            Minify inline css
+        """
+
+        # Minify internal css
+        out = ''
+        text = response
+        opening_tags = re.findall(r"<style\s*[^>]*>", text, re.M | re.I)
+        for tag in opening_tags:
+            i = text.find(tag)+len(tag)-1
+            e = text.find("</style>")+9
+            css = text[i:e]
+            out += text[0:i] + self._min_css(css)
+            text = text[e:]
+        out = out+text
+
+        # Minify inline css
+        out2 = ''
+        inlines = re.findall(r"<[A-Za-z0-9-]+[^>]+?style=\"[\s\S]+?\"",
+                             out,  re.M | re.I)
+        for inline in inlines:
+            i = out.find(inline)
+            j = out[i:].find("style=")+7
+            k = out[i+j:].find('"')
+            css = out[i+j:i+j+k+1]
+            out2 += out[0:i+j] + re.sub(r";+\s*(?=(\"|\'))", "",
+                                        self._min_css(css), re.I | re.M)
+            out = out[i+j+k+1:]
+        out2 += out
+        return out2
+
+    def _min_css(self, css):
+        if self.opts.get("remove_comments"):
+            css = cssmin.remove_comments(css)
+        css = cssmin.condense_whitespace(css)
+        css = css.replace('"\\"}\\""', "___PSEUDOCLASSBMH___")
+        css = cssmin.remove_unnecessary_whitespace(css)
+        css = cssmin.remove_unnecessary_semicolons(css)
+        css = cssmin.condense_zero_units(css)
+        css = cssmin.condense_multidimensional_zeros(css)
+        css = cssmin.condense_floating_points(css)
+        css = cssmin.normalize_rgb_colors_to_hex(css)
+        css = cssmin.condense_hex_colors(css)
+        return css
+
+    def exempt(self, obj):
+        """
+        decorator to mark a view as exempt from htmlmin.
+        """
+        name = '%s.%s' % (obj.__module__, obj.__name__)
+
+        @wraps(obj)
+        def __inner(*a, **k):
+            return obj(*a, **k)
+
+        self._exempt_routes.add(name)
+        return __inner
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..df5ccc9
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,11 @@
+[aliases]
+test = 'pytest'
+
+[tool:pytest]
+addopts = -s -p no:warnings --verbose
+python_files = test.py
+
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff --git a/setup.py b/setup.py
old mode 100644
new mode 100755
index 8b82aaf..78e28ca
--- a/setup.py
+++ b/setup.py
@@ -1,40 +1,51 @@
+#!/usr/bin/env python
 
 """
 Flask-HTMLmin
 -------------
 
-minimize your flask rendered html
+Minify flask text/html mime type responses
 """
 
 from setuptools import setup
 
+with open('README.md', 'r') as fh:
+    long_description = fh.read()
+
 setup(
     name='Flask-HTMLmin',
-    version='1.3.2',
+    version='2.2.1',
     url='https://github.com/hamidfzm/Flask-HTMLmin',
     license='BSD-3-Clause',
     author='Hamid FzM',
     author_email='hamidfzm@gmail.com',
-    description='Minimize render templates html',
-    long_description=__doc__,
-    py_modules=['flask_htmlmin'],
+    description="Minify flask text/html mime type responses",
+    long_description=long_description,
+    long_description_content_type='text/markdown',
+    py_modules=['HTMLMIN'],
+    packages=['flask_htmlmin'],
     zip_safe=False,
     include_package_data=True,
     platforms='any',
     install_requires=[
         'Flask',
-        'htmlmin'
+        'htmlmin',
+        'cssmin'
     ],
+    python_requires='>=3.6',
     classifiers=[
         'Environment :: Web Environment',
         'Intended Audience :: Developers',
         'License :: OSI Approved :: BSD License',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
-        'Programming Language :: Python :: 2.7',
-        'Programming Language :: Python :: 3.2',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
+        'Programming Language :: Python :: 3.9',
         'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Topic :: Software Development :: Libraries :: Python Modules',
         'Topic :: Text Processing :: Markup :: HTML',
-    ]
+    ],
 )

More details

Full run details