@topmindspace/tms-skills 0.3.5 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +88 -1
  2. package/README.en.md +4 -4
  3. package/README.md +4 -4
  4. package/bin/tms-skills.js +9 -1
  5. package/package.json +1 -1
  6. package/top-ppt-html/README.en.md +2 -2
  7. package/top-ppt-html/README.md +1 -1
  8. package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +43 -14
  9. package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +43 -14
  10. package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +43 -14
  11. package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.html +43 -14
  12. package/top-ppt-html/assets/pptx-export.js +42 -13
  13. package/top-ppt-html/assets/style-gallery.html +1 -1
  14. package/top-ppt-html/assets/templates/architecture.html +45 -15
  15. package/top-ppt-html/assets/templates/presentation.html +45 -15
  16. package/top-ppt-html/assets/templates/research.html +45 -15
  17. package/top-ppt-html/scripts/audit_css.py +1 -1
  18. package/top-ppt-html/scripts/build_pptx.js +136 -25
  19. package/top-ppt-html/scripts/layout-constants.json +1 -1
  20. package/top-ppt-html/scripts/regression.py +3 -3
  21. package/top-ppt-html/scripts/render_compare.py +1 -1
  22. package/top-ppt-html/scripts/scaffold_report.py +1 -1
  23. package/top-ppt-html/scripts/sync_runtime.py +14 -14
  24. package/top-ppt-html/scripts/validate_report.py +4 -0
  25. package/topmind-cover/README.en.md +8 -9
  26. package/topmind-cover/README.md +8 -9
  27. package/topmind-cover/SKILL.md +28 -8
  28. package/topmind-cover/assets/examples/README.md +2 -2
  29. package/topmind-cover/assets/examples/big-type-wechat.png +0 -0
  30. package/topmind-cover/assets/examples/big-type.png +0 -0
  31. package/topmind-cover/assets/examples/brand-launch-wechat.png +0 -0
  32. package/topmind-cover/assets/examples/brand-launch.png +0 -0
  33. package/topmind-cover/assets/examples/gan-huo-wechat.png +0 -0
  34. package/topmind-cover/assets/examples/gan-huo.png +0 -0
  35. package/topmind-cover/assets/examples/ip-fun-wechat.png +0 -0
  36. package/topmind-cover/assets/examples/ip-fun.png +0 -0
  37. package/topmind-cover/assets/examples/magazine-wechat.png +0 -0
  38. package/topmind-cover/assets/examples/magazine.png +0 -0
  39. package/topmind-cover/assets/examples/minimal-wechat.png +0 -0
  40. package/topmind-cover/assets/examples/minimal.png +0 -0
  41. package/topmind-cover/assets/examples/news-flash-wechat.png +0 -0
  42. package/topmind-cover/assets/examples/news-flash.png +0 -0
  43. package/topmind-cover/assets/examples/overview.png +0 -0
  44. package/topmind-cover/assets/examples/tutorial-steps-wechat.png +0 -0
  45. package/topmind-cover/assets/examples/tutorial-steps.png +0 -0
  46. package/topmind-cover/references/cover-styles.md +160 -172
  47. package/topmind-cover/references/impact-language.md +91 -0
  48. package/topmind-cover/scripts/crop-cover.py +19 -13
  49. package/topmind-wechat-post/README.en.md +2 -2
  50. package/topmind-wechat-post/README.md +2 -2
  51. package/topmind-wechat-post/SKILL.md +1 -1
  52. package/topmind-wechat-post/scripts/md2wechat.py +12 -3
  53. package/topmind-x-article/README.en.md +1 -1
  54. package/topmind-x-article/README.md +1 -1
  55. package/topmind-x-article/scripts/md2x.py +7 -2
@@ -31,7 +31,10 @@ def main() -> None:
31
31
 
32
32
  src = Path(args.src)
33
33
  out_dir = Path(args.out_dir)
34
- out_dir.mkdir(parents=True, exist_ok=True)
34
+ try:
35
+ out_dir.mkdir(parents=True, exist_ok=True)
36
+ except OSError as e:
37
+ sys.exit(f"错误:无法创建输出目录 {out_dir}({e})")
35
38
 
36
39
  if not src.is_file():
37
40
  sys.exit(f"错误:找不到输入图片 {src}")
