Yamato DaiwaFrontend (2.0.0-beta.4)

RegularWebPageTemplate

Основной Pug-шаблон для создания валидных HTML5-страниц, рекомендованный для большинства случаев.

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

<!DOCTYPE html>

  <html lang="en">

  <head>
    <title>Untitled</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  </head>

  <body></body>

</html>

Поскольку аттрибут lang у тэга html и тэг title являются обязательными, то они были сгенерированы в соответствии с настройками по умолчанию. Скорее всего, Вам потребуется их изменить, особенно если у Вас страница на русском или отличном от английского языке. Всё это и многое другое можно сделать с помощью JavaScript-класса конфигурации RegularWebPageTemplate__YDF, к которому можно обратиться из JavaScript-блоков препроцессора Pug.

Класс конфигурации RegularWebPageTemplate__YDF

Позволяет настроить генерацию типового HTML-кода. Данный класс доступен начиная с конца Pug-блока Functionality, но рекомендуется обращаться к этому классу в Pug-блоке Metadata, поскольку большинство настроек либо связаны с meta-тэгами, либо по своей сути являются метаданными:

block append Metadata

  -

    RegularWebPageTemplate__YDF.configure({
      metadata: {
        locale: "ru",
        title: "Спикок товаров — интернет-магазин «Изобилие»"
      }
    });

Указание настроек осуществляется посредством вызова статического метода configure, единственный параметр которого — многоуровневый объект конфигурации:

metadata.locale
Используется для заполнения аттрибута lang у тэга html. Поскольку данный аттрибут является обязательным для тэга html, то имеется значение по умолчанию — "en", которое необходимо заменить на другое для неанглоязычных страниц. Примечательно, но значение аттрибута lang официально называется «language tag», что запутывает, потому данное свойство и было названо locale.
metadata.title
Используется для заполнения тэга title. Поскольку это тэг обязателен, то имеется значение по умолчанию — "Untitled".
metadata.description
Если определено, то будет добавлен тэг meta c аттрибутами name="description" и content, последний из которых будет заполнен указанным значением.
metadata.keywords
Если определено, то будет добавлен тэг meta c аттрибутами name="keywords" и content, последний из которых будет заполнен указанным значением.
metadata.author
Если определено, то будет добавлен тэг meta c аттрибутами name="author" и content, последний из которых удет заполнен указанным значением.
faviconURI
Если определено, то будут добавлены 2 тэга link, один из которых имеет аттрибут rel="icon", другой — rel="shortcut icon", при этом у обоих будет заполнен аттрибут href указанным значением. Это значение должно быть валидным URI, ссылающимся на файл иконки для отображения на вкладке браузера.
AMP_VersionURI
Если определено, то будет добавлен тэг link c аттрибутами rel="amphtml" и href, последний из которых будет заполнен указанным значением. Это значение должно быть валидным URI, ссылающимся на AMP-версию этой же страницы.
stylesSheetsURIs
Если указан массив, то для каждого его элемента будет добавлен тэг link с аттрибутами rel="stylesheet" и href, последний из которых будет заполнен элементом массива. Каждый из этих элементов должен иметь строчный тип и являться валидным URI, ссылающимся на CSS-файл.
scripts.atEndOfHead

Если указан массив, то для каждого его элемента в конец тэга head будет добавлен тэг script с аттрибутом src, значение которого будет заполнено элементом массива. Каждый из этих элементов должен иметь строчный тип и являться валидным URI, ссылающимся на JavaScript-файл.

  • Обычно добавлять скрипты в конец тэга head не рекомендуется, поскольку без дополнительных мер отрисовка страницы будет приостановлена до тех пор, пока скрипты не будут загружены. Исключением являются такие случаи, сторонние скрипты для аналитики.
  • Добавленные таким образом тэги script не будут иметь никаких аттрибутов, кроме src. Если Вам нужно, чтобы были какие-либо другие аттрибуты, то добавьте тэг script скрипт вручную в с использованием Pug-блока HeadScripts.
scripts.atEndOfBody

