Multi target HAML (HAML for PHP, Twig, )


Multi target HAML

Build Status

MtHaml is a PHP implementation of the HAML language which can target multiple languages.

Currently supported targets are PHP and Twig, and new ones can be added easily.

Mt-Haml implements the exact same syntax as ruby-haml; the only difference is that any supported language can be used everywhere HAML expects Ruby code:


  - for user in users
      Email: #{}
      %a(href=user.url) Home page


<ul id="users">
  {% for user in users %}
    <li class="user">
      {{ }}
      Email: {{ }}
      <a href="{{ user.url }}">Home page</a>
  {% endfor %}


  - foreach($users as $user)
      = $user->getName()
      Email: #{$user->getEmail()}
      %a(href=$user->getUrl()) Home page


<ul id="users">
  <?php foreach($users as $user) { ?>
    <li class="user">
      <?php echo $user->getName(); ?>
      Email: <?php echo $user->getEmail(); ?>
      <a href="<?php echo $user->getUrl(); ?>">Home page</a>
  <?php } ?>



$haml = new MtHaml\Environment('php');
$executor = new MtHaml\Support\Php\Executor($haml, array(
    'cache' => sys_get_temp_dir().'/haml',

// Compiles and executes the HAML template, with variables given as second
// argument
$executor->display('template.haml', array(
    'var' => 'value',


$haml = new MtHaml\Environment('twig', array('enable_escaper' => false));

// Use a custom loader, whose responsibility is to convert HAML templates
// to Twig syntax, before handing them out to Twig:
$hamlLoader = new MtHaml\Support\Twig\Loader($haml, $twig->getLoader());

// Register the Twig extension before executing a HAML template
$twig->addExtension(new MtHaml\Support\Twig\Extension());

// Render templates as usual
$twig->render('template.haml', ...);

See examples and MtHaml with Twig


MtHaml escapes everything by default. Since Twig already supports auto escaping it is recommended to enable it in Twig and disable it in MtHaml:

new MtHaml\Environment('twig', array('enable_escaper' => false));

HAML/PHP is rendered like this when auto escaping is enabled:

Email #{$user->getEmail()}
%a(href=$user->getUrl()) Home page
Email <?php echo htmlspecialchars($user->getEmail(), ENT_QUOTES, 'UTF-8'); ?>
<a href="<?php echo htmlspecialchars($user->getUrl(), ENT_QUOTES, 'UTF-8'); ?>">Home page</a>


Using Twig in HAML gives more control over what can be executed, what variables and functions are exposed to the templates, etc. This also allows to use all of Twig's awesome features like template inheritance, macros, blocks, filters, functions, tests, ...

- extends "some-template.haml"

- macro printSomething()
  %p something

- block body
  %h1 Title
  = _self.printSomething()

Integration in Twig

MtHaml comes with an example Twig_Loader that will automatically convert HAML into Twig at loading time (Twig will then compile the resulting Twig script and cache it). Templates with a .haml extension, or whose source starts with {% haml %} will be converted, and the others will be left untouched.

The loader acts as a proxy and takes an other loader as parameter:


$haml = new MtHaml\Environment(...);

$twig_loader = new Twig_Loader_Filesystem(...);
$twig_loader = new MtHaml\Support\Twig\Loader($haml, $twig_loader);

Runtime support

Compiled MtHaml/Twig templates need support from MtHaml at runtime in some cases. Because of this, a Twig extension must be loaded before executing the templates.

// Register the MtHaml extension before executing the template:
$twig->addExtension(new MtHaml\Support\Twig\Extension());


The syntax is the same as HAML/Ruby's syntax, except that PHP or Twig have to be used where Ruby is expected.

See the tutorial and the reference


MtHaml converts HAML to PHP or Twig code. The resulting code can be cached and executed any number of times, and doesn't depend on HAML at runtime.

MtHaml has no runtime overhead.


Helpers in HAML/Ruby are just ruby functions exposed to templates. Any function can be made available to HAML templates by the target language (the function only have to be available at runtime).

In HAML/Twig you can use all of Twig's functions, filters, and tags. In HAML/PHP, you can use all PHP functions.


Filters take plain text input (with support for #{...} interpolations) and transform it, or wrap it.

Example with the javascript filter:

%p something
<script type="text/javascript">
  some.javascript.code("{{ var|escape('js') }}");

The following filters are available:

  • css: wraps with style tags
  • cdata: wraps with CDATA markup
  • coffee*: compiles coffeescript to javascript
  • escaped: html escapes
  • javascript: wraps with script tags
  • less*: compiles as Lesscss
  • markdown*: converts markdown to html
  • php: executes the input as php code
  • plain: does not parse the filtered text
  • preseve: preserves preformatted text
  • scss*: converts scss to css
  • twig: executes the input as twig code

Filter marked with * have runtime dependencies and are not enabled by default. Such filters need to be provided to MtHaml\Environment explicitly.

Example with the Coffee filter:


$coffeeFilter = new MtHaml\Filter\CoffeeScript(new CoffeeScript\Compiler);

$env = new MtHaml\Environment('twig', array(
    'enable_escaper' => false,
), array(
    'coffee' => $coffeeFilter,


Sass can be used in PHP projects without problem. It only depends on Ruby and does not need to be installed on production servers. So MtHaml will not re-implement Sass.

Frameworks and CMS support

Add yours:


MtHaml is released under the MIT license (same as HAML/Ruby).

  • Allow line breaking after commas

    Allow line breaking after commas

    Vanilla Haml allows line breaking after commas:

    %script{:type => "text/javascript",
            :src  => "javascripts/script_#{2 + 7}"}

    This allows breaking long lines (sometimes with nested objects) into multiple lines.

    It drastically improves readability and prevents horizontal scrolling.

    opened by lolmaus 12
  • Error on `switch` syntax

    Error on `switch` syntax

    A switch block like below

    - switch ($this->params['action']):
        - case 'edit'
            = $this->Html->tag('label', 'Username')
            = $this->Html->tag('p', $this->data['User']['username'])
            - break
        - case 'add'
            = $this->Form->input('username')
            = $this->Form->input('password')
            - break
    - endswitch

    is being rendered to

    <?php switch ($this->params['action']): { ?>
    <?php case 'edit' { ?>
      <?php echo $this->Html->tag('label', 'Username'); ?>
      <?php echo $this->Html->tag('p', $this->data['User']['username']); ?>
      <?php break; ?>
    <?php } ?>
    <?php case 'add' { ?>
      <?php echo $this->Form->input('username'); ?>
      <?php echo $this->Form->input('password'); ?>
      <?php break; ?>
    <?php } ?>
    <?php } ?>
    <?php endswitch; ?>

    which is produce a fatal error.

    If switch syntax is not supported yet, I would like to patch a fix for that. Please give me some clue on where should I start.

    opened by williamn 10
  • MtHaml::runtime


    Can I disable MtHaml::runtime in tag attributes?

    opened by huynhminhson 10
  • Modular Filters implementation proposal

    Modular Filters implementation proposal

    A proposition to add user filters, see #19

    As a proposition, i haven't wrote test right now...

    Anatomy of a filter class

    Filters should at least implements the MtHaml\Filter\FilterInterface. The best way is to extends your filter from MtHaml\Filter\FilterAbstract.

    class PhpFilter extends  MtHaml\Filter\FilterAbstract {
        protected $name = 'php';
        // The renderer is the current renderer instance
        // $options are the environment options
        public function enter($renderer, $options)
         * The parser call this method on each new line.
         * Depending on what you returns:
         * - NodeAbstract Object: the parser will treat "as it is"
         * - String: the Parser will compare the current buffer line and
         *  the string value, then replace the buffer line if String is different
         * - Void: The default parser behavior.
        public function line($buffer, $options)
            // The line will be treated as "raw" text.
            return new Text($buffer->getPosition(), $buffer->getLine());
        // Close the filter
        public function leave($renderer, $options)
            $renderer->write(' ?>'.PHP_EOL)->undent();
    // Add the filter, The filter will be available under :css
    $env = new Environment('php');
    $env->addFilter(new PhpFilter);

    Adding Filters

    1. Through environment configuration:
    $filters = array('textile' => 'Path\To\Class', 'saas' => new Saas);
    $env = new Environment('php', array(), filters);
    1. Through addFilter() method:
    // Add filter by class name: the class will be instanciated if filter is used
    $env->addFilter('saas', 'Project\\Saas');
    // Add filter by instance:
    $env->addFilter(new Saas);
    // you can override the instance filter name like this:
    $env->addFilter('custom', new Saas);
    opened by ronan-gloo 8
  • Laravel service provider

    Laravel service provider

    Hello folks,

    for easy integration with the Laravel framework's view system, we'd need two classes: a compiler adapter for Laravel's compiler interface, and a "service provider" to set up the necessary instances (compiler and an instance of MtHaml\Environment).

    That would allow for people adding this to their Laravel 4 projects just by adding one line to their composer.json and one line to their config file.

    I've got this working locally - if you're interested, I can submit a pull request.

    Great package! =)

    opened by franzliedke 8
  • The function

    The function "mthaml_attributes" does not exist

    I think I got it - I understand how it works now ! It's a nice job, but I'm still not completely sure I understand ...

    I get this exception : External exception (app/themes/yuuki/views/News/index.html.taml) : The function "mthaml_attributes" does not exist in "layouts/layout.html" at line 21

    This is my layouts/layout.html file :

    Thanks for your fast answer ;)

    opened by vendethiel 7
  • Add scalar, object ref name override and auto id incrementation support

    Add scalar, object ref name override and auto id incrementation support

    Some changes in Object Reference implementation:

    1. Scalars are supported, in order to follow original Ruby implementation:
    $str = 'hello';
    $int = 12;
    %div[$str] // generates <div class="string" id="string_hello">
    %div[$int] // generates <div class="integer" id="integer_12">
    1. Object ids are auto-incremented if there is no id methods. The aim is to prevent html ids collisions. Incrementation is based on class name:
    $std = new stdClass;
    %div[$std] // generates <div class="std_class" id="std_class_1">
    %div[$std] // generates <div class="sdt_class" id="std_class_2">
    $foo = new Foo();
    %div[$std] // generates <div class="foo" id="foo_1">
    1. Object Reference id can be overwritten with hamlObjectRef() method (see #23):
    class foo {
      public function hamlObjectRef() {
        return 'customId';

    4; Uses of is_callable() instead of method_exists(), in order to be sure that method is really callable in given context.

    opened by ronan-gloo 6
  • Providing attributes as a variable results in dropping predefined classnames: `.foo{$atts}` removes the `foo` class

    Providing attributes as a variable results in dropping predefined classnames: `.foo{$atts}` removes the `foo` class

    Example of correct behavior


    - $class = 'bar'
    .foo{'class' => $class} Baz


    <div class="foo bar">Baz</div>

    Example of buggy behavior


    - $attrs = array('class' = 'bar')
    .foo{$attrs} Baz

    Expected output:

    <div class="foo bar">Baz</div>

    This is how vanilla Haml works:

    Actual output:

    <div class="bar">Baz</div>
    opened by lolmaus 6
  • Attributes are always escaped

    Attributes are always escaped

    Even when disabling escaper and setting escape_attrs to false, dynamic attributes are always escaped in resultant php/html file. Here is my environment options:

    array('enable_escaper' => false, 'escape_attrs' => false)

    Haml: %div(class="#{body_class()}") %p test

    Output: <div <?php echo MtHaml\Runtime::renderAttributes(array(array('class', (body_class()))), 'html5', 'UTF-8'); ?>> <p>test</p> </div>

    I would expect it to work just as disabling escaper worked, where the echo is left in directly. So the output would be closer to <div class="<?php echo body_class(); ?>">

    opened by withjam 6
  • Won't compile on Linux

    Won't compile on Linux

    Hi! Yesterday I'm trying to complie very simple template:

        %title test

    On Windows it's compiles, but on Ubuntu (XAMPP for Linux 1.8.1) I've got:

    preg_match(): Compilation failed: internal error: previously-checked referenced subpattern not found at offset 358 /opt/lampp/htdocs/modules/haml/vendor/MtHaml/Parser/Buffer.php ... 74 if ($count = preg_match($pattern, $this->line, $match, PREG_OFFSET_CAPTURE)) { ...

    opened by kahurangitama 5
  • Compiler adding line numbers to twig output

    Compiler adding line numbers to twig output

    If I have a HAML file that looks like this:

    - block body
          %title = fn('wp_title')
          - if not fn('is_page','cv')

    MtHaml will compile it to this:

    {% block body %}
      <!DOCTYPE html>
          <title>{{ fn('wp_title') }}</title>
    {% line 7 %}      {% if not fn('is_page','cv') %}
          {% endif %}
    {% endblock %}

    MtHaml is adding these line numbers in places, like {% line 7 %}.

    opened by morgannunan 0
  • Nested hash-style error

    Nested hash-style error

    When using HAML and Twig together , HAML like the following fails :

    - set styles = loadStyles(["bootstrap" , "main" , "other_css" , "fontawesome"])
    !!! 5
        %meta(name="description" content="Free Web tutorials")
        %meta(name="keywords" content="HTML,CSS,XML,JavaScript")
        %meta(name="author" content="My name")
        %meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no")
          Page Title
        - for style in styles
          = style
        -# Navbar section start

                %img(src="#{getImageUrl('logo.png')}" alt="#{getBlogInfo('name')}")
              %button.navbar-toggler(type="button" ){:data => {:toggle => "collapse" , :target => "#navbarSupportedContent"} ,
                                                     :aria => {:controls => "navbarSupportedContent" , :expanded => "false" , :lable => "Toggle navigation"}}

    The resulting exception is : Fatal error: Uncaught Twig\Error\SyntaxError: A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "punctuation" of value ":" in "main.haml" at line 21. in path\vendor\twig\twig\src\ExpressionParser.php on line 386

    opened by morteza-jamali 0
  • XSS in Twig templates

    XSS in Twig templates

    When using HAML and Twig to render our templates, we have run into an issue that allows XSS.

    - set name = '"><script>alert(1);</script>'

    The compiled template is:

    {% set name = '"><script>alert(1);</script>' %}
    <input {{ mthaml_attributes([['value', name]], 'html5', 'UTF-8', false)|raw }}>

    We are using the Symfony bundle, which disables escaping by default.

    Is there anything we need to do to prevent this?

    opened by chadtomkiss-tbp 1
  • nesting within interpolated string is illegal in site

    nesting within interpolated string is illegal in site

    I'm using Laravel 5.7 clean installation, and while trying to add this package with composer, add it to the app.php as Service Provider. The template is giving: "a nesting within interpolated string is illegal in site". Any ideas how to solve this? It seems php 7.1 related.

    opened by dcnl1980 2
  • Using class constant fails

    Using class constant fails

    HAML like the following fails:

    %a(href="#{Namespace\ClassName\::CLASS_CONSTANT}") Label

    The resulting exception is MtHaml\Exception\SyntaxErrorException in vendor/mthaml/mthaml/lib/MtHaml/Parser.php on line 844 with message: Unexpected '"', expected target language expression in /var/www/content-vendor/app/templates/generic/components/topbar.haml on line x, column xx

    opened by Bonscho 1
  • Update twig loader to support Twig 2.x

    Update twig loader to support Twig 2.x

    getSource() was deprecated in twig 1.27

    opened by TechWilk 6
  • unmarked dependency on libpcre3 might break application

    unmarked dependency on libpcre3 might break application

    Hello MtHaml maintainers,

    This library does require libpcre3 to be installed on the system. This should be documented somewhere in this repository (ie. the README).

    I had the issue, that the libpcre3 version on my container was 2:8.35-3.3+deb8u4, which crashed as soon as i used MtHaml to render .haml files. I am aware, that this is not a problem of MtHaml itself, although lacking documentation on a dependency, thus increasing debug time, is a problem with the library.

    in the hopes all dependencies will be documented properly, best regards, scones

    opened by scones 0
  • Command to convert to phtml

    Command to convert to phtml

    This program looks quite awesome, however it's unrealistic to include the entire MtHaml API into a custom PHP module for an existing platform, it would be awesome if I could convert my MtHaml files into phtml files. Like the coffeescript command coffee -c $file would do.

    opened by jeffbdavenport 5
  • MtHaml Twig Loader is not compatible with Twig 2.x

    MtHaml Twig Loader is not compatible with Twig 2.x

    Class MtHaml\Support\Twig\Loader.php

    Has method public function getSource($name) but should be named public function getSourceContext($name) actually

    or PHP will throw an error:

    Class MtHaml\Support\Twig\Loader contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Twig_LoaderInterface::getSourceContext)

    class Loader implements \Twig_LoaderInterface, \Twig_ExistsLoaderInterface
        public function getSource($name)  // <------ SHOULD BE getSourceContext

    But Twig class expects in Twig\LoaderInterface.php:

    interface Twig_LoaderInterface
         * Returns the source context for a given template logical name.
         * @param string $name The template logical name
         * @return Twig_Source
         * @throws Twig_Error_Loader When $name is not found
        public function getSourceContext($name); // <------ NEEDS THIS NAME
    opened by ZaDarkSide 0
Arnaud Le Blanc
Arnaud Le Blanc
PHP Template Attribute Language — template engine for XSS-proof well-formed XHTML and HTML5 pages

PHPTAL - Template Attribute Language for PHP Requirements If you want to use the builtin internationalisation system (I18N), the php-gettext extension

PHPTAL 165 Nov 17, 2021
Provides TemplateView and TwoStepView using PHP as the templating language, with support for partials, sections, and helpers.

Aura View This package provides an implementation of the TemplateView and TwoStepView patterns using PHP itself as the templating language. It support

Aura for PHP 81 Nov 16, 2021
A complete and fully-functional implementation of the Jade template language for PHP

Tale Jade for PHP Finally a fully-functional, complete and clean port of the Jade language to PHP — Abraham Lincoln The Tale Jade Template Engine brin

Talesoft 93 May 4, 2021
The free-to-use template for your Imagehost-website made with PHP, HTML and CSS!

The free-to-use template for your Imagehost-website made with PHP, HTML and CSS! Some information before we start This repo is only code related, to a

Ilian 5 Nov 3, 2021
The free-to-use template for your Imagehost-website made with PHP, HTML and CSS!

The free-to-use template for your Imagehost-website made with PHP, HTML and CSS! Some information before we start This repo is only code related, to a

Ilian 5 Nov 3, 2021
PHP template engine for native PHP templates

FOIL PHP template engine, for PHP templates. Foil brings all the flexibility and power of modern template engines to native PHP templates. Write simpl

Foil PHP 163 Nov 20, 2021
A Mustache implementation in PHP.

Mustache.php A Mustache implementation in PHP. Usage A quick example: <?php $m = new Mustache_Engine(array('entity_flags' => ENT_QUOTES)); echo $m->re

Justin Hileman 3.1k Nov 17, 2021
Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.

Smarty 3 template engine Documentation For documentation see Requirements Smarty can be run with PHP 5.2 to PHP 7.4

Smarty PHP Template Engine 1.9k Nov 23, 2021
Native PHP template system

Plates Plates is a native PHP template system that's fast, easy to use and easy to extend. It's inspired by the excellent Twig template engine and str

The League of Extraordinary Packages 1.3k Nov 19, 2021
☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites.

Latte: amazing template engine for PHP Introduction Latte is a template engine for PHP which eases your work and ensures the output is protected again

Nette Foundation 731 Nov 27, 2021
View template engine of PHP extracted from Laravel

Blade 【简体中文】 This is a view templating engine which is extracted from Laravel. It's independent without relying on Laravel's Container or any others.

刘小乐 145 Aug 13, 2021
PHP 5.3 Mustache implementation

Phly\Mustache MOVED! This package has moved to phly/phly-mustache, and the package name has changed to phly/phly-mustache. I have updated packagist to

phly 124 Aug 17, 2021
TextGenerator is a PHP package that aims to generate automated texts from data.

TextGenerator TextGenerator is a PHP package that aims to generate automated texts from data. Feel free to comment and contribute. Features Text gener

Vincent Brouté 85 Jul 19, 2021
A faster, safer templating library for PHP

Brainy Brainy is a replacement for the popular Smarty templating language. It is a fork from the Smarty 3 trunk. Brainy is still very new and it's lik

Box 64 Jan 15, 2021
A ready-to-use Model View Controller template in PHP

PHP-MVC-Template A ready-to-use Model View Controller template in PHP Use this repo as a template! (Or clone it) Start to configure your MVC file Afte

Loule | Louis 6 Nov 19, 2021
Derste birlikte hazırladığımız PHP Tema Motoru kaynak kodları

Prototürk Template Engine Prototürk'de sorulan bir soru üzerine videoda birlikte hazırladığımız php ile geliştirilmiş basit bir tema motoru. Geçerli d

Tayfun Erbilen 12 Nov 1, 2021
Provides a GitHub repository template for a PHP package, using GitHub actions.

php-package-template Installation ?? This is a great place for showing how to install the package, see below: Run $ composer require ergebnis/php-pack

null 260 Nov 24, 2021
Qiq templates for PHP 8.

Qiq Templates for PHP 8 This package provides a PHP 8.0 implementation of the TemplateView and TwoStepView patterns using PHP itself as the templating

null 10 Nov 9, 2021
Standalone Skeltch templating engine for PHP

SkeltchGo is a standalone version of Glowie Skeltch templating engine for PHP, intented to use from outside the framework.

glowie 1 Nov 5, 2021