Сайт на GitHub Pages


Сайт на GitHub Pages

GitHub Pages — служба хостинга сайтов, которая позволяет вести персональные сайты, сайты организаций и сайты отдельных проектов GitHub.

Сайты GitHub Pages статические. Текст страниц в формате Markdown лежит в репозитории GitHub. Мы пишем новые статьи, фиксируем (commit) изменения и проталкиваем (push) их в ветку master центрального репозитория. GitHub самостоятельно запускает генератор Jekyll, и через несколько секунд публикует готовые HTML-страницы на сайте.

Возможности статических сайтов ограничены. Тем не менее Jekyll позволяет:

  1. Вести блог.
  2. Анонсировать записи в формате Atom.
  3. Подсвечивать код.
  4. Контролировать внешний вид сайта.

Быстрый старт

Исходный код сайта нужно разместить в правильном репозитории. Название организации Московский клуб программистов на GitHub progmsk, следовательно, URI страницы клуба https://github.com/progmsk, а для сайта я должен создать репозиторий progmsk.github.io.

Сразу после создания репозитория сайт становится доступен по адресу http://progmsk.github.io. Сейчас он совершенно пуст.

Пустой сайт на GitHub Pages

Нажмём кнопку Create new file в заголовке репозитория на сайте GitHub. В качестве имени нового файала укажем _layouts/default.html. По правилам GitHub это означает, что в корне проекта будет создана папка _layouts, а в ней — файл default.html. Разместим внутри основной шаблон сайта:

В корне создадим файл index.md, где запишем:

Наконец, в корне репозитория создадим пустой файл _config.yml.

После сохранения изменений (после фиксации их в ветке master ), GitHub запускает Jekyll, чтобы сгенерировать набор статических HTML-страниц. Как правило, в течение нескольких секунд вам доступна новая версия сайта.

Что у нас получилось? Во-первых, мы подготовили шаблон сайта. Ещё раз внимательно взгляните на default.html. Вместе с тегами HTML, шаблоны позволяют вставлять в текст страницы переменные или использовать управляющие конструкции, чтобы скрывать или повторять части страниц.

Дальше мы рассмотрим шаблонизатор детально.

Во-вторых, мы поняли, как описывать наши переменные. Всё, что относится к странице, можно описать в её заголовке, выделив его тройными дефисами.

Переменная layout показывает, что при генерации HTML надо применить шаблон default.html. Переменные lang , title и excerpt в тексте страницы доступны как page.lang , page.title и page.excerpt .

После всех мытарств, мы видим правильно оформленный результат генерации сайта.

Конфигурация сайта

Конечно, встречаются в этой жизни полиглоты, но вряд ли вы будете вести свой сайт на разных языках. Скорее всего, язык всегда будет один и тот же, скажем, русский. Вставлять в текст каждой страницы конструкцию lang: ru-RU вам быстро надоест. Что делать?

Делать надо переменные сайта. Описать их можно в том самом пока пустом файле _config.yml:

Здесь мы присвоили переменной lang значение ru-RU , в шаблонах она доступна нам как site.lang . Теперь становится понятен смысл конструкции:

Если не указать lang в тексте страницы, page.lang окажется пустым; и вместо него Jekyll подставит site.lang .

Часть переменных это на самом деле параметры. Они определяют, как должен выглядеть сайт.

permalink Задаёт структуру ссылок, то есть, по сути, структуру сайта. pretty — предопределённое значение, описанное в документации. «Красивые» (pretty) ссылки означают, что для страницы foo.md будет создана папка foo с файлом index.html внутри. В результате адресом страницы будет красивый /foo/, а не страшный /foo.html. highlighter Указывает инструмент, с помощью которого Jekyll подсвечивает код. По умолчанию применяется Rouge, который понимает больше 60-ти языков. markdown Указывает инструмент конвертации Markdown в HTML. Мы предпочли kramdown.

Если мы сейчас уберём lang: ru-RU из теста страницы index.md, язык документа всё равно будет указан, потому что теперь он берётся из _config.yml.

Оформление сайта — шаблоны

