Что такое pug html
Перейти к содержимому

Что такое pug html

  • автор:

Работаем с шаблонизатором PUG

Pug (ранее Jade) – инструмент для шаблонизации HTML-кода. Этот препроцессор HTML позволяет разработчикам значительно упростить процесс создания веб-страниц и веб-приложений. В этой статье мы рассмотрим основы Pug, его синтаксис, преимущества, а также приведем примеры его использования.

Если вы еще не начали карьеру в IT, приходите на наш бесплатный вебинар, чтобы узнать, как начать зарабатывать с помощью зерокодинга и нейросетей!

Основы Pug

Pug – это шаблонизатор HTML, который предоставляет удобный способ создания HTML-разметки с использованием упрощенного синтаксиса. Он является частью платформы Node.js и позволяет разработчикам генерировать HTML-код с помощью JavaScript.

Синтаксис отличается от обычного HTML и напоминает индентированный код. Вместо использования тегов и угловых скобок, Pug использует отступы для определения вложенности элементов. Вот пример сравнения синтаксиса Pug и HTML:

HTML:

Hello, World!

This is a paragraph.

Pug:

p This is a paragraph.

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

Преимущества

  • Удобство чтения и написания кода

Синтаксис Pug делает код более читаемым и компактным, что упрощает его написание и поддержку.

  • Возможность использования JavaScript

Вы можете встроить JavaScript-код непосредственно в шаблон, что делает его мощным инструментом для динамической генерации контента.

  • Поддержка переменных и данных

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

  • Поддержка вложенности

Отступы автоматически определяют вложенность элементов, что упрощает создание сложных структур документов.

Недостатки

Конечно, Pug имеет свои недостатки, которые стоит учитывать при выборе этого шаблонизатора. Рассмотрим некоторые из них:

  1. Изучение нового синтаксиса: для разработчиков, привыкших к стандартному HTML, изучение синтаксиса Паг может потребовать времени и усилий. Новичкам может быть сложно привыкнуть к использованию отступов вместо тегов и угловых скобок.
  2. Сложность отладки: отладка шаблонов может быть сложнее по сравнению с отладкой стандартного HTML. Ошибки в отступах или синтаксисе могут привести к неправильной генерации HTML, что может быть неочевидно на первый взгляд.
  3. Ограниченная поддержка IDE: не все интегрированные среды разработки (IDE) обладают хорошей поддержкой Паг. Это может затруднить разработку и отладку, особенно если вы привыкли к использованию мощных инструментов IDE.
  4. Невозможность использования напрямую в браузере: они не могут быть интерпретированы браузером напрямую. Вам всегда нужно компилировать Pug-код в HTML перед тем, как отдать его клиенту, что может потребовать дополнительных шагов в вашем рабочем процессе разработки.
  5. Не самый популярный выбор: Паг не так широко используется, как стандартный HTML, поэтому может быть сложнее найти поддержку и ресурсы для обучения. Это может создать проблемы при найме разработчиков.
  6. Сложности в командной работе: если ваша команда включает разработчиков, не знакомых с Pug, это может создать сложности в совместной работе. Необходимость в постоянном переводе Pug в стандартный HTML может замедлить разработку.

Пример

Для лучшего понимания того, как работает Pug, давайте рассмотрим простой пример создания веб-страницы.

Прежде чем начать использовать Pug, убедитесь, что у вас установлен Node.js. Затем установите шаблонизатор с помощью npm (Node Package Manager) следующей командой:

npm install pug

  • Создание простой веб-страницы

Давайте создадим простую веб-страницу с использованием Паг. В этом примере мы создадим страницу приветствия, которая будет содержать заголовок и абзац.

  • Создайте файл `index.pug` и добавьте следующий код:

title Welcome to Pug Example

p This is a simple Pug example.

  • Теперь мы можем скомпилировать этот файл в HTML с помощью команды:
  • После выполнения команды будет создан файл `index.html` с следующим содержанием:

Welcome to Pug Example

Hello, World!

This is a simple Pug example.

Теперь у вас есть простая веб-страница, созданная с использованием Pug.

Заключение

