Giter VIP home page Giter VIP logo

pyjade's Introduction

PyJade Build Status

Join the chat at https://gitter.im/syrusakbary/pyjade

PyJade is a high performance port of Jade-lang for python, that converts any .jade source to the each Template-language (Django, Jinja2, Mako or Tornado).

UTILITIES

To simply output the conversion to your console:

pyjade [-c django|jinja|mako|tornado] input.jade [output.html]

or, alternatively:

pyjade [-c django|jinja|mako|tornado] [-o output.html] < input.jade

To convert directly inside a python script:

import pyjade
jade_text = '''!!! 5
html
head
    body foo bar!
'''
print pyjade.simple_convert(jade_text)

INSTALLATION

First, you must do:

pip install pyjade

Or:

python setup.py install

Now simply name your templates with a .jade extension and this jade compiler will do the rest. Any templates with other extensions will not be compiled with the pyjade compiler.

Django

For Django 1.9

In settings.py, add a loader to TEMPLATES like so:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.core.context_processors.request'
            ],
            'loaders': [
                # PyJade part:   ##############################
                ('pyjade.ext.django.Loader', (
                    'django.template.loaders.filesystem.Loader',
                    'django.template.loaders.app_directories.Loader',
                ))
            ],
            'builtins': ['pyjade.ext.django.templatetags'],
        },
    },
]

For Django 1.8

In settings.py, add a loader to TEMPLATES like so:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.core.context_processors.request'
            ],
            'loaders': [
                # PyJade part:   ##############################
                ('pyjade.ext.django.Loader', (
                    'django.template.loaders.filesystem.Loader',
                    'django.template.loaders.app_directories.Loader',
                ))
            ],
        },
    },
]

Or, in Django 1.7 or earlier:

In settings.py, modify TEMPLATE_LOADERS like:

TEMPLATE_LOADERS = (
    ('pyjade.ext.django.Loader',(
        'django.template.loaders.filesystem.Loader',
        'django.template.loaders.app_directories.Loader',
    )),
)

Jinja2

Just add pyjade.ext.jinja.PyJadeExtension as extension:

jinja_env = Environment(extensions=['pyjade.ext.jinja.PyJadeExtension'])

Mako

Just add pyjade.ext.mako.preprocessor as preprocessor:

from pyjade.ext.mako import preprocessor as mako_preprocessor
mako.template.Template(jade_source,
    preprocessor=mako_preprocessor
)

Flask

Just add pyjade.ext.jinja.PyJadeExtension as extension to the environment of the app::

app.jinja_env.add_extension('pyjade.ext.jinja.PyJadeExtension')

Pyramid

Adjust your "your_project/init.py" and add the following line somewhere to in the main() function:

config.include('pyjade.ext.pyramid')

Tornado Templates

Append this after importing tornado.template

from tornado import template
from pyjade.ext.tornado import patch_tornado
patch_tornado()

(...)

Syntax

Exactly the same as the Jade Node.js module (except of cases, which are not implemented) https://github.com/visionmedia/jade/blob/master/README.md

Example

This code:

!!! 5
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript').
      if (foo) {
         bar()
      }
  body
    h1.title Jade - node template engine
    #container
      if youAreUsingJade
        p You are amazing
      else
        p Get on it!

Converts to:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{{pageTitle}}</title>
    <script type='text/javascript'>
      if (foo) {
         bar()
      }
    </script>
  </head>
  <body>
    <h1 class="title">Jade - node template engine</h1>
    <div id="container">
      {%if youAreUsingJade%}
        <p>You are amazing</p>
      {%else%}
        <p>Get on it!</p>
      {%endif%}
    </div>
  </body>
</html>

Register filters

If you want to register a function as a filter, you only have to decorate the function with pyjade.register_filter("filter_name")

import pyjade

@pyjade.register_filter('capitalize')
def capitalize(text,ast):
  return text.capitalize()

Using templatetags (and any feature of the compiled-to language)

Using Django and crispy-forms as an illustrative example but the information can be generalized.

If you need to use templatetags, you can use Jade's syntax for rendering code:

- load crispy_forms_tags
- crispy form

This will compile into

{% load crispy_forms_tags %}
{% crispy form %}

If you have any trouble with this feature, or there's some feature of your template language that is being misinterpreted when using this syntax, you can also do something like this:

| {% load crispy_forms_tags %}
| {% crispy form %}

This will compile into the same Django template snippet.

TESTING

You must have nose package installed. You can do the tests with

./test.sh

TODOs and BUGS

See: http://github.com/syrusakbary/pyjade/issues

pyjade's People

Contributors