Если указан массив, то для каждого его элемента в конец тэга body будет добавлен тэг script с аттрибутом src, значение которого будет заполнено элементом массива. Каждый из этих элементов должен иметь строчный тип и являться валидным URI, ссылающимся на JavaScript-файл.

  • Именно таким образом рекомендуется добавлять скрипты, поскольку их загрузка не будет задерживать отрисовку страницы.
  • Добавленные таким образом тэги script не будут иметь никаких аттрибутов, кроме src. Если Вам нужно, чтобы были какие-либо другие аттрибуты, то добавьте тэг script скрипт вручную в с использованием Pug-блока EndBodyScripts.

Метод configure можно вызывать многократно, но ввиду того, что повторное указание одних и тех же свойств приведёт к перезаписи прежних значений, повторно вызывать этот метод имеет смысл с указанием других свойств. Например, если у Вас на всём сайте или приложении один язык (допустим, русский), а автор всех страниц один и тот же, то имеет смысл прописать эти настройки один раз в отельном файле (скажем, CommonMetadata.pug):

-

  RegularWebPageTemplate__YDF.configure({
    metadata: {
      locale: "ru",
      author: "ОАО «Рога и копыта»"
    }
  });

Затем этот файл можно подключать в файлы страниц и далее уже указывать только особые метаданные для конкретной страницы:

block append Metadata

  include CommonMetadata.pug

  -

    RegularWebPageTemplate__YDF.configure({
      metadata: {
        title: "Услуги"
        // "locale" и "author" уже указаны ранее в «CommonMetadata.pug»
      }
    });

Pug-блоки

Модификация шаблонов в Pug осуществляется через Pug-блоки. В шаблоне RegularWebPageTemplate объявлены нижеследующие Pug-блоки.

Functionality

Используйте этот блок, если хотите написать какую-либо функциональность на встроенном JavaScript.

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug


block append Functionality

  -

    function sum(...summands) {
      return summands.reduce((interimSum, summand) => interimSum + summand, 0)
    }

Поскольку в этот блок подключена функциональность библиотеки «Yamato Daiwa ECMAScript Extensions» то начиная с этого блока Вы можете ей пользоваться, если при ссылке на блок указали ключевое слово append:

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug


block append Functionality

  -

    function formatPrice(amount) {
      return `${ separateEach3DigitsGroupWithComma(amount) }₽`;
    }

Data

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

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug


block append Data

  -

    const items = Array.from(new Array(16).keys()).map(
      index => ({
        ID: index,
        title: `Пункт номер ${ index + 1 }`
      })
    );

Requirements

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

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug


block append Requirements

  mixin ProductCard(product)
    .ProductCard
      h1= product.title
      p= product.description

Metadata

Используйте этот блок, если хотите определить метаданные HTML-страницы через JavaScript-переменные. В частности, рекомендуется вызывать RegularWebPageTemplate__YDF.configure({}) именно здесь.

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append Metadata

  -

    RegularWebPageTemplate__YDF.configure({
      metadata: {
        locale: "ru",
        author: "ОАО «Рога и копыта»"
      }
    });

StatesSimulations

Если планируется создать динамическую страницу, то на стадии вёрстки с помощью условного рендеринга в Pug можно проверить, нормально ли отображается страница в целом при наличии или отсутствии тех или иных элементов. В частности, можно условно отобразить разные состояния. Например, если на странице осуществляется динамическое отображение коллекции данных, получаемых с помощью AJAX, то страница может иметь следующие состояния:

  • Получение данных в процессе
  • Ошибка при получении данных
  • Нет данных
  • Есть данные, но нет результатов поиска
  • Данные успешно получены и отображаются

Все эти состояния можно определить в виде булевских переменных (в примере ниже это реализовано в виде класса со статическим полем объектного типа statesSimulations, свойствам которого соответствует то или иное состояние) и организовать их условное отображение:

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append Metadata

  -

    class ProductsListPage {

      static statesSimulations: {
        loading: false,
        loadingError: false,
        noData: false,
        noSearchingResults: false
      };

    }

