Что такое HTML, CSS, JavaScript и Bootstrap фреймворк сложно объяснять человеку который далек от IT. А что если нужен сайт на бесплатном хостинге, без привязки к онлайн конструкту именно этого хостинга?!
![](https://habrastorage.org/r/w780q1/files/98d/3bb/3ae/98d3bb3aef904d32bae88c5ac4af611a.jpg)
Как думаете, реально научить девушку обновлять свой сайт на GitHub Pages к Международному женскому дню?! Расскажу как мне это удалось с помощью генератора сайта, который доступен на Github и написан на Java + FreeMarker, к тому же старался автоматизировать публикацию контента в git репозитарий.
На днях помог осуществить мечту дизайнера по текстилю в интерьере о своем сайте, пока у меня уйма свободного времени. Она и сама пробовала создать макет с помощью конструктора на Wix. Но первый викс сайт комом вышел и нормально не отображался на мобильных телефонах… К тому же лучше не привязываться к конкретному хостингу.
Последнее что я верстал самостоятельно в HTML — был сайт художника во время учебы в университете и тогда была в моде табличная верстка. Веб разработка — не мой хлеб. А сейчас повсюду мобильные браузеры и блочная верстка. Барышня просто хотела сделать простой сайт-визитку, поэтому скрипты на сервере не нужны. При этом идеально было бы, чтобы обновляла фотографии и редактировала разделы этого веб ресурса с нулевым знанием HTML и без моей помощи.
Если ставить CMS — cистему управления содержимым, то хостинг сайта будет дороже и придется тратить время на настройку, шаблоны и безопасность. Слишком сложно для статичного сайта. Мне показалось все это очень похоже на задачу генерации сайта по шаблону. Не знал где найти в наши дни хостинг для сайта без рекламы. Поспрашивав у знакомых, посмотрев варианты и почитав заметки в сети, пришел к выводу что GitHub Pages — идеальный вариант. Бесплатный, версионируемый и поддерживает использование своего доменного имени для сайта.
Для GitHub Pages идеально подходит шаблонизатор jekyll, но разбираться с ним и настройкой на компьютере дизайнера Ruby и jekyll gem совсем не было времени. С jekyll я поиграюсь в другой раз, как будет нужен сайт для своего проекта на GitHub.
Для любого джависта ассоциация с шаблонами — FreeMarker, знакомый многим шаблонный движок. Мне нужно было быстро разработать сайт и генератор, учитывая что Java мой привычный инструмент в работе. Сравнивая FreeMarker с Velocity, первый до сих пор жив и выглядит более функциональным.
Начали с создания аккаунта для дизайнера на GitHub:
![](https://habrastorage.org/r/w1560/files/024/ee9/766/024ee97662bd4b73bd51ec1531e83950.png)
Потом перешли к дизайну и верстке. Bootstrap Carousel показался отличным решением для показа изображений, так как основным содержимым веб страниц будут фото из портфолио и просматривать страницы будут на мобильных устройствах.
Раз уж подключил к странице Bootstrap, пригодятся элемент Panel и иконки для навигации/контактов. Для меня верстка была самым нудным этапом в создании сайта. На втором месте по сложности было изменение размера, цветокоррекция и кадрирование большого числа фото для портфолио работ.
Следующий шаг — превращение верстки в шаблон генератора. В шаблоне FreeMarker итерации по коллекции объектов делаются с помощью директивы <#list product as prodItem>...</#list>, а условия с помощью <#if prodItem?is_first>...</#if>. Это все что используется в этих шаблонах генератора.
За основу формата данных для хранения данных выбрал XML разметку. Со структурой быстро определились, на основе макета:
Из XML файла сгенерировал XSD schema в IntelliJ Idea Community Edition.
![](https://habrastorage.org/r/w1560/files/59a/8c7/24c/59a8c724ce5d4071ab65446a3eb50777.png)
Классы с аннотациями JAXB для использования в шаблоне генерируются динамически из Maven с помощью jaxb2-maven-plugin. При сборке проекта эти классы размещаются в директории target/generated-sources/jaxb.
Пример фрагмента FreeMarker шаблона для вывода всех изображений портфолио для определенной категории:
А вот и пример данных, на основе которых генерируется страница:
В index.html генерируется оглавление на основе всех перечисленных в site.xml тегов <product...> с помощью шаблона.
Как «клей» для шаблонов, основную работу выполняет java класс src/main/java/Site.java и maven скрипт сборки: происходит копирование изображений из директории src/main/resources/img в target/site, из XML схемы генерируются классы c JAXB аннотациями и запускается программа на java с помощью exec-maven-plugin, которая с помощью FreeMarker и данных из site.xml генерирует сайт. Для плагина jaxb2-maven-plugin важно, чтобы xjc из JDK был доступен в одном из путей в переменной окружения PATH.
Чтобы на компьютере у барышни не приходилось ничего устанавливать кроме JDK, в проект добавил mvn-classloader-1.8.jar, который в первый раз загружает из центрального maven репозитария maven-embedder и запускает сборку проекта и генерацию сайта с параметрами «clean package» и «scm-publish:publish-scm» для публикации сайта на GitHub Pages. Запускает генерацию сайта build.cmd для систем на windows и build.sh для linux. Это сильно упрощает сборку проекта и очень похоже на Gradle Wrapper/Maven Wrapper. Библиотека для maven требует только наличие JVM и подключения к интернет с доступом к центральному репозитарию. Случай изолированных сетей здесь рассматривать не будем, но даже в этом случае работают настройки зеркал и прокси из ~/.m2/settings.xml. Про всю магию этой библиотеки недавно рассказывал в «Модуляризация в JavaSE без OSGI и Jigsaw».
Пару слов про процесс обучения. Рассказывать о системе контроля версий и командах в консоли для Git мне было сложно. Не то что это невыполнимо, но не программиста это пугает. Чтобы она не ошибалась в процессе публикации сайта, я начал искать возможность автоматизировать весь процесс. Чтобы сгенерировать и опубликовать сайт можно было в один клик. Поискав как же легко публиковать сайт в github, обнаружил maven-scm-publish-plugin плагин. Добавил его в maven сборку и сконфигурировал scmpublish.pubScmUrl на адрес репозитария.
Отвлекусь от технологий и вспомню про женский праздник. Все реже можно видеть современных девушек за шитьем и рукоделием. А тут была возможность понаблюдал за работой дизайнера и как она шила:
![](https://habrastorage.org/r/w780q1/files/73a/b1f/967/73ab1f967f3c4cf8b00dc1ae656a4b23.jpg)
Узнал про новую для себя область дизайна текстиля в интерьере. И даже не задумывался что существует столько видов штор, тканей и карнизов.
Еще до истории с сайтом смотрел, как она мастерила вместе с мамой подарок на День Рождения друга. Это были забавные чехлы на подушки с котенком и рыбкой, с собачкой.
![](https://habrastorage.org/r/w780q1/files/933/616/ce7/933616ce78d148f4b9bb1581983501b4.jpg)
Ээх, жаль что мне так давно не дарили handmade подарки, даже немного позавидовал.
Было интересно узнать про карнизы с электроприводом для «умного дома» и про опыт их установки. Хочу поэкспериментировать с электроприводом штор, прикрутить их к своему контроллеру на основе STM32 и автоматизировать открытие штор по датчику освещенности или управлять шторами удаленно с телефона. Разобраться с протоколом, подключить свой контроллер красиво и без синей изоленты! Но это уже будет, видимо, после того как разберусь с шаблонами jekyll. До этого видел подобные автоматические рулонные шторы только в Nordstar Tower.
Про то как обновлять контент… Первым делом надо выполнить команду
или скачать zip файл проекта с гитхаба:
![](https://habrastorage.org/r/w1560/files/33c/17b/554/33c17b5540f04a529324750ddbb40f20.png)
Дизайнер копирует обработанные изображения для портфолио в директорию src/main/resources/img и добавляет запись в раздел <product...> файла src/main/resources/site.xml. После этого запускает с помощью ярлыка скрипт build.cmd, который создает сайт из данных по шаблонам и публикует его на GitHub Pages в репозитарий nadinbox89.github.io. С небольшой задержкой после git push, версия сайта обновляется по такому же адресу, как и название репозитария на GitHub — nadinbox89.github.io. Если используете в репозитарии запись домена в CNAME, то произойдет автоматическое перенаправление на этот адрес. После обновления сайта, в репозитарии с именем nadinbox89.github.io появляется commit от плагина публикации:
![](https://habrastorage.org/r/w1560/files/c43/cef/6e1/c43cef6e19b843f4b6372b7fbd0ccc22.png)
Хорошо бы было спрятать от нее работу с XML совсем, но писать UI для генератора пока нет желания.
Сайт-визитку украсили доменным именем. Взять домен можно почти у любого регистратора за пару сотен рублей. После этого нужно добавить в корень вашего гитхаб репозитария сайта файл CNAME с именем домена. Отлично, если у регистратора доменов есть бесплатные DNS сервера. Их нужно сконфигурировать для GitHub Pages следующим образом:
Где 192.30.252.153, 192.30.252.154 — IP адреса гитхаба. Про настройку доменного имени хорошо описано на stackoverflow и в помощи GitHub. После этого проверил cервисом mobile-friendly и, в целом, сайт неполохо работает с мобильными браузерами.
![](https://habrastorage.org/r/w1560/files/4cf/8ea/021/4cf8ea021dab408593a4872403c09893.png)
Надеюсь, что мое участие в создании сайта закончилось и поддержка будет в таком же режиме, как в
Для хостинга простого статичного сайта-визитки отлично подходит GitHub Pages и все затраты — это время на верстку и покупка доменного имени за пару сотен рублей. Алгоритм не сложный и описан в этой статье:
Генерировать html можно как с помощью встроенного в GitHub шаблонного jekyll, так и с помощью java программы и шаблонов на FreeMarker, что с моим опытом показалось проще. Так же удобно публиковать сайт на GitHub сразу из maven сборки c помощью maven-scm-publish-plugin. Требуется только настроить логин/пароль в скрипте, чтобы плагин для публикации смог выполнить git push. Мой подарок к 8 марта удался!
![](https://habrastorage.org/files/98d/3bb/3ae/98d3bb3aef904d32bae88c5ac4af611a.jpg)
Как думаете, реально научить девушку обновлять свой сайт на GitHub Pages к Международному женскому дню?! Расскажу как мне это удалось с помощью генератора сайта, который доступен на Github и написан на Java + FreeMarker, к тому же старался автоматизировать публикацию контента в git репозитарий.
На днях помог осуществить мечту дизайнера по текстилю в интерьере о своем сайте, пока у меня уйма свободного времени. Она и сама пробовала создать макет с помощью конструктора на Wix. Но первый викс сайт комом вышел и нормально не отображался на мобильных телефонах… К тому же лучше не привязываться к конкретному хостингу.
Последнее что я верстал самостоятельно в HTML — был сайт художника во время учебы в университете и тогда была в моде табличная верстка. Веб разработка — не мой хлеб. А сейчас повсюду мобильные браузеры и блочная верстка. Барышня просто хотела сделать простой сайт-визитку, поэтому скрипты на сервере не нужны. При этом идеально было бы, чтобы обновляла фотографии и редактировала разделы этого веб ресурса с нулевым знанием HTML и без моей помощи.
Если ставить CMS — cистему управления содержимым, то хостинг сайта будет дороже и придется тратить время на настройку, шаблоны и безопасность. Слишком сложно для статичного сайта. Мне показалось все это очень похоже на задачу генерации сайта по шаблону. Не знал где найти в наши дни хостинг для сайта без рекламы. Поспрашивав у знакомых, посмотрев варианты и почитав заметки в сети, пришел к выводу что GitHub Pages — идеальный вариант. Бесплатный, версионируемый и поддерживает использование своего доменного имени для сайта.
Для GitHub Pages идеально подходит шаблонизатор jekyll, но разбираться с ним и настройкой на компьютере дизайнера Ruby и jekyll gem совсем не было времени. С jekyll я поиграюсь в другой раз, как будет нужен сайт для своего проекта на GitHub.
Для любого джависта ассоциация с шаблонами — FreeMarker, знакомый многим шаблонный движок. Мне нужно было быстро разработать сайт и генератор, учитывая что Java мой привычный инструмент в работе. Сравнивая FreeMarker с Velocity, первый до сих пор жив и выглядит более функциональным.
Начали с создания аккаунта для дизайнера на GitHub:
![](https://habrastorage.org/files/024/ee9/766/024ee97662bd4b73bd51ec1531e83950.png)
Потом перешли к дизайну и верстке. Bootstrap Carousel показался отличным решением для показа изображений, так как основным содержимым веб страниц будут фото из портфолио и просматривать страницы будут на мобильных устройствах.
Раз уж подключил к странице Bootstrap, пригодятся элемент Panel и иконки для навигации/контактов. Для меня верстка была самым нудным этапом в создании сайта. На втором месте по сложности было изменение размера, цветокоррекция и кадрирование большого числа фото для портфолио работ.
Следующий шаг — превращение верстки в шаблон генератора. В шаблоне FreeMarker итерации по коллекции объектов делаются с помощью директивы <#list product as prodItem>...</#list>, а условия с помощью <#if prodItem?is_first>...</#if>. Это все что используется в этих шаблонах генератора.
За основу формата данных для хранения данных выбрал XML разметку. Со структурой быстро определились, на основе макета:
<site>
<text>.......</text>
<product id="drapery" background-img="drapery.jpg" title-img="drapery-main.jpg">
<title>Портьеры, тюль</title>
<description>Портьеры из плотных тканей...</description>
<image img="drapery/1.jpg"/>
...
<image img="drapery/37.jpg"/>
</product>
...
<product .../>
</site>
Из XML файла сгенерировал XSD schema в IntelliJ Idea Community Edition.
![](https://habrastorage.org/files/59a/8c7/24c/59a8c724ce5d4071ab65446a3eb50777.png)
Классы с аннотациями JAXB для использования в шаблоне генерируются динамически из Maven с помощью jaxb2-maven-plugin. При сборке проекта эти классы размещаются в директории target/generated-sources/jaxb.
Пример фрагмента FreeMarker шаблона для вывода всех изображений портфолио для определенной категории:
<#list image as imageInfo>
<div class="item<#if imageInfo?is_first> active</#if>">
<img src="img/${imageInfo.img}" class="img-responsive center-block">
<div class="carousel-caption">
<#if imageInfo.title??>
<h3>${imageInfo.title}</h3>
<p></p>
</#if>
</div>
</div>
</#list>
А вот и пример данных, на основе которых генерируется страница:
<product id="pillow" background-img="pillow.jpg" title-img="pillow-main.jpg">
<title>Покрывала, подушки</title>
<shortDescription>Неотъемлемая часть текстильного декорирования Вашей спальни, придающее уют, изысканность и особенный стиль пространству</shortDescription>
<description>Роскошное покрывало - это неотъемлемая часть текстильного декорирования Вашей спальни, придающее уют, изысканность и особенный стиль пространству. Со вкусом подобранные ткани и фурнитура, которые сочетаются в шторах, покрывале и подушках, создают гармонию и целостность Вашему интерьеру.</description>
<image img="pillow/1.jpg"/>
<image img="pillow/2.jpg"/>
<image img="pillow/3.jpg"/>
<image img="pillow/4.jpg"/>
<image img="pillow/5.jpg"/>
<image img="pillow/6.jpg"/>
<image img="pillow/7.jpg"/>
<image img="pillow/8.jpg"/>
<image img="pillow/9.jpg"/>
<image img="pillow/10.jpg"/>
<image img="pillow/11.jpg"/>
<image img="pillow/12.jpg"/>
<image img="pillow/13.jpg"/>
<image img="pillow/14.jpg"/>
</product>
В index.html генерируется оглавление на основе всех перечисленных в site.xml тегов <product...> с помощью шаблона.
Как «клей» для шаблонов, основную работу выполняет java класс src/main/java/Site.java и maven скрипт сборки: происходит копирование изображений из директории src/main/resources/img в target/site, из XML схемы генерируются классы c JAXB аннотациями и запускается программа на java с помощью exec-maven-plugin, которая с помощью FreeMarker и данных из site.xml генерирует сайт. Для плагина jaxb2-maven-plugin важно, чтобы xjc из JDK был доступен в одном из путей в переменной окружения PATH.
public class Site {
public static void main(String[] args) throws Exception {
File targetDirectory = getTargetDirectory();
SiteType siteModel = readSiteModel();
Configuration cfg = getTemplateConfiguration();
generateIndex(targetDirectory, siteModel, cfg);
siteModel.getProduct().stream().forEach(product -> generateProduct(targetDirectory, cfg, product));
}
private static void generateIndex(File targetDirectory, SiteType siteModel, Configuration cfg) {
try(Writer out = new FileWriter(new File(targetDirectory, "index.html"))) {
Template template = cfg.getTemplate("index-template.html");
template.process(siteModel, out);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private static void generateProduct(File targetDirectory, Configuration cfg, ProductType product) {
try(Writer out = new FileWriter(new File(targetDirectory, product.getId() + ".html"))) {
Template prodTemplate = cfg.getTemplate("product-template.html");
prodTemplate.process(product, out);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
...
}
Чтобы на компьютере у барышни не приходилось ничего устанавливать кроме JDK, в проект добавил mvn-classloader-1.8.jar, который в первый раз загружает из центрального maven репозитария maven-embedder и запускает сборку проекта и генерацию сайта с параметрами «clean package» и «scm-publish:publish-scm» для публикации сайта на GitHub Pages. Запускает генерацию сайта build.cmd для систем на windows и build.sh для linux. Это сильно упрощает сборку проекта и очень похоже на Gradle Wrapper/Maven Wrapper. Библиотека для maven требует только наличие JVM и подключения к интернет с доступом к центральному репозитарию. Случай изолированных сетей здесь рассматривать не будем, но даже в этом случае работают настройки зеркал и прокси из ~/.m2/settings.xml. Про всю магию этой библиотеки недавно рассказывал в «Модуляризация в JavaSE без OSGI и Jigsaw».
Пару слов про процесс обучения. Рассказывать о системе контроля версий и командах в консоли для Git мне было сложно. Не то что это невыполнимо, но не программиста это пугает. Чтобы она не ошибалась в процессе публикации сайта, я начал искать возможность автоматизировать весь процесс. Чтобы сгенерировать и опубликовать сайт можно было в один клик. Поискав как же легко публиковать сайт в github, обнаружил maven-scm-publish-plugin плагин. Добавил его в maven сборку и сконфигурировал scmpublish.pubScmUrl на адрес репозитария.
Отвлекусь от технологий и вспомню про женский праздник. Все реже можно видеть современных девушек за шитьем и рукоделием. А тут была возможность понаблюдал за работой дизайнера и как она шила:
![](https://habrastorage.org/files/73a/b1f/967/73ab1f967f3c4cf8b00dc1ae656a4b23.jpg)
Узнал про новую для себя область дизайна текстиля в интерьере. И даже не задумывался что существует столько видов штор, тканей и карнизов.
Еще до истории с сайтом смотрел, как она мастерила вместе с мамой подарок на День Рождения друга. Это были забавные чехлы на подушки с котенком и рыбкой, с собачкой.
![](https://habrastorage.org/files/933/616/ce7/933616ce78d148f4b9bb1581983501b4.jpg)
Ээх, жаль что мне так давно не дарили handmade подарки, даже немного позавидовал.
Было интересно узнать про карнизы с электроприводом для «умного дома» и про опыт их установки. Хочу поэкспериментировать с электроприводом штор, прикрутить их к своему контроллеру на основе STM32 и автоматизировать открытие штор по датчику освещенности или управлять шторами удаленно с телефона. Разобраться с протоколом, подключить свой контроллер красиво и без синей изоленты! Но это уже будет, видимо, после того как разберусь с шаблонами jekyll. До этого видел подобные автоматические рулонные шторы только в Nordstar Tower.
Про то как обновлять контент… Первым делом надо выполнить команду
git clone https://github.com/nadinbox89/site.git
или скачать zip файл проекта с гитхаба:
![](https://habrastorage.org/files/33c/17b/554/33c17b5540f04a529324750ddbb40f20.png)
Дизайнер копирует обработанные изображения для портфолио в директорию src/main/resources/img и добавляет запись в раздел <product...> файла src/main/resources/site.xml. После этого запускает с помощью ярлыка скрипт build.cmd, который создает сайт из данных по шаблонам и публикует его на GitHub Pages в репозитарий nadinbox89.github.io. С небольшой задержкой после git push, версия сайта обновляется по такому же адресу, как и название репозитария на GitHub — nadinbox89.github.io. Если используете в репозитарии запись домена в CNAME, то произойдет автоматическое перенаправление на этот адрес. После обновления сайта, в репозитарии с именем nadinbox89.github.io появляется commit от плагина публикации:
![](https://habrastorage.org/files/c43/cef/6e1/c43cef6e19b843f4b6372b7fbd0ccc22.png)
Хорошо бы было спрятать от нее работу с XML совсем, но писать UI для генератора пока нет желания.
Сайт-визитку украсили доменным именем. Взять домен можно почти у любого регистратора за пару сотен рублей. После этого нужно добавить в корень вашего гитхаб репозитария сайта файл CNAME с именем домена. Отлично, если у регистратора доменов есть бесплатные DNS сервера. Их нужно сконфигурировать для GitHub Pages следующим образом:
@ A 192.30.252.153
@ A 192.30.252.154
www CNAME *ваш_github_аккаунт*.github.io.
Где 192.30.252.153, 192.30.252.154 — IP адреса гитхаба. Про настройку доменного имени хорошо описано на stackoverflow и в помощи GitHub. После этого проверил cервисом mobile-friendly и, в целом, сайт неполохо работает с мобильными браузерами.
![](https://habrastorage.org/files/4cf/8ea/021/4cf8ea021dab408593a4872403c09893.png)
Надеюсь, что мое участие в создании сайта закончилось и поддержка будет в таком же режиме, как в
старом добром видео
Заключение
Для хостинга простого статичного сайта-визитки отлично подходит GitHub Pages и все затраты — это время на верстку и покупка доменного имени за пару сотен рублей. Алгоритм не сложный и описан в этой статье:
- Регистрация аккаунта на github
- Создание репозитария *ваш_github_аккаунт*.github.io
- Сохранение статики (html, css, изображений) в репозитарий *ваш_github_аккаунт*.github.io
- Регистрация домена и создание записей DNS сервера указывающих на адрес из 3 пункта
- Добавить файл CNAME в корень репозитария с именем вашего домена
Генерировать html можно как с помощью встроенного в GitHub шаблонного jekyll, так и с помощью java программы и шаблонов на FreeMarker, что с моим опытом показалось проще. Так же удобно публиковать сайт на GitHub сразу из maven сборки c помощью maven-scm-publish-plugin. Требуется только настроить логин/пароль в скрипте, чтобы плагин для публикации смог выполнить git push. Мой подарок к 8 марта удался!