Skill: cizixiu/text-to-markdown (version 1.0.3)

--- name: text-to-markdown description: 纯文本格式预处理工具，自动插入换行、拆分长段落，为后续 AI/LLM 生成 Markdown 提供结构化输入。 --- # Text to Markdown ## 描述 纯文本格式预处理工具，自动插入换行、拆分长段落，为后续 AI/LLM 生成 Markdown 提供结构化输入。 ## 触发词 `转markdown`、`整理成markdown`、`格式化成markdown`、`转成md格式` --- ## 功能：文本预处理 本 skill 专注于**格式预处理**，将无结构的纯文本转换为结构化输出，为 AI/LLM 生成 Markdown 提供良好基础。 ### 预处理能力 | 能力 | 说明 | |------|------| | **插入换行** | 在标题前、转折词处自动插入换行 | | **长段落拆分** | 按语义（转折、因果）智能分段落 | | **特殊符号保留** | → ↔ ✓ ✗ 等符号保留原样 | | **IMA 笔记优化** | 专为无换行的 IMA 导出文本优化 | ### 特殊场景：IMA 笔记导出 IMA 导出的纯文本特征：无换行、长段落、标题混在段落中。 **处理策略**： 1. 用 `scripts/preprocess.py` 预处理（插入换行） 2. 自动在标题前、转折词处分段 3. 中文序号标题自动识别 ```powershell # 预处理 IMA 笔记 python "C:\Users\17116\.workbuddy\skills\Text to Markdown\scripts\preprocess.py" input.txt output.md ``` ### 执行流程 1. **预处理**：用 `scripts/preprocess.py` 插入换行、拆分段落 2. **AI 增强**：AI/LLM 基于预处理结果生成完整 Markdown（标题层级、加粗、列表等） ### 核心原则 > **只改格式，不改文字**：预处理过程中保持原文一字不变。 --- ## 快速核查 预处理完成后快速检查： - [ ] 原文文字一字未改 - [ ] 标题前已插入换行 - [ ] 长段落已拆分 - [ ] 特殊符号保留原样 --- ## 参考资料 - **IMA 笔记示例**：见 [references/examples.md](references/examples.md) --- ## 注意事项 预处理只负责格式调整，Markdown 语法（标题层级、加粗、列表等）由 AI/LLM 后续生成。

path: references/examples.md
content: # 转换示例参考

本文档收集更多 Markdown 转换示例，供复杂场景参考。

---

## 示例 1：完整段落转换

**输入**：
```
今天给大家介绍一个新工具。这个工具叫WorkBuddy，是一款AI助手。它有三个主要功能：第一个是写作，可以帮你写文章、报告、邮件；第二个是数据分析，可以处理表格、生成图表；第三个是代码开发，可以写代码、调试bug。了解更多请访问 http://example.com
```

**输出**：
```markdown
# 全新 **AI 助手 WorkBuddy** 介绍

今天给大家介绍一个新工具——**WorkBuddy**，一款功能强大的 **AI 助手**。

## 三大核心功能

WorkBuddy 提供三个主要功能：

1. **写作助手**
   - 帮你写**文章**
   - 撰写**报告**
   - 处理**邮件**

2. **数据分析**
   - 处理**表格**
   - 生成**图表**

3. **代码开发**
   - 编写**代码**
   - 调试 **bug**

了解更多：[链接](http://example.com)
```

---

## 示例 2：标题模式拆分

**输入**：
```
沟通话术：遇到客户投诉时，先倾听再回应。价格异议：强调性价比而非价格。售后服务：承诺24小时内处理。
```

**输出**：
```markdown
### 沟通话术

遇到客户投诉时，先倾听再回应。

### 价格异议

强调性价比而非价格。

### 售后服务

承诺 **24 小时**内处理。
```

---

## 示例 3：中文序号标题

**输入**：
```
一、准备工作
确认网络连接正常。
二、安装步骤
下载安装包并运行。
三、配置说明
打开设置页面进行配置。
```

**输出**：
```markdown
## 一、准备工作

确认网络连接正常。

## 二、安装步骤

下载安装包并运行。

## 三、配置说明

打开设置页面进行配置。
```

---

## 示例 4：带数字的纯文本

**输入**：
```
本次活动预计花费5万元，预算上限8万元。报名人数已达120人，预计总人数150人。活动时间定在3月15日周日下午2点。
```

**输出**：
```markdown
本次活动预计花费 **5 万元**，预算上限 **8 万元**。报名人数已达 **120 人**，预计总人数 **150 人**。活动时间定在 **3 月 15 日** 周日下午 **2 点**。
```

---

## 示例 5：步骤流程

**输入**：
```
第一步：打开软件，点击新建项目。
第二步：选择模板，填写项目名称。
第三步：添加成员，设置权限。
第四步：完成初始化，开始协作。
```

