@topmindspace/tms-skills 0.3.9 → 0.4.1

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 (161) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.en.md +11 -8
  3. package/README.md +11 -8
  4. package/bin/tms-skills.js +144 -12
  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/SKILL.md +8 -7
  9. package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +16 -171
  10. package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.model.json +13 -3
  11. package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +16 -324
  12. package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.model.json +15 -1
  13. package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +16 -917
  14. package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.model.json +15 -1
  15. package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.html +99 -18
  16. package/top-ppt-html/assets/icons/index.json +557 -0
  17. package/top-ppt-html/assets/icons//344/270/212/344/274/240.png +0 -0
  18. package/top-ppt-html/assets/icons//344/270/212/344/274/240.svg +1 -0
  19. package/top-ppt-html/assets/icons//344/270/213/350/275/275.png +0 -0
  20. package/top-ppt-html/assets/icons//344/270/213/350/275/275.svg +1 -0
  21. package/top-ppt-html/assets/icons//344/270/213/351/231/215.png +0 -0
  22. package/top-ppt-html/assets/icons//344/270/213/351/231/215.svg +1 -0
  23. package/top-ppt-html/assets/icons//344/271/246/347/255/276.png +0 -0
  24. package/top-ppt-html/assets/icons//344/271/246/347/255/276.svg +1 -0
  25. package/top-ppt-html/assets/icons//344/272/221.png +0 -0
  26. package/top-ppt-html/assets/icons//344/272/221.svg +1 -0
  27. package/top-ppt-html/assets/icons//344/275/215/347/275/256.png +0 -0
  28. package/top-ppt-html/assets/icons//344/275/215/347/275/256.svg +1 -0
  29. package/top-ppt-html/assets/icons//344/277/241/346/201/257.png +0 -0
  30. package/top-ppt-html/assets/icons//344/277/241/346/201/257.svg +1 -0
  31. package/top-ppt-html/assets/icons//345/210/206/344/272/253.png +0 -0
  32. package/top-ppt-html/assets/icons//345/210/206/344/272/253.svg +1 -0
  33. package/top-ppt-html/assets/icons//345/213/276/351/200/211.png +0 -0
  34. package/top-ppt-html/assets/icons//345/213/276/351/200/211.svg +1 -0
  35. package/top-ppt-html/assets/icons//345/215/240/346/257/224.png +0 -0
  36. package/top-ppt-html/assets/icons//345/215/240/346/257/224.svg +1 -0
  37. package/top-ppt-html/assets/icons//345/233/242/351/230/237.png +0 -0
  38. package/top-ppt-html/assets/icons//345/233/242/351/230/237.svg +1 -0
  39. package/top-ppt-html/assets/icons//345/233/276/350/241/250.png +0 -0
  40. package/top-ppt-html/assets/icons//345/233/276/350/241/250.svg +1 -0
  41. package/top-ppt-html/assets/icons//345/242/236/351/225/277.png +0 -0
  42. package/top-ppt-html/assets/icons//345/242/236/351/225/277.svg +1 -0
  43. package/top-ppt-html/assets/icons//345/256/211/345/205/250.png +0 -0
  44. package/top-ppt-html/assets/icons//345/256/211/345/205/250.svg +1 -0
  45. package/top-ppt-html/assets/icons//345/257/271/350/257/235.png +0 -0
  46. package/top-ppt-html/assets/icons//345/257/271/350/257/235.svg +1 -0
  47. package/top-ppt-html/assets/icons//345/267/245/345/205/267.png +0 -0
  48. package/top-ppt-html/assets/icons//345/267/245/345/205/267.svg +1 -0
  49. package/top-ppt-html/assets/icons//345/276/252/347/216/257.png +0 -0
  50. package/top-ppt-html/assets/icons//345/276/252/347/216/257.svg +1 -0
  51. package/top-ppt-html/assets/icons//346/210/220/346/236/234.png +0 -0
  52. package/top-ppt-html/assets/icons//346/210/220/346/236/234.svg +1 -0
  53. package/top-ppt-html/assets/icons//346/211/213/346/234/272.png +0 -0
  54. package/top-ppt-html/assets/icons//346/211/213/346/234/272.svg +1 -0
  55. package/top-ppt-html/assets/icons//346/225/210/347/216/207.png +0 -0
  56. package/top-ppt-html/assets/icons//346/225/210/347/216/207.svg +1 -0
  57. package/top-ppt-html/assets/icons//346/225/260/346/215/256.png +0 -0
  58. package/top-ppt-html/assets/icons//346/225/260/346/215/256.svg +1 -0
  59. package/top-ppt-html/assets/icons//346/226/207/344/273/266/345/244/271.png +0 -0
  60. package/top-ppt-html/assets/icons//346/226/207/344/273/266/345/244/271.svg +1 -0
  61. package/top-ppt-html/assets/icons//346/226/207/346/241/243.png +0 -0
  62. package/top-ppt-html/assets/icons//346/226/207/346/241/243.svg +1 -0
  63. package/top-ppt-html/assets/icons//346/227/227/345/270/234.png +0 -0
  64. package/top-ppt-html/assets/icons//346/227/227/345/270/234.svg +1 -0
  65. package/top-ppt-html/assets/icons//346/227/266/351/227/264.png +0 -0
  66. package/top-ppt-html/assets/icons//346/227/266/351/227/264.svg +1 -0
  67. package/top-ppt-html/assets/icons//346/230/237/346/240/207.png +0 -0
  68. package/top-ppt-html/assets/icons//346/230/237/346/240/207.svg +1 -0
  69. package/top-ppt-html/assets/icons//346/231/272/350/203/275.png +0 -0
  70. package/top-ppt-html/assets/icons//346/231/272/350/203/275.svg +1 -0
  71. package/top-ppt-html/assets/icons//346/235/203/351/231/220.png +0 -0
  72. package/top-ppt-html/assets/icons//346/235/203/351/231/220.svg +1 -0
  73. package/top-ppt-html/assets/icons//346/243/200/346/237/245.png +0 -0
  74. package/top-ppt-html/assets/icons//346/243/200/346/237/245.svg +1 -0
  75. package/top-ppt-html/assets/icons//346/264/236/345/257/237.png +0 -0
  76. package/top-ppt-html/assets/icons//346/264/236/345/257/237.svg +1 -0
  77. package/top-ppt-html/assets/icons//346/265/201/347/250/213.png +0 -0
  78. package/top-ppt-html/assets/icons//346/265/201/347/250/213.svg +1 -0
  79. package/top-ppt-html/assets/icons//346/270/205/345/215/225.png +0 -0
  80. package/top-ppt-html/assets/icons//346/270/205/345/215/225.svg +1 -0
  81. package/top-ppt-html/assets/icons//347/201/253/347/256/255.png +0 -0
  82. package/top-ppt-html/assets/icons//347/201/253/347/256/255.svg +1 -0
  83. package/top-ppt-html/assets/icons//347/201/257/346/263/241.png +0 -0
  84. package/top-ppt-html/assets/icons//347/201/257/346/263/241.svg +1 -0
  85. package/top-ppt-html/assets/icons//347/224/250/346/210/267.png +0 -0
  86. package/top-ppt-html/assets/icons//347/224/250/346/210/267.svg +1 -0
  87. package/top-ppt-html/assets/icons//347/233/256/346/240/207.png +0 -0
  88. package/top-ppt-html/assets/icons//347/233/256/346/240/207.svg +1 -0
  89. package/top-ppt-html/assets/icons//347/256/255/345/244/264.png +0 -0
  90. package/top-ppt-html/assets/icons//347/256/255/345/244/264.svg +1 -0
  91. package/top-ppt-html/assets/icons//347/273/204/347/273/207.png +0 -0
  92. package/top-ppt-html/assets/icons//347/273/204/347/273/207.svg +1 -0
  93. package/top-ppt-html/assets/icons//347/275/227/347/233/230.png +0 -0
  94. package/top-ppt-html/assets/icons//347/275/227/347/233/230.svg +1 -0
  95. package/top-ppt-html/assets/icons//350/241/250/346/240/274.png +0 -0
  96. package/top-ppt-html/assets/icons//350/241/250/346/240/274.svg +1 -0
  97. package/top-ppt-html/assets/icons//350/256/241/345/210/222.png +0 -0
  98. package/top-ppt-html/assets/icons//350/256/241/345/210/222.svg +1 -0
  99. package/top-ppt-html/assets/icons//350/256/276/347/275/256.png +0 -0
  100. package/top-ppt-html/assets/icons//350/256/276/347/275/256.svg +1 -0
  101. package/top-ppt-html/assets/icons//350/266/213/345/212/277.png +0 -0
  102. package/top-ppt-html/assets/icons//350/266/213/345/212/277.svg +1 -0
  103. package/top-ppt-html/assets/icons//351/202/256/344/273/266.png +0 -0
  104. package/top-ppt-html/assets/icons//351/202/256/344/273/266.svg +1 -0
  105. package/top-ppt-html/assets/icons//351/207/221/351/222/261.png +0 -0
  106. package/top-ppt-html/assets/icons//351/207/221/351/222/261.svg +1 -0
  107. package/top-ppt-html/assets/icons//351/223/276/346/216/245.png +0 -0
  108. package/top-ppt-html/assets/icons//351/223/276/346/216/245.svg +1 -0
  109. package/top-ppt-html/assets/icons//351/227/252/347/224/265.png +0 -0
  110. package/top-ppt-html/assets/icons//351/227/252/347/224/265.svg +1 -0
  111. package/top-ppt-html/assets/icons//351/243/216/351/231/251.png +0 -0
  112. package/top-ppt-html/assets/icons//351/243/216/351/231/251.svg +1 -0
  113. package/top-ppt-html/assets/pptx-export.js +2 -2
  114. package/top-ppt-html/assets/style-gallery.html +1 -1
  115. package/top-ppt-html/assets/templates/architecture.html +15 -3
  116. package/top-ppt-html/assets/templates/engine.css +12 -0
  117. package/top-ppt-html/assets/templates/presentation.html +15 -3
  118. package/top-ppt-html/assets/templates/research.html +15 -3
  119. package/top-ppt-html/package-lock.json +2 -2
  120. package/top-ppt-html/package.json +2 -2
  121. package/top-ppt-html/references/icons.md +22 -19
  122. package/top-ppt-html/references/layout-variants.md +69 -0
  123. package/top-ppt-html/references/style-pack.md +40 -0
  124. package/top-ppt-html/scripts/build_pptx.js +93 -26
  125. package/top-ppt-html/scripts/check_icons.py +119 -0
  126. package/top-ppt-html/scripts/hydrate_charts.py +60 -5
  127. package/top-ppt-html/scripts/icon_lib.js +66 -37
  128. package/top-ppt-html/scripts/layout-constants.json +91 -4
  129. package/top-ppt-html/scripts/make_icon_pack.py +172 -0
  130. package/top-ppt-html/scripts/model-schema.json +4 -1
  131. package/top-ppt-html/scripts/render_from_model.py +116 -55
  132. package/top-ppt-html/scripts/validate_pptx.py +1 -0
  133. package/top-ppt-html/scripts/validate_report.py +153 -0
  134. package/topmind-cover/README.en.md +4 -4
  135. package/topmind-cover/README.md +4 -4
  136. package/topmind-cover/SKILL.md +36 -18
  137. package/topmind-cover/assets/examples/README.md +13 -7
  138. package/topmind-cover/assets/examples/bg-blur-alt.png +0 -0
  139. package/topmind-cover/assets/examples/bg-blur-wechat.png +0 -0
  140. package/topmind-cover/assets/examples/bg-blur.png +0 -0
  141. package/topmind-cover/assets/examples/overview.png +0 -0
  142. package/topmind-cover/assets/examples/paper-collage-alt.png +0 -0
  143. package/topmind-cover/assets/examples/paper-collage-wechat.png +0 -0
  144. package/topmind-cover/assets/examples/paper-collage.png +0 -0
  145. package/topmind-cover/assets/examples/white-clean-alt-wechat.png +0 -0
  146. package/topmind-cover/assets/examples/white-clean-alt.png +0 -0
  147. package/topmind-cover/assets/examples/white-clean-wechat.png +0 -0
  148. package/topmind-cover/assets/examples/white-clean.png +0 -0
  149. package/topmind-cover/package.json +2 -2
  150. package/topmind-cover/references/cover-styles.md +146 -14
  151. package/topmind-cover/references/impact-language.md +9 -6
  152. package/topmind-cover/references/ref-white-clean-1.png +0 -0
  153. package/topmind-cover/references/ref-white-clean-2.png +0 -0
  154. package/topmind-wechat-post/README.en.md +1 -1
  155. package/topmind-wechat-post/README.md +1 -1
  156. package/topmind-wechat-post/scripts/md2wechat.py +130 -27
  157. package/topmind-wechat-post/scripts/negative_tests.py +74 -0
  158. package/topmind-x-article/README.en.md +1 -1
  159. package/topmind-x-article/README.md +1 -1
  160. package/topmind-x-article/scripts/md2x.py +18 -3
  161. package/topmind-x-article/scripts/negative_tests.py +17 -0