@@ -50,18 +53,21 @@ def main() -> None:
50
53
  x0, y0 = (w - cw) // 2, (h - ch) // 2
51
54
  base = img.crop((x0, y0, x0 + cw, y0 + ch))
52
55
 
53
- for name, (tw, th) in TARGETS.items():
54
- ratio = tw / th
55
- bw, bh = base.size
56
- if bw / bh > ratio:
57
- cw2, ch2 = int(bh * ratio), bh
58
- else:
59
- cw2, ch2 = bw, int(bw / ratio)
60
- x1, y1 = (bw - cw2) // 2, (bh - ch2) // 2
61
- out = base.crop((x1, y1, x1 + cw2, y1 + ch2)).resize((tw, th), Image.LANCZOS)
62
- dest = out_dir / name
63
- out.save(dest)
64
- print(f"OK {dest} ({tw}x{th})")
56
+ try:
57
+ for name, (tw, th) in TARGETS.items():
58
+ ratio = tw / th
59
+ bw, bh = base.size
60
+ if bw / bh > ratio:
61
+ cw2, ch2 = int(bh * ratio), bh
62
+ else:
63
+ cw2, ch2 = bw, int(bw / ratio)
64
+ x1, y1 = (bw - cw2) // 2, (bh - ch2) // 2
65
+ out = base.crop((x1, y1, x1 + cw2, y1 + ch2)).resize((tw, th), Image.LANCZOS)
66
+ dest = out_dir / name
67
+ out.save(dest)
68
+ print(f"OK {dest} ({tw}x{th})")
69
+ except OSError as e:
70
+ sys.exit(f"错误:写入封面图失败({e})")
65
71
 
66
72
 
67
73
  if __name__ == "__main__":
@@ -4,7 +4,7 @@
4
4
 
5
5
  Full lifecycle for WeChat articles: delivery package, review & rewrite, three quality gates, status sync, WeChat inline typography, and publish checklist.
6
6
 
7
- - Version: **v0.1.0** (same tag as `@topmindspace/tms-skills@0.3.5`)
7
+ - Version: **v0.1.0** (same tag as `@topmindspace/tms-skills@0.3.9`)
8
8
 
9
9
  ## Install
10
10
 
