!/bin/sh

НАСТРОЙКИ

Имя блога (используется в качестве хедера на главной странице, страницах категорий и тегов)

GEMLOG_NAME="# 無 Muu Online"

Описание блога, используется в составе хедера на главной странице, страницах категорий и тегов

GEMLOG_SUMMARY="Гемлог про у-вэй и юникс-вэй"

Футер для главной страницы, страниц категорий и тегов

GEMLOG_FOOTER="© Muu, 2023-2024 - Licensed under CC BY-SA 4.0"

Категория статьи по умолчанию (применяется если не указана в метаданных статьи)

DEFAULT_CATEGORY="Blog"

Контент - здесь лежит неупорядоченный контент (заготовки статей, черновики, прочие файлы)

CONTENT_DIR="content"

Каталог, куда будут опубликованы обработанные файлы для последующего деплоя на сервер

OUTPUT_DIR="output"

Каталог для не-гипертекстового контента (картинки и т.п.)

STATIC_DIR="static"

Браузер для предварительного просмотра локальной копии гемлога до публикации

GEM_BROWSER="amfora"

Скрипт для деплоя контента на удаленный хост

DEPLOY_SCRIPT="./deploy.sh"

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

GEM_EDITOR="nvim +star!"

Если = 1, будут выводиться дополнительные отладочные сообщения

DEBUG=0

Разберем параметры командной строки

case "$1" in