blx avatar char101 avatar chrishaines avatar damoxc avatar davidrios avatar delfick avatar floer32 avatar frgtn avatar gitter-badger avatar glennyonemitsu avatar hellysmile avatar homburg avatar htch avatar jeltef avatar jmp0xf avatar joshma avatar mibou avatar ollyc avatar reorx avatar rockerzz avatar singletoned avatar syabro avatar syrusakbary avatar tdamsma avatar thenoviceoof avatar twolfson avatar uolot avatar weapp avatar xiaq avatar yang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyjade's Issues

Invalid tag blocktrans

The {% blocktrans %} tag appears to be broken.

Even a simple template like:

| {% blocktrans %}
    Foo bar
| {% endblocktrans %}

This produces an Invalid block tag error. blocktrans can't be used like this:

- blocktrans
    Foo bar

Because the regexps in Django's manage.py makemessages only finds message strings inside {% %} tags.

In ext/django/__init__.py:

autocloseCode = 'if,ifchanged,ifequal,ifnotequal,for,block,filter,autoescape,with,trans,blocktrans,spaceless,comment,cache,localize,compress'.split(',')

In compiler.py:

autocloseCode = 'if,for,block,filter,autoescape,with,trans,spaceless,comment,cache,macro,localize,compress'.split(',')

The compiler.py list is missing blocktrans and a couple of others. However, adding blocktrans to this list didn't help.

The issue is definitely with blocktrans. Other tags work, such as:

| {% spaceless %}
    Foo bar
| {% endspaceless %}

Unescaped variables

Just wondering how I would output a variable unescaped into a pyjade template. My template looks like this:

!!!
!!! XML
html
    head
        title Test
    body
        p Test 
        p !{ value }
        p #{ value }
        p
            != value
        p
            = value

Django view:

def test(request):
    return render_to_response('test.jade', { 'value' : '<tag>"hello"</tag>' })

Which results in the following html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!DOCTYPE XML>
<html>
  <head>
    <title>Test
    </title>
  </head>
  <body>
    <p>Test 
    </p>
    <p>&lt;tag&gt;&quot;hello&quot;&lt;/tag&gt;
    </p>
    <p>&lt;tag&gt;&quot;hello&quot;&lt;/tag&gt;
    </p>
    <p>&lt;tag&gt;&quot;hello&quot;&lt;/tag&gt;
    </p>
    <p>&lt;tag&gt;&quot;hello&quot;&lt;/tag&gt;
    </p>
  </body>
</html>

How do i get my variable expanded unescaped? i.e. I would like to output:

<p><tag>"hello"</tag></p>

Thanks,
Tom

Markdown filter for Django will be deprecated in Django 1.5-6

The Django 1.5 release notes specify that django.contrib.markup is now (to be) deprecated. By Django 1.6 it will be gone and you will get an error like this when trying to use the pyjade template loader:

ImproperlyConfigured at /en/

Error importing template source loader pyjade.ext.django.Loader: "No module named markup.templatetags.markup"

(Got that using Django 1.6.dev20130131212124)

So it's not urgent, but the solution will be simple anyways: remove support for the markdown filter, and/or rely on a dedicated 3rd party package for markdown.

Thanks for porting this Python and writing a Django extension for it, this package is making my templates much more elegant (and therefore my life much more pleasant)

UnicodeDecodeError

 File "/usr/local/lib/python2.7/dist-packages/pyjade/ext/mako.py", line 79, in preprocessor
    return process(source,compiler=Compiler)
  File "/usr/local/lib/python2.7/dist-packages/pyjade/utils.py", line 223, in process
    return _compiler.compile().strip()
  File "/usr/local/lib/python2.7/dist-packages/pyjade/compiler.py", line 80, in compile
    return ''.join(self.buf)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 333: ordinal not in range(128)

It's Chinese when render error.

Installation with pip fails on windows with python 2.4

C:\Users\entwicklung>pip install pyjade
Downloading/unpacking pyjade
  Downloading pyjade-1.5.tar.gz
  Running setup.py egg_info for package pyjade
Installing collected packages: pyjade
  Running setup.py install for pyjade
    Installing pyjade-script.py script to c:\Python24\Scripts
    Installing pyjade.exe script to c:\Python24\Scripts
    Installing pyjade.exe.manifest script to c:\Python24\Scripts
      File "c:\Python24\Lib\site-packages\pyjade\compiler.py", line 155
        self.buffer('/>' if not self.terse and closed else '>')
                          ^
    SyntaxError: invalid syntax
      File "c:\Python24\Lib\site-packages\pyjade\convert.py", line 37
        file_output = options.output or (args[1] if len(args)>1 else None)
                                                  ^
    SyntaxError: invalid syntax
      File "c:\Python24\Lib\site-packages\pyjade\ext\django\__init__.py", line 5