block append PageContent

  main

    h1 Товары

    if ProductsListPage.statesSimulations.loading

      //-
        Для состояния загрузки подойдёт компонент, называемый «Loading Placeholder»
          (он же «Skeleton Loading» или «Content Placeholder»)

    else if ProductsListPage.statesSimulations.loadingError

      //- Сообщение об ошибке

    else if ProductsListPage.statesSimulations.noData

      //- Сообщение о том, что товаров нет или всё продано

    else if ProductsListPage.statesSimulations.noSearchingResults

      //- Сообщение о том, что по введённому поисковому запросу ничего не найдено

    else

      //- Список товаров

Для того, чтобы переключиться между состояниями, необходимо перезапустить Pug. Однако если Вы хотите показать заказчику все эти состояния в виде отдельных страниц до реализации JavaScript-динамики и серверной части, при этом минимизировать количество рутинной работы (в частности, избежать ручного создания файлов для каждого состояния), то обратите внимание на концепцию статического превью и на сборщик проектов Yamato Daiwa Automation (сокращённо: YDA), который имеет функциональность специально для таких случаев.

HeadBegin

Используйте этот блок, если хотите что-нибудь добавить в начало тэга head (перед другими дочерними элементами).

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

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

  // ...

block append HeadBeging

  link(rel="dns-prefetch" href="//example.com")
Для примера добавлен тэг link в начало тэга head, однако необходимости добавлять его именно в начало head причины не было.

Styles

Используйте этот блок, если Вас по какой-либо причине не устраивает указание ссылок на стили через конфигурацию (RegularWebPageTemplate__YDF.configure({})) или же Вы хотите объявить стили прямо в тэге head. В частности, поскольку тэги link, которые будут сгенерированы при указанных в конфигурации ссылках на стили не имеют никаких аттрибутов кроме href и rel="stylesheet", то если нужны какие-то другие аттрибуты, то добавьте тэги link в блок Styles вручную:

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append Styles

  link(
    rel="stylesheet"
    href="/path/to/style.css"
    type="text/css"
    media="screen"
    crossorigin="anonymous"
    integrity="sha384-oqVuAfXRKap7fdgcCY5hULvJ0GhBGDq4IcF3J08z9QY9l03VvH3p0EOTr4N3kR0o"
  )

Данный способ указания стилей не конфликтует с указанием таковых через конфигурацию, однако для правильного каскадирования стилей необходимо учитывать последовательность, в которой CSS-правила объявлены на странице. Поскольку приоритет в CSS зависит от нескольких факторов, то нельзя однозначно сказать, что только лишь последовательность объявления CSS-правил изменит отображение, тем не менее, последовательность — один из факторов, влияющий на конечное отображение.

  • Укажите ключевое слово prepend при использовании блока Styles, чтобы добавить стили перед теми, что указаны через конфигурацию.
  • Укажите ключевое слово append при использовании блока Styles, чтобы добавить стили после тех, что указаны через конфигурацию.

HeadScripts

Используйте этот блок, если Вас по какой-либо причине не устраивает указание ссылок на скрипты через конфигурацию (RegularWebPageTemplate__YDF.configure({})) или же Вы хотите объявить скрипты прямо в тэге head. В частности, поскольку тэги script, которые будут сгенерированы при указанных в конфигурации ссылках на скрипты, не имеют никаких аттрибутов кроме src, то если нужны какие-то другие аттрибуты, то добавьте тэги script в блок HeadScripts вручную:

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append HeadScripts

  script(
    src="/path/to/index.js"
    type="module"
    async
    defer
    crossorigin="anonymous"
    integrity="sha384-oqVuAfXRKap7fdgcCY5hULvJ0GhBGDq4IcF3J08z9QY9l03VvH3p0EOTr4N3kR0o"
    referrerpolicy="no-referrer"
    nonce="randomString"
  )

