#!/usr/bin/env python3 """主题生成器的本地预览服务。 为什么必须起服务:生成器不再自己画一个"仿制页面",而是把项目真实渲染出来的 页面(outputs/preview-*.html)放进 iframe 当画板,再往里注入正在编辑的主题 CSS。 file:// 下浏览器不允许父页面访问 iframe 的 DOM(即使同目录),预览就只能退回示意图。 起一个本地 HTTP 服务后父子同源,拖拽、注入、实时改令牌都能正常工作。 用法(在项目根目录执行任意一种): python dev/theme-builder/serve.py python -m http.server 8777 然后打开 http://localhost:8777/dev/theme-builder/ 这个脚本只读文件,不写任何东西,也不改项目配置。 """ import argparse import functools import http.server import os import socketserver import sys # dev/theme-builder/serve.py → 上两级就是项目根 PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) class Handler(http.server.SimpleHTTPRequestHandler): def end_headers(self): # 预览页是刚由 go test 生成的,禁止缓存,否则改了 CSS 看不到变化 self.send_header("Cache-Control", "no-store, must-revalidate") super().end_headers() def log_message(self, fmt, *args): # 只报 4xx/5xx,正常请求不刷屏 status = args[1] if len(args) > 1 else "" if str(status).startswith(("4", "5")): sys.stderr.write(" %s\n" % (fmt % args)) def main(): ap = argparse.ArgumentParser(description="TamaBox 主题生成器的本地预览服务") ap.add_argument("--port", type=int, default=8777, help="端口,默认 8777") ap.add_argument("--host", default="127.0.0.1", help="监听地址,默认 127.0.0.1") args = ap.parse_args() if not os.path.isdir(os.path.join(PROJECT_ROOT, "outputs")): sys.stderr.write( "还没生成预览快照。先在项目根执行:\n" " TEST_PREVIEW=1 go test ./templates -run TestGenPreview\n" ) handler = functools.partial(Handler, directory=PROJECT_ROOT) socketserver.TCPServer.allow_reuse_address = True with socketserver.TCPServer((args.host, args.port), handler) as httpd: url = "http://%s:%d/dev/theme-builder/" % (args.host, args.port) print("项目根:%s" % PROJECT_ROOT) print("生成器:%s" % url) print("Ctrl+C 停止") try: httpd.serve_forever() except KeyboardInterrupt: print("\n已停止") if __name__ == "__main__": main()