Coverage for agentos/marketplace/skills/markdown-toolkit/markdown-toolkit.py: 41%
63 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-04 16:43 +0800
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-04 16:43 +0800
1"""
2markdown-toolkit — Markdown 处理工具:转 HTML、提取标题、生成目录。
4Category: utility
5"""
8def run(action: str, file_path: str = "", text: str = "", output_path: str = "") -> str:
9 """Markdown 处理工具。action: toc/to_html/headings/stats。"""
10 import os, re
12 def _read():
13 if file_path and os.path.isfile(file_path):
14 with open(file_path,"r",encoding="utf-8") as f:
15 return f.read()
16 return text or ""
18 content = _read()
19 if not content:
20 return "[markdown-toolkit] 无内容输入"
22 try:
23 if action == "stats":
24 lines = content.split("\n")
25 words = len(content.split())
26 chars = len(content)
27 headings = len(re.findall(r"^#{1,6}\s", content, re.MULTILINE))
28 links = len(re.findall(r"\[.*?\]\(.*?\)", content))
29 code_blocks = len(re.findall(r"```", content)) // 2
30 return f"行数: {len(lines)}, 词数: {words}, 字符: {chars}, 标题: {headings}, 链接: {links}, 代码块: {code_blocks}"
32 if action == "headings":
33 matches = re.findall(r"^(#{1,6})\s+(.+)$", content, re.MULTILINE)
34 if not matches:
35 return "[markdown-toolkit] 未找到标题"
36 lines_out = []
37 for level, title in matches:
38 indent = " " * (len(level) - 1)
39 lines_out.append(f"{indent}- {title.strip()}")
40 return f"共 {len(matches)} 个标题:\n" + "\n".join(lines_out)
42 if action == "toc":
43 matches = re.findall(r"^(#{1,6})\s+(.+)$", content, re.MULTILINE)
44 if not matches:
45 return "[markdown-toolkit] 未找到标题"
46 lines_out = ["# 目录", ""]
47 for level, title in matches:
48 depth = len(level)
49 indent = " " * (depth - 1)
50 anchor = re.sub(r"[^\w\s-]", "", title.strip()).lower().replace(" ", "-")
51 lines_out.append(f"{indent}- [{title.strip()}](#{anchor})")
52 return "\n".join(lines_out)
54 if action == "to_html":
55 # Simple markdown-to-HTML converter (covers basics)
56 html = content
57 # Code blocks (```)
58 html = re.sub(r"```(\w*)\n(.*?)```", r"<pre><code class='\1'>\2</code></pre>", html, flags=re.DOTALL)
59 # Inline code
60 html = re.sub(r"`([^`]+)`", r"<code>\1</code>", html)
61 # Headings
62 for i in range(6, 0, -1):
63 html = re.sub(rf"^{'#'*i}\s+(.+)$", rf"<h{i}>\1</h{i}>", html, flags=re.MULTILINE)
64 # Bold/Italic
65 html = re.sub(r"\*\*\*(.+?)\*\*\*", r"<em><strong>\1</strong></em>", html)
66 html = re.sub(r"\*\*(.+?)\*\*", r"<strong>\1</strong>", html)
67 html = re.sub(r"\*(.+?)\*", r"<em>\1</em>", html)
68 # Links
69 html = re.sub(r"\[(.+?)\]\((.+?)\)", r'<a href="\2">\1</a>', html)
70 # Images
71 html = re.sub(r"!\[(.*?)\]\((.+?)\)", r'<img src="\2" alt="\1">', html)
72 # Unordered lists
73 html = re.sub(r"^- (.+)$", r"<li>\1</li>", html, flags=re.MULTILINE)
74 # Paragraphs (double newline)
75 html = re.sub(r"\n\n+", "</p><p>", html)
76 html = f"<p>{html}</p>"
77 if output_path:
78 with open(output_path,"w",encoding="utf-8") as f: f.write(html)
79 return f"已转换并写入: {output_path}"
80 # return first 2000 chars if too long
81 if len(html) > 2000:
82 return html[:2000] + f"\n... (共{len(html)}字符)"
83 return html
85 return f"[markdown-toolkit] 未知操作: {action}, 支持: toc/to_html/headings/stats"
86 except Exception as e:
87 return f"[markdown-toolkit] 失败: {e}"
90__all__ = ["run"]