[FIX] bundles: fix compiled css assets recomposition
authorFabien Meghazi <fme@openerp.com>
Tue, 19 Aug 2014 13:50:57 +0000 (15:50 +0200)
committerFabien Meghazi <fme@openerp.com>
Tue, 19 Aug 2014 13:50:57 +0000 (15:50 +0200)
- Do not include css in less source because malformed css will break
  less compilation
- Always recompose compiled css, even if not in debug mode
- Less and sass compilers mode @at-rules on top in order to comply
  to css 2.1, those @at-rules where left-over during the recompostion
  because they lost their marker. Those are now handled as virtual
  inline stylesheets.

openerp/addons/base/ir/ir_qweb.py

index c0b5388..b4352fc 100644 (file)
@@ -1072,8 +1072,7 @@ class AssetsBundle(object):
         response = []
         if debug:
             if css and self.stylesheets:
-                compiled = self.preprocess_css()
-                self.recompose_css(compiled)
+                self.preprocess_css()
                 if self.css_errors:
                     msg = '\n'.join(self.css_errors)
                     self.stylesheets.append(StylesheetAsset(self, inline=self.css_message(msg)))
@@ -1186,24 +1185,22 @@ class AssetsBundle(object):
             Checks if the bundle contains any sass/less content, then compiles it to css.
             Returns the bundle's flat css.
         """
-        sass = [asset for asset in self.stylesheets if isinstance(asset, SassStylesheetAsset)]
-        if sass:
-            cmd = sass[0].get_command()
-            source = '\n'.join([asset.get_source() for asset in sass])
-            compiled = self.compile_css(cmd, source)
-            self.recompose_css(compiled)
-
-        less = [asset for asset in self.stylesheets if isinstance(asset, LessStylesheetAsset)]
-        if less:
-            cmd = less[0].get_command()
-            source = ''
-            for asset in self.stylesheets:
-                if isinstance(asset, LessStylesheetAsset):
-                    source += asset.get_source()
-                else:
-                    source += asset.content
-            compiled = self.compile_css(cmd, source)
-            return compiled
+        for atype in (SassStylesheetAsset, LessStylesheetAsset):
+            assets = [asset for asset in self.stylesheets if isinstance(asset, atype)]
+            if assets:
+                cmd = assets[0].get_command()
+                source = '\n'.join([asset.get_source() for asset in assets])
+                compiled = self.compile_css(cmd, source)
+
+                fragments = self.rx_css_split.split(compiled)
+                at_rules = fragments.pop(0)
+                if at_rules:
+                    # Sass and less moves @at-rules to the top in order to stay css 2.1 compatible
+                    self.stylesheets.insert(0, StylesheetAsset(self, inline=at_rules))
+                while fragments:
+                    asset_id = fragments.pop(0)
+                    asset = next(asset for asset in self.stylesheets if asset.id == asset_id)
+                    asset._content = fragments.pop(0)
 
         return '\n'.join(asset.minify() for asset in self.stylesheets)
 
@@ -1238,14 +1235,6 @@ class AssetsBundle(object):
         compiled = result[0].strip().decode('utf8')
         return compiled
 
-    def recompose_css(self, compiled):
-        """Flattenize StylesheetAsset's content from compiled source"""
-        fragments = self.rx_css_split.split(compiled)[1:]
-        while fragments:
-            asset_id = fragments.pop(0)
-            asset = next(asset for asset in self.stylesheets if asset.id == asset_id)
-            asset._content = fragments.pop(0)
-
     def get_preprocessor_error(self, stderr, source=None):
         """Improve and remove sensitive information from sass/less compilator error messages"""
         error = stderr.split('Load paths')[0].replace('  Use --trace for backtrace.', '')
@@ -1318,7 +1307,7 @@ class WebAsset(object):
 
     @property
     def content(self):
-        if not self._content:
+        if self._content is None:
             self._content = self.inline or self._fetch_content()
         return self._content