Pug – это мощный шаблонизатор HTML, который упрощает разработку веб-приложений. Его удобный синтаксис и интеграция с JavaScript делают его привлекательным выбором для создания динамических и легко поддерживаемых веб-страниц и приложений. Если вы хотите упростить разработку и улучшить структурирование вашего HTML-кода, попробуйте использовать Pug в своих проектах.

Препроцессор Pug / Jade

Препроцессор Pug изначально назывался Jade, поэтому теперь можно встретить разные названия с одним и тем же описанием.

Комментарии (Comments)

// однострочный комментарий, преобразуется в html //- однострочный комментарий pug, не отображается в html //- Блочный комментрарий. Не преобразуется в html. // Блочный комментрарий. Преобразуется в html.
//[if lt IE 9]>

Доктайп (Doctype)

//- doctype html //- doctype xml //- doctype transitional //- doctype strict //- doctype frameset //- doctype 1.1 //- doctype basic //- doctype mobile //- doctype plist //- собственный doctype doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"

При создании собственного доктайпа следует учесть что:

  • тип закрывающих скобок />, > зависит от указанной спецификации XML или HTML
  • если нет возможности использовать слово doctype, но указать его все же хочется, можно воспользоваться специальными опциями. Больше информации на оф сайте pug

var pug = require('pug'); var source = 'img(src="https://www.riwkus.ru/notes/web/frontend/jade/foo.png")'; pug.render(source); // => '' pug.render(source, {doctype: 'xml'}); // => ' ' pug.render(source, {doctype: 'html'}); // => ' '

Тэги (Tags)

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

    li Item A |
  • Item A li Item B |
  • Item B li Item C |
  • Item C |

Атрибуты (Attributes)

Для записи id и классов можно использовать короткую запись:

.block Текст | 
Текст
span.icon Текст | Текст #block Текст |
Текст
p#chapter Текст |

Текст

Атрибуты похожи на html, однако их значения — это обычный JavaScript. Поэтому, если вы вставите туда выражение JS, оно сработает.

a(href='google.com') Google a(class='button' href='google.com') Google a(class='button', href='google.com') Google //- обработка js, присвоение класса в зависимости от переменной - var authenticated = true body(class=authenticated ? 'authed' : 'anonim') //- запись в несколько строк input( type='checkbox' name='agreement' checked ) //- не стандартные атрибуты. //- атрибуты со скобками указываются через , либо обрамляются кавычками div(class='div-class', (click)='play()') div(class='div-class' '(click)'='play()') //- переменные в атрибутах - var url = 'test.html', url_2 = 'https://example.com/' a(href='/' + url) Текст ссылки a(href=url_2) Вторая ссылка //- устаревший синтаксис интерполяции a(href="/#{url}") Текст ссылки //- если есть поддержка ES2015 - var btnType = 'info' - var btnSize = 'lg' button(type='button' + btnType + ' btn-' + btnSize) button(type='button' btn-${btnType} btn-${btnSize}`) //- чтобы символы не экранировались используется != div(escaped="") div(unescaped!="") //- стили можно записывать как привычной строкой, так и объектом a(style="color: 'red', background: 'green'") a(style={color: 'red', background: 'green'}) //- классы можно записывать как привычной строкой, так и массивом - var classes = ['foo', 'bar', 'baz'] a(class=classes) //- атрибут class может быть продублирован a.bang(class=classes атрибут также может быть объектом, сопоставляющим значения true и false - var currentUrl = '/about' a(class={active: currentUrl === '/'} href='/') Home | Home a(class={active: currentUrl === '/about'} href='/about') About | About

Логический тип данных

input(type='checkbox' checked) | input(type='checkbox' checked=true) | input(type='checkbox' checked=false) | input(type='checkbox' checked=true.toString()) | //- если указан docktype html, pug использует краткую запись doctype html | input(type='checkbox' checked) | input(type='checkbox' checked=true) | input(type='checkbox' checked=false) | input(type='checkbox' checked=true && 'checked')|

Запись &attributes

Может использоваться для разбивания объекта с атрибутами на части. Символы при этом не экранируются, если используются вне миксинов.

div.foo(data-bar="foo")&attributes({'data-foo': 'bar'}) | - var attributes = {}; - attributes.class = 'baz'; div.foo(data-bar="foo")&attributes(attributes) | 

Case (Case)

