bench/gen.py (4988B)
1 #!/usr/bin/env python3
2 """ssg 벤치마크 코퍼스 생성기. 본문 마크다운은 도구 간 바이트 동일, front matter 형식만 다르다."""
3 import os, shutil, subprocess, sys
4
5 S = os.path.dirname(os.path.abspath(__file__))
6 N = 1000
7 PARA = "The quick brown fox jumps over the lazy dog while the build system watches. " * 4
8
9 def code_block(page, blk, unique):
10 tag = f"page{page}_blk{blk}_" if unique else ""
11 lines = "\n".join(
12 f"fn {tag}handler_{j}(req: Request) -> Response {{ Response::ok(req.body_{tag}{j}()) }}"
13 for j in range(20)
14 )
15 return f"```rust\n{lines}\n```"
16
17 def body(scenario, i):
18 if scenario == "minimal":
19 return f"# Post {i}\n\n{PARA}\n"
20 if scenario == "blog":
21 nxt = f"/posts/post-{(i + 1) % N}/"
22 return (f"# Post {i}\n\n" + "\n\n".join([PARA] * 6)
23 + f"\n\n- one\n- two\n- three\n\n> quote block\n\n[next]({nxt})\n")
24 unique = scenario == "heavyu"
25 parts = [f"# Post {i}"]
26 for b in range(5):
27 parts.append(PARA)
28 parts.append(code_block(i, b, unique))
29 return "\n\n".join(parts) + "\n"
30
31 def w(path, content):
32 os.makedirs(os.path.dirname(path), exist_ok=True)
33 with open(path, "w") as f:
34 f.write(content)
35
36 SCENARIOS = ["minimal", "blog", "heavyr", "heavyu"]
37 SQZASS = os.environ.get("SQZASS", "target/release/sqzass")
38
39 for sc in SCENARIOS:
40 # --- sqzass: init 스캐폴드 + TOML +++ front matter
41 d = f"{S}/sqzass/{sc}"
42 if not os.path.exists(d):
43 subprocess.run([SQZASS, "init", d], check=True, capture_output=True)
44 w(f"{d}/content/posts/_index.md", '+++\ntitle = "posts"\n+++\n')
45 for i in range(N):
46 w(f"{d}/content/posts/post-{i}.md", f'+++\ntitle = "Post {i}"\n+++\n\n{body(sc, i)}')
47
48 # --- hugo: TOML +++ front matter (동일 형식)
49 d = f"{S}/hugo/{sc}"
50 w(f"{d}/hugo.toml", 'baseURL = "https://example.com/"\ntitle = "bench"\n')
51 w(f"{d}/layouts/_default/single.html",
52 "<!doctype html><html><head><meta charset=\"utf-8\"><title>{{ .Title }}</title></head>"
53 "<body><main>{{ .Content }}</main></body></html>\n")
54 w(f"{d}/layouts/_default/list.html",
55 "<!doctype html><html><head><meta charset=\"utf-8\"><title>{{ .Title }}</title></head>"
56 "<body><main>{{ range .Pages }}<a href=\"{{ .RelPermalink }}\">{{ .Title }}</a> {{ end }}</main></body></html>\n")
57 for i in range(N):
58 w(f"{d}/content/posts/post-{i}.md", f'+++\ntitle = "Post {i}"\n+++\n\n{body(sc, i)}')
59
60 # --- zola: TOML +++ front matter, highlight_code 명시적 활성화(기본 꺼짐)
61 d = f"{S}/zola/{sc}"
62 w(f"{d}/config.toml",
63 'base_url = "https://example.com"\ntitle = "bench"\ncompile_sass = false\n'
64 'build_search_index = false\n\n[markdown.highlighting]\ntheme = "github-dark"\n')
65 w(f"{d}/templates/index.html",
66 "<!doctype html><html><head><meta charset=\"utf-8\"><title>bench</title></head><body><main>index</main></body></html>\n")
67 w(f"{d}/templates/page.html",
68 "<!doctype html><html><head><meta charset=\"utf-8\"><title>{{ page.title }}</title></head>"
69 "<body><main>{{ page.content | safe }}</main></body></html>\n")
70 w(f"{d}/templates/section.html",
71 "<!doctype html><html><head><meta charset=\"utf-8\"><title>{{ section.title }}</title></head>"
72 "<body><main>{% for p in section.pages %}<a href=\"{{ p.permalink }}\">{{ p.title }}</a> {% endfor %}</main></body></html>\n")
73 w(f"{d}/content/posts/_index.md", '+++\ntitle = "posts"\n+++\n')
74 for i in range(N):
75 w(f"{d}/content/posts/post-{i}.md", f'+++\ntitle = "Post {i}"\n+++\n\n{body(sc, i)}')
76
77 # --- jekyll: YAML --- front matter
78 d = f"{S}/jekyll/{sc}"
79 w(f"{d}/_config.yml",
80 'title: bench\ndefaults:\n - scope: { path: "" }\n values: { layout: default }\n')
81 w(f"{d}/_layouts/default.html",
82 "<!doctype html><html><head><meta charset=\"utf-8\"><title>{{ page.title }}</title></head>"
83 "<body><main>{{ content }}</main></body></html>\n")
84 for i in range(N):
85 w(f"{d}/posts/post-{i}.md", f'---\ntitle: "Post {i}"\n---\n\n{body(sc, i)}')
86
87 # --- astro: YAML front matter + layout 지정, node_modules는 공용 심링크
88 d = f"{S}/astro/{sc}"
89 os.makedirs(d, exist_ok=True)
90 shutil.copy(f"{S}/astro-base/package.json", f"{d}/package.json")
91 w(f"{d}/astro.config.mjs", "export default { cacheDir: './.astro-cache' };\n")
92 if not os.path.islink(f"{d}/node_modules"):
93 os.symlink(f"{S}/astro-base/node_modules", f"{d}/node_modules")
94 w(f"{d}/src/layouts/Base.astro",
95 "---\nconst { frontmatter } = Astro.props;\n---\n"
96 "<!doctype html><html><head><meta charset=\"utf-8\"><title>{frontmatter.title}</title></head>"
97 "<body><main><slot /></main></body></html>\n")
98 for i in range(N):
99 w(f"{d}/src/pages/posts/post-{i}.md",
100 f'---\nlayout: ../../layouts/Base.astro\ntitle: "Post {i}"\n---\n\n{body(sc, i)}')
101
102 print("corpora ready:", ", ".join(SCENARIOS))