diff --git a/.claude/skills/text-formatter/SKILL.md b/.claude/skills/text-formatter/SKILL.md new file mode 100644 index 00000000..d8cb22cc --- /dev/null +++ b/.claude/skills/text-formatter/SKILL.md @@ -0,0 +1,185 @@ +--- +name: text-formatter +description: Transform and optimize text content with intelligent formatting. Output BBCode + Markdown hybrid format optimized for forums. Triggers on "format text", "text formatter", "排版", "格式化文本", "BBCode". +allowed-tools: Task, AskUserQuestion, Read, Write, Bash, Glob +--- + +# Text Formatter + +Transform and optimize text content with intelligent structure analysis. Output format: **BBCode + Markdown hybrid** optimized for forum publishing. + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Text Formatter Architecture (BBCode + MD Mode) │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Phase 1: Input Collection → 接收文本/文件 │ +│ ↓ │ +│ Phase 2: Content Analysis → 分析结构、识别 Callout/Admonition │ +│ ↓ │ +│ Phase 3: Format Transform → 转换为 BBCode+MD 格式 │ +│ ↓ │ +│ Phase 4: Output & Preview → 保存文件 + 预览 │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Key Design Principles + +1. **Single Format Output**: BBCode + Markdown hybrid (forum optimized) +2. **Pixel-Based Sizing**: size=150/120/100/80 (not 1-7 levels) +3. **Forum Compatibility**: Only use widely-supported BBCode tags +4. **Markdown Separators**: Use `---` for horizontal rules (not `[hr]`) +5. **No Alignment Tags**: `[align]` not supported, avoid usage + +--- + +## Format Specification + +### Supported BBCode Tags + +| Tag | Usage | Example | +|-----|-------|---------| +| `[size=N]` | Font size (pixels) | `[size=120]Title[/size]` | +| `[color=X]` | Text color | `[color=#2196F3]Blue[/color]` | +| `[b]` | Bold | `[b]Bold text[/b]` | +| `[i]` | Italic | `[i]Italic[/i]` | +| `[quote]` | Quote block | `[quote]Content[/quote]` | +| `[code]` | Code block | `[code]code[/code]` | +| `[img]` | Image | `[img]url[/img]` | +| `[url]` | Link | `[url=link]text[/url]` | +| `[list]` | List container | `[list][*]item[/list]` | + +### Unsupported Tags (Avoid!) + +| Tag | Reason | Alternative | +|-----|--------|-------------| +| `[align]` | Not rendered | Remove or use default left | +| `[hr]` | Shows as text | Use Markdown `---` | +| `
` | HTML not supported | Use BBCode only | +| `[table]` | Limited support | Use list or code block | + +### Size Hierarchy (Pixels) + +| Element | Size | Color | Usage | +|---------|------|-------|-------| +| **Main Title** | 150 | #2196F3 | Document title | +| **Section Title** | 120 | #2196F3 | Major sections (## H2) | +| **Subsection** | 100 | #333 | Sub-sections (### H3) | +| **Normal Text** | (default) | - | Body content | +| **Notes/Gray** | 80 | gray | Footnotes, metadata | + +### Color Palette + +| Color | Hex | Semantic Usage | +|-------|-----|----------------| +| **Blue** | #2196F3 | Titles, links, info | +| **Green** | #4CAF50 | Success, tips, features | +| **Orange** | #FF9800 | Warnings, caution | +| **Red** | #F44336 | Errors, danger, important | +| **Purple** | #9C27B0 | Examples, code | +| **Gray** | gray | Notes, metadata | + +--- + +## Mandatory Prerequisites + +> Read before execution: + +| Document | Purpose | Priority | +|----------|---------|----------| +| [specs/format-rules.md](specs/format-rules.md) | Format conversion rules | **P0** | +| [specs/element-mapping.md](specs/element-mapping.md) | Element type mappings | P1 | +| [specs/callout-types.md](specs/callout-types.md) | Callout/Admonition types | P1 | + +--- + +## Execution Flow + +``` +┌────────────────────────────────────────────────────────────────┐ +│ Phase 1: Input Collection │ +│ - Ask: paste text OR file path │ +│ - Output: input-config.json │ +├────────────────────────────────────────────────────────────────┤ +│ Phase 2: Content Analysis │ +│ - Detect structure: headings, lists, code blocks, tables │ +│ - Identify Callouts/Admonitions (>[!type]) │ +│ - Output: analysis.json │ +├────────────────────────────────────────────────────────────────┤ +│ Phase 3: Format Transform │ +│ - Apply BBCode + MD rules from specs/format-rules.md │ +│ - Convert elements with pixel-based sizes │ +│ - Use Markdown --- for separators │ +│ - Output: formatted content │ +├────────────────────────────────────────────────────────────────┤ +│ Phase 4: Output & Preview │ +│ - Save to .bbcode.txt file │ +│ - Display preview │ +│ - Output: final file │ +└────────────────────────────────────────────────────────────────┘ +``` + +## Callout/Admonition Support + +支持 Obsidian 风格的 Callout 语法,转换为 BBCode quote: + +```markdown +> [!NOTE] +> 这是一个提示信息 + +> [!WARNING] +> 这是一个警告信息 +``` + +转换结果: + +```bbcode +[quote] +[size=100][color=#2196F3][b]📝 注意[/b][/color][/size] + +这是一个提示信息 +[/quote] +``` + +| Type | Color | Icon | +|------|-------|------| +| NOTE/INFO | #2196F3 | 📝 | +| TIP/HINT | #4CAF50 | 💡 | +| SUCCESS | #4CAF50 | ✅ | +| WARNING/CAUTION | #FF9800 | ⚠️ | +| DANGER/ERROR | #F44336 | ❌ | +| EXAMPLE | #9C27B0 | 📋 | + +## Directory Setup + +```javascript +const timestamp = new Date().toISOString().slice(0,10).replace(/-/g, ''); +const workDir = `.workflow/.scratchpad/text-formatter-${timestamp}`; + +Bash(`mkdir -p "${workDir}"`); +``` + +## Output Structure + +``` +.workflow/.scratchpad/text-formatter-{date}/ +├── input-config.json # 输入配置 +├── analysis.json # 内容分析结果 +└── output.bbcode.txt # BBCode+MD 输出 +``` + +## Reference Documents + +| Document | Purpose | +|----------|---------| +| [phases/01-input-collection.md](phases/01-input-collection.md) | 收集输入内容 | +| [phases/02-content-analysis.md](phases/02-content-analysis.md) | 分析内容结构 | +| [phases/03-format-transform.md](phases/03-format-transform.md) | 格式转换 | +| [phases/04-output-preview.md](phases/04-output-preview.md) | 输出和预览 | +| [specs/format-rules.md](specs/format-rules.md) | 格式转换规则 | +| [specs/element-mapping.md](specs/element-mapping.md) | 元素映射表 | +| [specs/callout-types.md](specs/callout-types.md) | Callout 类型定义 | +| [templates/bbcode-template.md](templates/bbcode-template.md) | BBCode 模板 | diff --git a/.claude/skills/text-formatter/phases/01-input-collection.md b/.claude/skills/text-formatter/phases/01-input-collection.md new file mode 100644 index 00000000..2b48c8da --- /dev/null +++ b/.claude/skills/text-formatter/phases/01-input-collection.md @@ -0,0 +1,111 @@ +# Phase 1: Input Collection + +收集用户输入的文本内容。 + +## Objective + +- 获取用户输入内容(直接粘贴或文件路径) +- 生成输入配置文件 + +**注意**: 输出格式固定为 BBCode + Markdown 混合格式(论坛优化),无需选择。 + +## Input + +- 来源: 用户交互 +- 配置: 无前置依赖 + +## Execution Steps + +### Step 1: 询问输入方式 + +```javascript +const inputMethod = await AskUserQuestion({ + questions: [ + { + question: "请选择输入方式", + header: "输入方式", + multiSelect: false, + options: [ + { label: "直接粘贴文本", description: "在对话中粘贴要格式化的内容" }, + { label: "指定文件路径", description: "读取指定文件的内容" } + ] + } + ] +}); +``` + +### Step 2: 获取内容 + +```javascript +let content = ''; + +if (inputMethod["输入方式"] === "直接粘贴文本") { + // 提示用户粘贴内容 + const textInput = await AskUserQuestion({ + questions: [ + { + question: "请粘贴要格式化的文本内容(粘贴后选择确认)", + header: "文本内容", + multiSelect: false, + options: [ + { label: "已粘贴完成", description: "确认已在上方粘贴内容" } + ] + } + ] + }); + // 从用户消息中提取文本内容 + content = extractUserText(); +} else { + // 询问文件路径 + const filePath = await AskUserQuestion({ + questions: [ + { + question: "请输入文件路径", + header: "文件路径", + multiSelect: false, + options: [ + { label: "已输入路径", description: "确认路径已在上方输入" } + ] + } + ] + }); + content = Read(extractedFilePath); +} +``` + +### Step 3: 保存配置 + +```javascript +const config = { + input_method: inputMethod["输入方式"], + target_format: "BBCode+MD", // 固定格式 + original_content: content, + timestamp: new Date().toISOString() +}; + +Write(`${workDir}/input-config.json`, JSON.stringify(config, null, 2)); +``` + +## Output + +- **File**: `input-config.json` +- **Format**: JSON + +```json +{ + "input_method": "直接粘贴文本", + "target_format": "BBCode+MD", + "original_content": "...", + "timestamp": "2026-01-13T..." +} +``` + +## Quality Checklist + +- [ ] 成功获取用户输入内容 +- [ ] 内容非空且有效 +- [ ] 配置文件已保存 + +## Next Phase + +→ [Phase 2: Content Analysis](02-content-analysis.md) diff --git a/.claude/skills/text-formatter/phases/02-content-analysis.md b/.claude/skills/text-formatter/phases/02-content-analysis.md new file mode 100644 index 00000000..34d86729 --- /dev/null +++ b/.claude/skills/text-formatter/phases/02-content-analysis.md @@ -0,0 +1,248 @@ +# Phase 2: Content Analysis + +分析输入内容的结构和语义元素。 + +## Objective + +- 识别内容结构(标题、段落、列表等) +- 检测特殊元素(代码块、表格、链接等) +- 生成结构化分析结果 + +## Input + +- 依赖: `input-config.json` +- 配置: `{workDir}/input-config.json` + +## Execution Steps + +### Step 1: 加载输入 + +```javascript +const config = JSON.parse(Read(`${workDir}/input-config.json`)); +const content = config.original_content; +``` + +### Step 2: 结构分析 + +```javascript +function analyzeStructure(text) { + const analysis = { + elements: [], + stats: { + headings: 0, + paragraphs: 0, + lists: 0, + code_blocks: 0, + tables: 0, + links: 0, + images: 0, + quotes: 0, + callouts: 0 + } + }; + + // Callout 检测正则 (Obsidian 风格) + const CALLOUT_PATTERN = /^>\s*\[!(\w+)\](?:\s+(.+))?$/; + + const lines = text.split('\n'); + let currentElement = null; + let inCodeBlock = false; + let inList = false; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + // 检测代码块 + if (line.match(/^```/)) { + inCodeBlock = !inCodeBlock; + if (inCodeBlock) { + analysis.elements.push({ + type: 'code_block', + start: i, + language: line.replace(/^```/, '').trim() + }); + analysis.stats.code_blocks++; + } + continue; + } + + if (inCodeBlock) continue; + + // 检测标题 (Markdown 或纯文本模式) + if (line.match(/^#{1,6}\s/)) { + const level = line.match(/^(#+)/)[1].length; + analysis.elements.push({ + type: 'heading', + level: level, + content: line.replace(/^#+\s*/, ''), + line: i + }); + analysis.stats.headings++; + continue; + } + + // 检测列表 + if (line.match(/^[\s]*[-*+]\s/) || line.match(/^[\s]*\d+\.\s/)) { + if (!inList) { + analysis.elements.push({ + type: 'list', + start: i, + ordered: line.match(/^\d+\./) !== null + }); + analysis.stats.lists++; + inList = true; + } + continue; + } else { + inList = false; + } + + // 检测 Callout (Obsidian 风格) - 优先于普通引用 + const calloutMatch = line.match(CALLOUT_PATTERN); + if (calloutMatch) { + const calloutType = calloutMatch[1].toLowerCase(); + const calloutTitle = calloutMatch[2] || null; + // 收集 Callout 内容行 + const calloutContent = []; + let j = i + 1; + while (j < lines.length && lines[j].startsWith('>')) { + calloutContent.push(lines[j].replace(/^>\s*/, '')); + j++; + } + analysis.elements.push({ + type: 'callout', + calloutType: calloutType, + title: calloutTitle, + content: calloutContent.join('\n'), + start: i, + end: j - 1 + }); + analysis.stats.callouts++; + i = j - 1; // 跳过已处理的行 + continue; + } + + // 检测普通引用 + if (line.match(/^>\s/)) { + analysis.elements.push({ + type: 'quote', + content: line.replace(/^>\s*/, ''), + line: i + }); + analysis.stats.quotes++; + continue; + } + + // 检测表格 + if (line.match(/^\|.*\|$/)) { + analysis.elements.push({ + type: 'table_row', + line: i + }); + if (!analysis.elements.find(e => e.type === 'table')) { + analysis.stats.tables++; + } + continue; + } + + // 检测链接 + const links = line.match(/\[([^\]]+)\]\(([^)]+)\)/g); + if (links) { + analysis.stats.links += links.length; + } + + // 检测图片 + const images = line.match(/!\[([^\]]*)\]\(([^)]+)\)/g); + if (images) { + analysis.stats.images += images.length; + } + + // 普通段落 + if (line.trim() && !line.match(/^[-=]{3,}$/)) { + analysis.elements.push({ + type: 'paragraph', + line: i, + preview: line.substring(0, 50) + }); + analysis.stats.paragraphs++; + } + } + + return analysis; +} + +const analysis = analyzeStructure(content); +``` + +### Step 3: 语义增强 + +```javascript +// 识别特殊语义 +function enhanceSemantics(text, analysis) { + const enhanced = { ...analysis }; + + // 检测关键词强调 + const boldPatterns = text.match(/\*\*[^*]+\*\*/g) || []; + const italicPatterns = text.match(/\*[^*]+\*/g) || []; + + enhanced.semantics = { + emphasis: { + bold: boldPatterns.length, + italic: italicPatterns.length + }, + estimated_reading_time: Math.ceil(text.split(/\s+/).length / 200) // 200 words/min + }; + + return enhanced; +} + +const enhancedAnalysis = enhanceSemantics(content, analysis); +``` + +### Step 4: 保存分析结果 + +```javascript +Write(`${workDir}/analysis.json`, JSON.stringify(enhancedAnalysis, null, 2)); +``` + +## Output + +- **File**: `analysis.json` +- **Format**: JSON + +```json +{ + "elements": [ + { "type": "heading", "level": 1, "content": "Title", "line": 0 }, + { "type": "paragraph", "line": 2, "preview": "..." }, + { "type": "callout", "calloutType": "warning", "title": "注意事项", "content": "...", "start": 4, "end": 6 }, + { "type": "code_block", "start": 8, "language": "javascript" } + ], + "stats": { + "headings": 3, + "paragraphs": 10, + "lists": 2, + "code_blocks": 1, + "tables": 0, + "links": 5, + "images": 0, + "quotes": 1, + "callouts": 2 + }, + "semantics": { + "emphasis": { "bold": 5, "italic": 3 }, + "estimated_reading_time": 2 + } +} +``` + +## Quality Checklist + +- [ ] 所有结构元素已识别 +- [ ] 统计信息准确 +- [ ] 语义增强完成 +- [ ] 分析文件已保存 + +## Next Phase + +→ [Phase 3: Format Transform](03-format-transform.md) diff --git a/.claude/skills/text-formatter/phases/03-format-transform.md b/.claude/skills/text-formatter/phases/03-format-transform.md new file mode 100644 index 00000000..47b72b8d --- /dev/null +++ b/.claude/skills/text-formatter/phases/03-format-transform.md @@ -0,0 +1,237 @@ +# Phase 3: Format Transform + +将内容转换为 BBCode + Markdown 混合格式(论坛优化)。 + +## Objective + +- 根据分析结果转换内容 +- 应用像素级字号规则 +- 处理 Callout/标注语法 +- 生成论坛兼容的输出 + +## Input + +- 依赖: `input-config.json`, `analysis.json` +- 规范: `specs/format-rules.md`, `specs/element-mapping.md` + +## Format Specification + +### Size Hierarchy (Pixels) + +| Element | Size | Color | Usage | +|---------|------|-------|-------| +| **H1** | 150 | #2196F3 | 文档主标题 | +| **H2** | 120 | #2196F3 | 章节标题 | +| **H3** | 100 | #333 | 子标题 | +| **H4+** | (默认) | - | 仅加粗 | +| **Notes** | 80 | gray | 备注/元数据 | + +### Unsupported Tags (禁止使用) + +| Tag | Reason | Alternative | +|-----|--------|-------------| +| `[align]` | 不渲染 | 删除,使用默认左对齐 | +| `[hr]` | 显示为文本 | 使用 Markdown `---` | +| `[table]` | 支持有限 | 转为列表或代码块 | +| HTML tags | 不支持 | 仅使用 BBCode | + +## Execution Steps + +### Step 1: 加载配置和分析 + +```javascript +const config = JSON.parse(Read(`${workDir}/input-config.json`)); +const analysis = JSON.parse(Read(`${workDir}/analysis.json`)); +const content = config.original_content; +``` + +### Step 2: Callout 配置 + +```javascript +// Callout 类型映射(像素级字号) +const CALLOUT_CONFIG = { + // 信息类 + note: { icon: '📝', color: '#2196F3', label: '注意' }, + info: { icon: 'ℹ️', color: '#2196F3', label: '信息' }, + abstract: { icon: '📄', color: '#2196F3', label: '摘要' }, + summary: { icon: '📄', color: '#2196F3', label: '摘要' }, + tldr: { icon: '📄', color: '#2196F3', label: '摘要' }, + + // 成功/提示类 + tip: { icon: '💡', color: '#4CAF50', label: '提示' }, + hint: { icon: '💡', color: '#4CAF50', label: '提示' }, + success: { icon: '✅', color: '#4CAF50', label: '成功' }, + check: { icon: '✅', color: '#4CAF50', label: '完成' }, + done: { icon: '✅', color: '#4CAF50', label: '完成' }, + + // 警告类 + warning: { icon: '⚠️', color: '#FF9800', label: '警告' }, + caution: { icon: '⚠️', color: '#FF9800', label: '注意' }, + attention: { icon: '⚠️', color: '#FF9800', label: '注意' }, + question: { icon: '❓', color: '#FF9800', label: '问题' }, + help: { icon: '❓', color: '#FF9800', label: '帮助' }, + faq: { icon: '❓', color: '#FF9800', label: 'FAQ' }, + todo: { icon: '📋', color: '#FF9800', label: '待办' }, + + // 错误/危险类 + danger: { icon: '❌', color: '#F44336', label: '危险' }, + error: { icon: '❌', color: '#F44336', label: '错误' }, + bug: { icon: '🐛', color: '#F44336', label: 'Bug' }, + important: { icon: '⭐', color: '#F44336', label: '重要' }, + + // 其他 + example: { icon: '📋', color: '#9C27B0', label: '示例' }, + quote: { icon: '💬', color: 'gray', label: '引用' }, + cite: { icon: '💬', color: 'gray', label: '引用' } +}; + +// Callout 检测正则 (支持 +/- 折叠标记) +const CALLOUT_PATTERN = /^>\s*\[!(\w+)\][+-]?(?:\s+(.+))?$/; +``` + +### Step 3: Callout 解析器 + +```javascript +function parseCallouts(text) { + const lines = text.split('\n'); + const result = []; + let i = 0; + + while (i < lines.length) { + const match = lines[i].match(CALLOUT_PATTERN); + if (match) { + const type = match[1].toLowerCase(); + const title = match[2] || null; + const content = []; + i++; + + // 收集 Callout 内容行 + while (i < lines.length && lines[i].startsWith('>')) { + content.push(lines[i].replace(/^>\s*/, '')); + i++; + } + + result.push({ + isCallout: true, + type, + title, + content: content.join('\n') + }); + } else { + result.push({ isCallout: false, line: lines[i] }); + i++; + } + } + + return result; +} +``` + +### Step 4: BBCode+MD 转换器 + +```javascript +function formatBBCodeMD(text) { + let result = text; + + // ===== 标题转换 (像素级字号) ===== + result = result.replace(/^######\s*(.+)$/gm, '[b]$1[/b]'); + result = result.replace(/^#####\s*(.+)$/gm, '[b]$1[/b]'); + result = result.replace(/^####\s*(.+)$/gm, '[b]$1[/b]'); + result = result.replace(/^###\s*(.+)$/gm, '[size=100][color=#333][b]$1[/b][/color][/size]'); + result = result.replace(/^##\s*(.+)$/gm, '[size=120][color=#2196F3][b]$1[/b][/color][/size]'); + result = result.replace(/^#\s*(.+)$/gm, '[size=150][color=#2196F3][b]$1[/b][/color][/size]'); + + // ===== 文本样式 ===== + result = result.replace(/\*\*\*(.+?)\*\*\*/g, '[b][i]$1[/i][/b]'); + result = result.replace(/\*\*(.+?)\*\*/g, '[b]$1[/b]'); + result = result.replace(/\*(.+?)\*/g, '[i]$1[/i]'); + result = result.replace(/~~(.+?)~~/g, '[s]$1[/s]'); + result = result.replace(/==(.+?)==/g, '[color=yellow]$1[/color]'); + + // ===== 代码 ===== + result = result.replace(/```(\w*)\n([\s\S]*?)```/g, '[code]$2[/code]'); + // 行内代码保持原样 (部分论坛不支持 font=monospace) + + // ===== 链接和图片 ===== + result = result.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '[url=$2]$1[/url]'); + result = result.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '[img]$2[/img]'); + + // ===== 引用 (非 Callout) ===== + result = result.replace(/^>\s+(.+)$/gm, '[quote]$1[/quote]'); + + // ===== 列表 (使用 • 符号) ===== + result = result.replace(/^[-*+]\s+(.+)$/gm, '• $1'); + + // ===== 分隔线 (保持 Markdown 语法) ===== + // `---` 在混合格式中通常可用,不转换为 [hr] + + return result.trim(); +} +``` + +### Step 5: Callout 转换 + +```javascript +function convertCallouts(text) { + const parsed = parseCallouts(text); + + return parsed.map(item => { + if (item.isCallout) { + const cfg = CALLOUT_CONFIG[item.type] || CALLOUT_CONFIG.note; + const displayTitle = item.title || cfg.label; + + // 使用 [quote] 包裹,标题使用 size=100 + return `[quote] +[size=100][color=${cfg.color}][b]${cfg.icon} ${displayTitle}[/b][/color][/size] + +${item.content} +[/quote]`; + } + return item.line; + }).join('\n'); +} +``` + +### Step 6: 执行转换 + +```javascript +// 1. 先处理 Callouts +let formattedContent = convertCallouts(content); + +// 2. 再进行通用 BBCode+MD 转换 +formattedContent = formatBBCodeMD(formattedContent); + +// 3. 清理多余空行 +formattedContent = formattedContent.replace(/\n{3,}/g, '\n\n'); +``` + +### Step 7: 保存转换结果 + +```javascript +const outputFile = 'output.bbcode.txt'; +Write(`${workDir}/${outputFile}`, formattedContent); + +// 更新配置 +config.output_file = outputFile; +config.formatted_content = formattedContent; +Write(`${workDir}/input-config.json`, JSON.stringify(config, null, 2)); +``` + +## Output + +- **File**: `output.bbcode.txt` +- **Format**: BBCode + Markdown 混合格式 + +## Quality Checklist + +- [ ] 标题使用像素值 (150/120/100) +- [ ] 未使用 `[align]` 标签 +- [ ] 未使用 `[hr]` 标签 +- [ ] 分隔线使用 `---` +- [ ] Callout 正确转换为 [quote] +- [ ] 颜色值使用 hex 格式 +- [ ] 内容完整无丢失 + +## Next Phase + +→ [Phase 4: Output & Preview](04-output-preview.md) diff --git a/.claude/skills/text-formatter/phases/04-output-preview.md b/.claude/skills/text-formatter/phases/04-output-preview.md new file mode 100644 index 00000000..5a27a43f --- /dev/null +++ b/.claude/skills/text-formatter/phases/04-output-preview.md @@ -0,0 +1,183 @@ +# Phase 4: Output & Preview + +输出最终结果并提供预览。 + +## Objective + +- 保存格式化后的内容到文件 +- 提供预览功能 +- 显示转换统计信息 + +## Input + +- 依赖: `input-config.json`, `output.*` +- 配置: `{workDir}/input-config.json` + +## Execution Steps + +### Step 1: 加载结果 + +```javascript +const config = JSON.parse(Read(`${workDir}/input-config.json`)); +const analysis = JSON.parse(Read(`${workDir}/analysis.json`)); +const outputFile = `${workDir}/${config.output_file}`; +const formattedContent = Read(outputFile); +``` + +### Step 2: 生成统计摘要 + +```javascript +const summary = { + input: { + method: config.input_method, + original_length: config.original_content.length, + word_count: config.original_content.split(/\s+/).length + }, + output: { + format: config.target_format, + file: outputFile, + length: formattedContent.length + }, + elements: analysis.stats, + reading_time: analysis.semantics?.estimated_reading_time || 1 +}; + +console.log(` +╔════════════════════════════════════════════════════════════════╗ +║ Text Formatter Summary ║ +╠════════════════════════════════════════════════════════════════╣ +║ Input: ${summary.input.word_count} words (${summary.input.original_length} chars) +║ Output: ${summary.output.format} → ${summary.output.file} +║ Elements Converted: +║ • Headings: ${summary.elements.headings} +║ • Paragraphs: ${summary.elements.paragraphs} +║ • Lists: ${summary.elements.lists} +║ • Code Blocks: ${summary.elements.code_blocks} +║ • Links: ${summary.elements.links} +║ Estimated Reading Time: ${summary.reading_time} min +╚════════════════════════════════════════════════════════════════╝ +`); +``` + +### Step 3: HTML 预览(如适用) + +```javascript +if (config.target_format === 'HTML') { + // 生成完整 HTML 文件用于预览 + const previewHtml = ` + + + + + Text Formatter Preview + + + +
+ ${formattedContent} +
+ +`; + + Write(`${workDir}/preview.html`, previewHtml); + + // 可选:在浏览器中打开预览 + // Bash(`start "${workDir}/preview.html"`); // Windows + // Bash(`open "${workDir}/preview.html"`); // macOS +} +``` + +### Step 4: 显示输出内容 + +```javascript +// 显示格式化后的内容 +console.log('\n=== Formatted Content ===\n'); +console.log(formattedContent); +console.log('\n=========================\n'); + +// 提示用户 +console.log(` +📁 Output saved to: ${outputFile} +${config.target_format === 'HTML' ? '🌐 Preview available: ' + workDir + '/preview.html' : ''} + +💡 Tips: +- Copy the content above for immediate use +- Or access the saved file at the path shown +`); +``` + +### Step 5: 询问后续操作 + +```javascript +const nextAction = await AskUserQuestion({ + questions: [ + { + question: "需要执行什么操作?", + header: "后续操作", + multiSelect: false, + options: [ + { label: "完成", description: "结束格式化流程" }, + { label: "转换为其他格式", description: "选择另一种输出格式" }, + { label: "重新编辑", description: "修改原始内容后重新格式化" } + ] + } + ] +}); + +if (nextAction["后续操作"] === "转换为其他格式") { + // 返回 Phase 1 选择新格式 + console.log('请重新运行 /text-formatter 选择其他格式'); +} +``` + +## Output + +- **File**: `output.{ext}` (最终输出) +- **File**: `preview.html` (HTML 预览,仅 HTML 格式) +- **Console**: 统计摘要和格式化内容 + +## Final Output Structure + +``` +{workDir}/ +├── input-config.json # 配置信息 +├── analysis.json # 分析结果 +├── output.md # Markdown 输出(如选择) +├── output.bbcode.txt # BBCode 输出(如选择) +├── output.html # HTML 输出(如选择) +└── preview.html # HTML 预览页面 +``` + +## Quality Checklist + +- [ ] 输出文件已保存 +- [ ] 统计信息正确显示 +- [ ] 预览功能可用(HTML) +- [ ] 用户可访问输出内容 + +## Completion + +此为最终阶段,格式化流程完成。 diff --git a/.claude/skills/text-formatter/specs/callout-types.md b/.claude/skills/text-formatter/specs/callout-types.md new file mode 100644 index 00000000..0647b2a1 --- /dev/null +++ b/.claude/skills/text-formatter/specs/callout-types.md @@ -0,0 +1,293 @@ +# Callout Types + +Obsidian 风格的 Callout/Admonition 类型定义和转换规则。 + +## When to Use + +| Phase | Usage | Section | +|-------|-------|---------| +| Phase 2 | 检测 Callout | Detection patterns | +| Phase 3 | 格式转换 | Conversion rules | + +--- + +## Callout 语法 + +### Obsidian 原生语法 + +```markdown +> [!TYPE] 可选标题 +> 内容行1 +> 内容行2 +``` + +### 支持的类型 + +| Type | Alias | Icon | Color | 用途 | +|------|-------|------|-------|------| +| `note` | - | 📝 | blue | 普通提示 | +| `info` | - | ℹ️ | blue | 信息说明 | +| `tip` | `hint` | 💡 | green | 技巧提示 | +| `success` | `check`, `done` | ✅ | green | 成功状态 | +| `warning` | `caution`, `attention` | ⚠️ | orange | 警告信息 | +| `danger` | `error` | ❌ | red | 危险/错误 | +| `bug` | - | 🐛 | red | Bug 说明 | +| `example` | - | 📋 | purple | 示例内容 | +| `quote` | `cite` | 💬 | gray | 引用内容 | +| `abstract` | `summary`, `tldr` | 📄 | cyan | 摘要 | +| `question` | `help`, `faq` | ❓ | yellow | 问题/FAQ | +| `todo` | - | 📌 | orange | 待办事项 | + +--- + +## 检测 Pattern + +```javascript +// Callout 检测正则 +const CALLOUT_PATTERN = /^>\s*\[!(\w+)\](?:\s+(.+))?$/; + +// 检测函数 +function detectCallout(line) { + const match = line.match(CALLOUT_PATTERN); + if (match) { + return { + type: match[1].toLowerCase(), + title: match[2] || null + }; + } + return null; +} + +// 解析完整 Callout 块 +function parseCalloutBlock(lines, startIndex) { + const firstLine = lines[startIndex]; + const calloutInfo = detectCallout(firstLine); + + if (!calloutInfo) return null; + + const content = []; + let i = startIndex + 1; + + while (i < lines.length && lines[i].startsWith('>')) { + content.push(lines[i].replace(/^>\s*/, '')); + i++; + } + + return { + ...calloutInfo, + content: content.join('\n'), + endIndex: i - 1 + }; +} +``` + +--- + +## 转换规则 + +### BBCode 转换 + +```javascript +const CALLOUT_BBCODE = { + note: { + icon: '📝', + color: '#2196F3', + label: '注意' + }, + info: { + icon: 'ℹ️', + color: '#2196F3', + label: '信息' + }, + tip: { + icon: '💡', + color: '#4CAF50', + label: '提示' + }, + success: { + icon: '✅', + color: '#4CAF50', + label: '成功' + }, + warning: { + icon: '⚠️', + color: '#FF9800', + label: '警告' + }, + danger: { + icon: '❌', + color: '#F44336', + label: '危险' + }, + bug: { + icon: '🐛', + color: '#F44336', + label: 'Bug' + }, + example: { + icon: '📋', + color: '#9C27B0', + label: '示例' + }, + quote: { + icon: '💬', + color: '#9E9E9E', + label: '引用' + }, + question: { + icon: '❓', + color: '#FFEB3B', + label: '问题' + } +}; + +function calloutToBBCode(type, title, content, style = 'forum') { + const config = CALLOUT_BBCODE[type] || CALLOUT_BBCODE.note; + const displayTitle = title || config.label; + + if (style === 'compact') { + return `[quote][b]${config.icon} ${displayTitle}[/b] +${content}[/quote]`; + } + + // Forum style - more visual + return `[quote] +[color=${config.color}][size=4][b]${config.icon} ${displayTitle}[/b][/size][/color] + +${content} +[/quote]`; +} +``` + +### HTML 转换 + +```javascript +function calloutToHTML(type, title, content) { + const config = CALLOUT_BBCODE[type] || CALLOUT_BBCODE.note; + const displayTitle = title || config.label; + + return `
+
+ ${config.icon} + ${displayTitle} +
+
+ ${content} +
+
`; +} +``` + +### Hybrid 转换 + +```javascript +function calloutToHybrid(type, title, content) { + const config = CALLOUT_BBCODE[type] || CALLOUT_BBCODE.note; + const displayTitle = title || config.label; + + // HTML container + BBCode styling + MD content + return `
+ +[color=${config.color}][b]${config.icon} ${displayTitle}[/b][/color] + +${content} + +
`; +} +``` + +--- + +## Callout CSS 样式 + +```css +/* Base callout styles */ +.callout { + padding: 1rem; + margin: 1rem 0; + border-left: 4px solid; + border-radius: 4px; + background: #f8f9fa; +} + +.callout-title { + display: flex; + align-items: center; + gap: 0.5rem; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.callout-icon { + font-size: 1.2em; +} + +/* Type-specific colors */ +.callout-note, .callout-info { + border-color: #2196F3; + background: #E3F2FD; +} + +.callout-tip, .callout-success { + border-color: #4CAF50; + background: #E8F5E9; +} + +.callout-warning { + border-color: #FF9800; + background: #FFF3E0; +} + +.callout-danger, .callout-bug { + border-color: #F44336; + background: #FFEBEE; +} + +.callout-example { + border-color: #9C27B0; + background: #F3E5F5; +} + +.callout-quote { + border-color: #9E9E9E; + background: #FAFAFA; +} + +.callout-question { + border-color: #FFC107; + background: #FFFDE7; +} +``` + +--- + +## 折叠 Callout + +支持可折叠的 Callout 语法: + +```markdown +> [!NOTE]+ 默认展开 +> 内容 + +> [!NOTE]- 默认折叠 +> 内容 +``` + +### BBCode 折叠 + +```bbcode +[collapse=📝 注意] +内容 +[/collapse] +``` + +### HTML 折叠 + +```html +
+ 📝 注意 +
+ 内容 +
+
+``` diff --git a/.claude/skills/text-formatter/specs/element-mapping.md b/.claude/skills/text-formatter/specs/element-mapping.md new file mode 100644 index 00000000..1602454e --- /dev/null +++ b/.claude/skills/text-formatter/specs/element-mapping.md @@ -0,0 +1,209 @@ +# Element Mapping + +内容元素到 BBCode + Markdown 混合格式的映射表。 + +## When to Use + +| Phase | Usage | Section | +|-------|-------|---------| +| Phase 2 | 元素识别 | Detection patterns | +| Phase 3 | 格式转换 | Conversion rules | + +--- + +## Element Detection Patterns + +### 标题检测 + +| 类型 | Pattern | 示例 | +|------|---------|------| +| ATX 标题 | `/^#{1,6}\s+(.+)$/` | `# Title`, `## Subtitle` | +| Setext H1 | `/^(.+)\n={3,}$/` | `Title\n====` | +| Setext H2 | `/^(.+)\n-{3,}$/` | `Subtitle\n----` | + +### 列表检测 + +| 类型 | Pattern | 示例 | +|------|---------|------| +| 无序列表 | `/^[\s]*[-*+]\s+(.+)$/` | `- item`, `* item` | +| 有序列表 | `/^[\s]*\d+\.\s+(.+)$/` | `1. item`, `2. item` | +| 任务列表 | `/^[\s]*[-*]\s+\[([ x])\]\s+(.+)$/` | `- [ ] todo`, `- [x] done` | + +### Callout 检测 + +| 类型 | Pattern | 示例 | +|------|---------|------| +| Callout 开始 | `/^>\s*\[!(\w+)\](?:\s+(.+))?$/` | `> [!NOTE] 标题` | +| Callout 内容 | `/^>\s*(.*)$/` | `> 内容行` | +| 可折叠展开 | `/^>\s*\[!(\w+)\]\+/` | `> [!NOTE]+` | +| 可折叠收起 | `/^>\s*\[!(\w+)\]-/` | `> [!NOTE]-` | + +### 代码检测 + +| 类型 | Pattern | 示例 | +|------|---------|------| +| 代码块开始 | `/^```(\w*)$/` | ` ```js ` | +| 代码块结束 | `/^```$/` | ` ``` ` | +| 行内代码 | `/`([^`]+)`/` | `` `code` `` | + +### 其他元素 + +| 类型 | Pattern | 示例 | +|------|---------|------| +| 链接 | `/\[([^\]]+)\]\(([^)]+)\)/` | `[text](url)` | +| 图片 | `/!\[([^\]]*)\]\(([^)]+)\)/` | `![alt](url)` | +| 普通引用 | `/^>\s+(.+)$/` | `> quote` | +| 分隔线 | `/^[-*_]{3,}$/` | `---`, `***` | +| 高亮 | `/==(.+?)==/` | `==highlight==` | +| 粗体 | `/\*\*(.+?)\*\*/` | `**bold**` | +| 斜体 | `/\*(.+?)\*/` | `*italic*` | +| 删除线 | `/~~(.+?)~~/` | `~~strike~~` | + +--- + +## Element Conversion Matrix + +### 标题映射 (Pixel-Based) + +| Element | Markdown | BBCode Output | +|---------|----------|---------------| +| **H1** | `# text` | `[size=150][color=#2196F3][b]text[/b][/color][/size]` | +| **H2** | `## text` | `[size=120][color=#2196F3][b]text[/b][/color][/size]` | +| **H3** | `### text` | `[size=100][color=#333][b]text[/b][/color][/size]` | +| **H4** | `#### text` | `[b]text[/b]` | +| **H5** | `##### text` | `[b]text[/b]` | +| **H6** | `###### text` | `[b]text[/b]` | + +### 文本样式映射 + +| Element | Markdown | BBCode | +|---------|----------|--------| +| **Bold** | `**text**` | `[b]text[/b]` | +| **Italic** | `*text*` | `[i]text[/i]` | +| **Bold+Italic** | `***text***` | `[b][i]text[/i][/b]` | +| **Strike** | `~~text~~` | `[s]text[/s]` | +| **Highlight** | `==text==` | `[color=yellow]text[/color]` | +| **Code (inline)** | `` `text` `` | 保持原样 | + +### 块级元素映射 + +| Element | Markdown | BBCode | +|---------|----------|--------| +| **Code Block** | ` ```lang\ncode\n``` ` | `[code]code[/code]` | +| **Quote** | `> text` | `[quote]text[/quote]` | +| **HR** | `---` | `---` (保持 Markdown) | +| **List Item** | `- text` | `• text` | +| **Paragraph** | `text\n\ntext` | `text\n\ntext` | + +### 链接和媒体映射 + +| Element | Markdown | BBCode | +|---------|----------|--------| +| **Link** | `[text](url)` | `[url=url]text[/url]` | +| **Image** | `![alt](url)` | `[img]url[/img]` | + +--- + +## Callout Mapping + +### 类型到样式映射 + +| Callout Type | Color | Icon | Label | +|--------------|-------|------|-------| +| note | #2196F3 | 📝 | 注意 | +| info | #2196F3 | ℹ️ | 信息 | +| tip | #4CAF50 | 💡 | 提示 | +| hint | #4CAF50 | 💡 | 提示 | +| success | #4CAF50 | ✅ | 成功 | +| check | #4CAF50 | ✅ | 完成 | +| done | #4CAF50 | ✅ | 完成 | +| warning | #FF9800 | ⚠️ | 警告 | +| caution | #FF9800 | ⚠️ | 注意 | +| attention | #FF9800 | ⚠️ | 注意 | +| danger | #F44336 | ❌ | 危险 | +| error | #F44336 | ❌ | 错误 | +| bug | #F44336 | 🐛 | Bug | +| example | #9C27B0 | 📋 | 示例 | +| question | #FF9800 | ❓ | 问题 | +| help | #FF9800 | ❓ | 帮助 | +| faq | #FF9800 | ❓ | FAQ | +| quote | gray | 💬 | 引用 | +| cite | gray | 💬 | 引用 | +| abstract | #2196F3 | 📄 | 摘要 | +| summary | #2196F3 | 📄 | 摘要 | +| tldr | #2196F3 | 📄 | 摘要 | +| todo | #FF9800 | 📋 | 待办 | +| important | #F44336 | ⭐ | 重要 | + +### Callout 输出模板 + +```bbcode +[quote] +[size=100][color={color}][b]{icon} {title}[/b][/color][/size] + +{content} +[/quote] +``` + +--- + +## Unsupported Elements + +### 不支持转换的元素 + +| 元素 | 原因 | 降级方案 | +|------|------|----------| +| 表格 | BBCode 表格支持有限 | 转为代码块或列表 | +| 脚注 | 不支持 | 转为括号注释 `(注: ...)` | +| 数学公式 | 不支持 | 保留原始文本 | +| 嵌入内容 | 不支持 | 转为链接 | +| 任务列表 | 复选框不支持 | 转为普通列表 `☐`/`☑` | + +### 降级示例 + +**表格**: +``` +| A | B | +|---|---| +| 1 | 2 | + +→ 降级为: + +A: 1 +B: 2 +``` + +**脚注**: +``` +文本[^1] + +[^1]: 脚注内容 + +→ 降级为: + +文本 (注: 脚注内容) +``` + +**任务列表**: +``` +- [ ] 待办 +- [x] 已完成 + +→ 降级为: + +☐ 待办 +☑ 已完成 +``` + +--- + +## Validation Rules + +### 转换验证 + +- [ ] 所有 H1-H3 使用像素值 size (150/120/100) +- [ ] 未使用 `[align]` 标签 +- [ ] 未使用 `[hr]` 标签 +- [ ] 分隔线保持 `---` +- [ ] Callout 正确识别并转换 +- [ ] 颜色值使用 hex 格式 diff --git a/.claude/skills/text-formatter/specs/format-rules.md b/.claude/skills/text-formatter/specs/format-rules.md new file mode 100644 index 00000000..9db85f3b --- /dev/null +++ b/.claude/skills/text-formatter/specs/format-rules.md @@ -0,0 +1,260 @@ +# Format Conversion Rules + +BBCode + Markdown 混合格式转换规则(论坛优化)。 + +## When to Use + +| Phase | Usage | Section | +|-------|-------|---------| +| Phase 3 | 格式转换 | All sections | + +--- + +## Core Principles + +### 1. Pixel-Based Sizing + +**重要**: 使用像素值而非 1-7 级别 + +| 元素 | Size (px) | 说明 | +|------|-----------|------| +| 主标题 (H1) | 150 | 文档标题 | +| 章节标题 (H2) | 120 | 主要章节 | +| 子标题 (H3) | 100 | 子章节 | +| 正文 | (默认) | 不指定 size | +| 备注/灰色 | 80 | 脚注、元数据 | + +### 2. Supported Tags Only + +**支持的 BBCode 标签**: +- `[size=N]` - 字号(像素值) +- `[color=X]` - 颜色(hex 或名称) +- `[b]`, `[i]`, `[s]` - 粗体、斜体、删除线 +- `[quote]` - 引用块 +- `[code]` - 代码块 +- `[url]`, `[img]` - 链接、图片 +- `[list]`, `[*]` - 列表 + +**禁止使用的标签**: +- `[align]` - 不渲染,显示为文本 +- `[hr]` - 不渲染,使用 Markdown `---` +- `[table]` - 支持有限,避免使用 +- HTML 标签 (`
`, ``) - 不支持 + +### 3. Markdown as Separator + +分隔线使用 Markdown 语法:`---` + +--- + +## Element Conversion Rules + +### 标题转换 + +| Markdown | BBCode Output | +|----------|---------------| +| `# H1` | `[size=150][color=#2196F3][b]H1[/b][/color][/size]` | +| `## H2` | `[size=120][color=#2196F3][b]H2[/b][/color][/size]` | +| `### H3` | `[size=100][color=#333][b]H3[/b][/color][/size]` | +| `#### H4+` | `[b]H4[/b]` (不加 size) | + +### 文本样式 + +| Markdown | BBCode | +|----------|--------| +| `**bold**` | `[b]bold[/b]` | +| `*italic*` | `[i]italic[/i]` | +| `***both***` | `[b][i]both[/i][/b]` | +| `~~strike~~` | `[s]strike[/s]` | +| `==highlight==` | `[color=yellow]highlight[/color]` | + +### 代码 + +| Markdown | BBCode | +|----------|--------| +| `` `inline` `` | 保持原样或 `[color=#9C27B0]inline[/color]` | +| ` ```code``` ` | `[code]code[/code]` | + +### 链接和图片 + +| Markdown | BBCode | +|----------|--------| +| `[text](url)` | `[url=url]text[/url]` | +| `![alt](url)` | `[img]url[/img]` | + +### 列表 + +``` +Markdown: +- item 1 +- item 2 + - nested + +BBCode: +• item 1 +• item 2 + • nested +``` + +注意:使用 `•` 符号而非 `[list][*]`,因为部分论坛渲染有问题。 + +### 引用 + +``` +Markdown: +> quote text + +BBCode: +[quote] +quote text +[/quote] +``` + +--- + +## Callout (标注) 转换 + +### Obsidian Callout 语法 + +```markdown +> [!TYPE] 可选标题 +> 内容行 1 +> 内容行 2 +``` + +### 支持的 Callout 类型 + +| Type | Color | Icon | 中文标签 | +|------|-------|------|----------| +| note, info | #2196F3 | 📝 | 注意 / 信息 | +| tip, hint | #4CAF50 | 💡 | 提示 | +| success, check, done | #4CAF50 | ✅ | 成功 | +| warning, caution, attention | #FF9800 | ⚠️ | 警告 | +| danger, error, bug | #F44336 | ❌ | 危险 / 错误 | +| example | #9C27B0 | 📋 | 示例 | +| question, help, faq | #FF9800 | ❓ | 问题 | +| quote, cite | gray | 💬 | 引用 | +| abstract, summary, tldr | #2196F3 | 📄 | 摘要 | + +### Callout 转换模板 + +```bbcode +[quote] +[size=100][color={color}][b]{icon} {title}[/b][/color][/size] + +{content} +[/quote] +``` + +**示例**: + +```markdown +> [!WARNING] 注意事项 +> 这是警告内容 +``` + +转换为: + +```bbcode +[quote] +[size=100][color=#FF9800][b]⚠️ 注意事项[/b][/color][/size] + +这是警告内容 +[/quote] +``` + +### 可折叠 Callout + +Obsidian 支持 `> [!NOTE]+` (展开) 和 `> [!NOTE]-` (折叠)。 + +由于 BBCode 不支持折叠,统一转换为普通 quote。 + +--- + +## Color Palette + +### 语义颜色 + +| 语义 | Hex | 使用场景 | +|------|-----|----------| +| Primary | #2196F3 | 标题、链接、信息 | +| Success | #4CAF50 | 成功、提示、特性 | +| Warning | #FF9800 | 警告、注意 | +| Error | #F44336 | 错误、危险 | +| Purple | #9C27B0 | 示例、代码 | +| Gray | gray | 备注、元数据 | +| Dark | #333 | 子标题 | + +### 颜色使用规则 + +1. **标题颜色**: H1/H2 使用 #2196F3,H3 使用 #333 +2. **Callout 颜色**: 根据类型使用语义颜色 +3. **备注颜色**: 使用 gray +4. **强调颜色**: 根据语义选择(成功用绿色,警告用橙色) + +--- + +## Spacing Rules + +### 空行控制 + +| 元素 | 前空行 | 后空行 | +|------|--------|--------| +| 标题 | 1 | 1 | +| 段落 | 0 | 1 | +| 列表 | 0 | 1 | +| 代码块 | 1 | 1 | +| Callout | 1 | 1 | +| 分隔线 `---` | 1 | 1 | + +### 示例输出结构 + +```bbcode +[size=150][color=#2196F3][b]文档标题[/b][/color][/size] + +[size=80][color=gray]作者 | 日期[/color][/size] + +--- + +[size=120][color=#2196F3][b]第一章节[/b][/color][/size] + +正文内容... + +[quote] +[size=100][color=#4CAF50][b]💡 提示[/b][/color][/size] + +提示内容 +[/quote] + +--- + +[size=120][color=#2196F3][b]第二章节[/b][/color][/size] + +更多内容... + +--- + +[size=80][color=gray]— 全文完 —[/color][/size] +``` + +--- + +## Quality Checklist + +### 转换完整性 + +- [ ] 所有标题使用像素值 size +- [ ] 未使用 `[align]` 或 `[hr]` +- [ ] 分隔线使用 `---` +- [ ] Callout 正确转换为 quote +- [ ] 颜色符合语义规范 +- [ ] 空行控制正确 + +### 常见错误 + +| 错误 | 正确做法 | +|------|----------| +| `[size=5]` | `[size=120]` | +| `[align=center]` | 删除,默认左对齐 | +| `[hr]` | 使用 `---` | +| `
` | 删除 HTML 标签 | diff --git a/.claude/skills/text-formatter/templates/bbcode-template.md b/.claude/skills/text-formatter/templates/bbcode-template.md new file mode 100644 index 00000000..d854af5e --- /dev/null +++ b/.claude/skills/text-formatter/templates/bbcode-template.md @@ -0,0 +1,350 @@ +# BBCode Template + +论坛优化的 BBCode + Markdown 混合模板(像素级字号)。 + +## 核心规则 + +### 字号体系 (Pixels) + +| 元素 | Size | 说明 | +|------|------|------| +| 主标题 | 150 | 文档标题 | +| 章节标题 | 120 | H2 级别 | +| 子标题 | 100 | H3 级别 | +| 正文 | (默认) | 不指定 | +| 备注 | 80 | 灰色小字 | + +### 禁止使用 + +- `[align]` - 不渲染 +- `[hr]` - 不渲染,用 `---` +- `[table]` - 支持有限 +- HTML 标签 + +--- + +## 文档模板 + +### 基础文档结构 + +```bbcode +[size=150][color=#2196F3][b]{{title}}[/b][/color][/size] + +[size=80][color=gray]{{metadata}}[/color][/size] + +--- + +{{introduction}} + +--- + +[size=120][color=#2196F3][b]{{section1_title}}[/b][/color][/size] + +{{section1_content}} + +--- + +[size=120][color=#2196F3][b]{{section2_title}}[/b][/color][/size] + +{{section2_content}} + +--- + +[size=80][color=gray]— 全文完 —[/color][/size] +``` + +### 带目录的文档 + +```bbcode +[size=150][color=#2196F3][b]{{title}}[/b][/color][/size] + +[size=80][color=gray]{{author}} | {{date}}[/color][/size] + +--- + +[size=100][b]📋 目录[/b][/size] + +• {{section1_title}} +• {{section2_title}} +• {{section3_title}} + +--- + +[size=120][color=#2196F3][b]{{section1_title}}[/b][/color][/size] + +{{section1_content}} + +--- + +[size=120][color=#2196F3][b]{{section2_title}}[/b][/color][/size] + +{{section2_content}} + +--- + +[size=120][color=#2196F3][b]{{section3_title}}[/b][/color][/size] + +{{section3_content}} + +--- + +[size=80][color=gray]— 全文完 —[/color][/size] +``` + +--- + +## Callout 模板 + +### 提示 (Note/Info) + +```bbcode +[quote] +[size=100][color=#2196F3][b]📝 {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +### 技巧 (Tip/Hint) + +```bbcode +[quote] +[size=100][color=#4CAF50][b]💡 {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +### 成功 (Success) + +```bbcode +[quote] +[size=100][color=#4CAF50][b]✅ {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +### 警告 (Warning/Caution) + +```bbcode +[quote] +[size=100][color=#FF9800][b]⚠️ {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +### 危险/错误 (Danger/Error) + +```bbcode +[quote] +[size=100][color=#F44336][b]❌ {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +### 示例 (Example) + +```bbcode +[quote] +[size=100][color=#9C27B0][b]📋 {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +### 问题 (Question/FAQ) + +```bbcode +[quote] +[size=100][color=#FF9800][b]❓ {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +### 重要 (Important) + +```bbcode +[quote] +[size=100][color=#F44336][b]⭐ {{title}}[/b][/color][/size] + +{{content}} +[/quote] +``` + +--- + +## 代码展示模板 + +### 单代码块 + +```bbcode +[size=100][color=#9C27B0][b]代码示例[/b][/color][/size] + +[code] +{{code}} +[/code] + +[size=80][color=gray]说明: {{description}}[/color][/size] +``` + +### 带标题的代码 + +```bbcode +[size=100][b]{{code_title}}[/b][/size] + +[code] +{{code}} +[/code] +``` + +--- + +## 特性展示模板 + +### 特性列表 + +```bbcode +[size=120][color=#2196F3][b]功能特性[/b][/color][/size] + +• [color=#4CAF50][b]✨ {{feature1}}[/b][/color] — {{desc1}} +• [color=#2196F3][b]🚀 {{feature2}}[/b][/color] — {{desc2}} +• [color=#FF9800][b]⚡ {{feature3}}[/b][/color] — {{desc3}} +``` + +### 详细特性卡片 + +```bbcode +[size=120][color=#2196F3][b]功能特性[/b][/color][/size] + +[quote] +[size=100][color=#4CAF50][b]✨ {{feature1_title}}[/b][/color][/size] + +{{feature1_description}} + +[size=80][color=gray]适用场景: {{feature1_use_case}}[/color][/size] +[/quote] + +[quote] +[size=100][color=#2196F3][b]🚀 {{feature2_title}}[/b][/color][/size] + +{{feature2_description}} + +[size=80][color=gray]适用场景: {{feature2_use_case}}[/color][/size] +[/quote] +``` + +--- + +## 步骤指南模板 + +```bbcode +[size=120][color=#2196F3][b]操作步骤[/b][/color][/size] + +[size=100][color=#2196F3][b]步骤 1: {{step1_title}}[/b][/color][/size] + +{{step1_content}} + +[quote] +[size=100][color=#FF9800][b]💡 提示[/b][/color][/size] + +{{step1_tip}} +[/quote] + +[size=100][color=#2196F3][b]步骤 2: {{step2_title}}[/b][/color][/size] + +{{step2_content}} + +[size=100][color=#2196F3][b]步骤 3: {{step3_title}}[/b][/color][/size] + +{{step3_content}} + +--- + +[color=#4CAF50][b]✅ 完成![/b][/color] {{completion_message}} +``` + +--- + +## 版本更新模板 + +```bbcode +[size=150][color=#673AB7][b]🎉 版本 {{version}} 更新日志[/b][/color][/size] + +--- + +[size=120][color=#4CAF50][b]✨ 新功能[/b][/color][/size] + +• [b]{{new_feature1}}[/b]: {{new_feature1_desc}} +• [b]{{new_feature2}}[/b]: {{new_feature2_desc}} + +[size=120][color=#2196F3][b]🔧 改进[/b][/color][/size] + +• {{improvement1}} +• {{improvement2}} + +[size=120][color=#F44336][b]🐛 修复[/b][/color][/size] + +• {{bugfix1}} +• {{bugfix2}} + +--- + +[url={{download_url}}][b]📥 立即下载[/b][/url] +``` + +--- + +## FAQ 模板 + +```bbcode +[size=120][color=#2196F3][b]❓ 常见问题[/b][/color][/size] + +--- + +[size=100][color=#333][b]Q: {{question1}}[/b][/color][/size] + +[b]A:[/b] {{answer1}} + +--- + +[size=100][color=#333][b]Q: {{question2}}[/b][/color][/size] + +[b]A:[/b] {{answer2}} + +--- + +[size=100][color=#333][b]Q: {{question3}}[/b][/color][/size] + +[b]A:[/b] {{answer3}} +``` + +--- + +## 转换检查清单 + +### 必须检查 + +- [ ] 标题使用像素值 (150/120/100) +- [ ] 分隔线使用 `---` +- [ ] 未使用 `[align]` +- [ ] 未使用 `[hr]` +- [ ] 未使用 HTML 标签 +- [ ] Callout 标题 size=100 +- [ ] 灰色备注 size=80 + +### 颜色规范 + +| 用途 | 颜色 | +|------|------| +| 主标题 | #2196F3 | +| 章节标题 | #2196F3 | +| 子标题 | #333 | +| 成功/提示 | #4CAF50 | +| 警告 | #FF9800 | +| 错误/危险 | #F44336 | +| 示例 | #9C27B0 | +| 备注 | gray |