Сокращенный вариант JS условия switch.

- var friends = 10 case friends when 0 p you have no friends when 1 p you have a friend default p you have #{friends} friends //- как и в js можно пропускать значения - var friends = 0 case friends when 0 when 1 p you have very few friends default p you have #{friends} friends //- для прерывания условия стоит использовать break - var friends = 0 case friends when 0 - break when 1 p you have very few friends default p you have #{friends} friends //- запись в 1 строку - var friends = 1 case friends when 0: p you have no friends when 1: p you have a friend default: p you have #{friends} friends

Код (Code)

Пуг позволяет обрабатывать JS код, разделяя его на 3 типа: буферизированный, небуферизированный, неэкранированный буферизированный.

Небуферизованный код ничего не добавляет к выводам и начинается с —

//- запись в строку - for (var x = 0; x < 3; x++) li item //- запись блоком - var list = ["Uno", "Dos", "Tres", "Cuatro", "Cinco", "Seis"] each item in list li= item

Буферизированный код начинается с =, он вычисляет JS и выводит результат. Для безопасности html символы экранируются.

p = 'This code is !' //- инлайновая запись p= 'This code is' + ' !'

Неэкранированный буферизированный код начинается с !=, он вычисляет JS и выводит результат, без какой-либо экранизации, что не безопасно при использования пользователями.

p != 'This code is not escaped!' //- инлайновая запись p!= 'This code is' + ' not escaped!'

Условия (Conditionals)

Условия if, else if, else

- var user = { description: 'foo bar baz' } - var authorised = false #user if user.description h2.green Description p.description= user.description else if authorised h2.blue Description p.description. User has no description, why not add one. else h2.red Description p.description User has no description

с оператором сравнения:

if var=='text' p #{text}

условие unless (отрицательный if)

unless user.isAnonymous p You're logged in as #{user.name}

Фильтры (Filters)

Фильтры позволяют использовать другие языки в шаблонах Pug. Все модули JSTransformer могут использоваться в качестве фильтров Pug. Популярные фильтры: :babel, :uglify-js, :scss и :markdown-it.

Можно использовать как уже существующие, так и собственные фильтры.

Для вставки опций в фильтры заключите их в скобки записав после вызова фильтра: :less(ieCompat=false).

Если вы хотите использовать CoffeeScript и Markdown (используя Markdown-it renderer) в шаблоне Pug, сначала убедитесь, что эти функции установлены:

$ npm install --save jstransformer-coffee-script $ npm install --save jstransformer-markdown-it

Запись условия с фильтрами:

:markdown-it(linkify langPrefix='highlight-') # Markdown Markdown document with http://links.com and ```js var codeBlocks; ``` script :coffee-script console.log 'This is coffee script'

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

Инлайновая запись

p :markdown-it(inline) **BOLD TEXT** p. In the midst of a large amount of plain text, suddenly a wild #[:markdown-it(inline) *Markdown*] appeared.

Использование вместе с include

//- index.pug doctype html html head title An Article body include:markdown-it article.md # article.md This is an article written in markdown.

Вложенные фильтры

Фильтры применяются в обратном порядке.

script :cdata-js:babel(presets=['es2015']) const myFunc = () => `This is ES2015 in a CD${'ATA'}`;

Пользовательские фильтры

Cобственные фильтры добавляются через опцию filters.

options.filters = { 'my-own-filter': function (text, options) { if (options.addStart) text = 'Start\n' + text; if (options.addEnd) text = text + '\nEnd'; return text; } }; p :my-own-filter(addStart addEnd) Filter Body

Включения (Includes)

Includes позволяет включать содержимое одного файла в другой. Если подключать не pug файл, то в результат вставится содержимое файла.

//- includes/head.pug head title My Site script(src='/javascripts/jquery.js') script(src='/javascripts/app.js') //- includes/foot.pug footer#footer p Copyright (c) foobar //- index.pug doctype html html include includes/head.pug body h1 My Site p Welcome to my super lame site. include includes/foot.pug //- включения можно комбинировать с фильтрами //- index.pug doctype html html head title An Article body include:markdown-it article.md //- article.md # article.md This is an article written in markdown.

Наследование (Inheritance: Extends and Block)

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