1
        self.buf.append('{{%s%s}}'%(val,'|force_escape' if code.escape else ''))

                                                         ^
    SyntaxError: invalid syntax
      File "c:\Python24\Lib\site-packages\pyjade\ext\jinja.py", line 36
        self.buf.append('{{%s%s}}'%(val,'|escape' if code.escape else ''))
                                                   ^
    SyntaxError: invalid syntax
      File "c:\Python24\Lib\site-packages\pyjade\ext\mako.py", line 53
        self.buf.append('${%s%s}'%(val,'| h' if code.escape else '| n'))
                                              ^
    SyntaxError: invalid syntax
      File "c:\Python24\Lib\site-packages\pyjade\lexer.py", line 291
        tok.attrs[ns.key] = True if not ns.val else interpolate(ns.val)
                                  ^
    SyntaxError: invalid syntax
      File "c:\Python24\Lib\site-packages\pyjade\parser.py", line 187
        block = self.block() if 'indent' == self.peek().type else None
                              ^
    SyntaxError: invalid syntax
      File "c:\Python24\Lib\site-packages\pyjade\runtime.py", line 27
        buf.append('%s'%k if terse and t else '%s="%s"'%(k,v))
                           ^
    SyntaxError: invalid syntax
Successfully installed pyjade
Cleaning up...

C:\Users\entwicklung>

KeyError u'elif'

I'm getting a KeyError when using the elif conditional. Using Django 1.4.

Environment:

Request Method: GET
Request URL: http://localhost:8000/2012/4/

Django Version: 1.4
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.gis',
'django.contrib.humanize',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.markup',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.sitemaps',
'compressor',
'filer',
'easy_thumbnails',
'markitup',
'haystack',
'raven.contrib.django',
'blog',
'contact',
'portfolio',
'south',
'debug_toolbar')
Installed Middleware:
('django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
'raven.contrib.django.middleware.Sentry404CatchMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware')

