Yammy is an indent-based syntax for nice and clean templates of HTML pages. It also uses CSS-like selectors to define HTML tags.
Yammy translator is not a template engine. It does not handle expressions or condition blocks. It runs as a preprocessor for actual template engine like Jinja2, Twig or Django template engine.
Yammy comes with integration modules for Jinja2 and Django template engines.
There also is a command-line utility which can be used to convert Yammy template to HTML template.
Yammy was started as an experiment aimed to solve template merge troubles.
We often had a situations like this:
- some guy adds some classes or markups used by Javascript he develops,
- other guy fixes a browser-related issue by changing the same template lines,
- and their work gets totally ruined when it comes to merge and resolving of merge conflicts.
There were far too many merge conflicts because of all those really long lines with tons of {% if's %} in HTML tag attributes.
There were far too many characters on changed lines to understand what other developer did and how the merged code should look like.
We started with the following thoughts:
- It's much easier to solve conflicts in source files then in HTML templates simply because lines in source files are much shorter;
- It would be better to use indentation for nested tags just to stop loosing and misplacing closing tags,
- It would be better to use indentation just to make templates look great,
- We don't need all those <>'s and ""'s - keep them for browsers;
- Browsers don't need all those spaces and line breaks - keep them for developers;
- It would be great to use the CSS selectors to define HTML tags and attributes,
- There is no need for full HTML syntax support, one should be able to use HTML code in Yammy template if needs to.
Then we used YAML syntax as a base and got the name for the project: Yammy.
After a brief discussion we had an idea on template syntax, then we got an implementation and it worked for us surprisingly well.
The Yammy template syntax has much in common with the HAML, Slim and some other indent-based template engine languages.
Line meaning is being recognized by the first line's character:
- Lines starting with lowercase Latin letters are HTML tags.
- Lines starting with the '-' character are HTML tag attributes.
- Lines starting with the '|' (pipe character) define the HTML code and the text that occurs between that element's opening and closing tag.
- Lines starting with the '#' character are comments.
- Lines starting with the '!' character are multi-line escaping switchers.
Empty lines and trailing spaces are ignored.
You may use CSS-like selectors to define tag's attributes.
You may also use HTML code in Yammy templates so you can easily paste some generated HTML lines into Yammy template never caring of translating it into Yammy syntax.
Yammy Translates to
------------------------- -----------------------------------------------------------
div Some Text <div>Some text</div>
div <div>Some text</div>
| Some text
div.class#id Inner Text <div class="class" id="id">Inner Text</div>
div <div class="class" id="id">Inner Text</div>
- class class
- id id
| Inner Text
div.class1.class2#id <div class="class1 class2" id="id">Inner Text</div>
input[type="submit"] <input type="submit"/>
input[type=submit] <input type="submit"/>
Tag nesting is being declared using indentation:
Yammy Translates to
------------------------- -----------------------------------------------------------
div.outer <div class="outer"><div class="inner">Some text</div></div>
div.inner
Some text
Yammy Translates to
------------------------- -----------------------------------------------------------
<!doctype html> <!doctype html><html><body></body></html>
html
body
{% if target.hit %} {% if target.hit %}<div class="hit">Hit!</div>{% endif %}
div.hit Hit!
{% endif %}
Yammy Translates to
------------------------- -----------------------------------------------------------
html <html><body><div> <p>Hello!</p>
body <p>World!</p></div></body></html>
div
!HTML
<p>Hello</p>
!YAMMY
p World!
Yammy Translates to
------------------------------- -----------------------------------------------------
script <script>
$(function(){ $(function(){
$('.button').click( $('.button').click(
function(e){ function(e){
console.log(e); console.log(e);
} }
); );
}); });
</script>
Yammy does not support multiline comments. To add a single-line comment start it with the '#' character:
Yammy HTML
------------------------------- -----------------------------------------------------
div <div class="class" id="id">Inner Text</div>
# let's define a class
- class class
# let's specify the id
- id id
# let's add the inner text
| Inner Text
There are no extra brackets and quotes. Block nesting is defined by their indentation.
It's hard to work on the same HTML template with someone else: changes made to long lines with many attribute definitions are difficult to merge, nested single row condition statements are difficult to understand and maintain.
With Yammy you may split your template to as many lines as you wish and indent nested blocks.
So it's much easier to figure out what has been changed:
- <div class="row{% if needs_more_light }highlighted_less{% else %}highlighted{% endif %}">Highlighted row</div>
+ <div class="row{% if needs_more_light }highlighted_more{% else %}highlighted{% endif %}">Highlighted row</div>
- highlighted_less
+ highlighted_more
Yammy translator produces compact HTML code without extra space characters.
Yammy is available as PyPI package, so the easiest way to install Yammy is to use pip or easy_install Python package manager:
$ pip install yammy
You may also clone Mercurial repository:
$ hg clone https://quasinerd@bitbucket.org/quasinerd/yammy
and manually add the yammy package to your project.
Yammy Template → Django/Jinja HTML Template → Web Page
>>> from yammy import yammy_to_html
>>> yammy_to_html('template.yammy', 'template.html')
>>> from yammy import yammy_to_html_string
>>> yammy_to_html_string('div\n | Inner text')
You may use the yammy command-line utility for the batch processing of Yammy templates:
yammy <source file or folder> [--dest=<destination file or folder name>]
I used it in PHP projects to convert .ymy files to Twig templates.
Yammy integrates with Django, Jinja2 and Jingo (and any other thing you want). Make sure you use .ymy or .yammy extension for your Yammy template files. Note you can also mix Yammy templates with HTML ones.
Configure Django to use template loaders provided by yammy.django_loaders module using the TEMPLATE_LOADERS option in your settings.py:
TEMPLATE_LOADERS = (
'yammy.django_loaders.YammyFileSystemLoader',
'yammy.django_loaders.YammyPackageLoader',
)
Yammy comes with the Jinja2 integration module. The simplest way to enable a Yammy template processing in your application looks roughly like this:
from jinja2 import Environment
from yammy.jinja2_loaders import YammyPackageLoader
env = Environment(loader=YammyPackageLoader('yourapplication', 'templates'))
Jingo (http://pypi.python.org/pypi/jingo) is an adapter for using Jinja2 templates within Django.
The simpliest way to attach Yammy templates to Jingo adapter is by using the yammy.jingo_loaders module.
Change the TEMPLATE_LOADERS setting in your settings.py as follows:
TEMPLATE_LOADERS = (
'yammy.jingo_loaders.Loader',
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
This code also integrates Jingo/Jinga2 to your Django project.
At this moment there are Yammy syntax highlighting files for the Sublime Text 2 editor and Colorer Eclipse plugin.
Use Package Control to install the Yammy Syntax Highlighting package.
Clone the Sublime Text Yammy Syntax Highlighting package from GitHub repository and register this folder to the list of TextMate packages in PyCharm settings.
Make sure to define the IDE to TextMate color scheme map for Default scheme or you may get a package loading error.
You may find the Colorer Eclipse plugin files and installation instructions in editors/eclipse-colorer folder.