Каморка сурового программиста, дубль 2

Создаем блог на Swift с помощью Publish с размещением на GitHub Pages

У меня уже есть блог, он на WordPress и я устал от всей этой свистопляски с обновлением версии, плагинов, возможности взлома и прочего. Это буквально убивает желание продолжать его развивать. Моя цель - делиться с миром своими мыслями и находками, но при этом иметь полный контроль над своим сайтом. С недавних пор Github Pages предоставила возможность хранить простенькие сайты у них. Никаких баз данных и PHP, статический сайт, как в старые добрые. Для блога - идеально. А т.к. процесс деплоя будет проходить через GitHub - будет прозрачная история всех изменений, и полный контроль над тем, что реально находится на сайте, трояны и прочая нечисть не пройдут.

Но они предлагают использовать Jekyll, статический генератор сайтов написанный на Ruby. Все же хочется отачивать мастерство в том языке, который ты используешь ежедневно, поэтому в качестве альтернативы я взял свежий статический генератор написанный на Swift от John Sundell.

Нам предстоит сделать 3 вещи:

  1. создать блог на GitРub Pages
  2. разобраться с тем как работать с Publish
  3. залить свой новый блог на GitРub Pages

    Итак, перейдем к пункту 1

1. Создадим блог на Github Pages.

Официальная инструкция доступен по адресу https://pages.github.com

Основное условие - login блога должен совпадать с вашим логином на GitHub. В моем случае это sparklone

  • логинимся в GitHub
  • идем по адресу https://github.com/new
  • в качестве имени репозитория вводите login.github.io, в моем случае было sparklone.github.io
  • убеждаемся, что он будет Public
  • жмем Create Repository
  • все, наш блог уже доступен по адресу https://login.github.io

Но пока на сайте нет ни одного файл Можно переходить ко второму пункту

2. Разберёмся с тем как работать с Publish

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

Я предпочел установить напрямую через git, создал папку ~/Developer/tools и там выполнил

git clone https://github.com/JohnSundell/Publish.git
cd Publish
make

далее я создал папку где я планирую хранить свой сайт (точнее исходники его генератора), в моем случае это ~/Developer/my/blog

и внутри этой папки запускаем команду

publish new

Это создаст новый сайт, список опций для команды можно узнать просто запустив в консоли publish

publish run скомпилирует все исходники и запустит веб сервер на питоне (если прервать посредством Ctrl+C - веб сервер не умрет, и придется в процессах ковыряться чтобы убить Python)

Первая сборка занимает какое то время (подливаются нужные репозитории, компилируется все), при последующих запусках publish run - все происходит намного быстрее.

Открываем в браузере http://localhost:8000 и видим что получился за сайт

Не густо, но мы еще ничего собственно и не сделали, чтобы ожидать чего то большего.

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

  1. сделать изначальную настройку генератора для нашего сайта
  2. поменять пути по которым будут лежать записи и настроить меню
  3. добавить подсветку для исходных файлов и создание своей темы

1. Изначальная настройка генератора для нашего сайта


Посмотрим что нам сгенерировал Publish. Внутри папки будет файл Package.swift, его открываем XCode'ом (можно в консоли набрать open Package.swift), и это запускает процесс подтягивания всех нужных библиотек. На скрине видно что должно получится в итоге.

Тестовая запись лежит в Content/posts/first-post.md Проверим, что мы можем что то изменить и это отразится на сайте Подправим текст в first-post.md (можно поменять дату, теги, описания, и сам контент)

В Xcode выбираем Mac в качества таргета для которого надо запускать и делаем Run проекту.

После этого рефрешим веб страницу http://localhost:8000

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

Почему это важно сделать сразу? Если вы решите поменять пути после того как уже зальете часть постов - входящие ссылки на эти страницы станут невалидными, а т.к. это не свой сервер/VPS - будет довольно проблематично сделать редирект со старых ссылок на новые пути. Не невозможно (вот к примеру плагин для Jekyll), но зачем создавать себе головную боль в будущем если можно ее избежать.

По умолчанию все записи лежать в папке posts. Учитывая что в дальнейшем хочется бить на категории, а posts - общее название, - лучше переименовать папку в articles. Так же не помешает добавить страницу about

Но наш генератор пока ничего не знает про это.

В main.swift поменяем на

struct Blog: Website {
    enum SectionID: String, WebsiteSectionID {
        case articles
        case about
    }
}

