Skip to content

Perl implementation of JavaScript template engine Pug

Notifications You must be signed in to change notification settings

darutoko/Template-Pug

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NAME

Template::Pug - Pug templates implementation for Perl

SYNOPSIS

use Template::Pug;

my $tp = Template::Pug->new;
$tp->render(<<'EOF', {list_name => 'List', list => ['foo', 'bar']});
div
        p= $list_name
        ul#some_id
                - for my $item (@$list)
                        li.some_class= $item

my $tp = Template::Pug->new;
$tp->render_file('template.pug', { user => {name => 'Foo', count => 42} });
# template.pug
# div.
#       Hello, #{$user->{name}}!
#       You are #{$user->{count}}'th user to signup here!

DESCRIPTION

Template::Pug is a Perl implementation of JavaScript template engine Pug

SYNTAX

Attributes

Tag attributes look similar to HTML, but their values are Perl expressions.

a(href="yandex.ru") Yandex
// <a href="yandex.ru">Yandex</a>

a(href="yandex.ru" class="button") Yandex
// <a href="yandex.ru" class="button">Yandex</a>

Note: since it is impossible(for me) to parse Perl, you can define multiple attributes in one line if expression consists only of single/double quoted string followed by space or comma. Otherwise, every thing until the end of line or end of attribute block is considered single Perl expression.

// Wrong!
- my $authenticated = 1;
div(class=$authenticated ? 'auth' : 'anon' id="bar") Content

// Right
div(id="bar" class=$authenticated ? 'auth' : 'anon') Content

// Right
div(
        id=$id
        class=$authenticated ? 'auth' : 'anon'
        foo=$bar->baz()
) Content

By default, all attribute values are escaped. If you need to use special characters, use != instead of =.

div(escaped="<code>")
// <div escaped="&lt;code&gt;"></div>

div(unescaped!="<code>")
// <div unescaped="<code>"></div>

Boolean attributes are mirrored by Pug. Only literal string undef is considered false, every thing else is true. When no value is specified true is assumed.

input(foo bar='baz')
// <input bar="baz" foo="foo"/>

input(foo="foo" bar='baz')
// <input bar="baz" foo="foo"/>

input(bar='baz' foo=undef)
// <input bar="baz"/>

The style attribute can be a hash.

a(style={color => 'red', background => 'green'})
// <a style="background:green;color:red"></a>

The class attribute can be an array of names.

- my $classes = ['foo', 'bar', 'baz'];
a(class=$classes)
// <a class="foo bar baz"></a>

a.bang(
  class=$classes
  class=['bing']
)
// <a class="bang foo bar baz bing"></a>

It can also be a hash which maps class names to true or false values. This is useful for applying conditional classes

- my $currentUrl = '/about';
a(href='/' class={active => $currentUrl eq '/'}) Home
// <a href="/">Home</a>

a(href='/about' class={active => $currentUrl eq '/about'}) About
// <a class="active" href="/about">About</a>

Classes may be defined using a .classname syntax.

div.foo
// <div class="foo"></div>

div is the default tag so you can omit its tag name.

.foo
// <div class="foo"></div>

IDs may be defined using a #idname syntax.

div#foo
// <div id="foo"></div>

div is the default tag so you can omit its tag name.

#foo
// <div id="foo"></div>

Pronounced as “and attributes”, the &attributes syntax can be used to explode a hach into attributes of an element.

div#foo(data-bar="foo")&attributes({"data-foo" => "bar"})
// <div data-bar="foo" data-foo="bar" id="foo"></div>

- my $attributes = {id => undef, class => 'baz'};
div#foo(data-bar="foo")&attributes($attributes)
// <div class="baz" data-bar="foo"></div>

Attributes applied using &attributes are not automatically escaped.

Code

Code starts with - and does not directly add anything to the output. If code element have child than open and closing curly braces added around its content.

// Wrong!
- for (0..2) {
        li item
- }

// Right
- for (0..2)
        li item
// <li>item</li><li>item</li><li>item</li>