@@ -87,6 +87,80 @@ def main() -> None:
87
87
  check("md2wechat 分隔线无 inline-block 告警",
88
88
  "inline-block" not in r.stdout, r.stdout[:200])
89
89
 
90
+ # 9. 括号 URL 不被截断(链接与图片;历史 bug:`![a](img(1).png)` 被截成
91
+ # `img(1` 导致真实文件记成缺失;`[维基](…/猫_(动物))` 的 URL 被截断、
92
+ # 正文多个悬挂 `)`;`[t](url "title")` 被原样保留)
93
+ (td / "img(1).png").write_bytes(_b64.b64decode(png))
94
+ (td / "paren.md").write_text(
95
+ "# t\n\n![括号图](img(1).png)\n\n"
96
+ "[维基](https://zh.wikipedia.org/wiki/猫_(动物)) 与 "
97
+ "[带title](https://example.com/a \"标题文字\")。\n",
98
+ encoding="utf-8")
99
+ r = run("md2wechat.py", ["--input", str(td / "paren.md"),
100
+ "--out-dir", str(td / "o9"), "--slug", "t9",
101
+ "--no-toc", "--signature", "off"])
102
+ html = (td / "o9" / "t9-公众号版.html").read_text(encoding="utf-8")
103
+ check("md2wechat 括号图片不截断",
104
+ 'src="images/img(1).png"' in html and (td / "o9" / "images" / "img(1).png").exists(),
105
+ r.stdout[:200])
106
+ check("md2wechat 括号链接不截断",
107
+ "猫_(动物)" in html and ")</sup>" not in html,
108
+ r.stdout[:200])
109
+ check("md2wechat title 链接被转换",
110
+ "https://example.com/a" in html and '[带title](' not in html,
111
+ r.stdout[:200])
112
+
113
+ # 10. 脚注 URL 的 & 不双重转义(历史 bug:显示成 &amp;)
114
+ (td / "amp.md").write_text(
115
+ "# t\n\n[和号](https://x.com/?a=1&b=2)\n", encoding="utf-8")
116
+ r = run("md2wechat.py", ["--input", str(td / "amp.md"),
117
+ "--out-dir", str(td / "o10"), "--slug", "t10",
118
+ "--no-toc", "--signature", "off"])
119
+ html = (td / "o10" / "t10-公众号版.html").read_text(encoding="utf-8")
120
+ check("md2wechat 脚注 URL 不双重转义",
121
+ "a=1&amp;b=2" in html and "&amp;amp;" not in html)
122
+
123
+ # 11. 坏主题 JSON 干净报错(历史 crash:json Traceback)
124
+ (td / "bad-theme.json").write_text("{bad json", encoding="utf-8")
125
+ (td / "t11.md").write_text("# t\n\n正文。\n", encoding="utf-8")
126
+ r = run("md2wechat.py", ["--input", str(td / "t11.md"),
127
+ "--out-dir", str(td / "o11"), "--slug", "t11",
128
+ "--theme", str(td / "bad-theme.json")])
129
+ check("md2wechat 坏主题 JSON 干净报错",
130
+ r.returncode != 0 and "Traceback" not in r.stderr, r.stderr[:100])
131
+
132
+ # 12. 目录当输入:文案明确(与 md2x 一致),非零干净退出
133
+ r = run("md2wechat.py", ["--input", str(td),
134
+ "--out-dir", str(td / "o12"), "--slug", "t12"])
135
+ check("md2wechat 目录输入文案正确",
136
+ r.returncode != 0 and "输入是目录不是文件" in r.stderr
137
+ and "Traceback" not in r.stderr, r.stderr[:100])
138
+
139
+ # 13. yaml/diff 代码块不高亮 crash(历史 crash:(?m) 拼进 alternation
140
+ # 报 "global flags not at the start",任何 ```yaml 块都 Traceback)
141
+ (td / "hl.md").write_text(
142
+ "# t\n\n```yaml\nkey: value\n```\n\n```diff\n+add\n-del\n```\n",
143
+ encoding="utf-8")
144
+ r = run("md2wechat.py", ["--input", str(td / "hl.md"),
145
+ "--out-dir", str(td / "o13"), "--slug", "t13"])
146
+ html = (td / "o13" / "t13-公众号版.html").read_text(encoding="utf-8")
147
+ check("md2wechat yaml/diff 代码块不崩溃",
148
+ r.returncode == 0 and "Traceback" not in r.stderr
149
+ and "key" in html, r.stderr[:100])
150
+
151
+ # 14. 嵌套围栏:```` 开栏不被内层 ``` 提前闭合
152
+ (td / "nest.md").write_text(
153
+ "# t\n\n````markdown\n外层\n```python\nprint(1)\n```\n结束\n````\n",
154
+ encoding="utf-8")
155
+ r = run("md2wechat.py", ["--input", str(td / "nest.md"),
156
+ "--out-dir", str(td / "o14"), "--slug", "t14",
157
+ "--no-toc", "--signature", "off"])
158
+ html = (td / "o14" / "t14-公众号版.html").read_text(encoding="utf-8")
159
+ body = html.split('<article id="wx-body"')[1]
160
+ check("md2wechat 嵌套围栏不提前闭合",
161
+ r.returncode == 0 and "````markdown" not in body
162
+ and body.count("MARKDOWN</section>") == 1, r.stderr[:100])
163
+
90
164
  if fails:
