first commit
This commit is contained in:
41 files changed
+4964
No files matched your search
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build a portable v1 article package for the DWW11 userscript (standard library only)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import mimetypes
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def make_package(directory: str | Path, markdown: str | None = None) -> dict:
|
||||
"""Return JSON-serializable data; no network access or publishing side effects."""
|
||||
root = Path(directory).expanduser().resolve(strict=True)
|
||||
if not root.is_dir():
|
||||
raise ValueError("文章目录不存在")
|
||||
choices = sorted(path for path in root.rglob("*") if path.is_file() and path.suffix.lower() == ".md")
|
||||
if markdown:
|
||||
selected = (root / markdown).resolve(strict=True)
|
||||
elif len(choices) == 1:
|
||||
selected = choices[0].resolve()
|
||||
else:
|
||||
raise ValueError("目录必须包含一个 Markdown 文件,或通过 --markdown 指定目录内相对路径")
|
||||
if not selected.is_relative_to(root) or selected.suffix.lower() != ".md" or not selected.is_file():
|
||||
raise ValueError("Markdown 必须位于所选文章目录内")
|
||||
images = []
|
||||
# Package local supported images. The importer uploads only those referenced by Markdown.
|
||||
for path in sorted(root.rglob("*")):
|
||||
if not path.is_file() or path.suffix.lower() not in {".jpg", ".jpeg", ".png", ".gif"}:
|
||||
continue
|
||||
if not path.resolve().is_relative_to(root):
|
||||
raise ValueError(f"图片符号链接指向目录外:{path.name}")
|
||||
if not 0 < path.stat().st_size < 20 * 1024 * 1024:
|
||||
raise ValueError(f"图片为空或达到 20 MB:{path.name}")
|
||||
images.append({"path": path.relative_to(root).as_posix(),
|
||||
"mime": mimetypes.guess_type(path.name)[0] or "application/octet-stream",
|
||||
"base64": base64.b64encode(path.read_bytes()).decode("ascii")})
|
||||
return {"schemaVersion": 1, "markdownPath": selected.relative_to(root).as_posix(),
|
||||
"markdown": selected.read_text(encoding="utf-8-sig"), "images": images}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="把文章目录打包为油猴脚本可导入的 JSON;不上传或发布")
|
||||
parser.add_argument("directory", help="包含 Markdown 和图片的目录")
|
||||
parser.add_argument("--markdown", help="多个 Markdown 时指定目录内的相对路径")
|
||||
parser.add_argument("-o", "--output", help="输出文件路径;未指定时输出到标准输出")
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
content = json.dumps(make_package(args.directory, args.markdown), ensure_ascii=False, indent=2)
|
||||
if args.output:
|
||||
output = Path(args.output).expanduser()
|
||||
# Never silently overwrite an article or an existing package.
|
||||
with output.open("x", encoding="utf-8") as handle:
|
||||
handle.write(content + "\n")
|
||||
print(json.dumps({"ok": True, "package": str(output.resolve())}, ensure_ascii=False))
|
||||
else:
|
||||
print(content)
|
||||
except (OSError, ValueError) as error:
|
||||
parser.exit(1, f"打包失败:{error}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user