block — блоки кода, которые можно перезаписывать. В блок можно включить контент «по умолчанию», тогда он будет доступен на всех страницах к которым подключается, если его не перезапишут принудительно.

Так выглядит объявление блоков:

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

Команда extends добавляет данные из основного макета к новой странице.

Так выглядит дополнительный файл к которому подключается основная разметка блоков. Блок scripts перезаписывается, блок content заполняется данными, блок foot остается неизменным:

//- page-a.pug extends layout.pug block scripts script(src='/jquery.js') script(src='/pets.js') block content h1= title - var pets = ['cat', 'dog'] each petName in pets include pet.pug //- pet.pug p= petName

Block append / prepend

Изменение и расширение данных в блоках.

block name — блок с именем. При размещении на другой странице текста в блоке — значение по умолчанию затрется.

block appends name — добавить к блоку. При размещении на другой странице значение прибавится к значению по умолчанию.

block prepends name — указывает что в этом блоке надо обрабатывать условия appends блока.

//- layout.pug block vars - var text="Базовый текст" block content p #{text}

Пример изменения текста переменной в блоке

//- page.pug extends layout.pug block append vars - var text="Измененный текст" block prepend content p #{text}

Интерполяция (Interpolation)

Строковая интерполяция, экранируемая

- var simpletext = "Все, что сказано три раза, становится истиной"; - var numeric = 42; - var htmlstring = "текст в html тегах"; h1= simpletext p The Ultimate Question of Life, the Universe, and Everything: #{numeric} p Html теги без обработки: #{htmlstring} p Можно добавлять любые js выражения #{simpletext.toUpperCase()} p Можно не экранировать фигурные скобки #{'}'}! p Для отображения конструкции переменной можно использовать экранирование \#{interpolation} p или заключить в конструкцию повторно #{'#{interpolation}'}

Строковая интерполяция, не экранируемая

p !{simpletext}

Интерполяция тегов

p. В параграфы текста могут быть встроены интерполяторы тегов pug. Например: #[strong жирный текст] или #[em текст курсивный] и даже #[q(title="¡Hola Mundo!") теги с атрибутами] 

Интерполяция и пробелы

p | Если при написании параграфа использовать подобный вид интерполяции тегов strong жирный текст | или em курсив | слова будут склеиваться, т.к. пробелы удаляются. p. Чтобы пробелы оставались на месте, используйте интерполяцию тегов pug #[strong respected] и #[em everybody] 

Итерации (Iteration)

Pug поддерживает основные методы итераций: each, for и while.

each

//- простейшая запись ul each val in [1, 2, 3, 4, 5] li= val //- вывод индекса и значения ul each val, index in ['zero', 'one', 'two'] li= index + ': ' + val //- перебор объекта вместо массива ul each val, index in {1:'one',2:'two',3:'three'} li= index + ': ' + val //- в качестве массива может выступать любая js сущность - var values = []; ul each val in values.length ? values : ['There are no values'] li= val //- можно добавить блок else, выводящийся если у массивов или объектов нет каких-либо значений - var values = []; ul each val in values li= val else li There are no values

for

- for (var x = 0; x < 3; x++) li item

while

- var n = 0; ul while n < 4 li= n++

Миксины (Mixins)

Миксины позволяют создавать повторяющиеся блоки

//- декларация mixin list ul li foo li bar li baz //- использование +list +list

Преобразуются в функции и могут принимать аргументы:

mixin pet(name) li.pet= name ul +pet('cat') +pet('dog') +pet('pig')

Можно устанавливать значения по умолчанию:

mixin elements(num = 10) - for (var i = 0; i < num; i++) p #{i+1} из #{num} +elements() // выведет 10 элементов +elements(3) // выведет 3 элемента // Для длинных "значений по умолчанию" проще будет написать условие: mixin text(sometext) - sometext = sometext || 'длинный и очень интересный текст-рыба установленный по умолчанию. ' p #{sometext} 

Миксины могут принимать блоки pug контента, для последующего преобразования:

//- если под миксином указан контент, он будет добавлен в позицию block mixin article(title) .article .article-wrapper h1= title if block block else p No content provided +article('Hello world') +article('Hello world') p This is my p Amazing article

