sumulige-claude 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/hook-registry.json +0 -15
- package/.claude/rules/coding-style.md +18 -7
- package/.claude/rules/hooks.md +15 -4
- package/.claude/rules/performance.md +15 -5
- package/.claude/rules/security.md +140 -4
- package/.claude/rules/testing.md +138 -9
- package/.claude/rules/web-design-standard.md +16 -5
- package/.claude/skills/algorithmic-art/metadata.yaml +28 -0
- package/.claude/skills/api-tester/SKILL.md +61 -0
- package/.claude/skills/api-tester/examples/basic.md +3 -0
- package/.claude/skills/api-tester/metadata.yaml +30 -0
- package/.claude/skills/api-tester/templates/default.md +3 -0
- package/.claude/skills/brand-guidelines/metadata.yaml +26 -0
- package/.claude/skills/canvas-design/metadata.yaml +27 -0
- package/.claude/skills/code-reviewer-123/SKILL.md +61 -0
- package/.claude/skills/code-reviewer-123/examples/basic.md +3 -0
- package/.claude/skills/code-reviewer-123/metadata.yaml +30 -0
- package/.claude/skills/code-reviewer-123/templates/default.md +3 -0
- package/.claude/skills/doc-coauthoring/metadata.yaml +27 -0
- package/.claude/skills/docx/metadata.yaml +30 -0
- package/.claude/skills/frontend-design/metadata.yaml +28 -0
- package/.claude/skills/internal-comms/metadata.yaml +28 -0
- package/.claude/skills/mcp-builder/metadata.yaml +26 -0
- package/.claude/skills/my-skill/SKILL.md +61 -0
- package/.claude/skills/my-skill/examples/basic.md +3 -0
- package/.claude/skills/my-skill/metadata.yaml +30 -0
- package/.claude/skills/my-skill/templates/default.md +3 -0
- package/.claude/skills/pdf/metadata.yaml +29 -0
- package/.claude/skills/pptx/metadata.yaml +29 -0
- package/.claude/skills/react-best-practices/metadata.yaml +26 -0
- package/.claude/skills/react-node-practices/SKILL.md +409 -0
- package/.claude/skills/react-node-practices/metadata.yaml +56 -0
- package/.claude/skills/skill-creator/metadata.yaml +25 -0
- package/.claude/skills/slack-gif-creator/metadata.yaml +28 -0
- package/.claude/skills/test-skill-name/SKILL.md +61 -0
- package/.claude/skills/test-skill-name/examples/basic.md +3 -0
- package/.claude/skills/test-skill-name/metadata.yaml +30 -0
- package/.claude/skills/test-skill-name/templates/default.md +3 -0
- package/.claude/skills/test-workflow/metadata.yaml +32 -0
- package/.claude/skills/theme-factory/metadata.yaml +26 -0
- package/.claude/skills/threejs-fundamentals/metadata.yaml +27 -0
- package/.claude/skills/web-artifacts-builder/metadata.yaml +30 -0
- package/.claude/skills/web-design-guidelines/metadata.yaml +26 -0
- package/.claude/skills/webapp-testing/metadata.yaml +26 -0
- package/.claude/skills/xlsx/metadata.yaml +29 -0
- package/LICENSE +21 -0
- package/cli.js +1 -1
- package/package.json +25 -3
- package/.claude/.kickoff-hint.txt +0 -52
- package/.claude/.sumulige-claude-version +0 -1
- package/.claude/.version +0 -1
- package/.claude/AGENTS.md +0 -42
- package/.claude/ANCHORS.md +0 -40
- package/.claude/CLAUDE.md +0 -138
- package/.claude/MEMORY.md +0 -69
- package/.claude/PROJECT_LOG.md +0 -101
- package/.claude/THINKING_CHAIN_GUIDE.md +0 -287
- package/.claude/USAGE.md +0 -175
- package/.claude/boris-optimizations.md +0 -167
- package/.claude/handoffs/INDEX.md +0 -21
- package/.claude/handoffs/LATEST.md +0 -76
- package/.claude/handoffs/handoff_2026-01-22T13-07-04-757Z.md +0 -76
- package/.claude/quality-gate.json +0 -82
- package/.claude/rag/skill-index.json +0 -135
- package/.claude/settings.json +0 -99
- package/.claude/settings.local.json +0 -175
- package/.claude/templates/PROJECT_KICKOFF.md +0 -89
- package/.claude/templates/PROJECT_PROPOSAL.md +0 -227
- package/.claude/templates/TASK_PLAN.md +0 -121
- package/.claude/templates/hooks/README.md +0 -302
- package/.claude/templates/hooks/hook.sh.template +0 -94
- package/.claude/templates/hooks/user-prompt-submit.cjs.template +0 -116
- package/.claude/templates/hooks/user-response-submit.cjs.template +0 -94
- package/.claude/templates/hooks/validate.js +0 -173
- package/.claude/templates/tasks/develop.md +0 -69
- package/.claude/templates/tasks/research.md +0 -64
- package/.claude/templates/tasks/test.md +0 -96
- package/.claude/thinking-routes/.last-sync +0 -1
- package/.claude/thinking-routes/QUICKREF.md +0 -98
- package/.claude/workflow/document-scanner.js +0 -426
- package/.claude/workflow/knowledge-engine.js +0 -941
- package/.claude/workflow/notebooklm/browser.js +0 -1028
- package/.claude/workflow/phases/phase1-research.js +0 -578
- package/.claude/workflow/phases/phase1-research.ts +0 -465
- package/.claude/workflow/phases/phase2-approve.js +0 -722
- package/.claude/workflow/phases/phase3-plan.js +0 -1200
- package/.claude/workflow/phases/phase4-develop.js +0 -894
- package/.claude/workflow/search-cache.js +0 -230
- package/.claude/workflow/templates/approval.md +0 -315
- package/.claude/workflow/templates/development.md +0 -377
- package/.claude/workflow/templates/planning.md +0 -328
- package/.claude/workflow/templates/research.md +0 -250
- package/.claude/workflow/types.js +0 -37
- package/.claude/workflow/web-search.js +0 -278
- package/.claude-plugin/marketplace.json +0 -71
- package/.github/workflows/sync-skills.yml +0 -74
- package/.versionrc +0 -25
- package/AGENTS.md +0 -580
- package/CHANGELOG.md +0 -481
- package/CLAUDE-template.md +0 -114
- package/DEV_TOOLS_GUIDE.md +0 -190
- package/PROJECT_STRUCTURE.md +0 -266
- package/Q&A.md +0 -325
- package/config/defaults.json +0 -34
- package/config/official-skills.json +0 -183
- package/config/quality-gate.json +0 -67
- package/config/skill-categories.json +0 -40
- package/config/version-manifest.json +0 -85
- package/demos/power-3d-scatter.html +0 -683
- package/development/cache/web-search/search_1193d605f8eb364651fc2f2041b58a31.json +0 -36
- package/development/cache/web-search/search_3798bf06960edc125f744a1abb5b72c5.json +0 -36
- package/development/cache/web-search/search_37c7d4843a53f0d83f1122a6f908a2a3.json +0 -36
- package/development/cache/web-search/search_44166fa0153709ee168485a22aa0ab40.json +0 -36
- package/development/cache/web-search/search_4deaebb1f77e86a8ca066dc5a49c59fd.json +0 -36
- package/development/cache/web-search/search_94da91789466070a7f545612e73c7372.json +0 -36
- package/development/cache/web-search/search_dd5de8491b8b803a3cb01339cd210fb0.json +0 -36
- package/development/knowledge-base/.index.clean.json +0 -1
- package/development/knowledge-base/.index.json +0 -486
- package/development/knowledge-base/test-best-practices.md +0 -29
- package/development/projects/proj_mkh1pazz_ixmt1/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4jvnb_z7rwf/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4jxkd_ewz5a/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4k84n_ni73k/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4wfyd_u9w88/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4wsbo_iahvf/development/projects/proj_mkh4xbpg_4na5w/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4wsbo_iahvf/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4xulg_1ka8x/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4xwhj_gch8j/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4y2qk_9lm8z/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh4y2qk_9lm8z/phase2/requirements.md +0 -226
- package/development/projects/proj_mkh4y2qk_9lm8z/phase3/PRD.md +0 -345
- package/development/projects/proj_mkh4y2qk_9lm8z/phase3/TASK_PLAN.md +0 -284
- package/development/projects/proj_mkh4y2qk_9lm8z/phase3/prototype/README.md +0 -14
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/DEVELOPMENT_LOG.md +0 -35
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/TASKS.md +0 -34
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/.env.example +0 -5
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/README.md +0 -60
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/package.json +0 -25
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/index.js +0 -70
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/routes/index.js +0 -48
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/health.test.js +0 -20
- package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/jest.config.js +0 -21
- package/development/projects/proj_mkh7veqg_3lypc/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh7veqg_3lypc/phase2/requirements.md +0 -226
- package/development/projects/proj_mkh7veqg_3lypc/phase3/PRD.md +0 -345
- package/development/projects/proj_mkh7veqg_3lypc/phase3/TASK_PLAN.md +0 -284
- package/development/projects/proj_mkh7veqg_3lypc/phase3/prototype/README.md +0 -14
- package/development/projects/proj_mkh8k8fo_rmqn5/phase1/feasibility-report.md +0 -160
- package/development/projects/proj_mkh8xyhy_1vshq/phase1/feasibility-report.md +0 -178
- package/development/projects/proj_mkh8zddd_dhamf/phase1/feasibility-report.md +0 -377
- package/development/projects/proj_mkh8zddd_dhamf/phase2/requirements.md +0 -442
- package/development/projects/proj_mkh8zddd_dhamf/phase3/api-design.md +0 -800
- package/development/projects/proj_mkh8zddd_dhamf/phase3/architecture.md +0 -625
- package/development/projects/proj_mkh8zddd_dhamf/phase3/data-model.md +0 -830
- package/development/projects/proj_mkh8zddd_dhamf/phase3/risks.md +0 -957
- package/development/projects/proj_mkh8zddd_dhamf/phase3/wbs.md +0 -381
- package/development/todos/.state.json +0 -19
- package/development/todos/INDEX.md +0 -63
- package/development/todos/active/_README.md +0 -49
- package/development/todos/archived/_README.md +0 -11
- package/development/todos/backlog/_README.md +0 -11
- package/development/todos/backlog/mcp-integration.md +0 -35
- package/development/todos/completed/_README.md +0 -11
- package/development/todos/completed/boris-optimizations.md +0 -39
- package/development/todos/completed/develop/local-knowledge-index.md +0 -85
- package/development/todos/completed/develop/todo-system.md +0 -47
- package/development/todos/completed/develop/web-search-integration.md +0 -83
- package/development/todos/completed/test/phase1-e2e-test.md +0 -103
- package/docs/DEVELOPMENT.md +0 -461
- package/docs/MARKETPLACE.md +0 -352
- package/docs/RELEASE.md +0 -93
- package/jest.config.js +0 -63
- package/lib/commands.js +0 -3588
- package/lib/config-manager.js +0 -441
- package/lib/config-schema.js +0 -408
- package/lib/config-validator.js +0 -330
- package/lib/config.js +0 -122
- package/lib/errors.js +0 -305
- package/lib/incremental-sync.js +0 -274
- package/lib/marketplace.js +0 -487
- package/lib/migrations.js +0 -154
- package/lib/permission-audit.js +0 -255
- package/lib/quality-gate.js +0 -431
- package/lib/quality-rules.js +0 -373
- package/lib/utils.js +0 -150
- package/lib/version-check.js +0 -169
- package/lib/version-manifest.js +0 -171
- package/project-paradigm.md +0 -313
- package/prompts/how-to-find.md +0 -163
- package/prompts/linus-architect.md +0 -71
- package/prompts/software-architect.md +0 -173
- package/prompts/web-designer.md +0 -249
- package/scripts/fix-hooks.mjs +0 -97
- package/scripts/sync-external.mjs +0 -298
- package/scripts/sync-to-home.sh +0 -108
- package/scripts/update-registry.mjs +0 -325
- package/sources.yaml +0 -83
- package/tests/README.md +0 -263
- package/tests/commands.test.js +0 -1086
- package/tests/config-manager.test.js +0 -677
- package/tests/config-schema.test.js +0 -425
- package/tests/config-validator.test.js +0 -436
- package/tests/config.test.js +0 -100
- package/tests/errors.test.js +0 -477
- package/tests/manual/phase1-e2e.sh +0 -389
- package/tests/manual/phase2-test-cases.md +0 -311
- package/tests/manual/phase3-test-cases.md +0 -309
- package/tests/manual/phase4-test-cases.md +0 -414
- package/tests/manual/test-cases.md +0 -417
- package/tests/marketplace.test.js +0 -420
- package/tests/migrations.test.js +0 -187
- package/tests/quality-gate.test.js +0 -679
- package/tests/quality-rules.test.js +0 -619
- package/tests/sync-external.test.js +0 -214
- package/tests/update-registry.test.js +0 -251
- package/tests/utils.test.js +0 -171
- package/tests/version-check.test.js +0 -75
- package/tests/web-search.test.js +0 -392
- package/thinkinglens-silent.md +0 -138
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# 对话历史速查卡
|
|
2
|
-
|
|
3
|
-
> 快速找到你的对话记录
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🚀 最常用
|
|
8
|
-
|
|
9
|
-
| 命令 | 效果 |
|
|
10
|
-
|------|------|
|
|
11
|
-
| `tl` | 查看今日对话摘要 |
|
|
12
|
-
| `log` | 查看项目完整日志 |
|
|
13
|
-
| `memory` | 查看最近变更 |
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 📂 数据位置
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
.claude/
|
|
21
|
-
├── thinking-routes/
|
|
22
|
-
│ └── .conversation-flow.json ← 对话流数据
|
|
23
|
-
├── MEMORY.md ← 增量记忆
|
|
24
|
-
├── PROJECT_LOG.md ← 完整日志
|
|
25
|
-
└── ANCHORS.md ← 快速索引
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## 🔍 查找方式
|
|
31
|
-
|
|
32
|
-
### 按时间查找
|
|
33
|
-
```bash
|
|
34
|
-
# 最近对话摘要
|
|
35
|
-
.claude/hooks/tl-summary.sh
|
|
36
|
-
|
|
37
|
-
# 完整项目日志(按时间顺序)
|
|
38
|
-
cat .claude/PROJECT_LOG.md | grep "2026-01-11"
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### 按关键词查找
|
|
42
|
-
```bash
|
|
43
|
-
# 搜索思维节点
|
|
44
|
-
npx -p tsx tsx .claude/thinking-routes/index.ts search "数据分析"
|
|
45
|
-
|
|
46
|
-
# 在日志中搜索
|
|
47
|
-
cat .claude/PROJECT_LOG.md | grep -i "API"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 按类型查找
|
|
51
|
-
```bash
|
|
52
|
-
# 查看所有决策
|
|
53
|
-
cat .claude/PROJECT_LOG.md | grep "决策"
|
|
54
|
-
|
|
55
|
-
# 查看所有变更
|
|
56
|
-
cat .claude/MEMORY.md | grep "新增"
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## ⚡ 快捷别名
|
|
62
|
-
|
|
63
|
-
添加到 `~/.zshrc` 或 `~/.bashrc`:
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
# 对话历史
|
|
67
|
-
alias tl='.claude/hooks/tl-summary.sh'
|
|
68
|
-
alias log='less .claude/PROJECT_LOG.md'
|
|
69
|
-
alias memory='cat .claude/MEMORY.md'
|
|
70
|
-
|
|
71
|
-
# 思维节点
|
|
72
|
-
alias tl-recent='npx -p tsx tsx .claude/thinking-routes/index.ts recent'
|
|
73
|
-
alias tl-graph='npx -p tsx tsx .claude/thinking-routes/index.ts log --graph'
|
|
74
|
-
alias tl-search='npx -p tsx tsx .claude/thinking-routes/index.ts search'
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
---
|
|
78
|
-
|
|
79
|
-
## 📱 Claude Code 内置
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
# 查看对话历史列表
|
|
83
|
-
claude-code history
|
|
84
|
-
|
|
85
|
-
# 恢复某个对话
|
|
86
|
-
claude-code resume <conversation-id>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## 💡 使用建议
|
|
92
|
-
|
|
93
|
-
| 场景 | 使用 |
|
|
94
|
-
|------|------|
|
|
95
|
-
| 每天回顾 | `tl` |
|
|
96
|
-
| 找决策理由 | `tl-search "关键词"` |
|
|
97
|
-
| 了解项目全貌 | `log` |
|
|
98
|
-
| 查看最近变更 | `memory` |
|
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Document Scanner - Extract content and metadata from local files
|
|
3
|
-
*
|
|
4
|
-
* Supports:
|
|
5
|
-
* - Text extraction from multiple file formats
|
|
6
|
-
* - Metadata extraction (word count, headings, links)
|
|
7
|
-
* - Content checksum for change detection
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const crypto = require('crypto');
|
|
13
|
-
|
|
14
|
-
// ============================================================================
|
|
15
|
-
// Configuration
|
|
16
|
-
// ============================================================================
|
|
17
|
-
|
|
18
|
-
const MAX_CONTENT_SIZE = 500 * 1024; // 500KB - don't store content if larger
|
|
19
|
-
const MAX_SNIPPET_SIZE = 2000; // Store snippet for large files
|
|
20
|
-
|
|
21
|
-
// Supported file types for content scanning
|
|
22
|
-
const SCANNABLE_TYPES = [
|
|
23
|
-
'.md', '.markdown', // Markdown
|
|
24
|
-
'.txt', // Plain text
|
|
25
|
-
'.json', '.yaml', '.yml', // Config files
|
|
26
|
-
'.js', '.ts', '.jsx', '.tsx', // JavaScript/TypeScript
|
|
27
|
-
'.py', '.rs', '.go', '.java', '.c', '.cpp', '.h', '.hpp', // Code
|
|
28
|
-
'.sh', '.bash', '.zsh', '.fish', // Shell scripts
|
|
29
|
-
'.css', '.scss', '.less', // Stylesheets
|
|
30
|
-
'.html', '.htm', '.xml', // Markup
|
|
31
|
-
'.sql', '.graphql', '.gql' // Query languages
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
// ============================================================================
|
|
35
|
-
// Document Scanner Class
|
|
36
|
-
// ============================================================================
|
|
37
|
-
|
|
38
|
-
class DocumentScanner {
|
|
39
|
-
/**
|
|
40
|
-
* Check if a file type is scannable
|
|
41
|
-
*/
|
|
42
|
-
static isScannable(filePath) {
|
|
43
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
44
|
-
return SCANNABLE_TYPES.includes(ext);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Scan a file and extract metadata
|
|
49
|
-
*/
|
|
50
|
-
static scanFile(filePath, options = {}) {
|
|
51
|
-
const {
|
|
52
|
-
includeContent = true,
|
|
53
|
-
maxContentSize = MAX_CONTENT_SIZE
|
|
54
|
-
} = options;
|
|
55
|
-
|
|
56
|
-
if (!fs.existsSync(filePath)) {
|
|
57
|
-
throw new Error(`File not found: ${filePath}`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const stats = fs.statSync(filePath);
|
|
61
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
62
|
-
|
|
63
|
-
// Basic metadata
|
|
64
|
-
const metadata = {
|
|
65
|
-
path: filePath,
|
|
66
|
-
size: stats.size,
|
|
67
|
-
lastModified: stats.mtimeMs,
|
|
68
|
-
contentType: this.getMimeType(ext),
|
|
69
|
-
extension: ext
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// If file is too large or not scannable, skip content
|
|
73
|
-
if (!this.isScannable(filePath) || stats.size === 0) {
|
|
74
|
-
return {
|
|
75
|
-
...metadata,
|
|
76
|
-
scannable: false,
|
|
77
|
-
wordCount: 0,
|
|
78
|
-
headings: [],
|
|
79
|
-
links: [],
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Read file content
|
|
84
|
-
let content;
|
|
85
|
-
try {
|
|
86
|
-
content = fs.readFileSync(filePath, 'utf-8');
|
|
87
|
-
} catch (error) {
|
|
88
|
-
return {
|
|
89
|
-
...metadata,
|
|
90
|
-
scannable: false,
|
|
91
|
-
error: error.message
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Calculate checksum
|
|
96
|
-
const checksum = crypto
|
|
97
|
-
.createHash('md5')
|
|
98
|
-
.update(content)
|
|
99
|
-
.digest('hex');
|
|
100
|
-
|
|
101
|
-
// Extract metadata based on file type
|
|
102
|
-
const extracted = this.extractMetadata(content, ext);
|
|
103
|
-
|
|
104
|
-
// Determine whether to store full content or just snippet
|
|
105
|
-
const shouldStoreContent = includeContent && content.length <= maxContentSize;
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
...metadata,
|
|
109
|
-
scannable: true,
|
|
110
|
-
checksum,
|
|
111
|
-
wordCount: extracted.wordCount,
|
|
112
|
-
lineCount: extracted.lineCount,
|
|
113
|
-
headings: extracted.headings,
|
|
114
|
-
links: extracted.links,
|
|
115
|
-
codeBlocks: extracted.codeBlocks,
|
|
116
|
-
frontMatter: extracted.frontMatter,
|
|
117
|
-
// Content or snippet
|
|
118
|
-
content: shouldStoreContent ? content : null,
|
|
119
|
-
snippet: shouldStoreContent ? null : content.substring(0, MAX_SNIPPET_SIZE)
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Extract metadata from content based on file type
|
|
125
|
-
*/
|
|
126
|
-
static extractMetadata(content, ext) {
|
|
127
|
-
const lines = content.split('\n');
|
|
128
|
-
const wordCount = this.countWords(content);
|
|
129
|
-
const lineCount = lines.length;
|
|
130
|
-
|
|
131
|
-
let headings = [];
|
|
132
|
-
let links = [];
|
|
133
|
-
let codeBlocks = [];
|
|
134
|
-
let frontMatter = null;
|
|
135
|
-
|
|
136
|
-
// Markdown-specific extraction
|
|
137
|
-
if (['.md', '.markdown'].includes(ext)) {
|
|
138
|
-
const mdResult = this.extractMarkdownMetadata(content);
|
|
139
|
-
headings = mdResult.headings;
|
|
140
|
-
links = mdResult.links;
|
|
141
|
-
codeBlocks = mdResult.codeBlocks;
|
|
142
|
-
frontMatter = mdResult.frontMatter;
|
|
143
|
-
}
|
|
144
|
-
// Code-specific extraction
|
|
145
|
-
else if (['.js', '.ts', '.jsx', '.tsx', '.py', '.rs', '.go'].includes(ext)) {
|
|
146
|
-
const codeResult = this.extractCodeMetadata(content, ext);
|
|
147
|
-
headings = codeResult.headings; // Functions/classes as headings
|
|
148
|
-
links = codeResult.links; // Import/require statements
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
wordCount,
|
|
153
|
-
lineCount,
|
|
154
|
-
headings,
|
|
155
|
-
links,
|
|
156
|
-
codeBlocks,
|
|
157
|
-
frontMatter
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Extract Markdown-specific metadata
|
|
163
|
-
*/
|
|
164
|
-
static extractMarkdownMetadata(content) {
|
|
165
|
-
const headings = [];
|
|
166
|
-
const links = [];
|
|
167
|
-
const codeBlocks = [];
|
|
168
|
-
let frontMatter = null;
|
|
169
|
-
|
|
170
|
-
const lines = content.split('\n');
|
|
171
|
-
let inCodeBlock = false;
|
|
172
|
-
let codeBlockLang = null;
|
|
173
|
-
let currentCodeBlock = [];
|
|
174
|
-
|
|
175
|
-
// Check for YAML front matter
|
|
176
|
-
if (lines[0] === '---') {
|
|
177
|
-
const endIdx = lines.slice(1).findIndex(line => line === '---');
|
|
178
|
-
if (endIdx > 0) {
|
|
179
|
-
const frontMatterContent = lines.slice(1, endIdx + 1).join('\n');
|
|
180
|
-
frontMatter = this.parseFrontMatter(frontMatterContent);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
for (let i = 0; i < lines.length; i++) {
|
|
185
|
-
const line = lines[i];
|
|
186
|
-
|
|
187
|
-
// Track code blocks
|
|
188
|
-
if (line.startsWith('```')) {
|
|
189
|
-
if (!inCodeBlock) {
|
|
190
|
-
inCodeBlock = true;
|
|
191
|
-
codeBlockLang = line.substring(3).trim() || 'text';
|
|
192
|
-
currentCodeBlock = [];
|
|
193
|
-
} else {
|
|
194
|
-
codeBlocks.push({
|
|
195
|
-
language: codeBlockLang,
|
|
196
|
-
lineStart: i - currentCodeBlock.length,
|
|
197
|
-
preview: currentCodeBlock.slice(0, 3).join('\n')
|
|
198
|
-
});
|
|
199
|
-
inCodeBlock = false;
|
|
200
|
-
currentCodeBlock = [];
|
|
201
|
-
}
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (inCodeBlock) {
|
|
206
|
-
currentCodeBlock.push(line);
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Extract headings
|
|
211
|
-
const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
212
|
-
if (headingMatch) {
|
|
213
|
-
const level = headingMatch[1].length;
|
|
214
|
-
const text = headingMatch[2].trim();
|
|
215
|
-
headings.push({ level, text, line: i + 1 });
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Extract links
|
|
219
|
-
const linkMatch = line.match(/\[([^\]]+)\]\(([^)]+)\)/g);
|
|
220
|
-
if (linkMatch) {
|
|
221
|
-
linkMatch.forEach(link => {
|
|
222
|
-
const match = link.match(/\[([^\]]+)\]\(([^)]+)\)/);
|
|
223
|
-
if (match) {
|
|
224
|
-
links.push({ text: match[1], url: match[2] });
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return { headings, links, codeBlocks, frontMatter };
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Extract code-specific metadata (functions, classes, imports)
|
|
235
|
-
*/
|
|
236
|
-
static extractCodeMetadata(content, ext) {
|
|
237
|
-
const headings = [];
|
|
238
|
-
const links = [];
|
|
239
|
-
|
|
240
|
-
const lines = content.split('\n');
|
|
241
|
-
|
|
242
|
-
// Patterns for different languages
|
|
243
|
-
const patterns = {
|
|
244
|
-
'.js': { func: /^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)/, class: /^\s*class\s+(\w+)/, import: /^\s*import\s+.*from\s+['"]([^'"]+)['"]/ },
|
|
245
|
-
'.ts': { func: /^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)/, class: /^\s*class\s+(\w+)/, import: /^\s*import\s+.*from\s+['"]([^'"]+)['"]/ },
|
|
246
|
-
'.jsx': { func: /^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)/, class: /^\s*class\s+(\w+)/, import: /^\s*import\s+.*from\s+['"]([^'"]+)['"]/ },
|
|
247
|
-
'.tsx': { func: /^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)/, class: /^\s*class\s+(\w+)/, import: /^\s*import\s+.*from\s+['"]([^'"]+)['"]/ },
|
|
248
|
-
'.py': { func: /^\s*def\s+(\w+)\s*\(/, class: /^\s*class\s+(\w+)\s*:/, import: /^\s*(?:import|from)\s+(\w+)/ },
|
|
249
|
-
'.rs': { func: /^\s*(?:pub\s+)?fn\s+(\w+)\s*\(/, class: /^\s*(?:pub\s+)?(struct|enum|trait)\s+(\w+)/, import: /^\s*use\s+([^;]+);/ },
|
|
250
|
-
'.go': { func: /^\s*func\s+(?:\(\w+\s+\*?\w+\)\s+)?(\w+)\s*\(/, class: /^\s*type\s+(\w+)\s+struct/, import: /^\s*import\s+(?:\(|")([^")]+)/ }
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
const lang = patterns[ext] || patterns['.js'];
|
|
254
|
-
|
|
255
|
-
for (let i = 0; i < lines.length; i++) {
|
|
256
|
-
const line = lines[i];
|
|
257
|
-
|
|
258
|
-
// Extract functions
|
|
259
|
-
const funcMatch = line.match(lang.func);
|
|
260
|
-
if (funcMatch) {
|
|
261
|
-
headings.push({ type: 'function', name: funcMatch[1], line: i + 1 });
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Extract classes
|
|
265
|
-
const classMatch = line.match(lang.class);
|
|
266
|
-
if (classMatch) {
|
|
267
|
-
const name = classMatch[2] || classMatch[1];
|
|
268
|
-
headings.push({ type: 'class', name, line: i + 1 });
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Extract imports
|
|
272
|
-
const importMatch = line.match(lang.import);
|
|
273
|
-
if (importMatch) {
|
|
274
|
-
links.push({ type: 'import', name: importMatch[1], line: i + 1 });
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return { headings, links };
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Parse YAML front matter
|
|
283
|
-
*/
|
|
284
|
-
static parseFrontMatter(content) {
|
|
285
|
-
const result = {};
|
|
286
|
-
const lines = content.split('\n');
|
|
287
|
-
|
|
288
|
-
for (const line of lines) {
|
|
289
|
-
const match = line.match(/^(\w+):\s*(.+)$/);
|
|
290
|
-
if (match) {
|
|
291
|
-
result[match[1]] = match[2].trim();
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return result;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Count words in content (rough estimate for mixed content)
|
|
300
|
-
*/
|
|
301
|
-
static countWords(content) {
|
|
302
|
-
// For code files, count tokens more accurately
|
|
303
|
-
// For text files, count words
|
|
304
|
-
const tokens = content
|
|
305
|
-
.replace(/\s+/g, ' ')
|
|
306
|
-
.replace(/[{}();,.<>[\]]/g, ' ')
|
|
307
|
-
.split(' ')
|
|
308
|
-
.filter(t => t.length > 0);
|
|
309
|
-
|
|
310
|
-
return tokens.length;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Get MIME type for extension
|
|
315
|
-
*/
|
|
316
|
-
static getMimeType(ext) {
|
|
317
|
-
const mimeTypes = {
|
|
318
|
-
'.md': 'text/markdown',
|
|
319
|
-
'.markdown': 'text/markdown',
|
|
320
|
-
'.txt': 'text/plain',
|
|
321
|
-
'.json': 'application/json',
|
|
322
|
-
'.yaml': 'text/yaml',
|
|
323
|
-
'.yml': 'text/yaml',
|
|
324
|
-
'.js': 'text/javascript',
|
|
325
|
-
'.ts': 'text/typescript',
|
|
326
|
-
'.jsx': 'text/jsx',
|
|
327
|
-
'.tsx': 'text/tsx',
|
|
328
|
-
'.py': 'text/x-python',
|
|
329
|
-
'.rs': 'text/x-rust',
|
|
330
|
-
'.go': 'text/x-go',
|
|
331
|
-
'.java': 'text/x-java',
|
|
332
|
-
'.c': 'text/x-c',
|
|
333
|
-
'.cpp': 'text/x-c++',
|
|
334
|
-
'.h': 'text/x-c',
|
|
335
|
-
'.hpp': 'text/x-c++',
|
|
336
|
-
'.sh': 'text/x-shellscript',
|
|
337
|
-
'.bash': 'text/x-shellscript',
|
|
338
|
-
'.css': 'text/css',
|
|
339
|
-
'.scss': 'text/x-scss',
|
|
340
|
-
'.less': 'text/x-less',
|
|
341
|
-
'.html': 'text/html',
|
|
342
|
-
'.htm': 'text/html',
|
|
343
|
-
'.xml': 'text/xml',
|
|
344
|
-
'.sql': 'text/x-sql',
|
|
345
|
-
'.graphql': 'text/x-graphql',
|
|
346
|
-
'.gql': 'text/x-graphql'
|
|
347
|
-
};
|
|
348
|
-
return mimeTypes[ext.toLowerCase()] || 'text/plain';
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Scan a directory recursively
|
|
353
|
-
*/
|
|
354
|
-
static scanDirectory(dirPath, options = {}) {
|
|
355
|
-
const {
|
|
356
|
-
recursive = true,
|
|
357
|
-
maxDepth = 10,
|
|
358
|
-
includePatterns = [],
|
|
359
|
-
excludePatterns = ['node_modules', '.git', 'dist', 'build', 'coverage']
|
|
360
|
-
} = options;
|
|
361
|
-
|
|
362
|
-
if (!fs.existsSync(dirPath)) {
|
|
363
|
-
throw new Error(`Directory not found: ${dirPath}`);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const results = [];
|
|
367
|
-
const scanQueue = [{ dir: dirPath, depth: 0 }];
|
|
368
|
-
|
|
369
|
-
while (scanQueue.length > 0) {
|
|
370
|
-
const { dir, depth } = scanQueue.shift();
|
|
371
|
-
|
|
372
|
-
if (depth > maxDepth) continue;
|
|
373
|
-
|
|
374
|
-
let entries;
|
|
375
|
-
try {
|
|
376
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
377
|
-
} catch (error) {
|
|
378
|
-
continue; // Skip directories we can't read
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
for (const entry of entries) {
|
|
382
|
-
// Skip excluded directories
|
|
383
|
-
if (entry.isDirectory() && excludePatterns.includes(entry.name)) {
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
const fullPath = path.join(dir, entry.name);
|
|
388
|
-
|
|
389
|
-
if (entry.isDirectory() && recursive) {
|
|
390
|
-
scanQueue.push({ dir: fullPath, depth: depth + 1 });
|
|
391
|
-
} else if (entry.isFile()) {
|
|
392
|
-
// Check include patterns
|
|
393
|
-
if (includePatterns.length > 0) {
|
|
394
|
-
const matches = includePatterns.some(pattern => {
|
|
395
|
-
if (pattern instanceof RegExp) {
|
|
396
|
-
return pattern.test(fullPath);
|
|
397
|
-
}
|
|
398
|
-
return fullPath.includes(pattern);
|
|
399
|
-
});
|
|
400
|
-
if (!matches) continue;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
try {
|
|
404
|
-
const scanResult = this.scanFile(fullPath, options);
|
|
405
|
-
results.push(scanResult);
|
|
406
|
-
} catch (error) {
|
|
407
|
-
// Skip files that can't be scanned
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return results;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// ============================================================================
|
|
418
|
-
// Exports
|
|
419
|
-
// ============================================================================
|
|
420
|
-
|
|
421
|
-
module.exports = {
|
|
422
|
-
DocumentScanner,
|
|
423
|
-
SCANNABLE_TYPES,
|
|
424
|
-
MAX_CONTENT_SIZE,
|
|
425
|
-
MAX_SNIPPET_SIZE
|
|
426
|
-
};
|