Большинство страниц вашего сайта похожи друг на друга. У них одинаковы заголовки, подвалы, панель навигации, а если вас подводит творческое начало, то и содержание. Чтобы не повторять всё это на каждой странице, применяют шаблоны. GitHub позволяет описывать шаблоны страниц на языке Liquid.

Создадим в папке _layouts файл article.html рядом с default.html:

В заголовке шаблона мы видим констуркцию layout: default , которая означает, что в качестве основы мы используем шаблон default.html. Содержимое нашего шаблона будет встроено в default.html там, где указана конструкция > .

Теперь откроем index.md и изменим шаблон на новый article :

Наша страница будет вставлена в article.html, который, в свою очередь, будет вставлен в default.html, и в результате мы получим такой HTML:

Если шаблон оказался слишком большим, отдельные блоки можно вынести в другие файлы, и подключить их с помощью инстуркции include :

Например создадим в репозитории файл _includes/header.html:

И файл _includes/footer.html:

Поскольку оба они размещены в каталоге _includes, мы можем включить их в шаблон article.html без указания пути:

Оформление сайта — стили

Настало время рассмотреть детали генерации сайта. Каталоги, название которых начинается с подчёркивания, используются при генерации, но сами на сайт не попадают. Обычные каталоги копируются «как есть» вместе со всем содержимым. При этом Jekyll обрабатывает файлы с расширением .md и .html так, как мы разобрали выше.

Добавим на сайт описание стилей css/main.css:

Подключим стили в шаблоне default.html:

Немного странный href означает, что Jekyll будет генерировать корректный относительный путь к файлу стилей для каждой страницы. После фиксации изменений вы увидите, что сайт стал выглядеть «красиво».

Помимо CSS Jekyll умеет запускать шаблонизатор Sass для генерации стилей. Начнём редактирование main.css и заодно переименуем его в main.scss:

Обратите внимание, что в начале файла должны находиться две строки из трёх дефисов. Встретив файл с таким заголовком, Jekyll запустит Sass для его обработки и результат — main.css — скопирут в итоговый сайт в каталог css.

В _config.yml добавим строки:

В результате содержимое main.css будет максимально утрамбовано.

Своё доменное имя

Мы в клубе программистов зарегистрировали себе доменное имя prog.msk.ru и хотим, чтобы сайт был доступен по адресу http:/prog.msk.ru. Для этого надо выполнить два шага:

  1. На NS-сервере прописать две А-записи для prog.msk.ru, одну на IP 192.30.252.153, вторую на 192.30.252.154. После этого все обращения к prog.msk.ru будут вести на GitHub.
  2. В репозитории GitHub зайти в раздел Settings, найти настройки GitHub Pages и в поле Custom domain ввести prog.msk.ru.

Страницы, которые вы разместите в каталоге _posts при генерации сайта превратятся в записи блога. Названия страницам надо дать правильные, например 2018-04-02-first-post.md. В начале имени файла мы пишем дату, а через дефис — заголовок на английском языке, как он должен выглядеть в адресной строке браузера.

Создадим в GitHub файл _posts/2018-04-02-first-post.md:

Осталось показать запись в списке. Мы можем создать отдельную страницу, которая будет центральной страницей блога. Пока ограничимся тем, что внесём необходимые изменения в index.md:

Несколько секунд, и на нашем сайте появится ссылка на первый пост:

Посмотрим на то, какой код создал Jekyll. Дата 2018-04-02 (2 апреля 2018 года) была преобразована в часть пути. Сама страница получила имя first-post. Полное имя нашей записи на сервере — /2018/04/02/first-post/index.html. Так как раньше мы установили свойство сайта permalink в pretty, Jekyll для каждой страницы создаёт папку с файлом index.html внутри.

Взглянем на код, который выводит список записей:

Очевидно site.posts содержит все записи из каталога _posts. post.title — содержимое свойства title страницы, а post.url — её адрес. post.excerpt это анонс. Обычно Jekyll использует в качестве анонса первый абзац записи. Мы можем изменить это поведение, вписав в код страницы специальный маркер . Анонсом станет всё, что находится в тексте выше этого маркера.

Постраничый список записей

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