Code block starts with -\n.

-
        my @list = qw/one
                          two
                          three/;
- for(@list)
        li= $_
// <li>one</li><li>two</li><li>three</li>

Comments

Buffered comments // act like markup tags, producing HTML comments in the rendered page. Like tags, they must appear on their own line.

// some comments
div foo

Will produce:

<!-- some comments -->
<div>foo</div>

Unbuffered comments //- are only for commenting on the Pug code itself, and do not appear in the rendered HTML.

//- some comments
div foo

Will produce:

<div>foo</div>

Block comments are also an option.

// some
        multiline
        comment
div foo

Will produce:

<-- some
        multiline
        comment -->
<div>foo</div>

Moreover, since all lines beginning with < are treated as plain text, normal HTML-style conditional comments work just fine.

div
        <-- HTML comments -->
        foo

Will produce:

<div><-- HTML comments -->foo</div>

Doctype

There are shortcuts for commonly used doctypes:

doctype html
// <!DOCTYPE html>,

doctype xml
// <?xml version="1.0" encoding="utf-8" ?>,

doctype transitional
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">,

doctype strict
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">,

doctype frameset
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">,

doctype 1.1
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">,

doctype basic
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">,

doctype mobile
// <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">,

doctype plist
// <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

Or you can use custom doctype.

doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">

If, for whatever reason, it is not possible to use the doctype keyword, but you would still like to specify the doctype of the template, you can do so via the doctype option.

$tp->render('img src="foo"', {doctype => 'html'})
// <img src="foo">

$tp->render('img src="foo"', {doctype => 'xml'})
// <img src="foo"></img>

Expressions

Expression starts with =. It evaluates the Perl code and outputs the result. For security, expression output is HTML escaped.

p= 'This is <escaped> expression'
// <p>This is &lt;escaped&gt; expression</p>

Unescaped expression starts with !=.

p!= 'This is <unescaped> expression'
// <p>This is <unescaped> expression</p>

Includes

Includes allow you to insert the contents of one Template::Pug file into another.

// main.pug
div
        include head.pug
        p content
        include foot.pug

// head.pug
p head

// foot.pug
p foot

Will produce:

<div>
        <p>head</p>
        <p>content</p>
        <p>foot</p>
</div>

If the path is absolute (e.g., include /root.pug), it is resolved by prepending basedir option. Otherwise, paths are resolved relative to the current file being compiled. If no file extension is given, .pug is automatically appended to the file name.

Including files that are not a Template::Pug templates simply includes their raw text.

// main.pug
head
        style
                include style.css
        script
                include script.js
body
        div foo

// style.css
div {
        color: red;
}

// script.js
console.log('Hi!');

Will produce:

<head>
        <style>
                div {
                        color: red;
                }
        </style>
        <script>
                console.log('Hi!');
        </script>
</head>
<body>
        <div>foo</div>
</body>

Inheritance

Template::Pug supports template inheritance. Template inheritance works via the block and extends keywords. If no file extension is given, .pug is automatically appended to the file name. In a template, a block is simply a “block” of Template::Pug code that a child template may replace. This process is recursive. Blocks can have default content.

// layout.pug
html
        head
                title My Title
                block scripts
                        script(src='/jquery.js')
        body
                block content
                block foot
                        #footer
                                p some footer content

//- page-a.pug
extends layout.pug

block scripts
        script(src='/jquery.js')
        script(src='/pets.js')

block content
        h1= $title
        - my $pets = ['cat', 'dog'];
        - for my $pet (@$pets)
                include pet.pug

//- pet.pug
p= $pet

Template::Pug allows you to replace (default), prepend, or append blocks. For example you can have default scripts in head block that you want to use on every page and just append scripts you need for current page.

// layout.pug
html
        head
                block head
                        script(src='/jquery.js')
                        script(src='/default.js')
body
        block content

// page.pug
extends layout.pug

block append head
        script(src='/actions.js')

When using block append or block prepend, the word “block” is optional.

Interpolation

