From 3f6ad35ed1dfc5c2cb4139e5c6abfdf578ef3669 Mon Sep 17 00:00:00 2001
From: Fabien Meghazi <fme@openerp.com>
Date: Thu, 18 Sep 2014 17:37:49 +0200
Subject: [PATCH] [ADD] Add an html compressor option in website settings

---
 addons/website/models/ir_qweb.py    | 21 +++++++++++++++++++++
 addons/website/models/res_config.py |  1 +
 addons/website/models/website.py    |  3 ++-
 addons/website/views/res_config.xml |  8 ++++++++
 openerp/addons/base/ir/ir_qweb.py   | 10 ++++++++--
 5 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py
index 9d528c9329bb..1e328e5af46b 100644
--- a/addons/website/models/ir_qweb.py
+++ b/addons/website/models/ir_qweb.py
@@ -45,6 +45,14 @@ class QWeb(orm.AbstractModel):
         'a': 'href',
     }
 
+    re_remove_spaces = re.compile('\s+')
+    PRESERVE_WHITESPACE = [
+        'pre',
+        'textarea',
+        'script',
+        'style',
+    ]
+
     def add_template(self, qcontext, name, node):
         # preprocessing for multilang static urls
         if request.website:
@@ -67,6 +75,19 @@ class QWeb(orm.AbstractModel):
             'website.qweb.field.' + field_type,
             self.pool['website.qweb.field'])
 
+    def render_text(self, text, element, qwebcontext):
+        compress = request and not request.debug and request.website and request.website.compress_html
+        if compress and element.tag not in self.PRESERVE_WHITESPACE:
+            text = self.re_remove_spaces.sub(' ', text.lstrip())
+        return super(QWeb, self).render_text(text, element, qwebcontext)
+
+    def render_tail(self, tail, element, qwebcontext):
+        compress = request and not request.debug and request.website and request.website.compress_html
+        if compress and element.getparent().tag not in self.PRESERVE_WHITESPACE:
+            # No need to recurse because those tags children are not html5 parser friendly
+            tail = self.re_remove_spaces.sub(' ', tail.rstrip())
+        return super(QWeb, self).render_tail(tail, element, qwebcontext)
+
 class Field(orm.AbstractModel):
     _name = 'website.qweb.field'
     _inherit = 'ir.qweb.field'
diff --git a/addons/website/models/res_config.py b/addons/website/models/res_config.py
index dd86f8246027..4b757eb5ec07 100644
--- a/addons/website/models/res_config.py
+++ b/addons/website/models/res_config.py
@@ -19,6 +19,7 @@ class website_config_settings(osv.osv_memory):
         'social_linkedin': fields.related('website_id', 'social_linkedin', type="char", string='LinkedIn Account'),
         'social_youtube': fields.related('website_id', 'social_youtube', type="char", string='Youtube Account'),
         'social_googleplus': fields.related('website_id', 'social_googleplus', type="char", string='Google+ Account'),
+        'compress_html': fields.related('website_id', 'compress_html', type="boolean", string='Compress HTML'),
     }
 
     def on_change_website_id(self, cr, uid, ids, website_id, context=None):
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index b2d1bb67d6db..33f62b0e0582 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -162,13 +162,14 @@ class website(osv.osv):
         'social_googleplus': fields.char('Google+ Account'),
         'google_analytics_key': fields.char('Google Analytics Key'),
         'user_id': fields.many2one('res.users', string='Public User'),
+        'compress_html': fields.boolean('Compress HTML'),
         'partner_id': fields.related('user_id','partner_id', type='many2one', relation='res.partner', string='Public Partner'),
         'menu_id': fields.function(_get_menu, relation='website.menu', type='many2one', string='Main Menu')
     }
     _defaults = {
         'user_id': lambda self,cr,uid,c: self.pool['ir.model.data'].xmlid_to_res_id(cr, openerp.SUPERUSER_ID, 'base.public_user'),
         'company_id': lambda self,cr,uid,c: self.pool['ir.model.data'].xmlid_to_res_id(cr, openerp.SUPERUSER_ID,'base.main_company'),
-
+        'compress_html': False,
     }
 
     # cf. Wizard hack in website_views.xml
diff --git a/addons/website/views/res_config.xml b/addons/website/views/res_config.xml
index 81d8cf6c9d72..452dda3ae2a6 100644
--- a/addons/website/views/res_config.xml
+++ b/addons/website/views/res_config.xml
@@ -85,6 +85,14 @@
                                 name="%(website.action_website_menu)d"
                                 string="Configure website menus" class="oe_link"/>
                         </group>
+                        <group string="Advanced">
+                            <label for="compress_html"/>
+                            <div name="compress_html">
+                                <div class="oe_inline">
+                                    <field name="compress_html"/> Compress rendered html for a better google pagespeed result
+                                </div>
+                            </div>
+                        </group>
                     </div>
                 </form>
             </field>
diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py
index 5236e04dd841..2fab465014f5 100644
--- a/openerp/addons/base/ir/ir_qweb.py
+++ b/openerp/addons/base/ir/ir_qweb.py
@@ -288,7 +288,7 @@ class QWeb(orm.AbstractModel):
             result = self.render_element(element, template_attributes, generated_attributes, qwebcontext)
 
         if element.tail:
-            result += element.tail.encode('utf-8')
+            result += self.render_tail(element.tail, element, qwebcontext)
 
         if isinstance(result, unicode):
             return result.encode('utf-8')
@@ -303,7 +303,7 @@ class QWeb(orm.AbstractModel):
         if inner:
             g_inner = inner.encode('utf-8') if isinstance(inner, unicode) else inner
         else:
-            g_inner = [] if element.text is None else [element.text.encode('utf-8')]
+            g_inner = [] if element.text is None else [self.render_text(element.text, element, qwebcontext)]
             for current_node in element.iterchildren(tag=etree.Element):
                 try:
                     g_inner.append(self.render_node(current_node, qwebcontext))
@@ -333,6 +333,12 @@ class QWeb(orm.AbstractModel):
         else:
             return "<%s%s/>" % (name, generated_attributes)
 
+    def render_text(self, text, element, qwebcontext):
+        return text.encode('utf-8')
+
+    def render_tail(self, tail, element, qwebcontext):
+        return tail.encode('utf-8')
+
     # Attributes
     def render_att_att(self, element, attribute_name, attribute_value, qwebcontext):
         if attribute_name.startswith("t-attf-"):
-- 
GitLab