@topmindspace/topmind-writing-skills 0.7.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.
- package/CHANGELOG.md +931 -0
- package/LICENSE +21 -0
- package/README.en.md +124 -0
- package/README.md +124 -0
- package/bin/topmind-writing-skills.js +388 -0
- package/package.json +56 -0
- package/topmind-briefs/CHANGELOG.md +22 -0
- package/topmind-briefs/README.en.md +41 -0
- package/topmind-briefs/README.md +37 -0
- package/topmind-briefs/SKILL.md +101 -0
- package/topmind-briefs/dist/topmind-briefs.manifest.json +21 -0
- package/topmind-briefs/dist/topmind-briefs.zip +0 -0
- package/topmind-briefs/package-lock.json +13 -0
- package/topmind-briefs/package.json +1 -0
- package/topmind-briefs/references/examples.md +131 -0
- package/topmind-briefs/references/platform-specs.md +63 -0
- package/topmind-briefs/references/style-guide.md +60 -0
- package/topmind-briefs/scripts/audit_css.py +39 -0
- package/topmind-briefs/scripts/audit_docs.py +80 -0
- package/topmind-briefs/scripts/audit_skill.py +60 -0
- package/topmind-briefs/scripts/audit_styles.py +54 -0
- package/topmind-briefs/scripts/negative_tests.py +88 -0
- package/topmind-briefs/scripts/package_skill.py +188 -0
- package/topmind-cover/README.en.md +54 -0
- package/topmind-cover/README.md +54 -0
- package/topmind-cover/SKILL.md +134 -0
- package/topmind-cover/assets/examples/README.md +34 -0
- package/topmind-cover/assets/examples/bg-blur-alt.png +0 -0
- package/topmind-cover/assets/examples/bg-blur-wechat.png +0 -0
- package/topmind-cover/assets/examples/bg-blur.png +0 -0
- package/topmind-cover/assets/examples/big-type-wechat.png +0 -0
- package/topmind-cover/assets/examples/big-type.png +0 -0
- package/topmind-cover/assets/examples/brand-launch-wechat.png +0 -0
- package/topmind-cover/assets/examples/brand-launch.png +0 -0
- package/topmind-cover/assets/examples/gan-huo-wechat.png +0 -0
- package/topmind-cover/assets/examples/gan-huo.png +0 -0
- package/topmind-cover/assets/examples/ip-fun-wechat.png +0 -0
- package/topmind-cover/assets/examples/ip-fun.png +0 -0
- package/topmind-cover/assets/examples/magazine-wechat.png +0 -0
- package/topmind-cover/assets/examples/magazine.png +0 -0
- package/topmind-cover/assets/examples/minimal-wechat.png +0 -0
- package/topmind-cover/assets/examples/minimal.png +0 -0
- package/topmind-cover/assets/examples/news-flash-wechat.png +0 -0
- package/topmind-cover/assets/examples/news-flash.png +0 -0
- package/topmind-cover/assets/examples/overview.png +0 -0
- package/topmind-cover/assets/examples/paper-collage-alt.png +0 -0
- package/topmind-cover/assets/examples/paper-collage-wechat.png +0 -0
- package/topmind-cover/assets/examples/paper-collage.png +0 -0
- package/topmind-cover/assets/examples/tutorial-steps-wechat.png +0 -0
- package/topmind-cover/assets/examples/tutorial-steps.png +0 -0
- package/topmind-cover/assets/examples/white-clean-alt-wechat.png +0 -0
- package/topmind-cover/assets/examples/white-clean-alt.png +0 -0
- package/topmind-cover/assets/examples/white-clean-wechat.png +0 -0
- package/topmind-cover/assets/examples/white-clean.png +0 -0
- package/topmind-cover/package-lock.json +16 -0
- package/topmind-cover/package.json +16 -0
- package/topmind-cover/references/cover-prompts.md +436 -0
- package/topmind-cover/references/cover-styles.md +496 -0
- package/topmind-cover/references/impact-language.md +94 -0
- package/topmind-cover/references/ref-white-clean-1.png +0 -0
- package/topmind-cover/references/ref-white-clean-2.png +0 -0
- package/topmind-cover/scripts/audit_css.py +39 -0
- package/topmind-cover/scripts/audit_docs.py +80 -0
- package/topmind-cover/scripts/audit_skill.py +60 -0
- package/topmind-cover/scripts/audit_styles.py +54 -0
- package/topmind-cover/scripts/crop-cover.py +74 -0
- package/topmind-cover/scripts/negative_tests.py +71 -0
- package/topmind-cover/scripts/package_skill.py +188 -0
- package/topmind-wechat-post/README.en.md +111 -0
- package/topmind-wechat-post/README.md +111 -0
- package/topmind-wechat-post/SKILL.md +251 -0
- package/topmind-wechat-post/assets/themes/amber-review.json +35 -0
- package/topmind-wechat-post/assets/themes/graphite.json +35 -0
- package/topmind-wechat-post/assets/themes/minimal-ink.json +35 -0
- package/topmind-wechat-post/assets/themes/newsprint.json +35 -0
- package/topmind-wechat-post/assets/themes/tech-blue.json +35 -0
- package/topmind-wechat-post/package-lock.json +16 -0
- package/topmind-wechat-post/package.json +16 -0
- package/topmind-wechat-post/references/design.md +50 -0
- package/topmind-wechat-post/references/element-spec.md +163 -0
- package/topmind-wechat-post/references/known-pits.md +85 -0
- package/topmind-wechat-post/references/theme-map.md +139 -0
- package/topmind-wechat-post/references/typography-rules.md +62 -0
- package/topmind-wechat-post/references/wechat-constraints.md +111 -0
- package/topmind-wechat-post/references/workflow.md +102 -0
- package/topmind-wechat-post/references/writing-quality.md +105 -0
- package/topmind-wechat-post/scripts/audit_css.py +39 -0
- package/topmind-wechat-post/scripts/audit_docs.py +80 -0
- package/topmind-wechat-post/scripts/audit_skill.py +60 -0
- package/topmind-wechat-post/scripts/audit_styles.py +54 -0
- package/topmind-wechat-post/scripts/lint-wechat.py +446 -0
- package/topmind-wechat-post/scripts/md2wechat.py +1792 -0
- package/topmind-wechat-post/scripts/negative_tests.py +171 -0
- package/topmind-wechat-post/scripts/new-article.py +183 -0
- package/topmind-wechat-post/scripts/package_skill.py +188 -0
- package/topmind-wechat-post/scripts/push-to-topstream.py +226 -0
- package/topmind-wechat-post/scripts/scan_ai_flavor.py +464 -0
- package/topmind-wechat-post/scripts/sync-mapping.py +220 -0
- package/topmind-wechat-post/scripts/sync-status.py +187 -0
- package/topmind-x-article/README.en.md +109 -0
- package/topmind-x-article/README.md +104 -0
- package/topmind-x-article/SKILL.md +156 -0
- package/topmind-x-article/package-lock.json +16 -0
- package/topmind-x-article/package.json +16 -0
- package/topmind-x-article/references/publish-checklist.md +31 -0
- package/topmind-x-article/references/x-format.md +27 -0
- package/topmind-x-article/references/x-html-format.md +85 -0
- package/topmind-x-article/scripts/audit_css.py +39 -0
- package/topmind-x-article/scripts/audit_docs.py +80 -0
- package/topmind-x-article/scripts/audit_skill.py +60 -0
- package/topmind-x-article/scripts/audit_styles.py +54 -0
- package/topmind-x-article/scripts/md2x-html.py +522 -0
- package/topmind-x-article/scripts/md2x.py +323 -0
- package/topmind-x-article/scripts/negative_tests.py +91 -0
- package/topmind-x-article/scripts/package_skill.py +188 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""sync-status.py — 同步公众号交付包的「状态 ⇄ 目录名 ⇄ 字数」。
|
|
4
|
+
|
|
5
|
+
规则(与专题 topic.md 的目录规范一致):
|
|
6
|
+
status = 草稿 → 目录名 YYYY-MM-DD-<中文名>
|
|
7
|
+
status = 定稿 / 已发布 → 目录名 YYYY-MM-DD-<中文名>-released
|
|
8
|
+
|
|
9
|
+
同时刷新 frontmatter 的 word_count(正文中文字数)。
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
python3 sync-status.py # 扫描全部,只报告(dry-run)
|
|
13
|
+
python3 sync-status.py --apply # 实际重命名并回写字数
|
|
14
|
+
python3 sync-status.py --set 定稿 <包目录> # 改状态 + 同步目录名
|
|
15
|
+
python3 sync-status.py --base <专题目录>
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import os
|
|
20
|
+
import re
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
def _default_base():
|
|
24
|
+
"""交付包根:CLI --base → env TOPMIND_WECHAT_BASE → env TOPMIND_WORKSPACE 发现 → 惯例路径。"""
|
|
25
|
+
env = os.environ.get("TOPMIND_WECHAT_BASE") or os.environ.get("TOPMIND_WECHAT_PACKAGE_ROOT")
|
|
26
|
+
if env:
|
|
27
|
+
return os.path.abspath(os.path.expanduser(env))
|
|
28
|
+
ws = os.environ.get("TOPMIND_WORKSPACE")
|
|
29
|
+
if ws:
|
|
30
|
+
for rel in (
|
|
31
|
+
("40-创作", "2026-公众号"),
|
|
32
|
+
("20-专题", "2026-公众号"),
|
|
33
|
+
("88-交付", "2026-公众号"),
|
|
34
|
+
):
|
|
35
|
+
p = os.path.join(ws, *rel)
|
|
36
|
+
if os.path.isdir(p):
|
|
37
|
+
return p
|
|
38
|
+
return os.path.join(ws, "40-创作", "2026-公众号")
|
|
39
|
+
# 惯例:父工作区(可被 CLI 覆盖)
|
|
40
|
+
return os.path.join(
|
|
41
|
+
os.path.expanduser("~"), "TopWorkSpace", "topmind-workspace",
|
|
42
|
+
"40-创作", "2026-公众号")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _default_topstream():
|
|
46
|
+
env = os.environ.get("TOPSTREAM_ROOT") or os.environ.get("TOPMIND_TOPSTREAM")
|
|
47
|
+
if env:
|
|
48
|
+
return os.path.abspath(os.path.expanduser(env))
|
|
49
|
+
return os.path.join(os.path.expanduser("~"), "TopWorkSpace", "topstream")
|
|
50
|
+
|
|
51
|
+
DEFAULT_BASE = _default_base()
|
|
52
|
+
|
|
53
|
+
FINAL_STATUSES = ("定稿", "已发布")
|
|
54
|
+
VALID_STATUSES = ("草稿",) + FINAL_STATUSES
|
|
55
|
+
RELEASED_SUFFIX = "-released"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def split_fm(text):
|
|
59
|
+
"""返回 (frontmatter, body, head, tail_sep);无 frontmatter 时 fm=None"""
|
|
60
|
+
if not text.startswith("---\n"):
|
|
61
|
+
return None, text, "", ""
|
|
62
|
+
i = text.find("\n---", 3)
|
|
63
|
+
if i < 0:
|
|
64
|
+
return None, text, "", ""
|
|
65
|
+
return text[4:i], text[i + 4:].lstrip("\n"), text[:4], text[i:i + 4]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_field(fm, key):
|
|
69
|
+
m = re.search(r"^%s:\s*(.*)$" % re.escape(key), fm, re.M)
|
|
70
|
+
return m.group(1).strip().strip('"') if m else None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def set_field(fm, key, val):
|
|
74
|
+
line = "%s: %s" % (key, val)
|
|
75
|
+
pat = re.compile(r"^%s:\s*.*$" % re.escape(key), re.M)
|
|
76
|
+
if pat.search(fm):
|
|
77
|
+
return pat.sub(line, fm, count=1)
|
|
78
|
+
return fm.rstrip("\n") + "\n" + line + "\n"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def scan(base):
|
|
82
|
+
"""返回 [(dirname, status, word_count, needs_rename, target_name)]"""
|
|
83
|
+
rows = []
|
|
84
|
+
for name in sorted(os.listdir(base)):
|
|
85
|
+
pkg = os.path.join(base, name)
|
|
86
|
+
draft = os.path.join(pkg, "公众号稿.md")
|
|
87
|
+
if not os.path.isdir(pkg) or not os.path.exists(draft):
|
|
88
|
+
continue
|
|
89
|
+
text = open(draft, encoding="utf-8").read()
|
|
90
|
+
fm, body, head, sep = split_fm(text)
|
|
91
|
+
if fm is None:
|
|
92
|
+
rows.append((name, None, None, False, None, "无 frontmatter"))
|
|
93
|
+
continue
|
|
94
|
+
status = get_field(fm, "status") or "草稿"
|
|
95
|
+
cn = len(re.findall(r"[\u4e00-\u9fff]", body))
|
|
96
|
+
|
|
97
|
+
want_final = status in FINAL_STATUSES
|
|
98
|
+
stem = name[:-len(RELEASED_SUFFIX)] if name.endswith(RELEASED_SUFFIX) else name
|
|
99
|
+
target = stem + (RELEASED_SUFFIX if want_final else "")
|
|
100
|
+
rows.append((name, status, cn, target != name, target, ""))
|
|
101
|
+
return rows
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def apply_rename(base, name, target, draft_path, fm, body, head, new_fm):
|
|
105
|
+
"""写回 frontmatter 后重命名目录"""
|
|
106
|
+
open(draft_path, "w", encoding="utf-8").write("---\n" + new_fm + "\n---\n\n" + body)
|
|
107
|
+
if target != name:
|
|
108
|
+
os.rename(os.path.join(base, name), os.path.join(base, target))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def main():
|
|
112
|
+
ap = argparse.ArgumentParser()
|
|
113
|
+
ap.add_argument("--base", default=DEFAULT_BASE)
|
|
114
|
+
ap.add_argument("--apply", action="store_true", help="实际执行(默认只报告)")
|
|
115
|
+
ap.add_argument("--set", metavar="STATUS", choices=VALID_STATUSES,
|
|
116
|
+
help="把指定包改成该状态(需配合包名)")
|
|
117
|
+
ap.add_argument("pkg", nargs="?", help="包目录名(配合 --set 使用)")
|
|
118
|
+
args = ap.parse_args()
|
|
119
|
+
|
|
120
|
+
if not os.path.isdir(args.base):
|
|
121
|
+
print("✗ 专题目录不存在:%s" % args.base)
|
|
122
|
+
return 1
|
|
123
|
+
|
|
124
|
+
# 单包改状态
|
|
125
|
+
if args.set:
|
|
126
|
+
if not args.pkg:
|
|
127
|
+
print("✗ --set 需要指定包目录名")
|
|
128
|
+
return 1
|
|
129
|
+
draft = os.path.join(args.base, args.pkg, "公众号稿.md")
|
|
130
|
+
if not os.path.exists(draft):
|
|
131
|
+
print("✗ 找不到:%s" % draft)
|
|
132
|
+
return 1
|
|
133
|
+
text = open(draft, encoding="utf-8").read()
|
|
134
|
+
fm, body, head, sep = split_fm(text)
|
|
135
|
+
if fm is None:
|
|
136
|
+
print("✗ 该文件无 frontmatter")
|
|
137
|
+
return 1
|
|
138
|
+
fm = set_field(fm, "status", args.set)
|
|
139
|
+
cn = len(re.findall(r"[\u4e00-\u9fff]", body))
|
|
140
|
+
fm = set_field(fm, "word_count", str(cn))
|
|
141
|
+
|
|
142
|
+
want_final = args.set in FINAL_STATUSES
|
|
143
|
+
stem = args.pkg[:-len(RELEASED_SUFFIX)] if args.pkg.endswith(RELEASED_SUFFIX) else args.pkg
|
|
144
|
+
target = stem + (RELEASED_SUFFIX if want_final else "")
|
|
145
|
+
|
|
146
|
+
if args.apply:
|
|
147
|
+
apply_rename(args.base, args.pkg, target, draft, fm, body, head, fm)
|
|
148
|
+
print("✓ %s → status=%s,目录 %s(%d 中文字)" % (
|
|
149
|
+
args.pkg, args.set, target if target != args.pkg else "不变", cn))
|
|
150
|
+
else:
|
|
151
|
+
print("[dry-run] %s → status=%s,目录将变为 %s" % (args.pkg, args.set, target))
|
|
152
|
+
return 0
|
|
153
|
+
|
|
154
|
+
rows = scan(args.base)
|
|
155
|
+
if not rows:
|
|
156
|
+
print("专题下没有交付包:%s" % args.base)
|
|
157
|
+
return 0
|
|
158
|
+
|
|
159
|
+
print("%-44s %-6s %8s %s" % ("包目录", "状态", "中文字", "待同步"))
|
|
160
|
+
print("-" * 84)
|
|
161
|
+
changed = 0
|
|
162
|
+
for name, status, cn, needs, target, note in rows:
|
|
163
|
+
if status is None:
|
|
164
|
+
print("%-44s %-6s %8s %s" % (name, "-", "-", note))
|
|
165
|
+
continue
|
|
166
|
+
flag = "→ " + target if needs else ""
|
|
167
|
+
print("%-44s %-6s %8s %s" % (name, status, cn, flag))
|
|
168
|
+
|
|
169
|
+
if args.apply:
|
|
170
|
+
draft = os.path.join(args.base, name, "公众号稿.md")
|
|
171
|
+
text = open(draft, encoding="utf-8").read()
|
|
172
|
+
fm, body, head, sep = split_fm(text)
|
|
173
|
+
fm = set_field(fm, "word_count", str(cn))
|
|
174
|
+
apply_rename(args.base, name, target, draft, fm, body, head, fm)
|
|
175
|
+
if needs:
|
|
176
|
+
changed += 1
|
|
177
|
+
|
|
178
|
+
if args.apply:
|
|
179
|
+
print("\n✓ 已刷新 %d 个包的 word_count,重命名 %d 个目录" % (len(rows), changed))
|
|
180
|
+
else:
|
|
181
|
+
pending = sum(1 for r in rows if r[3])
|
|
182
|
+
print("\n[dry-run] %d 个包目录名与状态不一致,加 --apply 执行" % pending)
|
|
183
|
+
return 0
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if __name__ == "__main__":
|
|
187
|
+
sys.exit(main())
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# topmind-x-article · One-Click X Long-Form Publishing
|
|
2
|
+
|
|
3
|
+
**[中文](./README.md)** | English
|
|
4
|
+
|
|
5
|
+
Turn a Markdown draft into a "copy → paste → publish" X long-form (Article) package.
|
|
6
|
+
|
|
7
|
+
- Version: **v0.4.0** (same tag as `@topmindspace/topmind-writing-skills@0.7.1`)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @topmindspace/topmind-writing-skills install topmind-x-article
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 1. Draft → one-click-copy HTML (preferred)
|
|
19
|
+
python3 scripts/md2x-html.py <draft>.md --out <package>/X长文.html \
|
|
20
|
+
--images-from 公众号稿.md [--cover cover-1500x600.png]
|
|
21
|
+
# --images-from derives image order from the WeChat draft in document order
|
|
22
|
+
# (required when the X draft is derived from it);
|
|
23
|
+
# never hand-assemble --images (filename sort order != document order —
|
|
24
|
+
# this once misplaced a whole section's images).
|
|
25
|
+
# Open X长文.html in a browser → click the top 「一键复制全文」 button → paste into the X Article editor body
|
|
26
|
+
# (the first # heading is excluded from the clipboard — fill it into X's title field by hand;
|
|
27
|
+
# upload the cover separately via X's dedicated cover entry)
|
|
28
|
+
|
|
29
|
+
# 2. Plain-text fallback (when HTML copying misbehaves)
|
|
30
|
+
python3 scripts/md2x.py <draft>.md --out <package>/X发布稿.txt
|
|
31
|
+
|
|
32
|
+
# 3. Cover: generate a 1200×675 cover with topmind-cover
|
|
33
|
+
|
|
34
|
+
# 4. Follow references/publish-checklist.md item by item
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Conversion rules
|
|
38
|
+
|
|
39
|
+
The HTML path follows `references/x-html-format.md`: rich-text paste into the X editor
|
|
40
|
+
(headings/bold/links/lists/quote blocks preserved); ` ``` ` prompt blocks render as quote
|
|
41
|
+
blocks with a 「复制提示词」 copy button; GFM tables become lists (X drops `<table>` on paste);
|
|
42
|
+
the first `#` heading is excluded from the clipboard; images are base64-inlined and numbered
|
|
43
|
+
`[图N]`, with per-image 「下载图片」 download buttons as fallback upload.
|
|
44
|
+
|
|
45
|
+
Prompt copying is dual-channel: the author side uses the 「复制提示词」 button in the HTML
|
|
46
|
+
(to grab the text before publishing); the reader-side one-click copy can only come from X
|
|
47
|
+
native code blocks (convert each block by hand via Insert → Code — native code blocks carry a
|
|
48
|
+
native copy button, while pasted `<pre>` is discarded by X).
|
|
49
|
+
|
|
50
|
+
The plain-text fallback follows `references/x-format.md`: headings → plain text lines,
|
|
51
|
+
horizontal rules → blank lines, emphasis markers removed, links → `text(url)`, images →
|
|
52
|
+
`[图N]` (image list appended at the end), tables → "label:value" lists, blockquotes unquoted.
|
|
53
|
+
|
|
54
|
+
Read the result through once by hand after converting.
|
|
55
|
+
|
|
56
|
+
## Minimal example
|
|
57
|
+
|
|
58
|
+
Input (10 lines of markdown):
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
# Manus 2.0 发布了
|
|
62
|
+
|
|
63
|
+
**从零重建**的 Agent,新增了 Cue 个人助手。
|
|
64
|
+
|
|
65
|
+