Двойные блоки в миксине можно создавать так

 // initialization - blocks = {} mixin set(key) - blocks[key] = this.block // mixin definition mixin layout block .main if blocks.main - blocks.main() else //- Do nothing .side if blocks.side - blocks.side() else //- Do nothing +set('main') +set('side') p first mixin call +layout +set('main') p Main +set('side') p Side p second mixin call +layout +set('main') p new main +set('side') p Second side p third mixin call +layout +set('side') p Third side

Миксины могут принимать неявные аргументы, которые берутся из аргументов переданных в миксин

mixin link(href, name) //- attributes == {class: "btn"} a(class!=attributes.class href=href)= name +link('/foo', 'foo')(class="btn") //- по умолчанию значения в атрибутах экранированы, //- что бы избежать повторной экранизации используйте !=

Миксины можно использовать с &attributes

mixin link(href, name) a(href=href)&attributes(attributes)= name +link('/foo', 'foo')(class="btn")

Поскольку Pug пытается определить, является ли содержимое скобок атрибутами или аргументами, лучше использовать запись +link()(class="btn"), во избежании возможных ошибок. Синтаксис +link(class="btn" ) также действителен, но не рекомендован.

Можно указать бесконечное количество аргументов, используя синтаксис “rest arguments”

mixin list(id, . items) ul(id=id) each item in items li= item +list('my-list', 1, 2, 3, 4)

Переменная в атрибуте миксина:

- var name = 'Joe' +user(name)

Миксин в атрибуте миксина:

 +someMixin(['nextMixin'])

Миксины в атрибуте миксина:

// определяем миксины mixin header(leftside,rightside) header .head-left-wrap for mixleft in leftside +#{mixleft} .head-right-wrap.top-wrap for mixright in rightside +#{mixright} mixin first . mixin second . mixin third . // вызываем +header(['first', 'second'],['third'])

Вызов миксина в атрибуте блока:

.box(style="background:"+randcolor)

Такой вызов может сработать если в названии миксина нет сложных символов вроде «-» и если миксин не очень сложный. Иногда проще заменить миксин js функцией:

- function backimg(url) { return "background: url('"+url+"')"; } div(style=backimg("../img/img.jpg"))
+#{mixinName}() 

Пример использования динамического миксина:

// создаем миксин который будет генерировать динамические миксины mixin dynMixin(name) +#() 
// имеем какие-то миксины mixin a p AAA mixin b p BBB mixin c p CCC - // объявляем переменные var choiseMixin; var someCondition = 2; // switch (someCondition) { case 1: choiseMixin = 'b'; break; case 2: choiseMixin = 'c'; break; default: choiseMixin = 'a'; } +dynMixin(choiseMixin) //- равнознчно: +#{choiseMixin}() 

Note: Имя динамического миксина должно быть строкой (string).

Простой html текст (Plain Text)

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

Обернуть текст тегом

p Тут находится обычный длинный текст.

Использовать html занимающий всю строку

 body p Indenting the body tag here would make no difference. p HTML itself isn't whitespace-sensitive. 

С использованием префикса | (pipe)

p | The pipe always goes at the beginning of its own line, | not counting indentation.

Для больших html блоков стоит использовать символ . (точка)

script. if (usingPug) console.log('you are awesome') else console.log('use pug')
div p This text belongs to the paragraph tag. br . This text belongs to the div tag.

Массивы Pug / Jade

- var count = [ 'one', 'two', 'tree', ]

Массив с ключом:

- var text_cognitive = [ { name:'Амплификация', text: 'вложение в достижение цели больших усилий, чем необходимо, попытка «убить муху кувалдой». Вариант — чрезмерно детальное планирование в условиях отсутствия в достаточном объёме исходных данных и наличия сильно влияющих на результат неопределённых или случайных факторов.' }, { name: 'Ускорение', text: 'выполнение работы со скоростью большей, чем необходимо или даже допустимо.' }, { name: 'Опережение', text: 'неоправданно раннее начало действий по достижению цели.' }, { name: 'Уклон в сторону поиска информации', text: 'тенденция искать информацию даже тогда, когда она не влияет на действия или результат.' }, ]

Выводятся массивы через итерации или с указанием ключей. Миксин с рандомным выводом из массива:

mixin fish(type) - var num = Math.floor(Math.random()*txt.length); | #{txt[num][type]}

