[UPDATE] интеграция: безопасные маунты, кэш в tmpdir, только .tex/.pdf

This commit is contained in:
Arseny
2026-07-16 08:20:35 +03:00
parent 3a1acafc24
commit 08fc5d9aaa
4 changed files with 97 additions and 24 deletions
+1
View File
@@ -16,3 +16,4 @@ build/
# Report # Report
report.md report.md
output/
+4 -3
View File
@@ -20,8 +20,9 @@ RUN cd /tmp && \
fc-cache -f && \ fc-cache -f && \
rm -f /tmp/*.TTF /tmp/times32.exe rm -f /tmp/*.TTF /tmp/times32.exe
WORKDIR /app WORKDIR /build
COPY . . COPY . .
RUN uv sync --frozen --no-dev RUN uv pip install --system --no-cache .
ENTRYPOINT ["uv", "run", "--no-dev", "md2gost"] ENV UV_CACHE_DIR=/tmp/uv-cache
ENTRYPOINT ["md2gost"]
+59 -4
View File
@@ -4,12 +4,67 @@ set -euo pipefail
IMAGE="md2gost" IMAGE="md2gost"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
usage() {
echo "Использование: md2gost file.md [-o dir]"
echo " file.md — исходный Markdown-файл"
echo " -o dir — выходная директория (по умолчанию ./build)"
exit 1
}
# Парсим аргументы
INPUT_FILE=""
OUTPUT_DIR="./build"
while [[ $# -gt 0 ]]; do
case "$1" in
-o)
OUTPUT_DIR="${2:-}"
[[ -z "$OUTPUT_DIR" ]] && usage
shift 2
;;
-h|--help)
usage
;;
-*)
echo "неизвестный флаг: $1" >&2
usage
;;
*)
INPUT_FILE="$1"
shift
;;
esac
done
[[ -z "$INPUT_FILE" ]] && usage
# Проверяем входной файл
if [[ ! -f "$INPUT_FILE" ]]; then
echo "ошибка: $INPUT_FILE не найден" >&2
exit 1
fi
# Абсолютные пути
INPUT_ABS="$(realpath "$INPUT_FILE")"
OUTPUT_ABS="$(realpath -m "$OUTPUT_DIR")"
mkdir -p "$OUTPUT_ABS"
INPUT_BASE="$(basename "$INPUT_FILE")"
# Собираем образ если нужно
if ! docker image inspect "$IMAGE" &>/dev/null; then if ! docker image inspect "$IMAGE" &>/dev/null; then
echo " образ $IMAGE не найден, собираю..." echo "образ $IMAGE не найден, собираю..."
docker build -t "$IMAGE" "$SCRIPT_DIR" docker build -t "$IMAGE" "$SCRIPT_DIR"
fi fi
echo "→ конвертация $INPUT_FILE$OUTPUT_DIR/"
# Запуск контейнера:
# - вход: только .md файл (read-only)
# - выход: директория для .tex и .pdf
# - user: текущий пользователь (не root)
docker run --rm \ docker run --rm \
-e UV_CACHE_DIR=/tmp/uv-cache \ -v "$INPUT_ABS:/input/$INPUT_BASE:ro" \
-v "$(pwd):/app" \ -v "$OUTPUT_ABS:/output" \
"$IMAGE" "$@" --user "$(id -u):$(id -g)" \
"$IMAGE" "/input/$INPUT_BASE" -o /output
+24 -8
View File
@@ -1,6 +1,8 @@
import argparse import argparse
import shutil
import subprocess import subprocess
import sys import sys
import tempfile
from pathlib import Path from pathlib import Path
from md2gost.parser import Parser from md2gost.parser import Parser
@@ -44,27 +46,41 @@ def main():
renderer = Renderer(parser.tokens, parser.front_matter) renderer = Renderer(parser.tokens, parser.front_matter)
latex = renderer.render() latex = renderer.render()
tex_path = args.output / args.input.with_suffix(".tex").name # Собираем во временную директорию, копируем только .tex и .pdf
with tempfile.TemporaryDirectory(prefix="md2gost-") as cache:
cache_dir = Path(cache)
# Генерируем .tex в кэш
tex_name = args.input.with_suffix(".tex").name
tex_path = cache_dir / tex_name
tex_path.write_text(latex, encoding="utf-8") tex_path.write_text(latex, encoding="utf-8")
print(f"{tex_path}")
# Копируем .tex в выходную директорию
final_tex = args.output / tex_name
shutil.copy2(tex_path, final_tex)
print(f"{final_tex}")
if not args.no_pdf: if not args.no_pdf:
pdf_path = args.output / args.input.with_suffix(".pdf").name # Компилируем PDF в кэше (два прохода для TOC)
log_path = args.output / "report.log" if not run_xelatex(tex_path, cache_dir):
if not run_xelatex(tex_path, args.output):
print("ошибка: xelatex не собрал PDF", file=sys.stderr) print("ошибка: xelatex не собрал PDF", file=sys.stderr)
log_path = cache_dir / "report.log"
if log_path.exists(): if log_path.exists():
for line in log_path.read_text(errors="replace").splitlines(): for line in log_path.read_text(errors="replace").splitlines():
if line.startswith("!"): if line.startswith("!"):
print(f" {line}", file=sys.stderr) print(f" {line}", file=sys.stderr)
sys.exit(1) sys.exit(1)
if not run_xelatex(tex_path, args.output): if not run_xelatex(tex_path, cache_dir):
print("ошибка: xelatex (2-й проход) не собрал PDF", file=sys.stderr) print("ошибка: xelatex (2-й проход) не собрал PDF", file=sys.stderr)
sys.exit(1) sys.exit(1)
print(f"{pdf_path}") # Копируем .pdf в выходную директорию
pdf_name = args.input.with_suffix(".pdf").name
pdf_path = cache_dir / pdf_name
final_pdf = args.output / pdf_name
shutil.copy2(pdf_path, final_pdf)
print(f"{final_pdf}")
if __name__ == "__main__": if __name__ == "__main__":