|
|
66
|
+
|
|
67
|
+
| Token 消耗 | -23.2% |
|
|
68
|
+
| 耗时 | -28.2% |
|
|
69
|
+
|
|
70
|
+
详见[官方博客](https://manus.im/blog)。
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`python3 scripts/md2x.py draft.md --out X发布稿.txt` produces:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
Manus 2.0 发布了
|
|
77
|
+
|
|
78
|
+
从零重建的 Agent,新增了 Cue 个人助手。
|
|
79
|
+
|
|
80
|
+
[图1]
|
|
81
|
+
|
|
82
|
+
Token 消耗:-23.2%
|
|
83
|
+
耗时:-28.2%
|
|
84
|
+
|
|
85
|
+
详见官方博客(https://manus.im/blog)。
|
|
86
|
+
|
|
87
|
+
—— 配图清单 ——
|
|
88
|
+
[图1] 发布会现场
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Copy the whole `X发布稿.txt` → paste into the X Article editor → upload images in `[图N]` order → publish.
|
|
92
|
+
|
|
93
|
+
## Publishing
|
|
94
|
+
|
|
95
|
+
X long-form posts are currently published by hand-pasting into the X Article editor; the API does not publish long-form. After publishing, do per the checklist: pin a first comment with the extra info, fetch the full text back for verification.
|
|
96
|
+
|
|
97
|
+
## External dependencies
|
|
98
|
+
|
|
99
|
+
The following skills are **not in this repo** (usually provided by the user's local workbuddy environment). Missing ones disable the corresponding routed capability; the core flow (draft → text, cover, publish checklist) is unaffected:
|
|
100
|
+
|
|
101
|
+
- `topmind-x`: 280-char short posts (its xurl only covers short posts, not long-form).
|
|
102
|
+
- `topmind-capture`: the "archive only, don't publish" routing path.
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
python3 scripts/package_skill.py --check # pre-publish check
|
|
108
|
+
python3 scripts/negative_tests.py # bad-input tests
|
|
109
|
+
```
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# topmind-x-article · X 长文一键发布
|
|
2
|
+
|
|
3
|
+
[English](./README.en.md) | 中文
|
|
4
|
+
|
|
5
|
+
把 Markdown 原稿变成"复制 → 粘贴 → 发"的 X 长文(Article)发布包。
|
|
6
|
+
|
|
7
|
+
- 版本:**v0.4.0**(与 `@topmindspace/topmind-writing-skills@0.7.1` 同 tag)
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @topmindspace/topmind-writing-skills install topmind-x-article
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 用法
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 1. 原稿转一键复制 HTML(首选)
|
|
19
|
+
python3 scripts/md2x-html.py <原稿>.md --out <包>/X长文.html \
|
|
20
|
+
--images-from 公众号稿.md [--cover cover-1500x600.png]
|
|
21
|
+
# --images-from 从公众号稿按文档顺序派生图片(X 稿由公众号稿派生时必用);
|
|
22
|
+
# 禁止手工拼 --images 列表(文件名排序 ≠ 文档顺序,曾导致整段配图错位)。
|
|
23
|
+
# 浏览器打开 X长文.html → 点页顶「一键复制全文」→ 粘贴进 X Article 编辑器正文
|
|
24
|
+
# (首个 # 标题不进剪贴板,手动填入 X 标题栏;封面在 X 独立入口单独上传)
|
|
25
|
+
|
|
26
|
+
# 2. 纯文本兜底(HTML 复制异常时)
|
|
27
|
+
python3 scripts/md2x.py <原稿>.md --out <包>/X发布稿.txt
|
|
28
|
+
|
|
29
|
+
# 3. 封面图:用 topmind-cover 生成 1200×675
|
|
30
|
+
|
|
31
|
+
# 4. 按 references/publish-checklist.md 逐项发布
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 转换规则
|
|
35
|
+
|
|
36
|
+
HTML 链路按 `references/x-html-format.md`:富文本粘贴进 X 编辑器(标题/加粗/链接/
|
|
37
|
+
列表/引用块保留);` ``` ` 提示词块渲染为引用块 + 「复制提示词」按钮;GFM 表格转列表
|
|
38
|
+
(X 粘贴丢弃 `<table>`);首个 `#` 标题不进剪贴板;配图 base64 内嵌、按 `[图N]` 编号,
|
|
39
|
+
带不入编辑器时用图下「下载图片」按编号上传。
|
|
40
|
+
|
|
41
|
+
提示词的复制分双通道:作者侧用 HTML 里的「复制提示词」按钮(发布前取用文本);
|
|
42
|
+
读者侧一键复制只能来自 X 原生代码块(Insert → Code 手动逐块转换;原生代码块带
|
|
43
|
+
native copy button,粘贴 `<pre>` 会被 X 丢弃,走不过去)。
|
|
44
|
+
|
|
45
|
+
纯文本兜底按 `references/x-format.md`:标题→纯文本行、分隔线→空行、加粗/斜体/
|
|
46
|
+
行内代码去标记、链接→`文字(url)`、图片→`[图N]`(文末附配图清单)、表格→"项:值"列表、
|
|
47
|
+
引用去 `>`。转完必须人工通读一遍。
|
|
48
|
+
|
|
49
|
+
## 最小示例
|
|
50
|
+
|
|
51
|
+
输入(10 行 markdown):
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
# Manus 2.0 发布了
|
|
55
|
+
|
|
56
|
+
**从零重建**的 Agent,新增了 Cue 个人助手。
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
| Token 消耗 | -23.2% |
|
|
61
|
+
| 耗时 | -28.2% |
|
|
62
|
+
|
|
63
|
+
详见[官方博客](https://manus.im/blog)。
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`python3 scripts/md2x.py 原稿.md --out X发布稿.txt` 得到:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Manus 2.0 发布了
|
|
70
|
+
|
|
71
|
+
从零重建的 Agent,新增了 Cue 个人助手。
|
|
72
|
+
|
|
73
|
+
[图1]
|
|
74
|
+
|
|
75
|
+
Token 消耗:-23.2%
|
|
76
|
+
耗时:-28.2%
|
|
77
|
+
|
|
78
|
+
详见官方博客(https://manus.im/blog)。
|
|
79
|
+
|
|
80
|
+
—— 配图清单 ——
|
|
81
|
+
[图1] 发布会现场
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
复制 `X发布稿.txt` 全文 → 粘贴进 X Article 编辑器 → 按 `[图N]` 顺序上传配图 → 发布。
|
|
85
|
+
|
|
86
|
+
## 发布
|
|
87
|
+
|
|
88
|
+
X 长文目前走人工粘贴发布(X Article 编辑器),API 不发长文。
|
|
89
|
+
发布后按清单做:首条评论置顶补信息、全文抓回核对。
|
|
90
|
+
|
|
91
|
+
## 外部依赖
|
|
92
|
+
|
|
93
|
+
以下技能**不在本仓库**(一般随用户侧 workbuddy 环境提供)。缺失时对应路由能力
|
|
94
|
+
不可用,不影响本技能核心流程(原稿转文本、封面、发布清单):
|
|
95
|
+
|
|
96
|
+
- `topmind-x`:280 字短推文发布(xurl 只覆盖短推文,不发长文)。
|
|
97
|
+
- `topmind-capture`:「只想存档不发布」时的收录路由。
|
|
98
|
+
|
|
99
|
+
## 开发
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python3 scripts/package_skill.py --check # 发布前校验
|
|
103
|
+
python3 scripts/negative_tests.py # 异常输入测试
|
|
104
|
+
```
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: topmind-x-article
|
|
3
|
+
version: 0.4.0
|
|
4
|
+
description: "X 长文(Article)一键发布:Markdown 原稿 → 可直接复制的 X长文.html(富文本一键复制+配图内嵌)/ X发布稿.txt + 封面图 + 发布清单。沉淀自实战。Use when X 长文、发 X 文章、X article、长文发 X。Do NOT use for 短推文(→ topmind-x)、公众号(→ topmind-wechat-post)。"
|
|
5
|
+
action_category: write
|
|
6
|
+
triggers:
|
|
7
|
+
- X 长文
|
|
8
|
+
- 发 X 文章
|
|
9
|
+
- X article
|
|
10
|
+
- 长文发 X
|
|
11
|
+
- X 发长文
|
|
12
|
+
- 转纯文本
|
|
13
|
+
- X 纯文本
|
|
14
|
+
- 发 article
|
|
15
|
+
- 一键复制
|
|
16
|
+
triggers_cn:
|
|
17
|
+
- 写 X 长文
|
|
18
|
+
- X 长文发布
|
|
19
|
+
- 推特长文
|
|
20
|
+
- twitter 长文
|
|
21
|
+
author: TopMindspace
|
|
22
|
+
license: MIT
|
|
23
|
+
homepage: https://github.com/topmindspace/topmind-writing-skills#readme
|
|
24
|
+
updated: 2026-09-29
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# topmind-x-article · X 长文一键发布
|
|
28
|
+
|
|
29
|
+
把一篇 Markdown 原稿变成"复制 → 粘贴 → 发"的 X 长文发布包。
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
原稿.md → md2x-html.py → X长文.html(一键复制全文+配图)→ 封面图(topmind-cover) → 发布清单 → 人工粘贴发布
|
|
33
|
+
原稿.md → md2x.py → X发布稿.txt(纯文本兜底)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 语言铁律
|
|
37
|
+
|
|
38
|
+
- **默认中文**:标题、正文、配图文案一律用中文写作,这是默认行为,不需要用户每次声明。
|
|
39
|
+
- **英文是例外**:只有用户**明确说**"写英文文章/帖子"时才用英文。用户消息里夹杂英文词、
|
|
40
|
+
给英文参考素材、引用英文原文,都不算"要求写英文"。
|
|
41
|
+
- 引用英文一手素材(官方公告、模型卡、论文标题)时保留英文原文,正文主体仍是中文,
|
|
42
|
+
必要时在旁给中文翻译。
|
|
43
|
+
|
|
44
|
+
## 工作流
|
|
45
|
+
|
|
46
|
+
1. **转 HTML**(一键复制的核心,首选):
|
|
47
|
+
```bash
|
|
48
|
+
python3 scripts/md2x-html.py <原稿>.md --out <包>/X长文.html \
|
|
49
|
+
--images-from 公众号稿.md [--cover cover-1500x600.png]
|
|
50
|
+
```
|
|
51
|
+
`--images-from` 从公众号稿按文档顺序派生图片(X 稿永远由公众号稿派生时必用)。
|
|
52
|
+
**禁止手工拼 `--images` 列表**:文件名数字顺序 ≠ 文档顺序
|
|
53
|
+
(如 `14-kling` 与 `15-china-models` 按名排序会错位),手工传参曾导致整段配图错乱。
|
|
54
|
+
只有无公众号稿可派生的纯 X 原创稿,才允许用 `--images <图1> <图2> ...`,
|
|
55
|
+
此时必须逐张核对文件名与 `[图N]` 的对应关系。
|
|
56
|
+
单文件 HTML:内联样式 + 配图 base64 内嵌。浏览器打开后点页顶
|
|
57
|
+
「一键复制全文」,富文本(含格式)进剪贴板,去 X 文章编辑器粘贴。
|
|
58
|
+
转换规则见 `references/x-html-format.md`。
|
|
59
|
+
- `#` 首个标题**不进剪贴板**:手动填入 X 标题栏(工具栏有三步话术提示)。
|
|
60
|
+
- 每张配图自动编号 `[图N]`;图片 data-URI 内嵌,能随粘贴带入编辑器最好,
|
|
61
|
+
带不进去时用图下「下载图片」按钮按编号下载再上传——不用找文件、不用对顺序。
|
|
62
|
+
点击图片弹出 lightbox 放大看原图(右键可另存/截图,不拦截右键菜单)。
|
|
63
|
+
- 每个 ``` 提示词块渲染为引用块(X 可识别)+ 右上角「复制提示词」按钮,
|
|
64
|
+
一键复制该块纯文本。**复制分双通道**:作者侧用 HTML 里的按钮(发布前取用文本);
|
|
65
|
+
读者侧一键复制只能来自 X 原生代码块,需在编辑器里 Insert → Code 手动逐块转换
|
|
66
|
+
(X 原生代码块带 native copy button;粘贴 `<pre>` 会被 X 丢弃,走不过去)。
|
|
67
|
+
详见 `references/x-html-format.md`「提示词的复制链路(双通道)」。
|
|
68
|
+
- 封面走 `--cover` 只在页顶预览 + 提供下载;**封面始终在 X 编辑器单独上传**
|
|
69
|
+
(X 有独立封面入口)。
|
|
70
|
+
2. **转纯文本**(兜底):`python3 scripts/md2x.py <原稿>.md --out <包>/X发布稿.txt`,
|
|
71
|
+
规则见 `references/x-format.md`。HTML 复制异常时的备用入口。
|
|
72
|
+
转完**通读一遍**:X 不渲染 markdown,标记剥离后断句、emphasis 全靠文字本身,
|
|
73
|
+
读不顺就回原稿改。
|
|
74
|
+
3. **封面图**:调 `topmind-cover`,平台选 `x`,得 1500×600 主图。
|
|
75
|
+
4. **发布清单**:按 `references/publish-checklist.md` 逐项过。
|
|
76
|
+
5. **发布**:用户在 X Article 编辑器粘贴全文、上传封面与配图(按 `[图N]` 编号),
|
|
77
|
+
人工点发布。**API 不发长文**(topmind-x 的 xurl 只覆盖短推文)。
|
|
78
|
+
6. **收尾**:记录发布时间与链接;全文抓回核对一遍(标题、数字、图序)。
|
|
79
|
+
|
|
80
|
+
## 目录约定
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
<包>/
|
|
84
|
+
├── 原稿.md # 输入(或复用既有原稿)
|
|
85
|
+
├── X长文.html # 首选复制入口:浏览器打开,一键复制全文
|
|
86
|
+
├── X发布稿.txt # 纯文本兜底入口
|
|
87
|
+
├── cover-1500x600.png # 封面(topmind-cover 产出,X 编辑器单独上传)
|
|
88
|
+
└── 发布清单.md # 本次发布 checklist(含时间、链接)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 实战沉淀
|
|
92
|
+
|
|
93
|
+
- **事实铁律**:承重事实(数字、排名、发布日期、融资额)逐条回一手来源
|
|
94
|
+
(官方公告/模型卡/论文/财报);厂商给的数字标"厂商口径"或"官方口径";
|
|
95
|
+
媒体转引标"据 XX 报道";查不到一手来源的传闻删;推测必须显式标"(推测)",
|
|
96
|
+
与事实段落切割,不混写。改稿续写时正文已有数字回源重核(上一轮文本最不可信)。
|
|
97
|
+
- **文字铁律**:去 AI 味、精炼、不编造;看图即得的简单事实不再展开复述;
|
|
98
|
+
多用第三方客观素材,观点可以撞、表达必须原创。
|
|
99
|
+
- **交付铁律**:发布/分享时直接用交付的 HTML 原文件原样呈现,不临时重新生成版本。
|
|
100
|
+
- 补充信息(邀请码、链接、勘误)**不挤正文**,发在发布后首条评论并置顶
|
|
101
|
+
- 标题 ≤140 字符,首段 3 行内出钩子;配图逐张按 `[图N]` 顺序上传,传完对照清单点一遍
|
|
102
|
+
- 事实修正只改发布包,不回头改已发原文(除非勘误)
|
|
103
|
+
- 提示词密集型文章(如 N 条直出提示词),发布时建议把提示词引用块逐块转为
|
|
104
|
+
X 原生代码块(Insert → Code → 粘贴 → 删原块,每块约 10 秒):这是 X 平台唯一可靠的
|
|
105
|
+
读者侧一键复制链路(原生代码块带 native copy button,已实测确认)
|
|
106
|
+
- X 编辑器对剪贴板 data-URI 图片的处理不稳定:**文本格式一键复制可靠,
|
|
107
|
+
图片按"能带入则带入,带不入则按编号下载上传"处理**,不要承诺用户图片 100% 一键带图
|
|
108
|
+
|
|
109
|
+
## When NOT to use
|
|
110
|
+
|
|
111
|
+
- 280 字短推文 → `topmind-x`
|
|
112
|
+
- 公众号 → `topmind-wechat-post`
|
|
113
|
+
- 只想存档不发布 → `topmind-capture`
|
|
114
|
+
- 写稿(只有发布需求、无原稿时)→ 先走写作技能再回本技能
|
|
115
|
+
|
|
116
|
+
## 外部依赖
|
|
117
|
+
|
|
118
|
+
以下技能**不在本仓库**(一般随用户侧 workbuddy 环境提供);缺失时对应路由能力不可用,
|
|
119
|
+
本技能核心流程(原稿转文本、封面、发布清单)不受影响:
|
|
120
|
+
|
|
121
|
+
- `topmind-x`:280 字短推文发布(xurl 只覆盖短推文,不发长文)。
|
|
122
|
+
- `topmind-capture`:「只想存档不发布」时的收录路由。
|
|
123
|
+
|
|
124
|
+
## 实战沉淀(2026-10-01 九月全景项目)
|
|
125
|
+
|
|
126
|
+
- **HTML 占位符映射铁律**:`md2x-html.py --cover` 注入封面到 `__COVER__`,正文图按序注入
|
|
127
|
+
`__IMG_01__`–`__IMG_N__`。曾出现错位 bug(封面位置注入 `__IMG_01__`、正文图整体后移、
|
|
128
|
+
最后一张图跑到 `__COVER__`),原因是占位符替换顺序错误。修复后验收标准:
|
|
129
|
+
第一张 base64 图解码为 1500×600(封面尺寸),无占位符残留。
|
|
130
|
+
- **X发布稿.txt 图序**:由 `md2x.py` 从 X长文.md 生成,`[图N]` 编号与 HTML 正文图顺序一致,
|
|
131
|
+
封面不占编号(X 编辑器单独上传封面)。
|
|
132
|
+
|
|
133
|
+
## 实战沉淀(2026-10-01 九月全景·配图错位修复)
|
|
134
|
+
|
|
135
|
+
- **错位症状 A**:Grok 4.7 配图落在 Meta 段落之后;"国产模型一览"落在手机段落之后。
|
|
136
|
+
原因:改稿时只动文字不动图,图片 markdown 行被"落下"到下一段。
|
|
137
|
+
- **铁律**:图片必须紧跟它证明的那段文字(最多隔一段);改稿移动段落时,图片行一起搬。
|
|
138
|
+
- **错位症状 B(根本原因)**:旧版 X 构建从"六、工具与 Agent"起配图全错
|
|
139
|
+
(Codex 段配 OpenRouter 图、Harness 段配 AA 榜单图……)。
|
|
140
|
+
原因:`X长文.md` 里只有裸 `[图N]` 标记,图片靠 `--images` 命令行手工传参;
|
|
141
|
+
构建时按 `images/*` 文件名排序传入,而文件名数字顺序 ≠ 文档顺序
|
|
142
|
+
(`14-kling`/`15-china-models` 建图顺序与文档顺序相反;`21-codex`/`22-harness`
|
|
143
|
+
是后加的,排在 `16-openrouter` 之后)。从图 14 起全部错位一格,
|
|
144
|
+
图 14/15 互换不易察觉,到图 16(Codex 段)才明显暴露。
|
|
145
|
+
- **根治**:`md2x-html.py` 新增 `--images-from 公众号稿.md`,
|
|
146
|
+
从公众号稿的 `![]()` 按文档顺序自动派生图片,**不再允许手工排序**;
|
|
147
|
+
脚本内置校验:`[图N]` 必须连续编号且数量 = 图片数,否则直接报错退出
|
|
148
|
+
(不静默生成错版)。
|
|
149
|
+
- **构建后必跑三项校验**(缺一不可):
|
|
150
|
+
1. 脚本自校验通过(数量/连续性)。
|
|
151
|
+
2. 嵌入图顺序校验:逐张解码 base64,与源文件按文档顺序比对(像素或字节一致即过)。
|
|
152
|
+
3. 图文邻近校验:每张图前后各取 6 行,检查是否出现该图主题关键词
|
|
153
|
+
(如 Grok 图邻近必须有"Grok");章节题图(节首图)只查节标题相关性。
|
|
154
|
+
- **派生纪律**:`X长文.md` 永远由 `公众号稿.md` 重新派生(脚本重排 `[图N]`),
|
|
155
|
+
不手工改编号;派生后 `X发布稿.txt` 同步重生成。
|
|
156
|
+
`公众号稿.md` 是唯一真源:改图先改公众号稿,再重派生 X 稿,两边永不独立改图。
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "topmind-x-article",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"lockfileVersion": 3,
|
|
5
|
+
"requires": true,
|
|
6
|
+
"packages": {
|
|
7
|
+
"": {
|
|
8
|
+
"name": "topmind-x-article",
|
|
9
|
+
"version": "0.1.0",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "topmind-x-article",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "X 长文(Article)一键发布:Markdown 原稿转可直接粘贴的纯文本 + 封面图 + 发布清单。",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/topmindspace/topmind-writing-skills.git",
|
|
10
|
+
"directory": "topmind-x-article"
|
|
11
|
+
},
|
|
12
|
+
"type": "commonjs",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# X 长文发布清单
|
|
2
|
+
|
|
3
|
+
发布前逐项打勾,发布后填时间与链接归档。
|
|
4
|
+
|
|
5
|
+
## 发布前
|
|
6
|
+
|
|
7
|
+
- [ ] `X长文.html` 浏览器打开一遍:「一键复制全文」按钮可用、配图 11 张按序显示、
|
|
8
|
+
每个提示词块右上角「复制提示词」可用、封面预览 + 下载正常
|
|
9
|
+
- [ ] `X发布稿.txt` 通读一遍:断句顺、无 markdown 残留标记(HTML 复制异常时的兜底)
|
|
10
|
+
- [ ] 标题 ≤140 字符;首段 3 行内出钩子
|
|
11
|
+
- [ ] 承重数字与原稿一致(转格式不改数字)
|
|
12
|
+
- [ ] 封面图 1500×600 已备好,标题字无错别字
|
|
13
|
+
- [ ] 配图按 `[图N]` 顺序排好,清单与文件一一对应
|
|
14
|
+
- [ ] 话题标签想好(放文末,不超过 3 个)
|
|
15
|
+
- [ ] 提示词密集型文章:规划好哪些提示词块要在 X 里转原生代码块
|
|
16
|
+
(Insert → Code,读者侧一键复制的唯一链路;纯展示、无需取用的可跳过)
|
|
17
|
+
|
|
18
|
+
## 发布时
|
|
19
|
+
|
|
20
|
+
- [ ] 一键复制全文 → X 文章编辑器粘贴 → 封面单独上传 → 配图按 `[图N]` 编号插入
|
|
21
|
+
(图片若随粘贴带入则跳过上传;带不入则用图下「下载图片」按编号下载再上传)
|
|
22
|
+
- [ ] (提示词类文章推荐)提示词引用块逐块转 X 原生代码块,得读者侧一键复制:
|
|
23
|
+
HTML 里点该块「复制提示词」→ X 编辑器对应位置 Insert → Code → 粘贴 → 删除原引用块
|
|
24
|
+
- [ ] 预览一遍:图序、段落、标题
|
|
25
|
+
|
|
26
|
+
## 发布后
|
|
27
|
+
|
|
28
|
+
- [ ] 首条评论补信息(邀请码 / 链接 / 补充说明),置顶
|
|
29
|
+
- [ ] 记录:发布时间、文章链接
|
|
30
|
+
- [ ] 全文抓回核对一遍(标题、数字、图序),有误用评论勘误
|
|
31
|
+
- [ ] `发布清单.md` 归档进包
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# X Article 粘贴格式规则
|
|
2
|
+
|
|
3
|
+
X Article 编辑器对 markdown 支持弱且不稳定。`md2x.py` 按以下规则转纯文本,
|
|
4
|
+
转完人工通读一遍是硬性步骤。
|
|
5
|
+
|
|
6
|
+
| Markdown | 转后 |
|
|
7
|
+
|----------|------|
|
|
8
|
+
| `#` ~ `######` 标题 | 纯文本行,前后各一空行;标题内的加粗/链接等标记同样剥离 |
|
|
9
|
+
| `标题` + 下一行 `===`(Setext 一级标题) | 同上,转纯文本标题行 |
|
|
10
|
+
| `**加粗**` / `*斜体*` / `***粗斜体***` / `~~删除线~~` / `` `行内代码` `` | 去标记留文字(语气靠文字本身) |
|
|
11
|
+
| `[文字](url)` | `文字(url)`;url 里可含括号,`[文字](url "title")` 的 title 丢弃 |
|
|
12
|
+
| `[文字][ref]` / `[文字][]` / `[文字]`(引用式,有 `[ref]: url` 定义) | `文字(url)`;定义行不进正文 |
|
|
13
|
+
| `` / `![alt][ref]` | `[图N]`,文末附"配图清单"(`[图N] alt`;alt 为空记 `(未写图注)`) |
|
|
14
|
+
| `-` / `1.` 列表 | 保留原符号(含嵌套缩进);`- [ ]` / `- [x]` 任务列表都去勾选框留 `-`(完成状态不保留) |
|
|
15
|
+
| `>` 引用 | 去掉所有层级的 `>` 留文字;引用内的标题照转 |
|
|
16
|
+
| 表格(行首以 `|` 开头的标准写法;不带前导 `|` 的表格暂不转换) | 逐行转"项:值"列表(单元格内标记同样剥离);分隔行丢弃,复杂表请手动拆成段落 |
|
|
17
|
+
| `---` / `***` / `___` 分割线(允许空格,如 `* * *`) | 空行 |
|
|
18
|
+
| 代码块(``` 围栏;`~~~` 围栏暂不支持) | 去围栏,内容缩进 4 格;块内行原样保留(块内的 `---` 不再误判分割线) |
|
|
19
|
+
| `\` 转义(如 `\*`) | 去反斜杠留字符 |
|
|
20
|
+
| frontmatter | 整块丢弃(块内非空行须都含 `:` 才认定,文首的 `---` 分割线不会被误吞) |
|
|
21
|
+
|
|
22
|
+
## 写作时就按 X 想
|
|
23
|
+
|
|
24
|
+
- 段落短:手机阅读每段 ≤4 行
|
|
25
|
+
- 小标题就是一句话,不依赖加粗撑结构
|
|
26
|
+
- 数字、专有名词第一次出现就写全(剥离标记后无高亮可依靠)
|
|
27
|
+
- 需要强调的词:换说法前置,不要靠 `**`
|