优化SKILL
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""检查 Markdown 中引用的本地图片是否真实存在。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
from typing import Iterable, List, Optional
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
IMAGE_RE = re.compile(r"!\[[^\]]*\]\(([^)]+)\)")
|
||||
|
||||
|
||||
def die(message: str, code: int = 1) -> None:
|
||||
print(f"错误:{message}", file=sys.stderr)
|
||||
raise SystemExit(code)
|
||||
|
||||
|
||||
def normalize_target(raw: str) -> str:
|
||||
value = raw.strip()
|
||||
if value.startswith("<") and value.endswith(">"):
|
||||
return value[1:-1].strip()
|
||||
if " " in value:
|
||||
value = value.split()[0]
|
||||
return value.strip("'\"")
|
||||
|
||||
|
||||
def is_remote_or_anchor(target: str) -> bool:
|
||||
parsed = urlparse(target)
|
||||
return bool(parsed.scheme in {"http", "https", "data", "mailto"} or target.startswith("#"))
|
||||
|
||||
|
||||
def find_missing(markdown_path: Path) -> List[str]:
|
||||
text = markdown_path.read_text(encoding="utf-8")
|
||||
base_dir = markdown_path.parent
|
||||
missing: List[str] = []
|
||||
for match in IMAGE_RE.finditer(text):
|
||||
target = normalize_target(match.group(1))
|
||||
if not target or is_remote_or_anchor(target):
|
||||
continue
|
||||
image_path = Path(target)
|
||||
if not image_path.is_absolute():
|
||||
image_path = base_dir / image_path
|
||||
if not image_path.exists():
|
||||
missing.append(target)
|
||||
return missing
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(description="检查 Markdown 本地图片路径是否存在。")
|
||||
parser.add_argument("markdown", help="要检查的 article.md 或其他 Markdown 文件。")
|
||||
return parser
|
||||
|
||||
|
||||
def main(argv: Optional[Iterable[str]] = None) -> int:
|
||||
parser = build_parser()
|
||||
args = parser.parse_args(list(argv) if argv is not None else None)
|
||||
markdown_path = Path(args.markdown).expanduser().resolve()
|
||||
if not markdown_path.exists():
|
||||
die(f"Markdown 文件不存在:{markdown_path}")
|
||||
missing = find_missing(markdown_path)
|
||||
result = {
|
||||
"markdown": str(markdown_path),
|
||||
"missing_count": len(missing),
|
||||
"missing": missing,
|
||||
}
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return 1 if missing else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -29,38 +29,38 @@ DEFAULT_STYLE = "warm-fintech-guide"
|
||||
|
||||
STYLE_PRESETS: Dict[str, str] = {
|
||||
"warm-fintech-guide": (
|
||||
"MAOMOMO 暖橙金融教程风:明亮白底,暖橙强调色,干净卡片布局,友好的白橘猫作为向导,"
|
||||
"明亮白底,暖橙强调色,干净卡片布局,友好的白橘猫作为向导,"
|
||||
"适合港卡、银行活动、返现攻略和教程总览。"
|
||||
),
|
||||
"clean-editorial": (
|
||||
"清爽编辑部风:大标题、留白充足、少量暖橙和黑灰文字,像一张信息密度适中的中文攻略头图。"
|
||||
"大标题、留白充足、少量暖橙和黑灰文字,像一张信息密度适中的中文攻略头图。"
|
||||
),
|
||||
"data-card-dashboard": (
|
||||
"数据卡片仪表盘风:指标卡、时间线、计算公式和对比表清晰分区,适合返现、费用、门槛和路径对比。"
|
||||
"指标卡、时间线、计算公式和对比表清晰分区,适合返现、费用、门槛和路径对比。"
|
||||
),
|
||||
"handdrawn-note": (
|
||||
"手绘便签风:白底纸感、手绘箭头、便利贴、重点圈注和轻量猫咪贴纸,适合避坑经验和保姆式步骤。"
|
||||
"白底纸感、手绘箭头、便利贴、重点圈注和轻量猫咪贴纸,适合避坑经验和保姆式步骤。"
|
||||
),
|
||||
"xiaohongshu-vertical": (
|
||||
"小红书竖版攻略风:9:16 手机端可读,大字少字,强标题钩子,4 图系列一致视觉,带 MAOMOMO 标识。"
|
||||
"9:16 手机端可读,大字少字,强标题钩子,4 图系列一致视觉,带 MAOMOMO 标识。"
|
||||
),
|
||||
"clean-professional": (
|
||||
"清爽专业风:浅色背景、蓝绿或暖橙强调、结构化信息卡片和清晰层级,适合正式银行规则、开户教程和综合攻略。"
|
||||
"浅色背景、蓝绿或暖橙强调、结构化信息卡片和清晰层级,适合正式银行规则、开户教程和综合攻略。"
|
||||
),
|
||||
"creative-magazine": (
|
||||
"创意杂志风:大标题、强留白、编辑部排版和轻视觉冲击,适合传播型封面、观点总结和活动盘点。"
|
||||
"大标题、强留白、编辑部排版和轻视觉冲击,适合传播型封面、观点总结和活动盘点。"
|
||||
),
|
||||
"retro-flat-illustration": (
|
||||
"复古扁平插画风:低饱和暖色、扁平金融小物件、轻复古海报感,适合轻松羊毛攻略和经验分享。"
|
||||
"低饱和暖色、扁平金融小物件、轻复古海报感,适合轻松羊毛攻略和经验分享。"
|
||||
),
|
||||
"e-ink-editorial": (
|
||||
"电子墨水杂志风:纸感背景、黑白灰为主、少量强调色、强标题和元信息条,适合深度解释和观点型长文。"
|
||||
"纸感背景、黑白灰为主、少量强调色、强标题和元信息条,适合深度解释和观点型长文。"
|
||||
),
|
||||
"scientific-defense": (
|
||||
"科研答辩风:严谨浅色版式、证据图、流程框和来源标注,适合规则拆解、政策解读和多来源核对。"
|
||||
"严谨浅色版式、证据图、流程框和来源标注,适合规则拆解、政策解读和多来源核对。"
|
||||
),
|
||||
"mckinsey-brief": (
|
||||
"麦肯锡简报风:结论先行、矩阵、2x2、瀑布图和高对比商业配色,适合方案对比、路径选择和决策建议。"
|
||||
"结论先行、矩阵、2x2、瀑布图和高对比商业配色,适合方案对比、路径选择和决策建议。"
|
||||
),
|
||||
}
|
||||
|
||||
@@ -88,6 +88,24 @@ def read_json(path: Path) -> Any:
|
||||
return json.loads(read_text(path))
|
||||
|
||||
|
||||
def load_prompt_file(path: Path) -> str:
|
||||
text = read_text(path).strip()
|
||||
stripped = text.lstrip()
|
||||
if path.suffix.lower() == ".json" or stripped.startswith("{"):
|
||||
try:
|
||||
data = json.loads(text)
|
||||
except json.JSONDecodeError as exc:
|
||||
die(f"--prompt-file 看起来是 JSON,但解析失败:{path}: {exc}")
|
||||
if not isinstance(data, dict) or not isinstance(data.get("prompt"), str) or not data["prompt"].strip():
|
||||
die("--prompt-file 不能传入缺少 prompt 字段的 JSON。请先抽取 prompt 字段生成 .prompt.txt。")
|
||||
prompt = data["prompt"].strip()
|
||||
prompt_out = path.with_suffix(".prompt.txt")
|
||||
write_text(prompt_out, prompt + "\n")
|
||||
warn(f"--prompt-file 收到 JSON,已抽取 prompt 字段到:{prompt_out};后续请直接传入该 .prompt.txt。")
|
||||
return prompt
|
||||
return text
|
||||
|
||||
|
||||
def load_codex_config_base_url() -> Optional[str]:
|
||||
config_path = Path.home() / ".codex" / "config.toml"
|
||||
if not config_path.exists():
|
||||
@@ -183,14 +201,17 @@ def build_prompt(
|
||||
aspect_ratio: str,
|
||||
extra: str = "",
|
||||
) -> str:
|
||||
allowed_visible = [value for value in (title, core_text, "MAOMOMO") if value.strip()]
|
||||
allowed_visible_text = "、".join(f"「{value}」" for value in allowed_visible)
|
||||
parts = [
|
||||
"生成一张 MAOMOMO 中文金融实操文章配图。",
|
||||
f"图片类型:{image_type}",
|
||||
f"标题 / 主题:{title}",
|
||||
f"核心文案:{core_text}",
|
||||
f"画幅:{aspect_ratio}",
|
||||
f"视觉风格:{style_prompt(style)}",
|
||||
"硬性要求:包含清晰可见的 MAOMOMO 标识;中文文字清楚可读;信息层级明确;不要伪造真实 App 截图;不要使用未经提供的银行、券商、支付机构或卡组织 Logo;不要出现真实个人信息;猫咪不能承载第三方品牌 Logo。",
|
||||
f"画面呈现:{style_prompt(style)}",
|
||||
f"可见文字限制:画面只允许出现这些指定业务文案:{allowed_visible_text};不要添加副标题、风格标签、prompt 描述、说明文字、额外 slogan 或无关文字。",
|
||||
"硬性要求:包含清晰可见的 MAOMOMO 标识;中文文字清楚可读;信息层级明确;港币金额统一使用 HKD 写法;不要伪造真实 App 截图;不要使用未经提供的银行、券商、支付机构或卡组织 Logo;没有明确素材或指令时,信用卡画无卡组织标识的通用卡,不要凭空加入 Mastercard、Visa、UnionPay 或其他支付网络;不要出现真实个人信息;猫咪不能承载第三方品牌 Logo。",
|
||||
]
|
||||
if extra.strip():
|
||||
parts.append(f"补充要求:{extra.strip()}")
|
||||
@@ -253,7 +274,7 @@ def normalize_output(path: str, *, base_dir: Optional[Path]) -> Path:
|
||||
|
||||
def generate_one(args: argparse.Namespace) -> Dict[str, str]:
|
||||
if args.prompt_file:
|
||||
prompt = read_text(Path(args.prompt_file)).strip()
|
||||
prompt = load_prompt_file(Path(args.prompt_file))
|
||||
elif args.prompt:
|
||||
prompt = args.prompt.strip()
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user