diff --git a/hamlpy/ext.py b/hamlpy/ext.py index 096b8cc..c3d7bf1 100644 --- a/hamlpy/ext.py +++ b/hamlpy/ext.py @@ -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): @@ -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 + diff --git a/hamlpy/test/ext_test.py b/hamlpy/test/ext_test.py index a1c61b1..2fe88fd 100644 --- a/hamlpy/test/ext_test.py +++ b/hamlpy/test/ext_test.py @@ -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): """ @@ -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)) \ No newline at end of file + 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

goodbye

\n' + eq_(html, self._jinja_render(haml)) + + def test_haml_tag2(self): + haml = 'before{% haml %}.header.span-24.last{% endhaml %}after' + html = "before
\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) diff --git a/reference.md b/reference.md index 542bdb0..b79f288 100644 --- a/reference.md +++ b/reference.md @@ -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) @@ -396,6 +398,31 @@ is compiled to:
  • Item one
  • Item two
  • Item three
  • +## 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

    goodbye

    \nAfter + ## Filters ### :plain