[FIX] qweb: css minified in multiple page for IE
On internet explorer 6, 7, 8 and 9, the limit of CSS rules in a stylesheet is 4095 (http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/10164546.aspx). This commit breaks down a CSS bundle in several pages for these IE versions. To do this, the CSS tag added is of the kind : /web/css.0/{xmlid}/{version} in which there is: - the whole CSS if there is no more than one page, - a list of @import pointing to the multiple pages. note: if a modification lowers the number of page, an old page may stay in ir_attachment (e.g: go from 4 to 3 pages, the old 4th page of another version will not be deleted untill the number goes again up to 4). Note: the method css(self) previously returned an unicode variable (the first time) or an str variable (the following times, if already cached), the fix also correct this so an str variable is always returned. fixes #5050 opw-627116
This commit is contained in:
parent
b1dd5d6045
commit
37959d45f3
|
@ -534,14 +534,15 @@ class Home(http.Controller):
|
||||||
@http.route([
|
@http.route([
|
||||||
'/web/css/<xmlid>',
|
'/web/css/<xmlid>',
|
||||||
'/web/css/<xmlid>/<version>',
|
'/web/css/<xmlid>/<version>',
|
||||||
|
'/web/css.<int:page>/<xmlid>/<version>',
|
||||||
], type='http', auth='public')
|
], type='http', auth='public')
|
||||||
def css_bundle(self, xmlid, version=None, **kw):
|
def css_bundle(self, xmlid, version=None, page=None, **kw):
|
||||||
try:
|
try:
|
||||||
bundle = AssetsBundle(xmlid)
|
bundle = AssetsBundle(xmlid)
|
||||||
except QWebTemplateNotFound:
|
except QWebTemplateNotFound:
|
||||||
return request.not_found()
|
return request.not_found()
|
||||||
|
|
||||||
response = request.make_response(bundle.css(), [('Content-Type', 'text/css')])
|
response = request.make_response(bundle.css(page), [('Content-Type', 'text/css')])
|
||||||
return make_conditional(response, bundle.last_modified, max_age=BUNDLE_MAXAGE)
|
return make_conditional(response, bundle.last_modified, max_age=BUNDLE_MAXAGE)
|
||||||
|
|
||||||
class WebClient(http.Controller):
|
class WebClient(http.Controller):
|
||||||
|
|
|
@ -33,6 +33,8 @@ from openerp.tools.translate import _
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
MAX_CSS_RULES = 4095
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# QWeb template engine
|
# QWeb template engine
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
|
@ -1142,7 +1144,12 @@ class AssetsBundle(object):
|
||||||
else:
|
else:
|
||||||
url_for = self.context.get('url_for', lambda url: url)
|
url_for = self.context.get('url_for', lambda url: url)
|
||||||
if css and self.stylesheets:
|
if css and self.stylesheets:
|
||||||
href = '/web/css/%s/%s' % (self.xmlid, self.version)
|
suffix = ''
|
||||||
|
if request:
|
||||||
|
ua = request.httprequest.user_agent
|
||||||
|
if ua.browser == "msie" and int((ua.version or '0').split('.')[0]) < 10:
|
||||||
|
suffix = '.0'
|
||||||
|
href = '/web/css%s/%s/%s' % (suffix, self.xmlid, self.version)
|
||||||
response.append('<link href="%s" rel="stylesheet"/>' % url_for(href))
|
response.append('<link href="%s" rel="stylesheet"/>' % url_for(href))
|
||||||
if js:
|
if js:
|
||||||
src = '/web/js/%s/%s' % (self.xmlid, self.version)
|
src = '/web/js/%s/%s' % (self.xmlid, self.version)
|
||||||
|
@ -1178,7 +1185,10 @@ class AssetsBundle(object):
|
||||||
self.set_cache('js', content)
|
self.set_cache('js', content)
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def css(self):
|
def css(self, page_number=None):
|
||||||
|
if page_number is not None:
|
||||||
|
return self.css_page(page_number)
|
||||||
|
|
||||||
content = self.get_cache('css')
|
content = self.get_cache('css')
|
||||||
if content is None:
|
if content is None:
|
||||||
self.compile_sass()
|
self.compile_sass()
|
||||||
|
@ -1198,12 +1208,43 @@ class AssetsBundle(object):
|
||||||
|
|
||||||
matches.append(content)
|
matches.append(content)
|
||||||
content = u'\n'.join(matches)
|
content = u'\n'.join(matches)
|
||||||
if self.css_errors:
|
if not self.css_errors:
|
||||||
return content
|
self.set_cache('css', content)
|
||||||
self.set_cache('css', content)
|
content = content.encode('utf-8')
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
def css_page(self, page_number):
|
||||||
|
content = self.get_cache('css.%d' % (page_number,))
|
||||||
|
if page_number:
|
||||||
|
return content
|
||||||
|
if content is None:
|
||||||
|
css = self.css()
|
||||||
|
re_rules = '([^{]+\{(?:[^{}]|\{[^{}]*\})*\})'
|
||||||
|
re_selectors = '()(?:\s*@media\s*[^{]*\{)?(?:\s*(?:[^,{]*(?:,|\{(?:[^}]*\}))))'
|
||||||
|
css_url = '@import url(\'/web/css.%%d/%s/%s\');' % (self.xmlid, self.version)
|
||||||
|
pages = [[]]
|
||||||
|
page = pages[0]
|
||||||
|
page_selectors = 0
|
||||||
|
for rule in re.findall(re_rules, css):
|
||||||
|
selectors = len(re.findall(re_selectors, rule))
|
||||||
|
if page_selectors + selectors < MAX_CSS_RULES:
|
||||||
|
page_selectors += selectors
|
||||||
|
page.append(rule)
|
||||||
|
else:
|
||||||
|
pages.append([rule])
|
||||||
|
page = pages[-1]
|
||||||
|
page_selectors = selectors
|
||||||
|
if len(pages) == 1:
|
||||||
|
pages = []
|
||||||
|
for idx, page in enumerate(pages):
|
||||||
|
self.set_cache("css.%d" % (idx+1), ''.join(page))
|
||||||
|
content = '\n'.join(css_url % i for i in range(1,len(pages)+1))
|
||||||
|
self.set_cache("css.0", content)
|
||||||
|
if not content:
|
||||||
|
return self.css()
|
||||||
|
return content
|
||||||
|
|
||||||
def get_cache(self, type):
|
def get_cache(self, type):
|
||||||
content = None
|
content = None
|
||||||
domain = [('url', '=', '/web/%s/%s/%s' % (type, self.xmlid, self.version))]
|
domain = [('url', '=', '/web/%s/%s/%s' % (type, self.xmlid, self.version))]
|
||||||
|
|
Loading…
Reference in New Issue