feat: 가상화 문서들 추가
This commit is contained in:
Executable
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""그림을 PNG 로 떠서 눈으로 볼 수 있게 만든다.
|
||||
|
||||
lint 는 엣지가 노드를 지나가는 것은 잡지만 **라벨이 상자를 덮는 것**은 못 잡는다.
|
||||
라벨 폭을 재지 않고 앵커 점만 보기 때문이다. 그래서 컴파일한 뒤 한 번은 봐야 한다.
|
||||
|
||||
python3 scripts/preview-figure.py <프로젝트> # 그 프로젝트의 그림 전부
|
||||
python3 scripts/preview-figure.py --file 그림.svg
|
||||
python3 scripts/preview-figure.py <프로젝트> -o /tmp/png
|
||||
|
||||
Chrome 을 headless 로 띄워 SVG 를 그대로 찍는다. 경로가 다르면 CHROME 으로 알려 준다.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
SIZE = re.compile(r'width="(\d+)"\s+height="(\d+)"')
|
||||
|
||||
|
||||
def chrome() -> str:
|
||||
found = os.environ.get("CHROME") or shutil.which("google-chrome") \
|
||||
or shutil.which("chromium") or shutil.which("chromium-browser")
|
||||
if not found:
|
||||
sys.exit("Chrome 을 찾지 못했다. CHROME 으로 경로를 알려 준다.")
|
||||
return found
|
||||
|
||||
|
||||
def shoot(svg: str, out_dir: str, binary: str) -> str:
|
||||
body = open(svg, encoding="utf-8").read()
|
||||
m = SIZE.search(body)
|
||||
w, h = (int(m.group(1)), int(m.group(2))) if m else (1200, 800)
|
||||
name = os.path.basename(svg)[:-4]
|
||||
png = os.path.join(out_dir, f"{name}.png")
|
||||
with tempfile.NamedTemporaryFile("w", suffix=".html", delete=False,
|
||||
encoding="utf-8") as fh:
|
||||
fh.write("<style>html,body{margin:0;padding:0;background:#fff}"
|
||||
"img{display:block}</style>\n"
|
||||
f'<img src="file://{os.path.abspath(svg)}" width="{w}" height="{h}">')
|
||||
wrapper = fh.name
|
||||
try:
|
||||
subprocess.run([binary, "--headless", "--disable-gpu", "--no-sandbox",
|
||||
"--hide-scrollbars", f"--screenshot={png}",
|
||||
f"--window-size={w + 20},{h + 20}", f"file://{wrapper}"],
|
||||
check=True, capture_output=True)
|
||||
finally:
|
||||
os.unlink(wrapper)
|
||||
return png
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(description="그림을 PNG 로 떠서 눈으로 본다.")
|
||||
ap.add_argument("projects", nargs="*")
|
||||
ap.add_argument("--file", action="append", default=[])
|
||||
ap.add_argument("-o", "--out", default=None, help="PNG 를 둘 곳 (기본: 임시 폴더)")
|
||||
args = ap.parse_args()
|
||||
|
||||
targets = list(args.file)
|
||||
for project in args.projects:
|
||||
targets.extend(sorted(glob.glob(
|
||||
os.path.join(ROOT, "docs", project, "final", "assets", "**", "*.svg"),
|
||||
recursive=True)))
|
||||
if not targets:
|
||||
sys.exit("볼 그림을 주지 않았다.")
|
||||
|
||||
out_dir = args.out or tempfile.mkdtemp(prefix="figure-preview-")
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
binary = chrome()
|
||||
for svg in targets:
|
||||
print(shoot(svg, out_dir, binary))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user