feat: добавить build_all.command — сборка всех форматов разом

Три PDF (default, ebook, phone) + EPUB3 (pandoc) + MOBI/FB2 (ebook-convert из EPUB).
Проверка зависимостей, отчёт по шагам, exit code = число ошибок.
This commit is contained in:
2026-08-13 16:51:22 +03:00
parent 6c25c54e03
commit 735cff4a01
2 changed files with 116 additions and 0 deletions

View File

@@ -161,6 +161,8 @@ python3 scripts/build_book_pdf.py --source book --output BlackboxBook.pdf
`./build_pdf_phone.command` собирает phone-версию с узкой страницей для чтения на смартфоне без зума.
`./build_all.command` собирает всё разом: три PDF-варианта (default, ebook, phone) + EPUB3 (pandoc) + MOBI и FB2 (ebook-convert из EPUB).
Скрипт сборки работает с временной копией файлов, но исходные Markdown-файлы в `book/` должны оставаться человекочитаемыми и содержать исходные Unicode-символы. PDF собирается через `xelatex` с fallback-шрифтами для символов и математики; перед сборкой полезно прогонять `scripts/validate_book_format.py`.
---

114
build_all.command Executable file
View File

@@ -0,0 +1,114 @@
#!/bin/bash
set -u
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR" || exit 1
PDF_DEFAULT="$SCRIPT_DIR/BlackboxBook.pdf"
PDF_EBOOK="$SCRIPT_DIR/BlackboxBook_ebook.pdf"
PDF_PHONE="$SCRIPT_DIR/BlackboxBook_phone.pdf"
EPUB="$SCRIPT_DIR/BlackboxBook.epub"
MOBI="$SCRIPT_DIR/BlackboxBook.mobi"
FB2="$SCRIPT_DIR/BlackboxBook.fb2"
failures=0
report_step() {
if [ $1 -eq 0 ]; then
printf " ✓ %s\n" "$2"
else
printf " ✗ %s\n" "$2"
failures=$((failures + 1))
fi
}
require_tool() {
if ! command -v "$1" >/dev/null 2>&1; then
printf "ERROR: %s was not found in PATH.\n" "$1"
failures=$((failures + 1))
return 1
fi
return 0
}
printf "Building all formats...\n\n"
printf "[1/6] PDF (A4, default)\n"
require_tool python3 || true
if command -v python3 >/dev/null 2>&1; then
python3 "$SCRIPT_DIR/scripts/build_book_pdf.py" --source "$SCRIPT_DIR/book" --output "$PDF_DEFAULT"
report_step $? "$PDF_DEFAULT"
fi
printf "\n[2/6] PDF (ebook, 6x8in)\n"
python3 "$SCRIPT_DIR/scripts/build_book_pdf.py" \
--source "$SCRIPT_DIR/book" \
--output "$PDF_EBOOK" \
--layout-profile ebook \
--page-width 6in \
--page-height 8in \
--margin 0.35in \
--wrap-code-blocks \
--code-font-size footnotesize
report_step $? "$PDF_EBOOK"
printf "\n[3/6] PDF (phone, 4.1x9.1in)\n"
python3 "$SCRIPT_DIR/scripts/build_book_pdf.py" \
--source "$SCRIPT_DIR/book" \
--output "$PDF_PHONE" \
--layout-profile phone \
--page-width 4.1in \
--page-height 9.1in \
--margin 0.22in \
--wrap-code-blocks \
--code-font-size footnotesize
report_step $? "$PDF_PHONE"
printf "\n[4/6] EPUB3\n"
require_tool pandoc || true
if command -v pandoc >/dev/null 2>&1; then
pandoc "$SCRIPT_DIR"/book/*.md \
--resource-path="$SCRIPT_DIR/book" \
--standalone \
--toc --toc-depth=2 \
--metadata title="От чёрного ящика к инженерии" \
--metadata author="Руководство по механике LLM" \
--metadata lang=ru \
--metadata date="2026" \
--to epub3 \
-o "$EPUB"
report_step $? "$EPUB"
fi
printf "\n[5/6] MOBI (из EPUB)\n"
require_tool ebook-convert || true
if command -v ebook-convert >/dev/null 2>&1; then
ebook-convert "$EPUB" "$MOBI" >/dev/null 2>&1
report_step $? "$MOBI"
fi
printf "\n[6/6] FB2 (из EPUB)\n"
if command -v ebook-convert >/dev/null 2>&1; then
ebook-convert "$EPUB" "$FB2" >/dev/null 2>&1
report_step $? "$FB2"
fi
printf "\n---\n"
if [ "$failures" -eq 0 ]; then
printf "Все форматы собраны:\n"
for f in "$PDF_DEFAULT" "$PDF_EBOOK" "$PDF_PHONE" "$EPUB" "$MOBI" "$FB2"; do
if [ -f "$f" ]; then
printf " %s (%s)\n" "$(basename "$f")" "$(du -h "$f" | cut -f1)"
fi
done
else
printf "Сборка завершилась с %s ошибкой(ами).\n" "$failures"
fi
if [ -t 0 ]; then
printf "\nPress Enter to close..."
read -r _
fi
exit "$failures"