In text block any Perl expression put between #{ and } will be evaluated and result will be escaped and put in its place.

- my $foo = 'simple string';
- my $bar = '<p>string inside tag</p>';
p some text #{10+10} some text #{$foo} some text #{$bar}
// <p>some text 20 some text simple string some text &lt;p&gt;string inside tag&lt;/p&gt;</p> 

If you need to put literal #{ in text just put slash in front of it to escape.

p some text \#{foo} some text
// <p>some text #{foo} some text</p>

Use !{ } if you want an unescaped result.

- my $foo = '<p>string inside tag</p>';
div some text !{$foo}
// <div>some text<p>string inside tag</p></div>

Text between #[ and ] will be evaluated as Template::Pug code and result will be put in its place.

p text #[em foo] text #[em(foo='bar') baz] text
// <p>text <em>foo</em> text <em foo="bar">baz</em> text</p>

Mixins

There is no Mixins yet.

Tags

By default, text at the start of a line represents an HTML tag. Indented tags are nested, creating the tree structure of HTML.

body
        div
                h1 title
                p text

// <body>
//      <div>
//              <h1>title</h1>
//              <p>text</p>
//      </div>
// </body>

To save space, Template::Pug provides an inline syntax for nested tags.

a: img
// <a><img /></a>

Tags such as img, meta, and link are automatically self-closing (unless you use the XML doctype). You can also explicitly self close a tag by appending the / character.

foo/
foo(bar='baz')/
// <foo/>
// <foo bar="baz" />

Text

The easiest way to add plain text is inline. The first term on the line is the tag itself. Everything after the tag and one space will be the text contents of that tag.

p some plain <em>text</em>
// <p>some plain <em>text</em></p>

Lines starting with < or | are treated as plain text.

<body>
        p
                | some 
                | text
</body>

// <body>
//      <p>some text</p>
// </body>

To add block of text to a tag use . followed by a new line.

script.
        if(true) {
                console.log('true');
        } else {
                console.log('false');
        }

ATTRIBUTES

Template::Pug implements the following attributes.

append

my $code = $tp->append;
$tp = $tp->append('warn "Processed template"');

Append Perl code to compiled template.

basedir

my $basedir = $tp->basedir;
$tp = $tp->basedir('templates');

Bsaedir used to resolve absolute path in template includes and extends.

cache

my $cache = $tp->cache;
$tp = $tp->cache(1);

Cache is a flag, if set to true will cache and reuse compiled templates. Requires filename as a cache key. Defaults to false.

doctype

my $doctype = $tp->doctype;
$tp = $tp->doctype('html');

Doctype used to specify doctype if unable to do it in template.

encoding

my $encoding = $tp->encoding;
$tp = $tp->encoding('cp1251');

Encoding used for template files, defaults to UTF-8.

namespace

my $namespace = $tp->namespace;
$tp = $tp->namespace('main');

Namespace used to compile templates, defaults to Template::Pug::SandBox. Note that namespaces should only be shared very carefully between templates, since functions and global variables will not be cleared automatically.

prepend

my $code = $tp->prepend;
$tp = $tp->prepend('my $self = shift;');

Prepend Perl code to compiled template.

pretty

my $pretty = $tp->pretty;
$tp = $tp->pretty(1);

Pretty is a flag, if set to true adds whitespace to the resulting HTML to make it easier for a human to read using ' ' as indentation. Used for debugging only. Defaults to false.

METHODS

render

my $output = $tp->render('div Hello world!');
my $output = $tp->render('p= $foo', {foo => 'bar'});
my $output = $tp->render('p= 1 + 1', {namespace => 'main'});

Render inline template and return the result.

render_file

my $output = $tp->render_file('templates/foo.pug');
my $output = $tp->render_file('templates/foo.pug', {foo => 'bar'});
my $output = $tp->render_file('templates/foo.pug', {cache => 1});

Same as "render", but renders a template file.

SEE ALSO

Pug Mojolicious::Plugin::PugRenderer

About

Perl implementation of JavaScript template engine Pug

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published