**输出**：
```markdown
## 操作步骤

1. **打开软件**，点击新建项目

2. **选择模板**，填写项目名称

3. **添加成员**，设置权限

4. **完成初始化**，开始协作
```

---

## 示例 6：对比表格

**输入**：
```
功能对比：基础版包含文件管理、协作编辑；专业版增加数据分析、API接口；企业版包含全部功能，并提供专属客服。
```

**输出**：
```markdown
## 功能对比

| 功能 | 基础版 | 专业版 | 企业版 |
|------|--------|--------|--------|
| 文件管理 | ✓ | ✓ | ✓ |
| 协作编辑 | ✓ | ✓ | ✓ |
| 数据分析 | - | ✓ | ✓ |
| API 接口 | - | ✓ | ✓ |
| 专属客服 | - | - | ✓ |
```

---

## 示例 7：嵌套列表

**输入**：
```
项目计划包括：开发任务方面有前端开发、UI设计、后端API；测试任务方面有单元测试、集成测试、用户验收测试；运维任务方面有部署上线、监控告警、故障处理。
```

**输出**：
```markdown
## 项目计划

项目包括以下任务：

- **开发任务**
  - 前端开发
  - UI 设计
  - 后端 API

- **测试任务**
  - 单元测试
  - 集成测试
  - 用户验收测试

- **运维任务**
  - 部署上线
  - 监控告警
  - 故障处理
```

---

## 示例 8：代码片段识别

**输入**：
```
配置示例：在 config.json 中添加以下内容
{
  "name": "example",
  "version": "1.0.0",
  "debug": true
}
```

**输出**：
```markdown
## 配置示例

在 `config.json` 中添加以下内容：

```json
{
  "name": "example",
  "version": "1.0.0",
  "debug": true
}
`` `
```

---

## 示例 9：术语定义

**输入**：
```
API是什么？API全称Application Programming Interface，是应用程序对外提供的编程接口。
SDK是什么？SDK全称Software Development Kit，是软件开发工具包，包含开发所需的工具和库。
```

**输出**：
```markdown
## 术语说明

**API**：Application Programming Interface，应用程序对外提供的编程接口。

**SDK**：Software Development Kit，软件开发工具包，包含开发所需的工具和库。
```

---

## 示例 10：引用块

**输入**：
```
重要提示：请确保所有配置都已保存，否则重启后会丢失。
警告：删除操作不可恢复，请谨慎操作。
```

**输出**：
```markdown
> [!TIP]
> 请确保所有配置都已保存，否则重启后会丢失。

> [!WARNING]
> 删除操作不可恢复，请谨慎操作。
```


path: references/markdown-spec.md
content: # Markdown 格式规范参考

本文档提供 Markdown 格式的详细规范参考。

---

## 标题层级

| 层级 | 语法 | 使用场景 | 注意事项 |
|------|------|----------|----------|
| H1 | `# 标题` | 文章主标题，全文仅一个 | 位于文档最开头 |
| H2 | `## 标题` | 章节标题 | 不要跳过 H1 直接用 H2 |
| H3 | `### 标题` | 子章节标题 | 常见于"标题："模式拆分 |
| H4 | `#### 标题` | 更细划分 | 最多使用到 H4 |

**识别规则**：
- 中文序号：`一、`、`二、`、`三、` → H2
- 子序号：`（一）`、`（二）` → H3
- 西文序号：`(1)`、`(2)` → H3
- 阿拉伯数字：`第一步`、`第二段` → H2

---

## 文本强调

### 加粗 `**文字**`

**适用场景**：
- 重要数据：金额（**5 万元**）、日期（**3 月 15 日**）、人数（**120 人**）
- 关键概念：核心名词、结论性陈述
- 判断标准：这个词删掉会影响理解吗？

**适度使用**：每句话加粗 1-2 个核心词，避免过度。

### 斜体 `*文字*`

**适用场景**：
- 术语/专有名词：`*API*`、`*SDK*`
- 引用词汇：`*《活着》*`
- 文件名：`*config.json*`

### 行内代码 `` ` ``

**适用场景**：
- 命令/代码片段：`pip install`
- 文件名：`config.json`
- 快捷键：`Ctrl + C`
- 技术术语：`API`、`CLI`

---

## 列表规范

### 无序列表

```markdown
- 第一项
- 第二项
- 第三项
```

### 有序列表

```markdown
1. 第一步
2. 第二步
3. 第三步
```

### 嵌套列表

```markdown
- 一级列表
  - 二级列表（两个空格缩进）
    - 三级列表（四个空格缩进）
```

**规则**：
- 嵌套层级不要超过 3 层
- 同层级的列表符号必须统一
- 子项用两个空格缩进

---

## 表格规范

### 基础表格