Указание ключа массива в качестве переменной:

// Массив - var books = [{"id": 1}, {"id": 2},{"id": 3}] // Первый вариант вывода по id ul for book in books li= book.id else li sorry, no books! // Второй вариант вывода по id ul - if (books.length) -for (var i = 0; i < books.length; i++) li= books[i].id - else li sorry, no books!

Как использовать шаблонизаторы Pug, Handlebars, EJS

Освойте мощные шаблонизаторы Pug, Handlebars и EJS для создания динамических HTML-страниц с примерами и советами от опытного эксперта!

Алексей Кодов
Автор статьи
1 июня 2023 в 9:15

Шаблонизаторы, такие как Pug, Handlebars и EJS, являются мощными инструментами для веб-разработчиков, которые позволяют создавать динамические HTML-страницы с помощью переменных и логики. В этой статье мы познакомимся с основами использования этих шаблонизаторов и рассмотрим примеры их применения.

Pug

Pug (ранее известный как Jade) — это шаблонизатор, который предлагает синтаксис, похожий на HAML. Он позволяет создавать вложенные элементы без использования закрывающих тегов, что делает код более читабельным и компактным.

Пример использования Pug:

doctype html
html
head
title Pug Example
body
h1 Welcome to Pug!
p This is an example of how to use Pug.

Вышеуказанный код преобразуется в следующий HTML:

   Pug Example  

Welcome to Pug!

This is an example of how to use Pug.

Handlebars

Handlebars — это шаблонизатор, основанный на Mustache, с дополнительными возможностями. Он использует двойные фигурные скобки > для вставки переменных и блоков кода.

Пример использования Handlebars:

В этом примере > , > и > заменяются соответствующими значениями при обработке шаблона.

EJS

EJS (Embedded JavaScript) — это шаблонизатор, который позволяет вставлять JavaScript код прямо в HTML. Он использует теги для вставки кода и для вывода результатов.

Пример использования EJS:

В этом примере , и заменяются соответствующими значениями при обработке шаблона.

�� Теперь, когда вы знакомы с основами использования шаблонизаторов Pug, Handlebars и EJS, вы можете выбрать подходящий для вашего проекта и начать создавать динамические страницы. Удачи вам в веб-разработке!

Pug - шаблонизатор и препроцессор HTML

bg

Добавляем корневой элемент html. Пока никакой вложенности нет, поэтому без отступов. Обратите внимание, что атрибуты тегов записываются в круглых скобках. Закрывающие теги не прописываются. Они будут автоматически сгенегированы

doctype html html(lang="en") 

Добавляем два основных элемента HTML-страницы - head и body. Так как они должны быть вложены в корневой элемент html, то в строке перед head ставим один отступ Tab и в строке перед body ставим один отступ Tab. Это значит что элементы head и body будут находится внутри корневого элемента html. Опять же никаких закрывающих тегов мы не прописываем

doctype html html(lang="en") head body 

В head добавляем мета-тег кодировки документа. Атрибуты записываем в круглых скобках. Так как мета-тег кодировки должен быть внутри элемента head, то у мета-тега должен быть на один отступ Tab больше, чем у элемента head

doctype html html(lang="en") head meta(charset="UTF-8") body 

Аналогично добавляем мета-тег для адаптивности. Если у тега несколько атрибутов, то записываем их через пробел или через запятую. Так как второй мета-тег должен быть также внутри элемента head, то у второго мета-тега также должен быть на один отступ Tab больше, чем у элемента head

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") body 

Также в head добавляем тег title для названия страницы и теги link для подключения файлов стилей

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body 

Добавим первый элемент в body - тег header. У header на один отступ Tab больше, чем у body, так как он должен быть расположен внутри body

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body header 

Чтобы добавить класс для header, добавляем название класса через точку после названия тега, аналогично селекторам в файлах стилей CSS

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body header.header 

Далее добавляем div с классом container. В Pug если не указывать название тега перед названием класса, то по-умолчанию назначается тег div. Поэтому вместо записи div.container , мы просто указываем название класса как в файлах стилей CSS - .container . Так как container внутри header, то у container на один отступ Tab больше, чем у header

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body header.header .container 

