Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added {% hamlpy %} jinja2 tag, with tests and documentation #160

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions hamlpy/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ def has_any_extension(file_path, extensions):
return file_ext and extensions and file_ext in [clean_extension(e) for e in extensions]

if _jinja2_available:
import re
begin_tag_rx = r'\{%\-?\s*haml.*?%\}'
end_tag_rx = r'\{%\-?\s*endhaml\s*\-?%\}'

begin_tag_m = re.compile(begin_tag_rx)
end_tag_m = re.compile(end_tag_rx)

class HamlPyExtension(jinja2.ext.Extension):

def preprocess(self, source, name, filename=None):
Expand All @@ -40,3 +47,47 @@ def preprocess(self, source, name, filename=None):
raise jinja2.TemplateSyntaxError(e, 1, name=name, filename=filename)
else:
return source

class HamlPyTagExtension(jinja2.ext.Extension):
tags = set(['haml'])

def _get_lineno(self, source):
matches = re.finditer(r'\n', source)
if matches:
return len(tuple(matches))
return 0

def parse(self, parser):
haml_data = parser.parse_statements(['name:endhaml'])
parser.stream.expect('name:endhaml')
return [haml_data]

def preprocess(self, source, name, filename = None):
ret_source = ''
start_pos = 0

h = hamlpy.Compiler()

while True:
tag_match = begin_tag_m.search(source, start_pos)

if tag_match:
end_tag = end_tag_m.search(source, tag_match.end())

if not end_tag:
raise jinja2.TemplateSyntaxError('Expecting "endhaml" tag', self._get_lineno(source[:start_pos]))

haml_source = source[tag_match.end():end_tag.start()]

try:
ret_source += source[start_pos:tag_match.start()] + h.process(haml_source)
except jinja2.TemplateSyntaxError as e:
raise jinja2.TemplateSynxtaxError(e.message, e.lineno, name=name,filename=filename)

start_pos = end_tag.end()
else:
ret_source += source[start_pos:]
break

return ret_source

42 changes: 40 additions & 2 deletions hamlpy/test/ext_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest
import os
from hamlpy.ext import has_any_extension
from hamlpy.ext import has_any_extension, _jinja2_available

class ExtTest(unittest.TestCase):
"""
Expand Down Expand Up @@ -44,4 +44,42 @@ def test_has_any_extension(self):
self.assertTrue(has_any_extension('/home/user/dir.dot.hamlpy', extensions))
self.assertTrue(has_any_extension('/home/user/dir.dot.haml', extensions))
self.assertTrue(has_any_extension('/home/user/dir.dot.txt', extensions))
self.assertFalse(has_any_extension('/home/user/dir.dot.html', extensions))
self.assertFalse(has_any_extension('/home/user/dir.dot.html', extensions))

if _jinja2_available:
import jinja2
from hamlpy.ext import HamlPyTagExtension
from nose.tools import eq_

class JinjaHamlTagTest(unittest.TestCase):
def _jinja_render(self, s, **kwargs):
env = jinja2.Environment(extensions=[HamlPyTagExtension])

return env.from_string(s).render(**kwargs)

def test_empty_tag(self):
haml = '{% haml %}{% endhaml %}'
html = ''
eq_(html, self._jinja_render(haml))

def test_haml_tag(self):
haml = '{% haml %}- if something\n %p hello\n- else\n %p goodbye{% endhaml %}'
html = '\n <p>goodbye</p>\n'
eq_(html, self._jinja_render(haml))

def test_haml_tag2(self):
haml = 'before{% haml %}.header.span-24.last{% endhaml %}after'
html = "before<div class='header span-24 last'></div>\nafter"
eq_(html, self._jinja_render(haml))

def test_error1(self):
"jinja syntax error"
haml = '{% haml %}'
with self.assertRaises(jinja2.TemplateSyntaxError):
self._jinja_render(haml)

def test_error2(self):
"haml syntax error"
haml = '{% haml %}- endfor{% endhaml %}'
with self.assertRaises(TypeError):
self._jinja_render(haml)
27 changes: 27 additions & 0 deletions reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
- [Django Tags: -](#django-tags--)
- [Tags within attributes:](#tags-within-attributes)
- [Whitespace removal](#whitespace-removal)
- [Jinja2 Extension](#jinja2-specific)
- [Hamlpy Tag](#jinja2-hamlpy-tag)
- [Filters](#filters)
- [:plain](#plain)
- [:javascript](#javascript)
Expand Down Expand Up @@ -396,6 +398,31 @@ is compiled to:

<li>Item one</li><li>Item two</li><li>Item three</li>

## Jinja2 Extension

### Hamlpy Tag

You can embed hamlpy within jinja templates with the `{% haml %}` tag

:python
import jinja2
from hamlpy.ext import HamlPyTagExtension

env = jinja2.Environment(extensions=[HamlPyTagExtension])

haml = """\
Before:
{% haml %}
- if something
%p hello
- else
%p goodbye
{% endhaml %}
After"""

print(env.from_string(haml).render())
# Before:\n <p>goodbye</p>\nAfter

## Filters

### :plain
Expand Down