-l) 

    if [ $DEBUG = 1 ]; then echo "Передан параметр -l, запускаем $GEM_BROWSER"; fi

    # скорректируем все абсолютные ссылки для локальной навигации

    temp_path=$(pwd)

    mkdir -p ./preview

    cp -r ./$OUTPUT_DIR/* ./preview

    for filename in $(find ./preview -type f | grep gmi); do

        # awk в BSD, в отличие от GNU gawk не знает опции -i для инлайн-редактирования, 

        # поэтому трюк с временным файлом придется проделывать вручную

        awk '{gsub("=> /","=> '$(pwd)'/preview/",$0); print $0}' $filename > $filename.tmp

        mv $filename.tmp $filename

    done

    # запускаем браузер для просмотра

    $GEM_BROWSER "file:///$(pwd)/preview/index.gmi"

    # после просмотра удалим временные файлы

    rm -r ./preview

    exit 0

    ;;

-d) 

    if [ $DEBUG = 1 ]; then echo "Передан параметр -d, запускаем скрипт деплоя ./$DEPLOY_SCRIPT"; fi

    if [ ! -e ./$DEPLOY_SCRIPT ]; then 

        echo "Скрипт $DEPLOY_SCRIPT не найден в текущем каталоге!" 

        exit 1 

    else 

        /bin/sh -c "./$DEPLOY_SCRIPT"

        exit 0

    fi

    ;;

-n)

    # Проверяем, что указано имя файла для новой статьи

    if test -z "$2"; then echo "Не указано имя файла для новой статьи (без расширения .gmi)"; exit 1; fi

    # Проверяем, что нет такого файла

    if [ -e "./$CONTENT_DIR/$2.gmi" ]; then

        echo "Файл $2.gmi уже существует в $CONTENT_DIR!"

        exit 1

    fi

    if [ $DEBUG = 1 ]; then echo "Передан параметр -n, запускаем $GEM_EDITOR для $2.gmi"; fi

    # Создаем файл статьи и заполняем шаблон заголовка

    echo "# \n" >> "./$CONTENT_DIR/$2.gmi"

    echo "Опубликовано: $(date '+%Y-%m-%d')" >> "./$CONTENT_DIR/$2.gmi"

    echo "Категория: $DEFAULT_CATEGORY" >> "./$CONTENT_DIR/$2.gmi"

    echo "Теги: " >> "./$CONTENT_DIR/$2.gmi"

    echo "Статус: черновик (удалить для публикации)" >> "./$CONTENT_DIR/$2.gmi"

    $GEM_EDITOR "$CONTENT_DIR/$2.gmi"

    # если убрать exit в строке ниже, то после завершения редактирования проект будет пересобираться

    # автоматически, но я предпочитаю делать это вручную т.к. часто оставляю незавершенные черновики

    exit 0

    ;;

*) 

    if [ $DEBUG = 1 ]; then echo "Запуск без параметров: компилируем контент"; fi

    ;;

esac

Создадим каталог для вывода контента (если его нет)

mkdir -p "./$OUTPUT_DIR"

Очищаем OUTPUT_DIR (если он не пустой с прошлого запуска)

echo "Очищаем каталог $OUTPUT_DIR перед использованием..."

rm -r ./$OUTPUT_DIR

echo "Обрабатываем файлы из каталога $CONTENT_DIR..."

for CURRENT_FILE in ./$CONTENT_DIR/*; do

CURRENT_FILE=$(basename $CURRENT_FILE)

# Info-сообщение: какой файл обрабатываем

echo -n "Обрабатываем файл $CURRENT_FILE... "

# Проверяем, гипертекст в файле или другой контент, который нужно положить в папку статики

ext=$(echo $CURRENT_FILE | cut -d "." -f 2)

if [ $ext != "gmi" ]; then

    if [ $DEBUG = 1 ]; then 

        echo "\nФайл $CURRENT_FILE имеет расшиение = $ext, переносим как есть\n-----------------"; 

    else

        echo "скопирован."

    fi

    mkdir -p ./$OUTPUT_DIR/$STATIC_DIR

    cp ./$CONTENT_DIR/$CURRENT_FILE ./$OUTPUT_DIR/$STATIC_DIR

else

    if [ $DEBUG = 1 ]; then echo "\nФайл $CURRENT_FILE имеет расширение = $ext, парсим метаданные..."; fi

    # Определяем статус, если он = черновик, то пропускаем, иначе (иное или просто отсуствует) идем дальше

    if test ! -z "$(head ./$CONTENT_DIR/$CURRENT_FILE | grep "Статус: черновик")"; then 

        if [ $DEBUG = 1 ]; then 

            echo "Файл $CURRENT_FILE это черновик, пропускаем его.\n-----------------"

        else

            echo "черновик, пропущен."

        fi

    else 

        if [ $DEBUG = 1 ]; then echo "Файл $CURRENT_FILE НЕ является черновиком, продолжаем парсинг..."; fi

        # Ищем в файле дату-время публикации по мета DATE (если нет - берем текущее системное время), присваиваем 

        #       DATE_PUB - дата создания в формате YYYY-MM-DD, используется на главной странице

        #       YEAR = год из DATE_PUB, используется как имя каталога для хранения статьи

        #       MONTH = месяц из DATE_PUB, используется как имя подкаталога для хранения статьи

        if ! $(head ./$CONTENT_DIR/$CURRENT_FILE | grep "Опубликовано: " >/dev/null); then 

            if [ $DEBUG = 1 ]; then echo "Файл $CURRENT_FILE не содержит даты публикации, используем текущую"; fi

            DATE_PUB=$(date '+%Y-%m-%d')

            YEAR=$(echo $DATE_PUB | cut -c 1-4)

            MONTH=$(echo $DATE_PUB | cut -c 6-7)

        else 

            if [ $DEBUG = 1 ]; then echo "Файл $CURRENT_FILE содержит дату публикации, парсим дату"; fi

            DATE_PUB=$(head ./$CONTENT_DIR/$CURRENT_FILE | grep "Опубликовано: " | cut -c 15-24)

            YEAR=$(echo $DATE_PUB | cut -c 1-4)

            MONTH=$(echo $DATE_PUB | cut -c 6-7)

        fi

        # Определяем категорию публикации, при отсутствии таковой используем дефолт = Blog

        if ! $(head ./$CONTENT_DIR/$CURRENT_FILE | grep "Категория: " >/dev/null); then 

            if [ $DEBUG = 1 ]; then echo "Файл $CURRENT_FILE не содержит категории, используем ($DEFAULT_CATEGORY)"; fi 

            CATEGORY=$DEFAULT_CATEGORY

        else 

            if [ $DEBUG = 1 ]; then echo "Файл $CURRENT_FILE содержит категорию, обрабатываем"; fi

            CATEGORY=$(head ./$CONTENT_DIR/$CURRENT_FILE | grep "Категория: " | cut -d ":" -f 2 | cut -c 2- | tr -d ' ')

        fi

        # Определяем тему публикации как первый заголовок любого уровня (символы заголовка и пробел после них уберем)

        TITLE=$(grep -m 1 "#" ./$CONTENT_DIR/$CURRENT_FILE | sed 's/#//' | cut -c 2-)

        # Определяем теги публикации по мета TAGS = , при отсутствии = ""

        TAGS=$(head ./$CONTENT_DIR/$CURRENT_FILE | grep "Теги: " | cut -d ":" -f 2) 

        # Вывод результатов парсинга в режиме отладки

        if [ $DEBUG = 1 ]; then

            echo "Файл $CURRENT_FILE, результаты парсинга:"

            echo "    DATE_PUB = $DATE_PUB"

            echo "    YEAR = $YEAR"

            echo "    MONTH = $MONTH"

            echo "    CATEGORY = $CATEGORY"

            echo "    TITLE = $TITLE"

            echo "    TAGS = $TAGS"

            echo "-----------------"

        else

            echo "обработан."

        fi

        # Создаем (если не существуют) каталоги для года/месяца

        mkdir -p "./$OUTPUT_DIR/$YEAR/$MONTH"

        # и копируем туда текущий файл

        cp "./$CONTENT_DIR/$CURRENT_FILE" "./$OUTPUT_DIR/$YEAR/$MONTH"

        # пишем линк для текущего файла в помесячный интекс

        echo "=> /$YEAR/$MONTH/$CURRENT_FILE $DATE_PUB - $TITLE" >> ./$OUTPUT_DIR/$YEAR/$MONTH/index.gmi

        # и сортируем индекс-файл по дате статьи

        sort -k3,3r ./$OUTPUT_DIR/$YEAR/$MONTH/index.gmi -o ./$OUTPUT_DIR/$YEAR/$MONTH/index.gmi

        # теперь выводим то же самое в файл категорий, для которы создадим каталог

        mkdir -p ./$OUTPUT_DIR/Categories

        echo "=> /$YEAR/$MONTH/$CURRENT_FILE $DATE_PUB - $TITLE" >> ./$OUTPUT_DIR/Categories/$CATEGORY.gmi

        # в файле данной категории тоже отсортируем записи по дате

        sort -k3,3r ./$OUTPUT_DIR/Categories/$CATEGORY.gmi -o ./$OUTPUT_DIR/Categories/$CATEGORY.gmi

        # теперь в то же самое для тегов (для каждого создадим свой файл)

        mkdir -p ./$OUTPUT_DIR/Tags

        # если, конечно, для обрабатываемого файла список тегов вообще не пуст

        if test "! -z $TAGS"; then

            for current_tag in $TAGS; do 

                echo "=> /$YEAR/$MONTH/$CURRENT_FILE $DATE_PUB - $TITLE" >> ./$OUTPUT_DIR/Tags/$current_tag.gmi

                sort -k3,3r ./$OUTPUT_DIR/Tags/$current_tag.gmi -o ./$OUTPUT_DIR/Tags/$current_tag.gmi

            done

        fi

    # Конец условия, где мы проверяли, что это НЕ черновик

    fi

# Конец условия, где мы определяли это файл .gmi и его нужно парсить

fi

Конец цикла обработки файлов из папки с контентом

done

теперь дополним страницы с тегами

for cur_file in ./$OUTPUT_DIR/Tags/*; do

sed -i '1i\

'"$GEMLOG_NAME"'

' $cur_file

sed -i '2i\

'"$GEMLOG_SUMMARY"'\

\

' $cur_file

sed -i '3i\

\

Все записи с тегом: '"$(basename $cur_file | cut -d . -f 1)"'\

' $cur_file

echo "\n=> /Tags/index.gmi К списку тегов" >> $cur_file

echo "=> /index.gmi На главную" >> $cur_file

echo "\n$GEMLOG_FOOTER" >> $cur_file

done

Создадим страницу со списком всех тегов

echo "$GEMLOG_NAME" >> ./$OUTPUT_DIR/Tags/index.gmi

echo "$GEMLOG_SUMMARY\n" >> ./$OUTPUT_DIR/Tags/index.gmi

echo "## Список тегов:\n" >> ./$OUTPUT_DIR/Tags/index.gmi

for cur_file in ./$OUTPUT_DIR/Tags/*; do

if [ $cur_file != "./output/Tags/index.gmi" ]; then

    echo "=> /Tags/$(basename $cur_file) $(basename $cur_file | cut -d . -f 1)" >> ./$OUTPUT_DIR/Tags/index.gmi

fi

done

echo "\n=> /index.gmi На главную\n" >> ./$OUTPUT_DIR/Tags/index.gmi

echo "$GEMLOG_FOOTER" >> ./$OUTPUT_DIR/Tags/index.gmi

Дополним страницы категорий

for cur_file in ./$OUTPUT_DIR/Categories/*; do

sed в BSD не умеет в нотацию /n для перевода строки, в отличие от GNU sed

sed -i '1i\

'"$GEMLOG_NAME"'

' $cur_file

sed -i '2i\

'"$GEMLOG_SUMMARY"'\

\

' $cur_file

sed -i '3i\

\

Все записи в категории: '"$(basename $cur_file | cut -d . -f 1)"'\

' $cur_file

echo "\n=> /Categories/index.gmi К списку категорий" >> $cur_file

echo "=> /index.gmi На главную" >> $cur_file

echo "\n$GEMLOG_FOOTER" >> $cur_file

done

Создадим страницу со списком всех категорий

echo "$GEMLOG_NAME" >> ./$OUTPUT_DIR/Categories/index.gmi

echo "$GEMLOG_SUMMARY\n" >> ./$OUTPUT_DIR/Categories/index.gmi

echo "## Категории:\n" >> ./$OUTPUT_DIR/Categories/index.gmi

for cur_file in ./$OUTPUT_DIR/Categories/*; do

if [ $cur_file != "./output/Categories/index.gmi" ]; then

    echo "=> /Categories/$(basename $cur_file) $(basename $cur_file | cut -d . -f 1)" >> ./$OUTPUT_DIR/Categories/index.gmi

fi

done

echo "\n=> /index.gmi На главную\n" >> ./$OUTPUT_DIR/Categories/index.gmi

echo "$GEMLOG_FOOTER" >> ./$OUTPUT_DIR/Categories/index.gmi

Наконец создадим главную страницу

echo "$GEMLOG_NAME" >> ./$OUTPUT_DIR/index.gmi

echo "$GEMLOG_SUMMARY\n" >> ./$OUTPUT_DIR/index.gmi

echo "=> /Categories/index.gmi Поиск по категориям" >> ./$OUTPUT_DIR/index.gmi

echo "=> /Tags/index.gmi Поиск по тегам\n" >> ./$OUTPUT_DIR/index.gmi

for year_dir in $(ls -r ./$OUTPUT_DIR); do

year_dir=$(basename $year_dir)

# если текущий каталог не в списке специальных каталогов 1 уровня

if ! $(echo "Categories Tags static index.gmi" | grep -w -q "$year_dir"); then 

    echo "## $year_dir\n" >> ./$OUTPUT_DIR/index.gmi

    for month_dir in $(ls -r ./$OUTPUT_DIR/$year_dir); do

        month_dir=$(basename $month_dir)

        # в общем случае, локализованное название месяца может выдать команда date, но увы, это не

        # про OpenBSD, где все локали повыпиливали за неимением ресурсов на поддержку и date собрана без них

        case "$month_dir" in

            "12") month_name="Декабрь" ;;

            "11") month_name="Ноябрь" ;;

            "10") month_name="Октябрь" ;;

            "09") month_name="Сентябрь" ;;

            "08") month_name="Август" ;;

            "07") month_name="Июль" ;;

            "06") month_name="Июнь" ;;

            "05") month_name="Май" ;;

            "04") month_name="Апрель" ;;

            "03") month_name="Март" ;;

            "02") month_name="Февраль" ;;

            "01") month_name="Январь" ;;

        esac

        echo "### $month_name \n" >> ./$OUTPUT_DIR/index.gmi

        cat ./$OUTPUT_DIR/$year_dir/$month_dir/index.gmi >> ./$OUTPUT_DIR/index.gmi

        echo "" >> ./$OUTPUT_DIR/index.gmi

    done

fi

done

echo "$GEMLOG_FOOTER" >> ./$OUTPUT_DIR/index.gmi

Создадим файл /robots.txt - исключим из него каталоги Categories и Tags

echo "User-agent: *\nDisallow: /Categories\nDisallow: /Tags\n" >> ./$OUTPUT_DIR/robots.txt

Закончили все задачи

echo "Готово! Контент для гемлога размещен в каталоге $OUTPUT_DIR."

Proxy Information
Original URL
gemini://muu-online.ru/static/gemican.txt
Status Code
Success (20)
Meta
text/plain
Capsule Response Time
7355.289292 milliseconds
Gemini-to-HTML Time
5.004311 milliseconds

This content has been proxied by September (ba2dc).