Coverage for agentos/marketplace/skills/markdown-toolkit/markdown-toolkit.py: 3%

63 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-06 08:01 +0800

1""" 

2markdown-toolkit — Markdown 处理工具:转 HTML、提取标题、生成目录。 

3 

4Category: utility 

5""" 

6 

7 

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 

11 

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 "" 

17 

18 content = _read() 

19 if not content: 

20 return "[markdown-toolkit] 无内容输入" 

21 

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}" 

31 

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) 

41 

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) 

53 

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 

84 

85 return f"[markdown-toolkit] 未知操作: {action}, 支持: toc/to_html/headings/stats" 

86 except Exception as e: 

87 return f"[markdown-toolkit] 失败: {e}" 

88 

89 

90__all__ = ["run"]