Traceback:
File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/core/handlers/base.py" in get_response

  1.                 response = response.render()
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/response.py" in render
  2.         self._set_content(self.rendered_content)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/response.py" in rendered_content
  3.     template = self.resolve_template(self.template_name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/response.py" in resolve_template
  4.         return loader.select_template(template)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in select_template
  5.         return get_template(template_name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in get_template
  6. template, origin = find_template(template_name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in find_template
  7.         source, display_name = loader(name, dirs)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in call
  8.     return self.load_template(template_name, template_dirs)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/ext/django/loader.py" in load_template
  9.             template = get_template_from_string(source, origin, template_name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in get_template_from_string
  10. return Template(source, origin, name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/debug_toolbar/panels/template.py" in new_template_init
  11. old_template_init(self, template_string, origin, name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/base.py" in init
  12.     self.nodelist = compile_string(template_string, origin)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/base.py" in compile_string
  13. return parser.parse()
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/base.py" in parse
  14.                 compiled_result = compile_func(self, token)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader_tags.py" in do_extends
  15. nodelist = parser.parse()
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/base.py" in parse
  16.                 compiled_result = compile_func(self, token)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader_tags.py" in do_block
  17. nodelist = parser.parse(('endblock',))
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/base.py" in parse
  18.                 compiled_result = compile_func(self, token)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader_tags.py" in do_include
  19.                                isolated_context=isolated_context)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader_tags.py" in init
  20.         t = get_template(template_path)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in get_template
  21. template, origin = find_template(template_name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in find_template
  22.         source, display_name = loader(name, dirs)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/src/django/django/template/loader.py" in call
  23.     return self.load_template(template_name, template_dirs)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/ext/django/loader.py" in load_template
  24.             source=self._preprocess(source,name=template_name)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/ext/django/loader.py" in _preprocess
  25.     return compiler.compile().strip()
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in compile
  26.     self.visit(self.node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visit
  27.     self.visitNode(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitNode
  28.     return getattr(self,'visit%s'%name)(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitBlock
  29.         self.visit(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visit
  30.     self.visitNode(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitNode
  31.     return getattr(self,'visit%s'%name)(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitTag
  32.         self.visit(tag.block)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visit
  33.     self.visitNode(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitNode
  34.     return getattr(self,'visit%s'%name)(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitBlock
  35.         self.visit(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visit
  36.     self.visitNode(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitNode
  37.     return getattr(self,'visit%s'%name)(node)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitConditional
  38.           self.visitConditional(next)
    
    File "/Users/dustinfarris/Sites/dustinfarris/env/lib/python2.7/site-packages/pyjade/compiler.py" in visitConditional
  39.     self.buf.append('{%% %s %%}'%TYPE_CODE[conditional.type](conditional.sentence))
    

Exception Type: KeyError at /2012/4/
Exception Value: u'elif'

Unable to extend block defined in included template (using flask/jinja)

Example:

layout.jade

block head
  title layout

include nav

nav.jade

block nav
  a(href="default_link")

page.jade

extends layout

block nav
  a(href="page_link")

rendering page.jade outputs

<title>layout</title><a href="default_link"></a>

instead of

<title>layout</title><a href="page_link"></a>

AttributeError: 'str' object has no attribute '__unicode__'

Hi

In runtime.py at the bottom of the attrs function you have

st = ' '.join(buf)
st.__html__ = st.__unicode__
return st

This makes django say "AttributeError: 'str' object has no attribute 'unicode'"
and if I change it to say just doing unicode(st) then it complains that "AttributeError: 'str' object has no attribute 'html'"

I was able to fix it by changing it to

st = ' '.join(buf)
if hasattr(st, '__unicode__'):
    __html__ = st.__unicode__
else:
    __html__ = unicode(st)
return type("st", (unicode, ), {"__html__" : __html__})(st)

....
(I'm running python 2.7.3)

Django: Cache Jade Render

Is it possible to cache the result of a compiled pyjade template? I've noticed that pyjade seems to add a noticeable amount of overhead on load time.

I don't mean caching the resulting HTML, but just caching the lexical analysis of Jade --- the DjangoHTML template equivalent so to speak.

TemplateSyntaxError on empty blocks

Just installed 1.6 from pypi
previously, it was possible to declare an empty block just with:

-blockname

this will now cause a TemplateSyntaxError exception: Unclosed tag 'block'. Looking for one of: endblock

Workaround is adding a comment to the block:

-blockname
    //-comment about this block

Jinja: functions with named parameters?

Hello,

I thought I was having a similar issue to what was happening in issue #5, but now that it is corrected, I am still getting the same issue.

Basically, I'm trying to do the following:
link(type='text/css', rel='stylesheet', href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}")

Using url_for like this in Jinja would normally work fine for loading files from the static folder. But with PyJade, I get the following error:
TemplateSyntaxError: expected token ',', got 'filename'

I just started using PyJade, so maybe there is a special case for this that I'm just unaware of, but if not, then it definitely isn't working. My workaround for now is to just reference the static URL directly, but I know this is going to cause problems for me later if named parameters don't work correctly.

Other than that, PyJade rocks! Keep up the good work!

Marc

I'm looking to add jade mixin support in django...

I am using pyjade in a django project and was curious if there was a specific reason why jade mixins are not supported in django. Is there a specific technical barrier that is stopping it from being implementing in django? Is there any information I should know before diving into adding mixin support? Any suggestions or information you can provide that can help me evaluate and understand the situation will be greatly appreciated.

Thanks!

Pyjade/Pyramid leaving quotes around variables used in attributes

I'm passing a dict called 'name' to my Jade template and using this markup

a(href=name['firstName']) #{name['firstName']}

and here is what is outputted:

<a href=""Tim"">Tim</a>

Notice the redundant quotes. Why is pyjade leaving extra quotes when the variable is used in an attribute?

Attributes and Linebreaks

It seems that when linebreaks are inserted into attributes pyjade breaks something like the following currently doesn't work:

a(href='http://github.com/'
    class='classy')

Note that Node-flavored Jade supports linebreaks in attributes (see the section on attributes).

Unable to use dict in tag

I have code like this:

for item in items
option(value='#{item.data}') #{item.data}

The second item.data works, but the first does not. Django produces an AttributeError: 'dict' object has no attribute 'data'. I've tried:

value=item.data
value='#{item.data}'
value="#{item.data}"
value!=item.data

and a few other combinations, but none of them work. Is this a bug, or is different syntax needed to access a dict while in a tag?

&#34; quote!

div.wrapper
  hello

->

<div class=&#34;wrapper&#34;>
hello
</div>

??? why not class="wrapper" (I'm using it in mako)

runtime.py - escape(s)

I had exception UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128) when I tried to pass list of unicode strings to template.loader.generate function using tornado templates. In generated code, there is statement:

       if isinstance(_tmp, _string_types): _tmp = _utf8(_tmp)  # search_results.jade:4 (via layout.jade:33)

which passed unicode string to function, where it should be converted to unicode string and some symbols should be escaped. So if you pass unicode string, it should cause exception described because line

      return (unicode(str(s), 'utf8')

raised exception.

So my workaround is to replace lines in runtime.py:

def escape(s):
    """Convert the characters &, <, >, ' and " in string s to HTML-safe
    sequences.  Use this if you need to display text that might contain
    such characters in HTML.  Marks return value as markup string.
    """
    if hasattr(s, '__html__'):
        return s.__html__()

    return (unicode(str(s), 'utf8')
        .replace('&', '&amp;')
        .replace('>', '&gt;')
        .replace('<', '&lt;')
        .replace("'", '&#39;')
        .replace('"', '&#34;')
    )

to:

def escape(s):
    """Convert the characters &, <, >, ' and " in string s to HTML-safe
    sequences.  Use this if you need to display text that might contain
    such characters in HTML.  Marks return value as markup string.
    """
    if hasattr(s, '__html__'):
        return s.__html__()

    if isinstance(s, str):
        s = unicode(str(s), 'utf8')

    return (s
        .replace('&', '&amp;')
        .replace('>', '&gt;')
        .replace('<', '&lt;')
        .replace("'", '&#39;')
        .replace('"', '&#34;')
    )

variable escaping issues.

Hello,

First a quick thank you for those who have created this great package.

I am seeing weird behaviour regarding escaping of context variables. I initially was working with Bottle using the view decorator mentioned in issue 20 in a gist at https://gist.github.com/412900ebbf1e6c079eb8 . In that environment using #{var} and !{var} produces the same unescaped output. I wanted to test if this was an issue with the code from the gist so I created a simple Django project and got the opposite result where both #{var} and !{var} were escaped. Here is the template used:

views/index.jade (Bottle) or templates/index.jade (Django):

html
    head
        title test
    body
        .esc The following text should be escaped:
            p #{esc}
        .no_esc The following text should not be escaped:
            p !{no_esc}

and here is the Bottle app excluding an unmodified copy of the file from the gist:

app.py:

#!/usr/bin/env python
import bottle

from jadeview import jade_view


app = bottle.Bottle()


@app.route('/')
@jade_view('index.jade')
def index(**kwargs):
    kwargs['esc'] = 'Hello World<script>alert("XSS RISK")</script>'
    kwargs['no_esc'] = 'Hello World<script>alert("ACCEPTABLE XSS RISK")</script>'
    return kwargs


bottle.run(app)

and the Django urls.py:

from django.conf.urls import patterns, url

from pyjade_test.views import TestView


urlpatterns = patterns('', url(r'^$', TestView.as_view(), name='index'),)

and views.py:

from django.views.generic import TemplateView


class TestView(TemplateView):
    template_name = 'index.jade'

    def get_context_data(self, **kwargs):
        kwargs = super(TestView, self).get_context_data()
        kwargs['esc'] = 'Hello World<script>alert("XSS RISK")</script>'
        kwargs['no_esc'] = 'Hello World<script>alert("ACCEPTABLE XSS RISK")</script>'
        return kwargs

and here are the resulting HTML pages, first for Bottle:

<html>
  <head>
    <title>test
    </title>
  </head>
  <body>
    <div class="esc">The following text should be escaped:
      <p>Hello World<script>alert("XSS RISK")</script>
      </p>
    </div>
    <div class="no_esc">The following text should not be escaped:
      <p>Hello World<script>alert("ACCEPTABLE XSS RISK")</script>
      </p>
    </div>
  </body>
</html>

and for Django:

<html>
  <head>
    <title>test
    </title>
  </head>
  <body>
    <div class="esc">The following text should be escaped:
      <p>Hello World&lt;script&gt;alert(&quot;XSS RISK&quot;)&lt;/script&gt;
      </p>
    </div>
    <div class="no_esc">The following text should not be escaped:
      <p>Hello World&lt;script&gt;alert(&quot;ACCEPTABLE XSS RISK&quot;)&lt;/script&gt;
      </p>
    </div>
  </body>
</html>

I'm going to try to look into the source of the issues but I thought I should get the info out there first since not being completely familiar with code base for PyJade or Jinja2 it may take me a while. Even though I want to try using Bottle (it would be nice if I could drop the Jinja2 dependency BTW) I'll probably look at Django first because I am more familiar with it.

As a side note, is there a reason the pyjade CLI command doesn't allow returning from the simple HTML compiler for quick and easy tests?

Support +mixin

Jade supports a +mixin syntax that does the same thing as mixin mixin. This should be supported in pyjade. This is not documented in the main readme for jade.

Line continuations not supported?

It seems like expressions broken over multiple lines does not work. The following:

mixin styles("/static/css", [ 
    "skeleton/base", 
    "skeleton/layout", 
    "skeleton/skeleton",     
    "style"])  

Produces a long traceback:

File "C:\Python27\lib\site-packages\jinja2-2.5.5-py2.7.egg\jinja2\parser.py", line 32, in __init__
self.stream = environment._tokenize(source, name, filename, state)
  File "C:\Python27\lib\site-packages\jinja2-2.5.5-py2.7.egg\jinja2\environment.py", line 428, in     _tokenize
    source = self.preprocess(source, name, filename)
  File "C:\Python27\lib\site-packages\jinja2-2.5.5-py2.7.egg\jinja2\environment.py", line 422, in     preprocess
    self.iter_extensions(), unicode(source))
  File "C:\Python27\lib\site-packages\jinja2-2.5.5-py2.7.egg\jinja2\environment.py", line 421, in     <lambda>
    return reduce(lambda s, e: e.preprocess(s, name, filename),
  File "C:\Python27\lib\site-packages\pyjade\ext\jinja.py", line 104, in preprocess
    return process(source,filename=name,compiler=Compiler)
  File "C:\Python27\lib\site-packages\pyjade\utils.py", line 221, in process
    block = _parser.parse()
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 47, in parse
    else: block.append(self.parseExpr())
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 84, in parseExpr
    return getattr(self,funcName)()
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 306, in parseTag
    block = self.block()
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 249, in block
    block.append(self.parseExpr())
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 84, in parseExpr
    return getattr(self,funcName)()
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 306, in parseTag
    block = self.block()
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 249, in block
    block.append(self.parseExpr())
  File "C:\Python27\lib\site-packages\pyjade\parser.py", line 87, in parseExpr
    (t, self.filename, self.line()))
Exception: unexpected token "attrs" in file index.jade on line 10

Conditionals do not work with Django simple tags

I'm new to this module, so it is possible that I am doing something incorrectly. In Django 1.5, I defined the following template tag:

debug_tags.py

from django import template
from django.conf import settings

register = template.Library()

@register_simple_tag
def debug_on():
    """
    When DEBUG = True in settings, returns True.
    Returns False otherwise.
    """"
    return settings.DEBUG

test.jade

{% load debug_tags %}

// Defined template tag
// Prints True
p {% debug_on %}

// Defined template tag, does not work as expected
// Prints False
if debug_on
  p True
else
  p False

// Undefined variable, works as expected
// Prints False
if xxx
  p True
else
  p False

// Works as expected
if request.user.is_authenticated
  p User authenticated
else
  p User is not authenticated

test.html (rendered)

<!-- Defined template tag-->
<!-- Prints True-->
<p>True
</p>
<!-- Defined template tag, does not work as expected-->
<!-- Prints False-->
<p>False
</p>
<!-- Undefined variable, works as expected-->
<!-- Prints False-->
<p>False
</p>
<!-- Works as expected-->
<p>User authenticated
</p>

Can't be clone on Windows.

I can't clone this on Windows.

"aux" is not a valid name for a folder on Windows. Raise a error when try to create "pyjade / testsuite / cases / aux" folder.

{{var}} and {{var|filter}} and {% tag %} in <tag> attrs for django

Hello,

In my branch of pyjade over here https://github.com/delfick/pyjade/commits/master (forked from pyjade in December 2011) I was able to make it so the following examples worked::

h3: a(href={{news.url}})
a(href="{% url nav.section %}")
img(src="{{nav.image|static}}" alt="{{nav.title}}")

Just then I updated to latest pyjade (so many changes!) and attempted to get the same thing working.

Unfortunately in latest pyjade, because it copes with this by transforming it into

{% __pyjade_attrs attrs=[('href',({{news.url}}))] %}

There are two problems when attempting to solve my requirements

  • anything that has a %} in it breaks it
  • the exec that happens over "attrs=[('href',({{news.url}}))]" can't translate {{news.url}}

I'm sure there's some nice pyjade way of dealing with this requirement (in terms of changing my templates).
But I prefer my django syntax in this particular case (also don't have to change all my templates :p)

So I'm more than willing to stay on my branch (very slow moving project, it'll be fine) but at the same time I'm wondering if there does exist a solution to this problem (in pyjade code)
if not just for the sake of solving a problem.

Thankyou.

Stephen.

__pyjade_attrs everywhere

How I can get rid of these?

In [18]: jade_source = """!!! 5
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript')
      if (foo) {
         bar()
      }
  body
    h1.title Jade - node template engine
    #container
      if youAreUsingJade
        p You are amazing
      else
        p Get on it!"""

In [19]: from pyjade.utils import process

In [20]: print process(jade_source)
<!DOCTYPE html>
<html{{__pyjade_attrs(terse=True, attrs=[('lang',("en"))])}}>
  <head>
    <title>{{pageTitle|escape}}
    </title>
    <script{{__pyjade_attrs(terse=True, attrs=[('type',('text/javascript'))])}}>if (foo) {
   bar()
}
    </script>
  </head>
  <body>
    <h1{{__pyjade_attrs(terse=True, attrs=[('class', (('title')))])}}>Jade - node template engine
    </h1>
    <div{{__pyjade_attrs(terse=True, attrs=[('id',('container'))])}}>{% if  youAreUsingJade %}
      <p>You are amazing
      </p>{% else %}
      <p>Get on it!
      </p>{% endif %}
    </div>
  </body>

Why there are '__pyjade_attrs' in converted html?

This is my original layout.jade file content

doctype 5
html
  head
    title= title
    meta(charset='UTF-8')
    link(rel='icon', href='/images/favicon.ico', type='image/x-icon')
    link(rel='stylesheet', href='/stylesheets/next.css')
    block head
  body
    block content
    block footer
      p.footer
        a(href='/about') About

Below is what I got from running command pyjade layout.jade

<!DOCTYPE html>
<html>
  <head>
    <title>{{title|force_escape}}
    </title>
    <meta{% __pyjade_attrs terse=True, attrs=[('charset',('UTF-8'))] %}>
    <link{% __pyjade_attrs terse=True, attrs=[('rel',('icon')), ('href',('/images/favicon.ico')), ('type',('image/x-icon'))] %}>
    <link{% __pyjade_attrs terse=True, attrs=[('rel',('stylesheet')), ('href',('/stylesheets/next.css'))] %}>{% block head %}{% endblock %}
  </head>
  <body>{% block content %}{% endblock %}{% block footer %}
    <p{% __pyjade_attrs terse=True, attrs=[('class', (('footer')))] %}><a{% __pyjade_attrs terse=True, attrs=[('href',('/about'))] %}>About</a>
    </p>{% endblock %}
  </body>
</html>

I don't understand why tag attributes are not normally converted, but show __pyjade_attrs instead,
is this a bug or I didn't got the right way to use it ?

ps. I have run test.sh and all testcases were passed on my computer.

PyJade incorrectly interprets <blockquote> tag as a block

In PyJade, <blockquote> tags get incorrectly interpreted as template blocks, and not as HTML elements.

Testcase:

import pyjade
pyjade.ext.html.process_jade('blockquote\n  p test')

Result:

{% block quote %}
<p>test</p>
{% endblock %}

Expected result:

<blockquote>
<p>test</p>
</blockquote>

Clarify filter registration

Hi, I successfully registered markdown/coffeescript filters with

import coffeescript 
import markdown
pyjade.compiler.Compiler.filters['coffeescript'] = lambda x,y: coffeescript.compile(x)
pyjade.compiler.Compiler.filters['markdown'] = lambda x,y: markdown.markdown(x, output_format='html5')

Is this the correct way, is there an API I'm missing?

You might consider registering these two if the libraries are available.

Django Block Within Tag Attribute

Wondering if it's possible to do something like this:

<body class="{% block bodyclass %}{% endblock bodyclass %}">

I tried:

body(class='{% block bodyclass %}{% endblock %}')

but it didn't work.

obscure exception messages

If the parser fails because of an error in a template, it will tell you what went wrong. It doesn't tell you where however. Showing template filename and line number for the error in exception messages would be a great help for debugging templates

{{ STATIC_URL }} support?

I have some trouble adding my CSS in my template using {{ STATIC_URL }}. The tag does not work inside the link markup, but works anywhere else. This:

{{ STATIC_URL }}

correctly translated into

/static/

, but

link(href="{{ STATIC_URL }}css/bla.css"

become

link href="{{ STATIC_URL }}css/bla.css"

I use pyjade with Django. Anybody can help on this?

also asked at SO:
http://stackoverflow.com/questions/13029876/static-url-with-pyjade-in-django


Uh oh, I found the answer in the issue below, had to use '!='. Sorry

Including External Mixins

Mixins defined in a file are not correctly imported when the file is included in a larger template. eg:

helper.jade:

mixin foo()
  p test

master.jade:

include helper
mixin foo()

will throw an error that foo is undefined unless foo is manually imported via raw jinja syntax eg:

master.jade:

{% from 'helpers.jade' import foo %}
mixin foo()

Problems installing PyJade in Windows/Python3.2

I cannot install pyjade on Windows 7 / Python 3.2.

Running pip install pyjade gives me:

E:\>pip install pyjade
Downloading/unpacking pyjade
  Downloading pyjade-1.5.tar.gz
  Running setup.py egg_info for package pyjade
Installing collected packages: pyjade
  Running setup.py install for pyjade
      File "C:\Python32\Lib\site-packages\pyjade\convert.py", line 35
        print "Specify the input file as the first argument."
                                                        ^
    SyntaxError: invalid syntax
      File "C:\Python32\Lib\site-packages\pyjade\lexer.py", line 249
        key = u''
                ^
    SyntaxError: invalid syntax
    Installing pyjade-script.py script to C:\Python32\Scripts
    Installing pyjade.exe script to C:\Python32\Scripts
Successfully installed pyjade
Cleaning up...
E:\>

See this image:
http://imageshack.us/photo/my-images/406/pyjadeinstallwindowspyt.jpg/

Is pyjade supposed to work in python 3?

Control followed by "a" fails

Input:

if True
    a stuff

error:

Traceback (most recent call last):
  File "/opt/google-appengine-python/lib/webapp2/webapp2.py", line 1536, in __call__
    rv = self.handle_exception(request, response, e)
  File "/opt/google-appengine-python/lib/webapp2/webapp2.py", line 1530, in __call__
    rv = self.router.dispatch(request, response)
  File "/opt/google-appengine-python/lib/webapp2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/opt/google-appengine-python/lib/webapp2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/home/kit/Programming/Python/GAE/wisty/wisty/pages/__init__.py", line 31, in dispatch
    webapp2.RequestHandler.dispatch(self)
  File "/opt/google-appengine-python/lib/webapp2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/opt/google-appengine-python/lib/webapp2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/home/kit/Programming/Python/GAE/wisty/wisty/pages/pages.py", line 92, in get
    self.response.write(self.render_jade("test.jade"))
  File "/home/kit/Programming/Python/GAE/wisty/wisty/pages/__init__.py", line 42, in render_jade
    return mako_render.get_template(template).render(**kwargs)
  File "/home/kit/Programming/Python/GAE/wisty/mako/lookup.py", line 240, in get_template
    return self._load(srcfile, uri)
  File "/home/kit/Programming/Python/GAE/wisty/mako/lookup.py", line 306, in _load
    **self.template_args)
  File "/home/kit/Programming/Python/GAE/wisty/mako/template.py", line 291, in __init__
    module = self._compile_from_file(path, filename)
  File "/home/kit/Programming/Python/GAE/wisty/mako/template.py", line 368, in _compile_from_file
    filename)
  File "/home/kit/Programming/Python/GAE/wisty/mako/template.py", line 615, in _compile_text
    generate_magic_comment=template.disable_unicode)
  File "/home/kit/Programming/Python/GAE/wisty/mako/template.py", line 597, in _compile
    node = lexer.parse()
  File "/home/kit/Programming/Python/GAE/wisty/mako/lexer.py", line 233, in parse
    if self.match_control_line():
  File "/home/kit/Programming/Python/GAE/wisty/mako/lexer.py", line 427, in match_control_line
    self.append_node(parsetree.ControlLine, keyword, isend, text)
  File "/home/kit/Programming/Python/GAE/wisty/mako/lexer.py", line 131, in append_node
    node = nodecls(*args, **kwargs)
  File "/home/kit/Programming/Python/GAE/wisty/mako/parsetree.py", line 77, in __init__
    code = ast.PythonFragment(text, **self.exception_kwargs)
  File "/home/kit/Programming/Python/GAE/wisty/mako/ast.py", line 78, in __init__
    code, **exception_kwargs)
CompileException: Fragment 'if  True:<a>stuff</a>' is not a partial control statement in file 'wisty/pages/jade_templates/test.jade' at line: 3 char: 1

Happens similarly for for loops and using the - if notation

This is running on the latest Google App Engine dev_appserver.py with mako 0.7.1 and pyjade 1.5

Doc update: note differences from node.js jade implementaton

Hi, just wanted to note that the documentation (eg, README.md) could use a brief list of features that differ between the node.js version of jade and the one that this module supports.

In particular, one small thing that surprised me initially was that the jade #{interpolate} syntax isn't translated by pyjade into the native syntax in its target template language (in my case, I'm using the Jinja2 extension so the native syntax is {{interpolate}}).

I also have no idea whether the node.js include and extends features are supported. Since that sort of thing is so template-engine dependent, I'm assuming not, but it would be nice if the README specified clearly one way or another.

Ultimately this stuff isn't very difficult to find out, but updating the docs to reflect the state of the code would be helpful people using this package. (Also, thanks, I like pyjade.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.