```markdown
| 列1 | 列2 | 列3 |
|-----|-----|-----|
| A   | B   | C   |
| D   | E   | F   |
```

### 对齐方式

| 对齐 | 语法 | 适用 |
|------|------|------|
| 左对齐 | `:---` | 默认，通用 |
| 居中 | `:---:` | 标题、强调 |
| 右对齐 | `---:` | 数字、金额 |

### 示例

```markdown
| 功能 | 基础版 | 专业版 | 企业版 |
|:-----|:------:|:------:|-------:|
| 文件管理 | ✓ | ✓ | ✓ |
| 价格 | 免费 | ¥99/月 | ¥299/月 |
```

---

## 引用块

### 普通引用

```markdown
> 这是一段引用内容
```

### 提示块

```markdown
> [!TIP]
> 这是提示内容

> [!WARNING]
> 这是警告内容

> [!NOTE]
> 这是备注内容
```

---

## 代码块

### 基础语法

````markdown
```语言
代码内容
```
````

### 常用语言标识

| 内容特征 | 语言标识 |
|---------|---------|
| Python | `python` |
| JavaScript | `javascript` |
| Bash/Linux | `bash` |
| PowerShell | `powershell` |
| JSON | `json` |
| YAML | `yaml` |
| HTML | `html` |
| CSS | `css` |
| SQL | `sql` |
| 未知 | `text` |

### 行内代码

使用反引号包裹：`` `code` ``

---

## 链接和图片

### 链接

```markdown
[链接文字](url)
```

**自动识别**：
- `http://example.com` → `[链接](http://example.com)`
- `https://example.com` → `[链接](https://example.com)`

### 图片

```markdown
![替代文字](图片链接)
```

---

## 特殊符号处理

### 保留原样的符号

| 符号 | 说明 |
|------|------|
| → | 箭头 |
| ↔ | 双向箭头 |
| ✓ | 对勾 |
| ✗ | 叉号 |
| ★ | 星号（文字中的） |

### 需要转义的符号