91
165
  print(f"\n[negative_tests] {len(fails)} 项失败")
92
166
  sys.exit(1)
@@ -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.9`)
7
+ - Version: **v0.1.0** (same tag as `@topmindspace/tms-skills@0.4.1`)
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.9` 同 tag)
7
+ - 版本:**v0.1.0**(与 `@topmindspace/tms-skills@0.4.1` 同 tag)
8
8
 
9
9
  ## 安装
10
10
 
@@ -193,6 +193,7 @@ def convert(md: str):
193
193
  defs = {}
194
194
  out_lines = []
195
195
  in_code = False
196
+ fence_len = 0
196
197
 
197
198
  md, esc_store = _protect_escapes(md)
198
199
  md = _strip_frontmatter(md)
@@ -209,9 +210,23 @@ def convert(md: str):
209
210
  for raw in body:
210
211
  line = raw.rstrip()
211
212
 
212
- # 代码块:先处理围栏,块内行原样缩进(分割线规则不进代码块)
213
- if line.strip().startswith("```"):
214
- in_code = not in_code
213
+ # 代码块:先处理围栏,块内行原样缩进(分割线规则不进代码块)。
214
+ # 围栏反引号数 >= 3:```` 开栏只能由 >= 4 反引号闭合(CommonMark),
215
+ # 否则 markdown 示例里的内层 ``` 会把外层栏提前"闭合",造成静默错排。
216
+ stripped = line.strip()
217
+ if stripped.startswith("```"):
218
+ k = 0
219
+ while k < len(stripped) and stripped[k] == "`":
220
+ k += 1
221
+ if not in_code:
222
+ in_code = True
223
+ fence_len = k
224
+ elif k >= fence_len and not stripped[k:].strip():
225
+ in_code = False
226
+ fence_len = 0
227
+ else:
228
+ # 栏内误写的短栏 / 带信息串的栏是代码内容,不是闭合栏
229
+ out_lines.append(" " + line)
215
230
  continue
