Небольшой генератор статических сайтов с горячей перезагрузкой из оболочки. Предполагается Bash 4.4+.
ВНИМАНИЕ: Здесь будут яки!
Задача shite
— помочь мне создать мой веб-сайт: https://evalapply.org. Таким образом, объем shite
, (неправильный) набор функций, полировка всегда будут производственного уровня, где производство «работает на моей машине(ах). )" :)
Оглавление
Ну, цель shite
— создавать сайты.
Это небольшая система публикации, состоящая из конвейерных рабочих процессов, опционально управляемых потоками файловых событий (для битов горячей перезагрузки).
Это не удивит джентльмена-хакера Perl/PHP из прошлого века.
Оно существует потому, что насвистывают глупые мелодии и бреют яков.
По сути, это именно то, что он делает (ссылка: функция shite_templating_publish_sources
).
cat " ${watch_dir} /sources/ ${url_slug} " |
__shite_templating_compile_source_to_html ${file_type} |
__shite_templating_wrap_content_html ${content_type} |
__shite_templating_wrap_page_html |
${html_formatter_fn} |
tee " ${watch_dir} /public/ ${slug} .html "
# The complete "business logic" is 300-ish lines as of this comment,
# counted as all lines except comments and blank lines.
grep -E -v " s?#|^$ "
./bin/{events,metadata,templating,utils,hotreload}.sh |
wc -l
Прежде чем вы слишком разволнуетесь, позвольте мне предупредить вас, что лицензия MIT означает, что мне плевать, если этот маленький производитель дерьма не сможет заставить ваше дерьмо работать. Содействие изобилует большим количеством предупреждений.
И последнее, но не менее важное: настоящим постановляю, что все тексты здесь будут читаться на языке Шона Коннери.
В своих shite
мечтах я желаю...
Прежде всего, чтобы она («бизнес-логика») оставалась маленькой . Достаточно маленький, чтобы кэшировать, отлаживать и рефакторить в моей голове.
Устанавливать и использовать без разрешения суперпользователя.
Крайне избегать цепочек инструментов и строить зависимости. Никаких драгоценных камней/НПМ/Венвсов/что-то еще. Таким образом, Bash — это язык, потому что Bash есть везде. И стандартные пакеты, такие как pandoc
или tidy
, когда вам нужна конкретная расширенная функциональность.
Шаблоны без зависимостей с простым HTML-кодом, установленным в старых добрых документах.
Простая система метаданных, пространство имен контента, статическая организация активов и т. д.
Веб-сервер необязательно (или любой другой серверный процесс, если на то пошло). В конце концов, мы стремимся к статическим сайтам, которые прекрасно работают с навигацией file://
.
Собрать его из небольших, компонуемых, чисто функциональных частей, похожих на инструменты Unix, потому что мне очень нравятся подобные вещи.
Чтобы создать для себя плавный рабочий процесс редактирования-сохранения-сборки-предварительного просмотра, подобный REPL.
Я случайно возобновил ведение блога после долгого перерыва. Прежде чем я смог передать слова в облако, я возился с «современными» генераторами статических сайтов. Потому что WordPress — это прошлый век (по крайней мере, я так сказал себе). Затем меня разозлила магия построенных на заказ шаблонов SSG Jamstack и т. д. Теперь я нахожусь на темном пути создания этого. Об этом пишут в блоге: дерьмо: статические сайты из оболочки: часть 1/2.
Я использую дерьмо в основном в режиме «горячей загрузки», в основном для написания постов (в режиме org) и их предварительного просмотра (в Firefox). Менее важно для оперативного предварительного просмотра изменений стилей и/или шаблонов страниц. По меньшей мере, после бесконечной работы над постом я использую его в режиме «не горячей перезагрузки», чтобы выполнить полную перестройку сайта.
демо-примеры ниже.
По сути, это означает, что если я создаю, обновляю, удаляю любой файл в sources
, он должен автоматически переводиться в HTML, публиковаться локально в public
и вызывать соответствующую навигацию по странице или действие перезагрузки в веб-браузере, где открыт мой сайт.
Вызовите «основной» сценарий в новом сеансе терминала или в панели tmux.
./shite.sh
Он открывает индексный файл в Firefox в соответствии со значениями по умолчанию, которые я установил в массиве shite_global_data
в ./shite.sh
.
В вашем Emacs или Vim откройте какой-нибудь файл содержимого в разделе sources
. Редактируйте, сохраняйте и наблюдайте, как контент появляется в браузере. (Да, указывать Emacs/Vim глупо, потому что я запускаю горячие действия на основе событий inotify. Очевидно, разные редакторы обновляют файлы по-разному. Я использую Emacs или Vim, поэтому я слежу за событиями, которые они вызывают, поэтому это работает на моей машине. : )).
Часто браузер запоминает положение прокрутки, и это очень удобно. Иногда горячая перезагрузка - это вообще дерьмо. Поэтому я просто нажимаю пробел и сохраняю файл содержимого, чтобы снова запустить горячую перезагрузку.
Перейдите к какому-нибудь статическому ресурсу, например к таблице стилей CSS. Измените что-нибудь, например значение цвета фона. Сохраните и наблюдайте за изменением цвета в браузере.
Измените какой-нибудь фрагмент шаблона в templates.sh
— скажем, шаблон сообщения в блоге. Затем переключитесь на какой-нибудь файл содержимого сообщения в блоге и измените его, чтобы запустить создание страницы с измененным шаблоном (например, нажмите пробел и сохраните).
Это хак. Корневая страница index.org в разделе «Источники» особенная. Если я его изменю, это означает, что я хочу перестроить списки сообщений для индексной страницы, для тегов, а также перестроить связанные метафайлы, такие как RSS-канал, карта сайта, robots.txt и т. д.
В новом чистом сеансе терминала вызовите shite.sh
с «no» и, при необходимости, с помощью base_url
среды развертывания:
Перестроить полный сайт для «локальной» навигации по файлу:///. Действительно «бессерверный» :)
./shite.sh " no "
Полностью перестроить сайт для публикации под моим доменом.
./shite.sh " no " " https://evalapply.org "
Эти флаги изменяют поведение системы.
SHITE_BUILD
значения «горячий» запустит систему событий в режиме «мониторинга», что, в свою очередь, приводит к горячей перезагрузке. Установка значения «нет» отключит горячую перезагрузку браузера.SHITE_DEBUG_TEMPLATES
значения «отладка» приведет к тому, что сначала будут получены исходные шаблоны, а затем будет опубликовано любое исходное содержимое шаблонов. shite
внутри довольно Unixy. Или мне так хотелось бы думать.
Код представляет собой функциональный стиль программирования Bash. Все является функцией. Большинство функций представляют собой чистые функции — небольшие инструменты Unix сами по себе. Большая часть логики ориентирована на конвейер. Это работает на удивление хорошо, поскольку Shell — неплохое место для FP.
Я также хотел получить живой интерактивный опыт, подобный REPL, при написании с помощью shite
, потому что мне нравится работать в живых/интерактивных средах выполнения, таких как Clojure и Emacs.
Итак, shite
превратилось в полностью реактивную, управляемую событиями систему, способную к горячей сборке и перезагрузке при сохранении.
Существует три основных пространства имен каталогов:
sources
содержащие «исходный» контент, такие как сообщения в блогах, написанные в режиме организации, а также CSS, Javascript и другие статические ресурсы.public
цель для скомпилированных/собранных артефактовbin
для дерьмового кода Схема именования URL-адресов соответствует структуре подкаталогов в sources
и копируется как есть в структуре pubilic
каталогов. Поскольку это стандартная схема пространства имен URL-адресов, она также применяется непосредственно к опубликованному контенту. Вот так:
file:///absolute/path/to/shite/posts/slug/index.html
http://localhost:8080/posts/slug/index.html
https://your-domain-name.com/posts/slug/index.html
Все «публичные» функции располагаются в пространстве имен shite_the_func_name
. Все «частные» функции имеют пространство имен __shite_the_func_name
.
Функции существуют для:
В новом чистом сеансе терминала:
source ./bin/utils_dev.sh
shitTABTAB
или __shiTABTAB
в командной строке для автозаполнения.type -a func_name
, чтобы распечатать определение функции и прочитать ее API.shite_global_data
и shite_page_data
по мере необходимости. Шаблоны существуют для фрагментов страниц (например, верхнего, нижнего колонтитула, навигации) и для полных определений страниц (например, шаблона страницы по умолчанию). Они написаны в виде простого HTML, завернутого в heredocs. ./bin/templates.sh
предоставляет их.
Шаблоны заполняются переменными данными из разных источников:
shite_global_data
содержит метаданные всего сайта, а shite_page_data
содержит метаданные, специфичные для страницы. Какой-то внешний процесс должен предварительно установить эти массивы перед обработкой любой страницы.Например, полная страница может быть построена следующим образом:
cat ./sample/hello.md |
pandoc -f markdown -t html |
cat << EOF
<!DOCTYPE html>
<html>
<head>
$( shite_template_common_meta )
$( shite_template_common_links )
${shite_page_data[canonical_url]}
</head>
<body ${shite_page_data[page_id]} >
$( shite_template_common_header )
<main>
$( cat - )
</main>
$( shite_template_common_footer )
</body>
</html>
EOF
Система метаданных shite
определяется как пары ключ-значение. Ключи называют элементы метаданных и будут связаны с любым значением этого типа. Примеры ниже.
Как отмечалось ранее, метаданные времени выполнения передаются в среде ассоциативными массивами shite_global_data
и shite_page_data
. Они могут быть заполнены путем прямого построения, а также обновлены из внешних источников.
Каждая страница может указывать свои собственные метаданные во «вступительной части» вверху страницы. Это будет использоваться в дополнение к метаданным страницы, полученным из других источников.
shite
ожидает, что мы напишем вступительную часть, используя синтаксис, совместимый с данным типом контента, как показано ниже.
Используйте строки комментариев # SHITE_META
, чтобы разграничить метаданные в стиле организации, которые shite
также должен анализировать как метаданные, специфичные для страницы.
# SHITE_META
#+title: This is a Title
#+slug: this/is/a/slug
#+date: Friday 26 August 2022 03:38:01 PM IST
#+tags: foo bar baz quxx
# SHITE_META
#+more_org_metadata: but not processed as shite metadata
#+still_more_org_metadata: and still not processed as shite metadata
* this is a top level heading
this is some orgmode content
#+TOC: headlines 1 local
** this is a sub heading
- this is a point
- this is another point
- a third point
Напишите вступительную часть YAML в стиле Jekyll, поместив ее между разделителями ---
.
---
TITLE : This is a Title
slug : this/is/a/slug
DATE : Friday 26 August 2022 03:38:01 PM IST
TAGS : foo BAR baz QUXX
---
# this is a heading
this is some markdown content
## this is a subheading
- this is a point
- this is another point
- a third point
Мы можем просто использовать стандартные теги <meta>
, которые подчиняются этому соглашению: <meta name="KEY" content="value">
.
< meta name =" TITLE " content =" This is a Title " >
< meta name =" slug " content =" this/is/a/slug " >
< meta name =" DATE " content =" Friday 26 August 2022 03:38:01 PM IST " >
< meta name =" TAGS " content =" foo BAR baz QUXX " >
< h1 > This is a heading </ h1 >
< p > This is some text </ p >
< h2 > This is a subheading </ h2 >
< p >
< ul >
< li > This is a point </ li >
< li > This is another point. </ li >
< li > This is a third point. </ li >
</ ul >
</ p >
Вот Яки!
Будучи полностью избалованным живыми интерактивными рабочими процессами в стиле Clojure/Lisp/Spreadsheet, я также хочу горячую перезагрузку и горячую навигацию в создании дерьма.
Но, похоже, не существует отдельного действующего сервера/инструмента веб-разработки, который также не хотел бы, чтобы я загружал половину известного Интернета в качестве зависимостей. Как я уже говорил, этого мне крайне не хочется делать.
DuckSearch предоставил нетерпеливый режим Emacs, который довольно горяч, но я не хочу жестко запрограммировать его в своем Emacs. К счастью, он также вызвал интересную волну идей с использованием «inotify-tools» и «xdotool»: github.com/traviscross/inotify-refresh
Горячая копия!
Потому что что может быть жарче, чем мой компьютер, нажимающий на меня клавишу F5? Как будто он знал , чего я действительно хочу в глубине своего сердца.
Подсистема событий ортогональна всему остальному и согласуется с остальной частью системы.
Дизайн представляет собой стандартную потоковую архитектуру, а именно. следите за событиями файловой системы, затем фильтруйте, дедуплицируйте, анализируйте и направляйте их (tee) в разные обработчики событий. На данный момент существует всего два таких процессора; один для компиляции и публикации страницы или ресурса, связанного с событием, другой для горячей перезагрузки браузера (или горячей навигации) в зависимости от того же события.
Как ни странно это:
# detect file events
__shite_detect_changes ${watch_dir} ' create,modify,close_write,moved_to,delete ' |
__shite_events_gen_csv ${watch_dir} |
# hot-compile-and-publish content, HTML, static, etc.
tee >( shite_templating_publish_sources > /dev/null ) |
# browser hot-reload
tee >( __shite_hot_cmd_public_events ${window_id} ${base_url} |
__shite_hot_cmd_exec )
События — это просто поток записей CSV, структурированный следующим образом:
unix_epoch_seconds,event_type,base_dir,sub_dir,url_slug,file_type,content_type `
Мы используем разные части записи события, чтобы вызывать разные виды действий.
Связанный выше сценарий inotify-refresh пытается периодически обновлять набор окон браузера. Однако мы хотим быть очень нетерпеливыми. Любое действие по редактированию наших файлов контента и/или статических ресурсов должно мгновенно вызывать горячую перезагрузку/действия навигации на вкладке браузера, на которой отображается наше дерьмо.
Мы хотим определить отдельные сценарии перезагрузки: взаимоисключающие, коллективно исчерпывающие сегменты, в которые мы можем сопоставлять события файлов, которые хотим отслеживать.
Если мы сделаем это, то мы сможем моделировать обновления как своего рода журнал упреждающей записи, пропуская события через конвейер анализа, связывая их со сценарием точного соответствия, а затем, наконец, вызывая действие. Например:
Обновить текущую вкладку, когда
Иди домой, когда
Перейдите к содержимому, когда
Поскольку мы заставляем компьютер имитировать наши собственные действия с клавиатуры, он может испортить наши личные действия. Если мы продолжим писать нашу чушь в текстовом редакторе и позволим компьютеру делать горячую перезагрузку, мы не будем раздражаться.
В мире много Яков.
Для действительно повсеместного распространения моджо публикации на нескольких сайтах:
shite
должно быть доступно в моем PATHЭто маленький як. Я, наверное, скоро его попрошу.
Очевидно, что можно использовать задания CI популярных хостов git для запуска shite
сборок. Но зачем использовать неуклюжие технологии текущего века, если мы уже достигли уровня искусства конца 1900-х годов… полностью потокового и полностью реактивного?
Если оставить в стороне сарказм, я не понимаю, почему ту же систему событий нельзя использовать для добавления поддержки горячего развертывания на удаленной машине, которую я запускаю.
На удаленном ящике:
sources
сайтаsources
(за исключением просмотра браузера).На моем локальном ящике:
https://mydomain.com/posts/hello/index.html
Сделайте что-нибудь через SSH, чтобы вернуть обновление браузера на локальный компьютер в случае горячего развертывания на удаленном сервере.
Может быть, какой-нибудь сценарий настройки времени «разработки/черчения»/демонтажа? Может быть, функция «dev_server», которую мы используем, чтобы начать новый сеанс написания дерьма?
Если вы дошли до сюда и все еще хотите внести свой вклад...
Почему?
Почему, во имя всего святого и хорошего, ты хочешь этого? Разве не очевидно, что это работа дурака? Разве вы не слышали, что Bash даже не настоящий язык программирования? И неужели не очевидно, что ваши пиары будут томиться вечно, а комментарии упадут в безымянную пустоту?
Да, рассылать патчи — ужасная идея.
Но , пожалуйста, напишите мне о своих надеждах и мечтах о вашем дерьмопроизводителе! Я читаю электронную почту на свое имя и фамилию в Gmail.
Вместе мы можем насвистывать глупые мелодии и стричь своих яков вместе, по-своему.
Да пребудет с нами Источник.
Эта работа имеет двойную лицензию: лицензию MIT и лицензию CC By-SA 4.0.
Идентификатор лицензии SPDX: mit OR cc-by-sa-4.0