Files
stack/design-refs/mockup/build.sh

82 lines
3.5 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 设计稿构建:把整页 HTML 按顶层 .page 拆成单页 → html2poster 逐页渲染 → 合并为 PDF
# 用法:bash build.sh [src ...] # src 为相对 mockup 的 html 路径(如 components.html 或 design-system/01-colors.html)
# 默认:历史 mockup(course-shelf/components/color-system)+ design-system 四部分文档
set -euo pipefail
cd "$(dirname "$0")"
PDF_SKILL_DIR="${PDF_SKILL_DIR:-$HOME/.zcode/cli/plugins/cache/zcode-plugins-official/pdf/0.1.7/skills/pdf}"
export PDF_SKILL_DIR
# 本地渲染器(固定 headless-shell 规避系统 Chrome 占用;TMPDIR 重定向规避 /tmp 磁盘配额)
HTML2POSTER="$PWD/tools/html2poster.js"
H2P_CHROMIUM="${H2P_CHROMIUM:-$HOME/.cache/ms-playwright/chromium_headless_shell-1234/chrome-headless-shell-linux64/chrome-headless-shell}"
export HTML2POSTER H2P_CHROMIUM
mkdir -p "$HOME/.cache/h2p-tmp"
export TMPDIR="$HOME/.cache/h2p-tmp"
# build_one <src.html> <out.pdf>
build_one() {
local SRC="$1" PDF_OUT="$2"
local STEM; STEM=$(basename "${SRC%.html}")
local OUT_DIR="single-${STEM}"
mkdir -p "$OUT_DIR" "$(dirname "$PDF_OUT")"
# 1. 按顶层 .page 拆单页(固定布局必须走 html2poster,不能用 html2pdf-next)
python3 - "$SRC" "$OUT_DIR" <<'EOF'
import re, sys
src, out_dir = sys.argv[1], sys.argv[2]
html = open(src, encoding="utf-8").read()
head, rest = html.split("<body>", 1)
body_inner = rest.rsplit("</body>", 1)[0]
pat = re.compile(r'(?=<div class="page(?: cover)?">)')
chunks = [c for c in pat.split(body_inner) if c.lstrip().startswith('<div class="page')]
for i, page_html in enumerate(chunks, 1):
page_html = re.sub(r'<!-- =+[^>]+-->\s*$', '', page_html.rstrip()) + "\n"
page_html = page_html.replace("page-break-after: always;", "page-break-after: auto;")
open(f"{out_dir}/page-{i}.html", "w", encoding="utf-8").write(head + "<body>\n" + page_html + "</body>\n</html>\n")
print(f"[{src}] split {len(chunks)} pages")
EOF
# 2. 单页素材(img 相对路径以单页目录为基准)
[ -d assets ] && cp -r assets "$OUT_DIR/assets"
# 3. 逐页渲染
python3 - "$OUT_DIR" <<'EOF'
import glob, os, re, subprocess, sys
out_dir = sys.argv[1]
pages = sorted(glob.glob(f"{out_dir}/page-*.html"), key=lambda p: int(re.search(r"(\d+)", os.path.basename(p)).group(1)))
for p in pages:
out = p.replace(".html", ".pdf")
subprocess.run(["node", os.environ['HTML2POSTER'], p, "--output", out, "--width", "1280px"], check=True, capture_output=True)
print(f"[{out_dir}] rendered {len(pages)} pages")
EOF
# 4. 合并 + 元数据(只取第 1 页:Chromium 打印偶发产生一个空白尾页)
python3 - "$OUT_DIR" "$PDF_OUT" <<'EOF'
import glob, os, re, sys
from pypdf import PdfWriter
out_dir, pdf_out = sys.argv[1], sys.argv[2]
pdfs = sorted(glob.glob(f"{out_dir}/page-*.pdf"), key=lambda p: int(re.search(r"(\d+)", os.path.basename(p)).group(1)))
w = PdfWriter()
for p in pdfs:
w.append(p, pages=(0, 1))
w.add_metadata({"/Title": f"设计系统 · {os.path.splitext(os.path.basename(pdf_out))[0]} · stack idealjs", "/Author": "Z.ai", "/Creator": "Z.ai"})
with open(pdf_out, "wb") as f:
w.write(f)
print(f"merged {len(pdfs)} pages -> {pdf_out}")
EOF
echo "done: $PDF_OUT"
}
SRCS=("$@")
if [ ${#SRCS[@]} -eq 0 ]; then
SRCS=(course-shelf.html components.html color-system.html design-system/01-colors.html design-system/02-symbols.html design-system/03-components.html design-system/04-examples.html)
fi
for SRC in "${SRCS[@]}"; do
[ -f "$SRC" ] || { echo "!! 缺少 $SRC,跳过"; continue; }
build_one "$SRC" "${SRC%.html}.pdf"
done