Pug — синтаксис, теги, свойства, doctype

шаблонизатор Pug
  1. Синтаксис
  2. Doctype
  3. Теги
  4. Атрибуты

Pug, как заявлено, делает разметку более простой и читаемой. Достигается это за счёт упрощённого синтаксиса.

Синтаксис

В Pug нет закрывающих тегов, а сами теги пишутся без угловых скобок. Вложенность определяется отступами.

doctype html
html(lang="ru")
  head
    title Pug
  body
    h1 Pug - node template engine
    #container.col
      p.
        Pug - языком шаблонов с акцент 
        на производительность и функции.

Такая разметка будет трансформирована в

<!DOCTYPE html>
<html lang="ru">
  <head>
    <title>PUG</title>
  </head>
  <body>
    <h1>Pug - node template engine</h1>
    <div class="col" id="container">
      <p>
        Pug - языком шаблонов с акцент 
        на производительность и функции.
      </p>
    </div>
  </body>
</html>

Doctype

Для HTML5 достаточно короткой версии

doctype html
<!DOCTYPE html>

Другие варианты doctype для XML, strict и прочего смотрите на сайте pug  https://pugjs.org/language/doctype.html

Doctype влияет на компиляцию.  Например, конец самозакрывающихся тегов (/> >) или вывод логических атрибутов зависит от того, указан HTML или XML.
Если по какой-либо причине невозможно использовать ключевое слово doctype (рендеринг фрагментов HTML), но вы все равно хотите указать тип документа в шаблоне, вы можете сделать это с помощью параметра doctype.

let pug = require('pug');

let source = 'img(src="foo.png")';

pug.render(source);
// => '<img src="foo.png"/>'

pug.render(source, {doctype: 'xml'});
// => '<img src="foo.png"></img>'

pug.render(source, {doctype: 'html'});
// => '<img src="foo.png">'

Теги

По умолчанию текст в начале строки (или после пробела) представляет собой HTML-тег. Теги с отступом вкладываются, создавая древовидную структуру HTML.

ul
  li Item A
  li Item B
  li Item C
<ul>
  <li>Item A</li>
  <li>Item B</li>
  <li>Item C</li>
</ul>

Pug знает, какие элементы являются самозакрывающимися:

img
<img/>

Для экономии места, в Pug предусмотрен инлайн синтаксис для вложеных тегов

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

Такие теги, как img, meta и link, автоматически закрываются (если вы не используете тип документа XML). Можно явно закрыть тег самостоятельно, добавив символ /.

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

Атрибуты

Атрибуты тегов в Pug похожи на HTML (с необязательными запятыми), но их значения являются обычным JavaScript.

a(href='google.com') Google
|
|
a(class='button' href='google.com') Google
|
|
a(class='button', href='google.com') Google
<a href="google.com">Google</a>
<a class="button" href="google.com">Google</a>
<a class="button" href="google.com">Google</a>

Javascript выражения тоже работают

- let authenticated = true
body(class=authenticated ? 'authed' : 'anon')
<body class="authed"></body>

Если у тега много атрибутов можно разделить их по строкам

input(
  type='checkbox'
  name='agreement'
  checked
)
<input type="checkbox" name="agreement" checked="checked" />

Если имя вашего атрибута содержит необычные символы, которые могут мешать синтаксису JavaScript. Примеры таких символов включают [] и () (часто используется в Angular 2). В примере ниже `(click)` рассматривается как вызов функции вместо имени атрибута,  в результате ошибка

div(class='div-class' (click)='play()')
/var/www/html/pug/Untitled-1.pug:1:11
  > 1| div(class='div-class' (click)='play()')
-----------------^

Syntax Error: Assigning to rvalue

Либо заключите атрибут в кавычки, либо используйте запятые для разделения различных атрибутов.

div(class='div-class', (click)='play()')
div(class='div-class' '(click)'='play()')
<div class="div-class" (click)="play()"></div>
<div class="div-class" (click)="play()"></div>

Далее будет несколько примеров того, как можно использовать переменные в атрибутах.

1. Записать атрибуты в Javascript

- let url = 'pug-test.html';
a(href='/' + url) Link
|
|
- url = 'https://example.com/'
a(href=url) Another link
<a href="/pug-test.html">Link</a>
<a href="https://example.com/">Another link</a>

2. Использовать шаблонные литералы

- let btnType = 'info'
- let btnSize = 'lg'
button(type='button' class='btn btn-' + btnType + ' btn-' + btnSize)
|
|
button(type='button' class=`btn btn-${btnType} btn-${btnSize}`)
<button class="btn btn-info btn-lg" type="button"></button>
<button class="btn btn-info btn-lg" type="button"></button>

По умолчанию все атрибуты экранированы, чтобы предотвратить атаки (например, межсайтовый скриптинг). Если вам нужно использовать специальные символы, используйте! = Вместо =.

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

Булевы атрибуты принимают значения true и false. Если значение не указано, предполагается true.

input(type='checkbox' checked)
|
|
input(type='checkbox' checked=true)
|
|
input(type='checkbox' checked=false)
|
|
input(type='checkbox' checked=true.toString())
<input type="checkbox" checked="checked" />
<input type="checkbox" checked="checked" />
<input type="checkbox" />
<input type="checkbox" checked="true" />

Если doctype html, Pug знает, что не нужно указывать атрибут, и вместо этого использует краткий стиль (понятный всем браузерам).

doctype html
|
|
input(type='checkbox' checked)
|
|
input(type='checkbox' checked=true)
|
|
input(type='checkbox' checked=false)
|
|
input(type='checkbox' checked=true && 'checked')
<!DOCTYPE html>
<input type="checkbox" checked>
<input type="checkbox" checked>
<input type="checkbox">
<input type="checkbox" checked="checked">

Атрибут style может быть строкой, как любой нормальный атрибут; но это также может быть объект, который удобен, когда стили генерируются JavaScript.

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

Атрибут class может быть строкой, как любой другой атрибут, но это также может быть массив имен классов, что удобно при генерации из JavaScript.

- let classes = ['foo', 'bar', 'baz']
a(class=classes)
|
|
//- атрибут класса также может быть повторен для объединения массивов
a.bang(class=classes class=['bing'])
<a class="foo bar baz"></a>
<a class="bang foo bar baz bing"></a>

Атрибут class может быть объектом, который отображает имена классов в значения true или false. Это полезно для применения условий в определении классов.

- let currentUrl = '/about'
a(class={active: currentUrl === '/'} href='/') Home
|
|
a(class={active: currentUrl === '/about'} href='/about') About
<a href="/">Home</a>
<a class="active" href="/about">About</a>

Классы можно задавать записывая название через точку после тега. Задавая класс для div, сам тег можно не указывать.

a.button
|
|
.content
<a class="button"></a>

<div class="content"></div>

ID элемента указывается как класс, только вместо точки используется #

a#main-link
|
|
#content
<a id="main-link"></a>

<div id="content"></div>

&attributes синтаксис  может использоваться для разделения атрибутов элемента.

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

В приведенном выше примере используется литерал объекта. Но вы также можете использовать переменную, значение которой также является объектом.

- let attributes = {};
- attributes.class = 'baz';
div#foo(data-bar="foo")&attributes(attributes)
<div class="baz" id="foo" data-bar="foo"></div>

Атрибуты, примененные с использованием &attributes, автоматически не экранируются. Вы должны обязательно проверять любые пользовательские данные, чтобы избежать  cross-site scripting (XSS).