216
231
  if in_code:
217
232
  out_lines.append(" " + line)
@@ -64,6 +64,23 @@ def main() -> None:
64
64
  out = (td / "o6.txt").read_text(encoding="utf-8") if (td / "o6.txt").exists() else ""
65
65
  check("正常输入含配图清单", r.returncode == 0 and "[图1]" in out)
66
66
 
67
+ # 7. 嵌套围栏:```` 开栏不被内层 ``` 提前闭合(内层栏是代码内容)
68
+ (td / "nest.md").write_text(
69
+ "# t\n\n````markdown\n外层\n```python\nprint(1)\n```\n结束\n````\n",
70
+ encoding="utf-8")
71
+ r = run([str(td / "nest.md"), "--out", str(td / "o7.txt")])
72
+ out = (td / "o7.txt").read_text(encoding="utf-8") if (td / "o7.txt").exists() else ""
73
+ check("嵌套围栏不提前闭合",
74
+ r.returncode == 0 and " ```python" in out and "print(1)" in out)
75
+
76
+ # 8. 括号 URL 链接不断裂(与 md2wechat 对齐的守卫)
77
+ (td / "paren.md").write_text(
78
+ "# t\n\n[维基](https://zh.wikipedia.org/wiki/猫_(动物))\n", encoding="utf-8")
79
+ r = run([str(td / "paren.md"), "--out", str(td / "o8.txt")])
80
+ out = (td / "o8.txt").read_text(encoding="utf-8") if (td / "o8.txt").exists() else ""
81
+ check("括号 URL 不截断",
82
+ r.returncode == 0 and "猫_(动物)" in out)
83
+
67
84
  if fails:
68
85
  print(f"\n[negative_tests] {len(fails)} 项失败")
69
86
  sys.exit(1)