Обычно, скрипты рекомендуется добавлять в конец тэга body, поскольку скрипты, указанные ранее, могут замедлить отрисовку (рендеринг) страницы. Однако в некоторых случаях скрипты требуется добавлять именно в тэг head, в особенности если эти сторонние скрипты для аналитики, такие как Google Analytics:

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append HeadScripts

  script(
    async
    src="https://www.googletagmanager.com/gtag/js?id=G-F3D8Is3NGR4S56G4EBS"
  )

  script.

    window.dataLayer = window.dataLayer || [];

    function gtag() {
      dataLayer.push(arguments);
    }

    gtag("js", new Date());
    gtag("config", "G-S3L0PQFKMV");

Данный способ указания скриптов не конфликтует с указанием таковых через конфигурацию, и если скрипты независимы друг от друга (в современности это чаще всего так, чего нельзя сказать про устаревшие сайты и приложения), то можно использовать оба способа.

  • Укажите ключевое слово prepend при использовании блока HeadScripts, чтобы добавить скрипты перед теми, что указаны через конфигурацию.
  • Укажите ключевое слово append при использовании блока HeadScripts, чтобы добавить скрипты после тех, что указаны через конфигурацию.

PageContent

Добавьте внутрь этого блока видимое содержимое страницы. Тэг body будет при этом прямым родителем сгенерированного HTML-кода.

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append PageContent

  header.TopPage-Header

    //- ...

  main

    //- ...

  footer

    //- ...

EndBodyContent

Согласно некоторым методологиям, элементы с фиксированным позиционированием, такие как модальные диалоги, принято помещать после всех остальных элементов (но, разумеется, внутри тэга body). Если Вы придерживаетесь такой рекомендации, то используйте блок EndBodyContent — содержимое этого блока будет идти сразу после содержимого PageContent.

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append PageContent

  //- ...

block append EndBodyContent

  +ContactRequestPage-ModalDialog

EndBodyScripts

Используйте этот блок, если Вас по какой-либо причине не устраивает указание ссылок на скрипты через конфигурацию (RegularWebPageTemplate__YDF.configure({})) или же Вы хотите объявить скрипты прямо в тэге body. В частности, поскольку тэги script, которые будут сгенерированы при указанных в конфигурации ссылках на скрипты, не имеют никаких аттрибутов кроме src, то если нужны какие-то другие аттрибуты, то добавьте тэги script в блок EndBodyScripts вручную:

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append PageContent

  // ...

block append EndBodyScripts

  script(
    src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
    integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
    crossorigin="anonymous"
  )

Данный способ указания скриптов не конфликтует с указанием таковых через конфигурацию, и если скрипты независимы друг от друга (в современности это чаще всего так, чего нельзя сказать про устаревшие сайты и приложения), то можно использовать оба способа.

  • Укажите ключевое слово prepend при использовании блока EndBodyScripts, чтобы добавить скрипты перед теми, что указаны через конфигурацию.
  • Укажите ключевое слово append при использовании блока EndBodyScripts, чтобы добавить скрипты после тех, что указаны через конфигурацию.

Многоуровневое наследование

Если в Вашем проекте несколько страниц, при этом многие их них имеют общую часть (например, общие шапку, подвал и сайдбар), то Pug-файлы страниц имеет смысл наследовать от RegularWebPageTemplate не напрямую, а через промежуточные шаблоны страниц, содержание общую для унаследованных страниц разметку. Обычно имеется основной шаблон, шаблон для админ-панели, шаблон для аутентификации и так далее.

Ниже представлен пример шаблона страниц, включающий в себя разметку одноколоночного макета. Для того, чтобы встраивать в него контент, уникальный для конкретной страницы, определён новый Pug-блок SpecificContent:

extends ../../node_modules/@yamato-daiwa/frontend/PagesTemplates/RegularWebPage.pug

block append PageContent

  .MainLayout

      .MainLayout-UpperFixedContentSlot

        +Header
        +NavigationBar


      main.MainLayout-SpecificContent

        block SpecificContent


      +Footer

Теперь от этого шаблона страниц можно наследовать уже конкретные страницы:

extends ../Layouts/OneColumnLayout.pug

block append SpecificContent

  h1 Товары