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