Далее все аналогично - добавим header__flex внутри container, добавим header__logo внутри header__flex.

Теперь мы хотим добавить второй класс для header__logo - добавляем его через точку без пробелов - .header__logo.logo

Если захотим для header__logo добавить еще идентификатор, то запись будет следующей - .header__logo.logo#logo - порядок не имеет значения, так что запись может быть и такой - #logo.header__logo.logo

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body header.header .container .header__flex .header__logo.logo 

Добавим logo__title c текстом. Текст записывается через пробел после названия тега или тега с классом

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body header.header .container .header__flex .header__logo.logo .logo__title Pug 
     Pug    
Pug

Добавим в header__flex еще тег nav c классом header__nav и внутри него список ul c элементами списка li, которые в свою очередь содержать ссылки a c текстом.

Каждый дочерний элемент должен иметь на один отступ Tab больше, чем родительский. Но есть еще более краткая запись, через двоеточие, которую лучше использовать только для элементов, которые содержат в себе только один дочерний элемент, например li: a(href="") Home

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body header.header .container .header__flex .header__logo.logo .logo__title Pug nav.header__nav ul li: a(href="") Home li: a(href="") Portfolio li: a(href="") About 

Первое время рекомендую самостоятельно, пошагово, добавляя по одному элементу в index.pug, смотреть на сгенерированный index.html, чтобы для себя более подробно понять, как из синтаксиса Pug генерируется разметка HTML

Нюансы синтакcиса Pug

Частая задача - в блоке с текстом необходимо определенную часть текста выделить в теги span (strong, i и другие) или сделать ссылкой a

В Pug есть два способа это сделать.

Первый способ - использовать обычные теги HTML - открывающий и закрывающий.

p Lorem ipsum dolor sit amet, consectetur adipisicing elit. Praesentium ad, ab accusamus. Minima delectus alias atque a, tenetur perspiciatis reiciendis eligendi quaerat. 
Quos pariatur, fugit enim quod eaque, rerum.

Второй способ - использовать синтаксис Pug - #[tagname text] - знак решётки, затем в квадратных скобках на первом месте имя тега, на втором месте через пробел текст, который будет находится в теге

p Lorem ipsum dolor sit amet, consectetur #[strong adipisicing] elit. Praesentium ad, ab accusamus. #[a(href="") Minima delectus] alias atque a, tenetur perspiciatis reiciendis eligendi quaerat. #[br]Quos pariatur, fugit enim quod eaque, rerum. 

Javascript файлы подключаем, также как и остальные теги

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body script(src="https://frontips.ru/pug-shablonizator-i-preprocessor-html/js/jquery-3.5.1.min.js") script(src="https://frontips.ru/pug-shablonizator-i-preprocessor-html/js/main.js") 

Но если необходимо добавить javascript код прямо на странице, то используем следующий синтаксис - script. - добавляем точку после имени тега script и на следующей строке с отступом на один больше, чем у тега script пишем необходимый код

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body script(src="https://frontips.ru/pug-shablonizator-i-preprocessor-html/js/jquery-3.5.1.min.js") script(src="https://frontips.ru/pug-shablonizator-i-preprocessor-html/js/main.js") script. console.log('1') 

Шаблонизатор

Когда верстаем многостраничный сайт, при внесении изменений, например в header, необходимо открыть каждый *.html файл, который содержит header и внести эти изменения в каждом файле.

Чтобы решить данную проблему, выделим общий фрагмент кода в отдельный файл и подключим его в шаблон

Предположим, у нас есть макет сайта с тремя страницами, где есть общие блоки header и footer, а блок main будет на каждой странице отличаться.

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body header.header .container .header__flex .header__logo.logo .logo__title Pug nav.header__nav ul li: a(href="") Home li: a(href="") Portfolio li: a(href="") About main.main .container .main__title Index Page .main__text p Lorem ipsum dolor sit amet, consectetur #[strong adipisicing] elit. Praesentium ad, ab accusamus. #[a(href="") Minima delectus] alias atque a, tenetur perspiciatis reiciendis eligendi quaerat. #[br]Quos pariatur, fugit enim quod eaque, rerum. footer.footer .container .footer__copyright © Pug 2020 