Добавим файл about.md в папку Content и заполним немного информации о себе

К слову эту статью я пишу в XCode, редактируя md файл, и периодически запуская проект, чтобы посмотреть в браузере как это смотрится.

Я долго колебался заморачиваться ли с датой у файлов *.md, ну т.е. называть не my-article.md, а к примеру 2020-07-10-my-article.md. И все же решил отказаться от этой идеи. Т.к. в самих md файлах есть метаданные (поле date), это при желании позволит в будущем добавлять дату автоматически. И не придется следить за корректностью даты в имени файла, к тому же это убережет от расхождений, если в имени файла одна дата, а в метаданных внутри - другая. Недостатком такого решения я вижу то, что гипотетически могут в будущем быть коллизии в именах md файлов, но все таки это маловероятно, к тому же мы об этом узнаем при создании поста, а не сохранении.

3. Добавляем подсветку для исходных файлов

Автором генератора Publish так же была написана библиотека Splash позволяющая делать подсветку исходных кодов. Подключается она как package в Swift Package Manager

Открываем файл Package.swift и добавляем поддержку, по сути нужно добавить 2 строки Вот что получилось у меня

let package = Package(
    name: "Blog",
    products: [
        .executable(
            name: "Blog",
            targets: ["Blog"]
        )
    ],
    dependencies: [
        .package(name: "Publish", url: "https://github.com/johnsundell/publish.git", from: "0.6.0"),
        .package(name: "SplashPublishPlugin", url: "https://github.com/johnsundell/splashpublishplugin", from: "0.1.0")
    ],
    targets: [
        .target(
            name: "Blog",
            dependencies: [
                "Publish",
                "SplashPublishPlugin"
            ]
        )
    ]
)

А чтобы подсветка начала применяться при генерации нужно подклбючить плагин в main.swift

try Blog().publish(withTheme: .foundation)

я поменял на

try Blog().publish(
    withTheme: .foundation,
    plugins: [.splash(withClassPrefix: "")]
)

Не забываем добавить в main.swift импорт плагина import SplashPublishPlugin

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

Но вот проблема - куда добавлять этот CSS? Если покопаться в исходниках, то станет видно, что все это решается на уровне темы. Тема у нас стандартная foundation, и она лежит в самом пакете Publish по пути Sources/Publish/API/Theme+Foundation.swift

Внутри своего проекта (Blog) в папке где лежит main.swift я создал подобный файл Theme+Blog.swift Так же внутри папки Resources я создал папку Blog и поместил туда файл styles.css Внутрь файла я поместил содержимое CSS от темы Foundation ну и CSS от Splash Да, лучше было бы разделить, а может вообще темы вынести в отдельный package, но не будем усложнять раньше времени.

Итого у меня в файле темы пришлось поменять на следующее

import Plot
import Publish

public extension Theme {
    static var blog: Self {
        Theme(
            htmlFactory: BlogHTMLFactory(),
            resourcePaths: ["resources/blog/styles.css"]
        )
    }
}

Если бы мы добавили еще один css, нам потребовалось бы не только добавит его в resourcePaths, но так же добавлять в каждый head страниц, чего мне делать совершенно не хотелось в данный момент

.head(for: item, on: context.site, stylesheetPaths: ["/styles.css", "/splash.css"]),

Итого сейчас у меня в проекте файловая структура выглядит как то так:

3. Зальём свой новый блог на GitРub Pages

Итак, воспользуемся встроенным инструментом Publish для заливки нашего блога. В main.swift добавим

.deploy(using: .gitHub("login/login.github.io", useSSH: false))

итого у меня получилось

try Blog().publish(
    withTheme: .blog,
    deployedUsing: .gitHub("sparklone/sparklone.github.io", useSSH: false),
    plugins: [.splash(withClassPrefix: "")]
)

Проверяем в последний раз, что все работает. Последний штрих - мне кажется, что нет смысла хранить в git нашего репозитория с темплейтами как строить сайт содержимое папки Output, для этого у нас будет отдельный репозиторий как раз таки login.github.io Если вы согласны - исключим эту папку из .gitignore, добавив туда строку /Output в конце Если все ок выполняем в консоли (из папки где мы выполняли publish new)

git add .
git commit -m "post title or some description"
git push origin
publish deploy

В течении минуты GitHub Pages подхватит ваши изменения и все появится онлайн.


Поздравляю! )

Tagged with: