If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

27 Dec 09 edit to protect script blocks

When web2py renders a template, it leaves extra blank lines in the output, making the html harder to read, and looking, well, generated. Removing those lines improves the appearance of the html.

The following snippet filters out those excess lines. Place it in a controller.py file to filter the output of that controller, or in a models.py file to filter the entire application.

import re
def filter(d):
    if not isinstance(d,dict):  d = d()
    return re.compile(r'\n([ \t]+\n)+').sub('\n',response.render(d))
response._caller=filter

A slightly more complex approach leaves <pre> and <script> blocks untouched:

import re
def  save_block(match):
    s = match.group()
    if  s.startswith('<'): return s
    return '/n'

def filter(d):
    if not isinstance(d,dict):  d = d()
    pat = '\n([ \t]+\n)+'             # match empty lines that start with spaces
    pat += '|(?s)<script.*?</script'  # OR script blocks 
    pat += '|(?s)<pre.*?</pre'        # OR pre blocks 
    cpat = re.compile(pat)
    return cpat.sub(save_block, response.render(d))

response._caller=filter

Note: This is said to mess up flash.

Related slices

Comments (9)

  • Login to post



  • 0
    mrfreeze 14 years ago
    No, you're right. I'll see what I can do to make it more usable.

  • 0
    thadeusb 14 years ago
    it also messes up javascript. How to add to this? I have been playing around but no luck.

  • 0
    kbochert 14 years ago
    To leave both pre blocks and script blocks untouched Try: def save_block(match): s = match.group() if s.startswith('<'): return s return '\n' def filter(d): if not isinstance(d,dict): d = d() cpat = re.compile(r'\n([ \t]+\n)+|(?s)
    .*
    |(?s)') return cpat.sub(save_block, response.render(d)) response._caller=filter

  • 0
    kbochert 14 years ago
    What happened with that! It had an error anyway import re def save_block(match): s = match.group() if s.startswith('<'): return s return '\n' def filter(d): if not isinstance(d,dict): d = d() cpat = re.compile(r'\n([ \t]+\n)+|(?s)
    .*?
    |(?s)

  • 0
    thadeusb 14 years ago
    The following works perfectly.. The broken javascript was to incorrect syntax, that for some reason when not minified, ran fine, but had a ton of errors when placed on one line, once those got situated out the javascript ran fine. However my end result is the following, it doesn't touch 'pre', 'blockquote', or 'textarea'. Size reduction is from 76.8KB to 66.5KB. Also another bug, is if you return any kind of json objects, or stream a download, the response._caller will override it and encode it into html (not good!) So a check must be made on what function is being called to see if it's ok to replace the caller. import re def save_pre(match): s = match.group() if s.startswith('|(?s)|(?s)') return cpat.sub(save_pre, response.render(d)) if request.controller not in ['',] \ and request.function not in ['preview_markdown', 'download', 'call']: response._caller = compress_response

  • 0
    thadeusb 14 years ago
    Gah... bad formatter!!!! (jk) http://pastebin.com/f3f812b00

  • 0
    aleksdj 15 years ago
    Many thanks for both solutions. This result in a better debug and presentation output of html.

  • 0
    aleksdj 15 years ago
    Another note: using this output render reduce the size of html considerably, otherwise the html output its 2x in size approximately for a 1000 lines of html code. (that is bandwidth and cost consumption)

  • 0
    thadeusb 15 years ago
    Alternatively if you have utidy installed... def utidy(d): if not isinstance(d, dict): d = d() import tidy pretty = dict(output_xhtml=1, add_xml_decl=1, indent=1, tidy_mark=1, wrap=0, ) if True: #if you want to compress pretty['indent'] = 0 return tidy.parseString(response.render(d), **pretty) response._caller = utidy

Hosting graciously provided by:
Python Anywhere