Наследование HTML файлов в xslt-стиле

в 4:53, , рубрики: grunt, html, node.js, nodejs, npm, наследование, шаблонизация, метки: , , , , ,

Проблема

Однажды, в ходе переписывания большого проекта, возникла необходимость улучшить механизм кастомизации html шаблонов под разные версии нашего web-приложения. В старой версии кастомизация выглядела подобным образом:

{{if app.version==versions.main}}
<!--один html код-->
{{else if app.version==versions.custom1}}
<!--другой html код-->
{{else if app.version==versions.custom2}}
<!--и ещё html код-->
{{endif}}

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

Привыкнув к удобным методам управления версиями приложения с помощью инъекции зависимостей, когда в зависимости от версии используются разные реализации интерфейсов, я решил изобрести свой велосипед для XSLT-подобного управления версиями html файлов: grunt-html-inheritance. Он позволяет подменять кусочки базового html-файла с помощью маленьких патчей.

При переписывании проекта в качестве фреймворка был выбран AngularJS, поэтому вёрстка в приложении хранится в виде множества html файлов, подгружаемых при необходимости, что позволило легко внедрить систему сборки этих файлов с кастомизацией под разные версии приложения.

Пример

Давайте представим, что у нас имеется следующий кусок вёрстки в HTML файле «myfile.html»:

<div>
    Blah blah blah
    <div>Main version</div>
</div>

И, как часто бывает в разных версиях приложения, нам понадобилось, чтобы в версии «myversion» вместо одного текста «Main version» отображался другой: «My version». Чтобы сделать это с помощью html-inheritance, нужно сделать 2 простых шага:

1. Добавить к кастомизируемому тегу аттрибут, начинающийся на «bl-»:

<div>
    Blah blah blah
    <div bl-mytag>Main version</div>
</div>
2. Создать файл «myfile.myversion.html» с патчем к родительскому файлу:

    <div bl-mytag="replace">My version</div>

Всё! При билде проекта все html файлы будут аккуратно сложены в указанную папку с разбивкой по версиям:

dist
  |
  main/
     myfile.html
  myversion/
     myfile.html

Теперь достаточно указать вашему приложению, откуда грузить html файлы в зависимости от версии, и всё будет работать само по себе!

Установка

Чтобы добавить grunt-html-inheritance в ваш проект, нужно установить npm модуль командой

npm install grunt-html-inheritance --save-dev

или добавить зависимость в package.json, загрузить задачу в Gruntfile.js командой

grunt.loadNpmTasks('grunt-html-inheritance');

и настроить задачу следующим образом:


grunt.initConfig({
  html_inheritance: {
      main: {
          files: { 
            src:'**.html' //селектор для файлов
          },
          options: {
              modules: ["version1", "version2"], //список модулей
              dstDir: "../dist",//папка, в которую будут складываться скомпиленные файлы
          },
      },
  },
});

В AngularJS приложении важным условием легкого переключения между версиями HTML файлов является использование хелпера для построения путей к файлам шаблонов вместо жёсткого прописывания этих путей в директивах и роутингах.

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

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

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

Кроме замены базового тега в патче, описанного в примере выше, так же доступны следующие режимы:

  1. Удаление — удаление в патче родительского элемента
  2. Вставка — вставка в патче элемента, тогда как в основной версии элемента не будет
  3. Модификация аттрибутов — удаление и добавление аттрибутов к родительскому элементу, удаление и добавление классов.

Полная документация доступна на странице пакета или в репозитории на github. Модуль покрыт тестами и нуждается в дальнейшем совершенстовании. Приглашаю сообщество помочь в развитии, писылайте pull-реквесты!

Автор: Houston

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js