| 符号 | 转义写法 |
|------|---------|
| `*` | `\*`（仅在列表或加粗外） |
| `#` | `\#`（仅在标题外） |
| `` ` `` | `` \` ``（行内代码外） |

---

## 段落与换行

| 规则 | 说明 |
|------|------|
| 段落之间 | 空一行 |
| 句子之间 | 正常书写，不额外换行 |
| 列表项之间 | 不空行（除非逻辑分组） |
| 标题前后 | 标题前空一行，标题后不空行 |

---

## 纯文本表格识别

### 识别特征

- 对齐的分隔符（空格或逗号分隔）
- 连续的键值对（3列以上）
- 重复出现的模式行

### 示例

原始：
```
姓名  年龄  城市
张三  25   北京
李四  30   上海
```

转为：
```markdown
| 姓名 | 年龄 | 城市 |
|------|------|------|
| 张三 | 25   | 北京 |
| 李四 | 30   | 上海 |
```

**注意**：如果表格结构不清晰，保持原文不变。


path: scripts/preprocess.py
content: #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
用于处理 IMA 笔记等无换行的纯文本，自动插入换行符

用法：
    python preprocess.py <input.txt> [output.md]
    python preprocess.py --stdin < input.txt > output.md
"""

import re
import sys
import io
from pathlib import Path

# Windows 编码设置
if sys.platform == 'win32':
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')


# 中文序号标题模式
TITLE_PATTERNS = [
    (r'([一二三四五六七八九十]+[、.])', '\n\\1'),  # 一、二、三、四、
    (r'([（\(][一二三四五六七八九十]+[）\)])', '\n\\1'),  # （一）、(一)
    (r'(\([1-9][\d]*\))', '\n\\1'),  # (1), (2)
]

# 标题关键词
TITLE_KEYWORDS = [
    '背景', '前言', '介绍', '概述', '总结', '结论',
    '方法', '步骤', '流程', '过程',
    '原因', '结果', '影响', '分析',
    '问题', '方案', '对策', '建议',
    '场景', '情况', '案例', '示例',
    '配置', '安装', '部署', '使用', '教程',
    '沟通话术', '价格异议', '注意事项', '说明', '提示',
    '优势', '特点', '功能', '特性',
]

# 转折词（分段标记）
TRANSITION_WORDS = [
    '但是', '然而', '不过', '可是', '只是',
    '因此', '所以', '于是', '从而', '故',
    '而且', '并且', '同时', '另外', '此外',
    '总之', '综上所述', '总而言之',
    '首先', '其次', '最后', '接着',
]

# 分隔线模式
SEPARATOR_PATTERNS = [
    r'^---+$',  # ---
    r'^=+$',     # ===
    r'^__+$',   # ___
]


def has_chinese_numbering(text: str) -> bool:
    """检查文本是否包含中文序号标题"""
    patterns = [
        r'^[一二三四五六七八九十]+[、.]',
        r'^[第一二三四五六七八九十]+[章节步段]',
        r'^[（\(][一二三四五六七八九十]+[）\)]',
        r'^\([1-9][\d]*\)',
    ]
    for p in patterns:
        if re.match(p, text.strip()):
            return True
    return False


def is_title_keyword_line(text: str) -> bool:
    """检查是否是标题关键词行（仅当关键词在行开头时）"""
    text = text.strip()
    # 只检查行开头是否是标题关键词
    for kw in TITLE_KEYWORDS:
        if text.startswith(kw + '：') or text.startswith(kw + ':'):
            return True
        if text == kw:
            return True
    return False


def split_sentences(text: str) -> list:
    """将长段落按句子分割"""
    # 句号、问号、感叹号后分段
    sentences = re.split(r'([。！？])', text)

    result = []
    current = []

    for i, part in enumerate(sentences):
        if not part:
            continue

        if i % 2 == 0:
            # 普通句子部分
            current.append(part)
        else:
            # 标点符号部分，合并到前一句
            current.append(part)
            result.append(''.join(current))
            current = []

    # 处理最后可能剩余的内容
    if current:
        result.append(''.join(current))

    return result


def preprocess_plain_text(text: str) -> str:
    """
    预处理纯文本，在适当位置插入换行符

    处理策略：
    1. 识别并标记标题行
    2. 在标题前插入换行
    3. 在转折词前插入换行
    4. 对超长段落进行分句
    """
    lines = text.split('\n')
    result_lines = []

    for line in lines:
        line = line.strip()
        if not line:
            result_lines.append('')
            continue

        # 检查是否包含多个标题关键词（用于分段）
        has_title = False
        for kw in TITLE_KEYWORDS:
            if f'{kw}：' in line or f'{kw}:' in line:
                has_title = True
                break

        if has_title:
            # 按标题关键词分割
            pattern = '|'.join(rf'({kw}[：:])' for kw in TITLE_KEYWORDS)
            parts = re.split(pattern, line)
            for part in parts:
                if part:
                    part = part.strip()
                    if part:
                        result_lines.append(part)
        elif has_chinese_numbering(line):
            # 中文序号标题分割
            # 先匹配中文序号，然后在每个序号前插入换行
            new_line = line
            for pattern_str, replacement in TITLE_PATTERNS:
                new_line = re.sub(pattern_str, replacement, new_line)
            # 清理开头多余的换行，然后按换行分割
            new_line = new_line.lstrip('\n')
            parts = new_line.split('\n')
            for part in parts:
                part = part.strip()
                if part:
                    result_lines.append(part)
        elif any(tw in line for tw in TRANSITION_WORDS):
            # 包含转折词的段落，在转折词前分段
            new_line = line
            for tw in TRANSITION_WORDS:
                new_line = new_line.replace(tw, f'\n{tw}')
            new_line = new_line.lstrip('\n')
            parts = new_line.split('\n')
            for part in parts:
                part = part.strip()
                if part:
                    result_lines.append(part)
        elif len(line) > 200:
            # 超长段落按句号分句
            sentences = split_sentences(line)
            result_lines.extend(sentences)
        else:
            result_lines.append(line)

    # 再次处理，在标题前插入换行
    final_lines = []
    prev_was_empty = True

    for line in result_lines:
        line = line.strip()
        if not line:
            final_lines.append('')
            prev_was_empty = True
            continue

        # 恢复标题标记
        if '__TITLE_START__' in line:
            line = line.replace('__TITLE_START__', '')

        # 检查是否是标题
        is_title = has_chinese_numbering(line) or is_title_keyword_line(line)

        if is_title and not prev_was_empty:
            final_lines.append('')

        final_lines.append(line)
        prev_was_empty = False

    return '\n'.join(final_lines)


def main():
    input_text = ''
    output_path = None

    if len(sys.argv) > 1:
        if sys.argv[1] == '--stdin':
            input_text = sys.stdin.read()
        else:
            input_path = Path(sys.argv[1])
            if not input_path.exists():
                print(f"错误：文件不存在 - {input_path}", file=sys.stderr)
                sys.exit(1)
            input_text = input_path.read_text(encoding='utf-8')

            if len(sys.argv) > 2:
                output_path = Path(sys.argv[2])
    else:
        # 尝试从 stdin 读取
        if not sys.stdin.isatty():
            input_text = sys.stdin.read()
        else:
            print(__doc__)
            sys.exit(0)

    if not input_text:
        print("错误：没有输入内容", file=sys.stderr)
        sys.exit(1)

    result = preprocess_plain_text(input_text)

    if output_path:
        output_path.write_text(result, encoding='utf-8')
        print(f"已保存到：{output_path}")
    else:
        print(result)


if __name__ == '__main__':
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)