Jekyll разбивает записи на страницы с помощью плагина jekyll-paginate. Подключим и настроим его в конфигурационном файле _config.yml:

Параметр paginate позволяет указать количество записей на странице, а paginate_path устанавливает формат пути. Скажем, формат /blog/page:num означает, что для всех страниц будут созданы каталоги /blog/page1, /blog/page2, и так далее.

Нашему формату /:num соответствуют каталоги /1, /2, /3, …

Теперь организуем постраничный вывод записей. Первое, что нам потербуется: переделать index.md в index.html, потому что jekyll-paginate работает только с .html-файлами. Второе: вместо переменной site.posts мы будем получать записи из paginator.posts . Итак, откроем index.md, переименуем его в index.html и перепишем содержимое так:

Как и прежде, публикация списка записей реализована просто. Зато ниже мы видим сложный код, который отвечает отображает ссылки на следующую и предыдующую страницы.

Синдикация новостей

Jekyll умеет создавать ленту новостей в формате Atom. В список gems файла _config.yml добавим плагин jekyll-feed и опишем имя XML-файла, куда попадут анонсы записей:

Наконец, нам потребуется подставить ссылку Atom в заголовок наших страниц. Добавим мета-тег в заголовок основного HTML-шаблона default.html:

После компиляции сайта в коде страницы мы увидим ссылку на документ Atom как раз на месте .

Наконец, вот и сам документ:

Страницы

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

Создадим в корне репозитория файл blog/index.html и перенесём туда код генерации списка записей:

В корневом index.html поставим ссылку на блог:

Чтобы ссылки на страницы блога привести к общему виду, в файле _config.yml изменим параметр paginate_path :

Динамическое содержимое

Поскольку наш сайт статический, кажется, что мы не можем показывать динамическое содержимое. Но мы можем — с помощью JavaScript.

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

Мы хотим, чтобы наша программа загружала ленту в формате Atom и выводила их прямо на страницу. Читатель сайта ожидает увидеть заголовки записей, оформленные в виде ссылок, дату публикации, автора и анонс.

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

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

Метод addEventListener поддерживается IE, начиная с 9-й версии, но к счастью, сама 9-я версия уже давно почила в бозе и мы этот метод можем вызывать без опаски. Событие ‘load’ возникнет после загрузки страницы. Наряду со всеми обработчиками, которые будут зарегистрированы через addEventListener , браузер вызовет и нашу функцию.

Итак, мы должны загрузить новостную ленту в формате Atom. JavaScript предоставляет для этих целей объект XMLHttpRequest :

Загрузка данных осуществляется асинхронно. Мы вызываем метод send , который инициирует запрос к серверу и немедленно возвращает управление. Получив с сервера ответ, объект request вызовет наш обработчик, передав ему в качестве параметра результаты запроса. В поле data.target.status мы увидим статус HTTP, который, если всё нормально, будет в диапазоне 200..299. В поле data.target.responseXML мы получим разобранный браузером XML в виде объекта Document .

Метод Document.getElementsByTagName(‘entry’) извлечёт из документа все элементы с тегом ‘entry’ и вернёт их в виде коллекции. Напомню, как выглядит типичная запись в формате Atom:

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

В фигурных скобках указано, откуда брать значения. Мы вынесем код, который будет разбирать entry в метод parsePost , а код формирования HTML — в appendPost .

Первый метод извлекает значения атрибутов и текстовое содержимое из дочерних элементов entry и складывает их в объект. Нет гарантий, что запись будет содержать все нужные данные. Чтобы избежать ошибок, мы проверяем, что результат вызова querySelect не null , прежде чем извлекать значение атрибута или текст.

Метод appendPost тоже разобьём на части:

Каждый участок HTML строится по частям. Чтобы сформировать

>

мы сначала создаём элемент a , устанавливаем у него атрибут href и записываем внутрь текст. Только потом готовый элемент a можно поместить в h2 .

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

Целиком index.html в корне репозитория должен выглядеть так:

Похожим способом мы можем динамически формировать содержимое страницы даже на статическом сайте, созданным с помощью Jekyll.


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

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