Когда сверстали главную страницу, сохраним блоки header и footer в соответствующие файлы header.pug и footer.pug в отдельную папку includes (создаем там же, где лежит основной файл index.pug)

4

5

Отдельная папка includes для общих фрагментов верстки нужна для того, чтобы они не генерировались как отдельные html файлы, а только подключались в шаблоны страниц. Если сохраним их рядом с index.pug, то они будут сгенерированы, как отдельные страницы header.html и footer.html, а это некорректно.

Рядом с файлом index.pug сохраняем только те файлы, которые должны быть сгенерированы, как отдельные страницы. Об этом чуть ниже

header.pug

header.header .container .header__flex .header__logo.logo .logo__title Pug nav.header__nav ul li: a(href="") Home li: a(href="") Portfolio li: a(href="") About 

footer.pug

footer.footer .container .footer__copyright © Pug 2020 

Обратите внимание, что в отдельных файлах header и footer отступы сбрасываются - основные родительские элементы header.header и footer.footer в отдельных файлах не имеют отступа. Это важно при подключении этих файлов в шаблоны.

Подключим эти файлы в index.pug. Для этого используем служебное слово include .

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body include includes/header main.main .container .main__title Index Page .main__text p Lorem ipsum dolor sit amet, consectetur #[strong adipisicing] elit. Praesentium ad, ab accusamus. #[a(href="") Minima delectus] alias atque a, tenetur perspiciatis reiciendis eligendi quaerat. #[br]Quos pariatur, fugit enim quod eaque, rerum. include includes/footer 

Так как отступы в отдельных файлах header.pug и footer.pug сброшены, то при подключении header.pug через служебное слово include следим, чтобы подключение было именно в том месте, где изначально был header.header , то есть на один отступ Tab больше, чем у body. Тоже самое и с footer.pug

Теперь на основе шаблона index.pug, в этой же папке создадим еще два шаблона - portfolio.pug и about.pug

6

portfolio.pug

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body include includes/header main.main .container .main__title Portfolio Page .main__portfolio include includes/footer 

about.pug

doctype html html(lang="en") head meta(charset="UTF-8") meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") title Pug link(rel="stylesheet", href="css/bootstrap-reboot.min.css") link(rel="stylesheet", href="css/main.css") body include includes/header main.main .container .main__title About Page .main__about Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fuga laudantium labore eos, nobis accusantium? Totam rem culpa fuga saepe facere. include includes/footer 

Теперь генерируются 3 страницы - index.html, portfolio.html и about.html

7

При изменении header.pug или footer.pug, эти изменения будут применены сразу на всех трёх страницах

В простом примере польза шаблонизации не ощущается в полной мере, но когда реальный проект состоит более чем из 10 страниц и более 20 общих фрагментов, в которые так или иначе в процессе верстки вносятся изменения, то польза становится намного ощутимей

Возможные проблемы и их решения

В окне командной строки, где запущен Gulp, ошибки выглядят следующим образом

3

На скриншоте выше выделена наиболее информативная часть, где можно видеть код ошибки (code), информация об ошибке (msg), строка с ошибкой (line), файл с ошибкой (filename)

Основная ошибка - это использование в отступах Пробелы вместо Tab. В документации сказано, что в качестве отступов можно использовать или только Пробелы или только Tab.

Решить эту проблему очень просто. В редакторе кода, в файле index.pug выделяем весь код сочетанием клавиш Ctrl+A и ищем настройку Tab size (в Sublime Text и VS Code справа внизу), нажимаем и выбираем пункт Convert Indentation to Tabs - все отступы конвентируются в Tab

Преимущества верстки с Pug

У Pug много возможностей. Мы разобрали только базовые для ускорения и упрощения процесса верстки, но можем выделить следующие преимущества

  1. Краткий, информативный, чистый синтаксис, не нужно следить за закрывающими тегами
  2. Разбивка верстки на отдельные фрагменты, подключение этих фрагментов в шаблоны, и изменения в общем фрагменте применяются сразу на всех страницах, где он подключен
  3. Сгенерированна верстка является валидной (проверка W3C - Markup Validation Service)

2

В следующей статье познакомимся и разберем работу со вторым очень полезным инструментом для ускорения верстки и более комфортной работы со стилями - Stylus (препроцессор CSS)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *