refactor: restructure mytoolkit with new subcommands and md-to-pdf improvements

- Add new subcommands: convert, preflight, server, templates, webpage
- Migrate config from bin/config.json to ~/.config/mytoolkit
- Fix expand_bookmarks to modify writer objects instead of reader
- Improve md_to_pdf with CJK bookmark support
- Update README and project metadata
This commit is contained in:
Zhengshou Lai
2026-05-04 17:19:32 +08:00
parent 38328c28d0
commit 3e4cf618a8
20 changed files with 1846 additions and 214 deletions
+53
View File
@@ -1,10 +1,14 @@
"""Image utilities."""
import base64
import os
import subprocess
import urllib.request
from pathlib import Path
import click
from bin.config import config
from bin.utils import handle_errors, run_command
@@ -181,3 +185,52 @@ def compress_images(files, target_mb, max_width, quality, suffix, dry_run):
size_mb = output.stat().st_size / (1024 * 1024)
click.echo(f"Compressed: {img_file} -> {output} ({size_mb:.2f} MB)")
@image.command("generate")
@click.argument("prompt", required=False)
@click.option("-f", "--file", type=click.Path(exists=True), help="从文件读取 prompt")
@click.option("-s", "--size", default="2K", type=click.Choice(["1K", "2K"]), help="图片尺寸")
@click.option("-o", "--output", help="保存路径(默认只输出 URL")
@click.option("--no-watermark", is_flag=True, help="不添加豆包水印")
@click.option("--b64", is_flag=True, help="使用 b64_json 格式获取图片数据")
@handle_errors
def generate_image_cmd(prompt, file, size, output, no_watermark, b64):
"""使用豆包/Seedream 模型生成图片。"""
from openai import OpenAI
if file:
prompt = Path(file).read_text(encoding="utf-8").strip()
elif not prompt:
raise click.UsageError("必须提供 prompt 或使用 -f/--file 从文件读取")
api_key = config.get("apikey_ark")
if not api_key:
click.echo("Error: apikey_ark not set. Run: mytoolkit env set apikey_ark <value>", err=True)
raise click.Abort()
client = OpenAI(
base_url="https://ark.cn-beijing.volces.com/api/v3",
api_key=api_key,
)
resp = client.images.generate(
model="doubao-seedream-5-0-260128",
prompt=prompt,
size=size,
response_format="b64_json" if b64 else "url",
extra_body={"watermark": not no_watermark},
)
if b64:
image_bytes = base64.b64decode(resp.data[0].b64_json)
save_path = output or "generated_image.png"
Path(save_path).write_bytes(image_bytes)
click.echo(os.path.abspath(save_path))
else:
url = resp.data[0].url
if output:
urllib.request.urlretrieve(url, output)
click.echo(os.path.abspath(output))
else:
click.echo(url)