Pug. Начало работы. Часть первая из двух

18.06.2021

Теги: HTMLJavaScriptWeb-разработкаВерсткаТеорияШаблонСайта

Pug — это шаблонизатор и html-препроцессор, написанный на javascript для платформы Node.js, с целью ускорения верстки. Это даже быстрее, чем при использовании emmet — так что будет полезен любому веб-разработчику. Тем более, что освоить Pug можно за пару часов, синтаксис достаточно прост и интуитивно понятен.

Создание проекта

Давайте создадим директорию project, а внутри нее еще две директории — src и dist. В директории src будут исходники, а в директории dist — готовая сборка. И откроем проект в VS Code — нужно кликнуть по иконке папки project правой кнопкой мыши и выбрать в контекстном меню «Открыть с помощью VS Code».

Установка Pug

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

> npm install pug-cli --g
> npm install pug --save-dev # из директории проекта

Пробуем на зуб

Создадим в директории src файл index.pug следующего содержания:

html(lang="ru")
  head
    meta(charset="utf-8")
    title= "Pug. Начало работы"
  body
      h1 Hello, World!

Переходим в директорию src и выполняем команду:

> pug --pretty index.pug

Чтобы следить за изменениями index.pug — нужно добавить ключ -w:

> pug --pretty -w index.pug

Установка Gulp

Как работать с gulp — это тема для отдельной статьи, так что без подробностей.

> npm install gulp --save-dev # из директории проекта
> npm install gulp-pug --save-dev # из директории проекта

Создаем файл gulpfile.js с тремя задачами для преобразования pug-файлов и отслеживания изменений.

const gulp = require('gulp');
const pug = require('gulp-pug');

gulp.task('pug', function () {
    return gulp.src('src/*.pug')
        .pipe(pug({pretty: true}))
        .pipe(gulp.dest('dist'));
});

gulp.task('watch', function () {
    return gulp.watch('src/**/*.pug', gulp.parallel('pug'))
});

gulp.task('default', gulp.parallel('watch'));

Наш файл package.json сейчас имеет только три зависимости:

{
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-pug": "^5.0.0",
    "pug": "^3.0.2"
  }
}

Синтаксис Pug

Синтаксис Pug достаточно прост. Он не имеет угловых скобок и закрывающих тегов. Вложенность элементов определяется отступом — табуляция или пробел. Классы css задаются через точку, идентификаторы — через решетку, атрибуты — в круглых скобках.

1. Теги, классы, идентификаторы

Давайте создадим маркированный список:

ul
    li Значение 1
    li Значение 2
    li Значение 3
<ul>
    <li>Значение 1</li>
    <li>Значение 2</li>
    <li>Значение 3</li>
</ul>

Теперь добавим css-классы нашей разметке:

ul.list
    li.list__item Значение 1
    li.list__item Значение 2
    li.list__item Значение 3
<ul class="list">
    <li class="list__item">Значение 1</li>
    <li class="list__item">Значение 2</li>
    <li class="list__item">Значение 3</li>
</ul>

Добавим тегу <ul> еще и идентификатор:

ul#items.list
    li.list__item Значение 1
    li.list__item Значение 2
    li.list__item Значение 3
<ul id="items" class="list">
    <li class="list__item">Значение 1</li>
    <li class="list__item">Значение 2</li>
    <li class="list__item">Значение 3</li>
</ul>

2. Атрибуты элемента

Чтобы указать атрибут элементу — достаточно указать его в круглых скобках:

a(href="#", target="_blank") Ссылка
a(href="#" target="_blank") Ссылка
<a href="#" target="_blank">Ссылка</a>

Если атрибутов много, то можно указать их многострочными линиями:

input(
  type='checkbox'
  name='agreement'
  checked
)
Если с атрибутами необходимо указать класс и/или индификатор, то указываются они до атрибутов.

3. Текст элемента

Текст элементу указывается через пробел, после символа | или после точки .:

p.paragraph Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.
p.paragraph
    | Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.
p.paragraph.
    Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.

Результат будет одинаковым:

<p class="paragraph">Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.</p>

4. Буферизация и экранирование

Текст элементу можно присвоить — это что-то вроде работы с переменными. Как будто содержимое элемента — это переменная и мы присваиваем ей значение. При этом значение сперва вычисляется как javascript-выражение. И еще производится экранизация символов <, > и &.

p.paragraph= 'Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.'
p.paragraph
    = 'Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.'
<p class="paragraph">Lorem ipsum &lt;em&gt;dolor&lt;/em&gt; sit amet, consectetur adipisicing elit.</p>

Чтобы избежать экранирования, надо использовать !=:

p.paragraph!= 'Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.'
p.paragraph
    != 'Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.'
<p class="paragraph">Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.</p>

5. Вывод переменных

Есть два способа вывести значение переменной — с экранированием символов <, >, & и без экранирования.