@@ -60,7 +60,7 @@ Output `demo/demo-公众号版.html` (open in a browser → click "复制正文"
60
60
 
61
61
  ```html
62
62
  <!-- h2 auto-numbered; closing chapters like "总结" get ∞ -->
63
- <h2 ...><span ...>01</span>Chapter One</h2>
63
+ <h2 ...><span ...>1</span>Chapter One</h2>
64
64
  <!-- images inlined as base64, pasted along with the text -->
65
65
  <img src="data:image/png;base64,iVBORw0KGgo..." ...>
66
66
  ```
@@ -4,7 +4,7 @@
4
4
 
5
5
  公众号文章全生命周期:交付包、审校改写、质量三关、状态同步、微信内联排版与发布清单。
6
6
 
7
- - 版本:**v0.1.0**(与 `@topmindspace/tms-skills@0.3.5` 同 tag)
7
+ - 版本:**v0.1.0**(与 `@topmindspace/tms-skills@0.3.9` 同 tag)
8
8
 
9
9
  ## 安装
10
10
 
@@ -59,7 +59,7 @@ python3 scripts/md2wechat.py --input demo.md --out-dir demo --slug demo --embed-
59
59
 
60
60
  ```html
61
61
  <!-- 二级标题自动编号;"总结"类末章编号为 ∞ -->
62
- <h2 ...><span ...>01</span>第一章</h2>
62
+ <h2 ...><span ...>1</span>第一章</h2>
63
63
  <!-- 图片 base64 内嵌,粘贴即带图 -->
64
64
  <img src="data:image/png;base64,iVBORw0KGgo..." ...>
65
65
  ```
@@ -50,7 +50,7 @@ updated: 2026-09-29
50
50
  | `scripts/scan_ai_flavor.py` | 中文去 AI 味扫描(与 `qu-aiwei-zh` 同源) |
51
51
 
52
52
  ```bash
53
- # 路径解析:CLI --base/--workspace → env TOPMIND_WECHAT_BASE / TOPMIND_WORKSPACE / TOPSTREAM_ROOT → 惯例
53
+ # 路径解析:CLI --base → env TOPMIND_WECHAT_BASE / TOPMIND_WORKSPACE / TOPSTREAM_ROOT → 惯例
54
54
  export TOPMIND_WORKSPACE=/path/to/workspace # 推荐
55
55
  python3 scripts/new-article.py --slug demo --title "标题" --direction reverse
56
56
  python3 scripts/lint-wechat.py --input <包>/公众号稿.md --fix
@@ -920,7 +920,10 @@ def resolve_image(src, md_path, out_dir, assets, asset_root):
920
920
  "missing": True})
921
921
  return src
922
922
  img_dir = os.path.join(out_dir, "images")
923
- os.makedirs(img_dir, exist_ok=True)
923
+ try:
924
+ os.makedirs(img_dir, exist_ok=True)
925
+ except OSError as e:
926
+ sys.exit("错误:无法创建图片目录 %s(%s)" % (img_dir, e))
924
927
  base = os.path.basename(abs_path)
925
928
  target = os.path.join(img_dir, base)
926
929
  n = 1
@@ -929,7 +932,10 @@ def resolve_image(src, md_path, out_dir, assets, asset_root):
929
932
  target = os.path.join(img_dir, "%s-%d%s" % (stem, n, ext))
930
933
  n += 1
931
934
  if not os.path.exists(target):
932
- shutil.copy2(abs_path, target)
935
+ try:
936
+ shutil.copy2(abs_path, target)
937
+ except OSError as e:
938
+ sys.exit("错误:复制图片失败 %s → %s(%s)" % (abs_path, target, e))
933
939
  rel = os.path.relpath(target, out_dir)
934
940
  assets.append({"src": src, "local": rel, "remote": False,
935
941
  "basename": os.path.basename(target),
@@ -1609,7 +1615,10 @@ def main():
1609
1615
  except OSError as e:
1610
1616
  sys.exit("错误:无法读取输入文件 %s(%s)" % (args.input, e))
1611
1617
 
1612
- os.makedirs(args.out_dir, exist_ok=True)
1618
+ try:
1619
+ os.makedirs(args.out_dir, exist_ok=True)
1620
+ except OSError as e:
1621
+ sys.exit("错误:无法创建输出目录 %s(%s)" % (args.out_dir, e))
1613
1622
  body, assets, diagrams, footnotes = convert(
1614
1623
  md_text, os.path.abspath(args.input), args.out_dir, theme,
1615
1624
  args.link_mode, args.render_mermaid, args.asset_root or None,
@@ -4,7 +4,7 @@
4
4
 
5
5
  Turn a Markdown draft into a "copy → paste → publish" X long-form (Article) package.
6
6
 
7
- - Version: **v0.1.0** (same tag as `@topmindspace/tms-skills@0.3.5`)
7
+ - Version: **v0.1.0** (same tag as `@topmindspace/tms-skills@0.3.9`)
8
8
 
9
9
  ## Install
10
10
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  把 Markdown 原稿变成"复制 → 粘贴 → 发"的 X 长文(Article)发布包。
6
6
 
7
- - 版本:**v0.1.0**(与 `@topmindspace/tms-skills@0.3.5` 同 tag)
7
+ - 版本:**v0.1.0**(与 `@topmindspace/tms-skills@0.3.9` 同 tag)
8
8
 
9
9
  ## 安装
10
10
 
@@ -281,6 +281,8 @@ def main() -> None:
281
281
 
282
282
  inp = Path(args.input)
283
283
  if not inp.is_file():
284
+ if inp.is_dir():
285
+ sys.exit(f"错误:输入是目录不是文件 {inp}")
284
286
  sys.exit(f"错误:找不到输入文件 {inp}")
285
287
  try:
286
288
  md = inp.read_text(encoding="utf-8-sig")
@@ -291,8 +293,11 @@ def main() -> None:
291
293
  text, images = convert(md)
292
294
 
293
295
  out = Path(args.out)
294
- out.parent.mkdir(parents=True, exist_ok=True)
295
- out.write_text(text, encoding="utf-8")
296
+ try:
297
+ out.parent.mkdir(parents=True, exist_ok=True)
298
+ out.write_text(text, encoding="utf-8")
299
+ except OSError as e:
300
+ sys.exit(f"错误:无法写入输出文件 {out}({e})")
296
301
 
297
302
  chars = len(text.replace("\n", ""))
298
303
  print(f"OK {out}")