- var content = 'ipsum <em>dolor sit</em> amet'
p.paragraph Lorem #{content}, consectetur adipisicing elit.
p.paragraph Lorem !{content}, consectetur adipisicing elit.
<p class="paragraph">Lorem ipsum &lt;em&gt;dolor sit&lt;/em&gt; amet, consectetur adipisicing elit.</p>
<p class="paragraph">Lorem ipsum <em>dolor sit</em> amet, consectetur adipisicing elit.</p>

6. Элемент внутри элемента

Давайте разместим изображение внутри параграфа:

p.paragraph: img.image(src="picture.jpg" alt="Изображение")
<p class="paragraph"><img class="image" src="picture.jpg" alt="Изображение"/></p>

Еще один пример — параграф, внутри которого <em> и ссылка:

p Lorem ipsum <em>dolor</em> sit amet, consectetur #[a.link(href="page.html") adipisicing] elit.
<p>Lorem ipsum <em>dolor</em> sit amet, consectetur <a class="link" href="page.html">adipisicing</a> elit.</p>

7. Комментарии в коде

Однострочный комментарий начинается с символов // — такой комментарий будет виден в итоговом html-коде. Чтобы комментарий не попал в итоговый html-код — он должен начинаться с символов //-.

// Этот комментарий виден в итоговом html-коде
p.paragraph Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.
//- Этот комментарий будет удален из html-кода
p.paragraph: img.image(src="picture.jpg" alt="Изображение")
<!-- Этот комментарий виден в итоговом html-коде -->
<p class="paragraph">Lorem ipsum <em>dolor</em> sit amet, consectetur adipisicing elit.</p>
<p class="paragraph"><img class="image" src="picture.jpg" alt="Изображение"/></p>

8. Подключения (include)

Большим достоинством Pug является возможность подключения отдельных фрагментов кода. То есть можно выносить в отдельные фрагменты кода целые области сайта. Например, вынести в отдельные файлы header, sidebar, content, footer и все это собрать в одном индексном файле.

// файл index.pug
doctype html
html(lang="ru")
    head
        meta(charset="utf-8")
        title Подключения (include)
    body
        include ./parts/header.pug
        include ./parts/content.pug 
        include ./parts/footer.pug 
// файл parts/header.pug
header Это шапка сайта

// файл parts/content.pug
div.content
    main Это основной контент сайта
    aside Это контент сайдбара сайта

// файл parts/footer.pug
footer Это подвал сайта

Итоговый файл index.html:

<!-- файл index.pug -->
<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>Подключения (include)</title>
  </head>
  <body>
    <!-- файл parts/header.pug -->
    <header>Это шапка сайта</header>
    <!-- файл parts/content.pug -->
    <div class="content">
      <main>Это основной контент сайта</main>
      <aside>Это контент сайдбара сайта</aside>
    </div>
    <!-- файл parts/footer.pug -->
    <footer>Это подвал сайта</footer>
  </body>
</html>

9. Наследование шаблонов

Наследование шаблонов работает через ключевые слова block и extend. В родительском шаблоне block — это просто заглушка, которая «резервирует» место. Дочерний шаблон на это «зарезервированное» место вставляет какой-то контент. При этом block в родительском шаблоне может иметь контент по умолчанию. А дочерний шаблон может либо заместить (replace) этот контент, либо дополнить его — append и prepend.

Родительский шаблон layout.pug:

block variables
    - var title = 'Это мой сайт'
    - var head1 = 'Это заголовок по умолчанию'
    - var content = 'Это контент страницы по умолчанию'

doctype html
html(lang="ru")
    head
        title #{title}
        block scripts
            script(src='/js/jquery.js')
    body
        block header
            header Это шапка сайта
        block content
            main
                h1 #{head1}
                div.content
                    p #{content}
        block footer
            footer Это подвал сайта

Дочерний шаблон contact.pug:

extends layout.pug

// этот блок будет замещен (replace)
block variables
    - var title = 'Контакты'
    - var head1 = 'Контактная информация'
    - var content = 'Контактная информация: адрес, почта, телефон'

// этот блок будет дополнен (append)
block append scripts
    script(src='/js/script.js')

// этот блок будет дополнен (prepend)
block prepend content
    // Этот комментарий будет добавлен на страницу в самое начало блока

Итоговый файл contact.html:

<!DOCTYPE html>
<html lang="ru">
  <head>
    <title>Контакты</title>
    <script src="/js/jquery.js"></script>
    <script src="/js/script.js"></script>
  </head>
  <body>
    <header>Это шапка сайта</header>
    <!-- Этот комментарий будет добавлен на страницу в самое начало блока -->
    <main>
      <h1>Контактная информация</h1>
      <div class="content">
        <p>Контактная информация: адрес, почта, телефон</p>
      </div>
    </main>
    <footer>Это подвал сайта</footer>
  </body>
</html>

Поиск: HTML • Web-разработка • JavaScript • Теория • Pug • Верстка

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.