# Markdown Reference Checker
一个用于检查 Markdown 文件中引用完整性的工具,特别适用于 Obsidian 风格的 wiki 链接。
## 特性
- 支持两种引用语法:
- `[[file]]` - 创建到文件的链接
- `![[file]]` - 嵌入并渲染文件内容
- 支持引用任意类型文件(无扩展名时默认为 .md)
- 支持引用别名 (`[[file|alias]]` 或 `![[file|alias]]`)
- 支持标题引用 (`[[file#heading]]`)
- 支持标准 Markdown 图片语法 (`![alt](image)`)
- 检测未使用的图片
- 检测单向链接(A引用B但B没有引用A)
- 支持 `.gitignore` 和自定义忽略规则
- 详细的错误报告(包含行号和列号)
- 生成引用统计信息
## 安装
### 使用 pip 安装
```bash
pip install md-ref-checker
```
### 从源码安装
```bash
# 克隆仓库
git clone https://github.com/chess99/md-ref-checker.git
cd md-ref-checker
# 创建并激活虚拟环境
python -m venv venv
source venv/bin/activate # Linux/macOS
# 或
venv\Scripts\activate # Windows
# 安装开发依赖
pip install -e ".[dev]"
```
## 使用方法
### 命令行工具
```bash
# 检查当前目录
md-ref-checker
# 检查指定目录
md-ref-checker -d /path/to/docs
# 显示详细信息
md-ref-checker -v 2
# 忽略特定文件
md-ref-checker -i "*.tmp" -i "draft/*"
# 删除未使用的图片
md-ref-checker -r
# 显示调试信息
md-ref-checker -D
# 严格图片引用模式
md-ref-checker --strict-image-refs
```
### 命令行选项
- `-d, --dir`: 要检查的目录路径(默认为当前目录)
- `-v, --verbosity`: 输出详细程度(0-2)
- 0: 只显示无效引用和未使用的图片
- 1: 显示无效引用、未使用的图片和单向链接
- 2: 显示所有引用统计信息
- `-n, --no-color`: 禁用彩色输出
- `-i, --ignore`: 添加要忽略的文件模式(可多次使用)
- `-r, --delete-unused-images`: 删除未被引用的图片文件
- `-D, --debug`: 显示调试信息
- `--strict-image-refs`: 严格图片引用模式(只将 ![[]] 和 ![] 视为图片引用)
### Python API
```python
from md_ref_checker import ReferenceChecker
# 创建检查器
checker = ReferenceChecker("docs")
# 启用严格图片引用模式(只将 ![[]] 和 ![] 视为图片引用)
checker = ReferenceChecker("docs", strict_image_refs=True)
# 添加忽略规则
checker.fs.ignore_patterns.extend(["*.tmp", "draft/*"])
# 检查整个目录
result = checker.check_directory()
# 检查单个文件
result = checker.check_file("docs/note.md")
# 处理结果
if result.invalid_refs:
print("发现无效引用:")
for ref in result.invalid_refs:
print(f"{ref.source_file}:{ref.line_number} - {ref.target}")
if result.unused_images:
print("未使用的图片:")
for image in result.unused_images:
print(image)
if result.unidirectional_links:
print("单向链接:")
for source, target in result.unidirectional_links:
print(f"{source} -> {target}")
```
## 开发
项目使用 `pre-commit` 钩子和 `make` 命令来简化开发流程。
#### 初始化开发环境
```bash
# 安装所有依赖并设置 pre-commit 钩子
make install
```
#### 常用命令
```bash
# 格式化代码
make format
# 运行所有代码检查
make lint
# 运行测试
make test
# 清理临时文件和缓存
make clean
```
#### 运行测试
```bash
# 运行所有测试
pytest
# 运行特定测试
pytest tests/test_models.py
# 显示测试覆盖率
pytest --cov=md_ref_checker
```
#### 代码质量工具
项目使用以下工具保证代码质量:
- Black: 代码格式化
- Ruff: 代码检查和导入排序
- MyPy: 类型检查
- pre-commit: Git 提交前自动运行检查
所有这些检查都会在提交代码时自动运行。你也可以手动运行它们:
```bash
# 手动运行 pre-commit 检查
pre-commit run --all-files
# 单独运行格式化
black src tests
# 单独运行代码检查
ruff check src tests
# 单独运行类型检查
mypy src tests
```
## 贡献
欢迎贡献!请参考以下步骤:
1. Fork 项目
2. 创建功能分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 创建 Pull Request
## 许可证
本项目采用 MIT 许可证 - 详见 [LICENSE](LICENSE) 文件。
Raw data
{
"_id": null,
"home_page": null,
"name": "md-ref-checker",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "checker, markdown, obsidian, reference",
"author": null,
"author_email": "chess99 <chess99@126.com>",
"download_url": "https://files.pythonhosted.org/packages/ae/09/c7740ece9b62dcfe6f24a5b1c3f393429109a1d8c86eef5c9a086a8aa75d/md_ref_checker-0.2.3.tar.gz",
"platform": null,
"description": "# Markdown Reference Checker\n\n\u4e00\u4e2a\u7528\u4e8e\u68c0\u67e5 Markdown \u6587\u4ef6\u4e2d\u5f15\u7528\u5b8c\u6574\u6027\u7684\u5de5\u5177\uff0c\u7279\u522b\u9002\u7528\u4e8e Obsidian \u98ce\u683c\u7684 wiki \u94fe\u63a5\u3002\n\n## \u7279\u6027\n\n- \u652f\u6301\u4e24\u79cd\u5f15\u7528\u8bed\u6cd5\uff1a\n - `[[file]]` - \u521b\u5efa\u5230\u6587\u4ef6\u7684\u94fe\u63a5\n - `![[file]]` - \u5d4c\u5165\u5e76\u6e32\u67d3\u6587\u4ef6\u5185\u5bb9\n- \u652f\u6301\u5f15\u7528\u4efb\u610f\u7c7b\u578b\u6587\u4ef6\uff08\u65e0\u6269\u5c55\u540d\u65f6\u9ed8\u8ba4\u4e3a .md\uff09\n- \u652f\u6301\u5f15\u7528\u522b\u540d (`[[file|alias]]` \u6216 `![[file|alias]]`)\n- \u652f\u6301\u6807\u9898\u5f15\u7528 (`[[file#heading]]`)\n- \u652f\u6301\u6807\u51c6 Markdown \u56fe\u7247\u8bed\u6cd5 (`![alt](image)`)\n- \u68c0\u6d4b\u672a\u4f7f\u7528\u7684\u56fe\u7247\n- \u68c0\u6d4b\u5355\u5411\u94fe\u63a5\uff08A\u5f15\u7528B\u4f46B\u6ca1\u6709\u5f15\u7528A\uff09\n- \u652f\u6301 `.gitignore` \u548c\u81ea\u5b9a\u4e49\u5ffd\u7565\u89c4\u5219\n- \u8be6\u7ec6\u7684\u9519\u8bef\u62a5\u544a\uff08\u5305\u542b\u884c\u53f7\u548c\u5217\u53f7\uff09\n- \u751f\u6210\u5f15\u7528\u7edf\u8ba1\u4fe1\u606f\n\n## \u5b89\u88c5\n\n### \u4f7f\u7528 pip \u5b89\u88c5\n\n```bash\npip install md-ref-checker\n```\n\n### \u4ece\u6e90\u7801\u5b89\u88c5\n\n```bash\n# \u514b\u9686\u4ed3\u5e93\ngit clone https://github.com/chess99/md-ref-checker.git\ncd md-ref-checker\n\n# \u521b\u5efa\u5e76\u6fc0\u6d3b\u865a\u62df\u73af\u5883\npython -m venv venv\nsource venv/bin/activate # Linux/macOS\n# \u6216\nvenv\\Scripts\\activate # Windows\n\n# \u5b89\u88c5\u5f00\u53d1\u4f9d\u8d56\npip install -e \".[dev]\"\n```\n\n## \u4f7f\u7528\u65b9\u6cd5\n\n### \u547d\u4ee4\u884c\u5de5\u5177\n\n```bash\n# \u68c0\u67e5\u5f53\u524d\u76ee\u5f55\nmd-ref-checker\n\n# \u68c0\u67e5\u6307\u5b9a\u76ee\u5f55\nmd-ref-checker -d /path/to/docs\n\n# \u663e\u793a\u8be6\u7ec6\u4fe1\u606f\nmd-ref-checker -v 2\n\n# \u5ffd\u7565\u7279\u5b9a\u6587\u4ef6\nmd-ref-checker -i \"*.tmp\" -i \"draft/*\"\n\n# \u5220\u9664\u672a\u4f7f\u7528\u7684\u56fe\u7247\nmd-ref-checker -r\n\n# \u663e\u793a\u8c03\u8bd5\u4fe1\u606f\nmd-ref-checker -D\n\n# \u4e25\u683c\u56fe\u7247\u5f15\u7528\u6a21\u5f0f\nmd-ref-checker --strict-image-refs\n```\n\n### \u547d\u4ee4\u884c\u9009\u9879\n\n- `-d, --dir`: \u8981\u68c0\u67e5\u7684\u76ee\u5f55\u8def\u5f84\uff08\u9ed8\u8ba4\u4e3a\u5f53\u524d\u76ee\u5f55\uff09\n- `-v, --verbosity`: \u8f93\u51fa\u8be6\u7ec6\u7a0b\u5ea6\uff080-2\uff09\n - 0: \u53ea\u663e\u793a\u65e0\u6548\u5f15\u7528\u548c\u672a\u4f7f\u7528\u7684\u56fe\u7247\n - 1: \u663e\u793a\u65e0\u6548\u5f15\u7528\u3001\u672a\u4f7f\u7528\u7684\u56fe\u7247\u548c\u5355\u5411\u94fe\u63a5\n - 2: \u663e\u793a\u6240\u6709\u5f15\u7528\u7edf\u8ba1\u4fe1\u606f\n- `-n, --no-color`: \u7981\u7528\u5f69\u8272\u8f93\u51fa\n- `-i, --ignore`: \u6dfb\u52a0\u8981\u5ffd\u7565\u7684\u6587\u4ef6\u6a21\u5f0f\uff08\u53ef\u591a\u6b21\u4f7f\u7528\uff09\n- `-r, --delete-unused-images`: \u5220\u9664\u672a\u88ab\u5f15\u7528\u7684\u56fe\u7247\u6587\u4ef6\n- `-D, --debug`: \u663e\u793a\u8c03\u8bd5\u4fe1\u606f\n- `--strict-image-refs`: \u4e25\u683c\u56fe\u7247\u5f15\u7528\u6a21\u5f0f\uff08\u53ea\u5c06 ![[]] \u548c ![] \u89c6\u4e3a\u56fe\u7247\u5f15\u7528\uff09\n\n### Python API\n\n```python\nfrom md_ref_checker import ReferenceChecker\n\n# \u521b\u5efa\u68c0\u67e5\u5668\nchecker = ReferenceChecker(\"docs\")\n\n# \u542f\u7528\u4e25\u683c\u56fe\u7247\u5f15\u7528\u6a21\u5f0f\uff08\u53ea\u5c06 ![[]] \u548c ![] \u89c6\u4e3a\u56fe\u7247\u5f15\u7528\uff09\nchecker = ReferenceChecker(\"docs\", strict_image_refs=True)\n\n# \u6dfb\u52a0\u5ffd\u7565\u89c4\u5219\nchecker.fs.ignore_patterns.extend([\"*.tmp\", \"draft/*\"])\n\n# \u68c0\u67e5\u6574\u4e2a\u76ee\u5f55\nresult = checker.check_directory()\n\n# \u68c0\u67e5\u5355\u4e2a\u6587\u4ef6\nresult = checker.check_file(\"docs/note.md\")\n\n# \u5904\u7406\u7ed3\u679c\nif result.invalid_refs:\n print(\"\u53d1\u73b0\u65e0\u6548\u5f15\u7528:\")\n for ref in result.invalid_refs:\n print(f\"{ref.source_file}:{ref.line_number} - {ref.target}\")\n\nif result.unused_images:\n print(\"\u672a\u4f7f\u7528\u7684\u56fe\u7247:\")\n for image in result.unused_images:\n print(image)\n\nif result.unidirectional_links:\n print(\"\u5355\u5411\u94fe\u63a5:\")\n for source, target in result.unidirectional_links:\n print(f\"{source} -> {target}\")\n```\n\n## \u5f00\u53d1\n\n\u9879\u76ee\u4f7f\u7528 `pre-commit` \u94a9\u5b50\u548c `make` \u547d\u4ee4\u6765\u7b80\u5316\u5f00\u53d1\u6d41\u7a0b\u3002\n\n#### \u521d\u59cb\u5316\u5f00\u53d1\u73af\u5883\n\n```bash\n# \u5b89\u88c5\u6240\u6709\u4f9d\u8d56\u5e76\u8bbe\u7f6e pre-commit \u94a9\u5b50\nmake install\n```\n\n#### \u5e38\u7528\u547d\u4ee4\n\n```bash\n# \u683c\u5f0f\u5316\u4ee3\u7801\nmake format\n\n# \u8fd0\u884c\u6240\u6709\u4ee3\u7801\u68c0\u67e5\nmake lint\n\n# \u8fd0\u884c\u6d4b\u8bd5\nmake test\n\n# \u6e05\u7406\u4e34\u65f6\u6587\u4ef6\u548c\u7f13\u5b58\nmake clean\n```\n\n#### \u8fd0\u884c\u6d4b\u8bd5\n\n```bash\n# \u8fd0\u884c\u6240\u6709\u6d4b\u8bd5\npytest\n\n# \u8fd0\u884c\u7279\u5b9a\u6d4b\u8bd5\npytest tests/test_models.py\n\n# \u663e\u793a\u6d4b\u8bd5\u8986\u76d6\u7387\npytest --cov=md_ref_checker\n```\n\n#### \u4ee3\u7801\u8d28\u91cf\u5de5\u5177\n\n\u9879\u76ee\u4f7f\u7528\u4ee5\u4e0b\u5de5\u5177\u4fdd\u8bc1\u4ee3\u7801\u8d28\u91cf\uff1a\n\n- Black: \u4ee3\u7801\u683c\u5f0f\u5316\n- Ruff: \u4ee3\u7801\u68c0\u67e5\u548c\u5bfc\u5165\u6392\u5e8f\n- MyPy: \u7c7b\u578b\u68c0\u67e5\n- pre-commit: Git \u63d0\u4ea4\u524d\u81ea\u52a8\u8fd0\u884c\u68c0\u67e5\n\n\u6240\u6709\u8fd9\u4e9b\u68c0\u67e5\u90fd\u4f1a\u5728\u63d0\u4ea4\u4ee3\u7801\u65f6\u81ea\u52a8\u8fd0\u884c\u3002\u4f60\u4e5f\u53ef\u4ee5\u624b\u52a8\u8fd0\u884c\u5b83\u4eec\uff1a\n\n```bash\n# \u624b\u52a8\u8fd0\u884c pre-commit \u68c0\u67e5\npre-commit run --all-files\n\n# \u5355\u72ec\u8fd0\u884c\u683c\u5f0f\u5316\nblack src tests\n\n# \u5355\u72ec\u8fd0\u884c\u4ee3\u7801\u68c0\u67e5\nruff check src tests\n\n# \u5355\u72ec\u8fd0\u884c\u7c7b\u578b\u68c0\u67e5\nmypy src tests\n```\n\n## \u8d21\u732e\n\n\u6b22\u8fce\u8d21\u732e\uff01\u8bf7\u53c2\u8003\u4ee5\u4e0b\u6b65\u9aa4\uff1a\n\n1. Fork \u9879\u76ee\n2. \u521b\u5efa\u529f\u80fd\u5206\u652f (`git checkout -b feature/amazing-feature`)\n3. \u63d0\u4ea4\u66f4\u6539 (`git commit -m 'Add amazing feature'`)\n4. \u63a8\u9001\u5230\u5206\u652f (`git push origin feature/amazing-feature`)\n5. \u521b\u5efa Pull Request\n\n## \u8bb8\u53ef\u8bc1\n\n\u672c\u9879\u76ee\u91c7\u7528 MIT \u8bb8\u53ef\u8bc1 - \u8be6\u89c1 [LICENSE](LICENSE) \u6587\u4ef6\u3002\n",
"bugtrack_url": null,
"license": null,
"summary": "A tool for checking references in Markdown files",
"version": "0.2.3",
"project_urls": {
"Homepage": "https://github.com/chess99/md-ref-checker",
"Repository": "https://github.com/chess99/md-ref-checker.git"
},
"split_keywords": [
"checker",
" markdown",
" obsidian",
" reference"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "84406bf93e54186b92f5de88598391e8453894e95c3120af6384d761ae973e20",
"md5": "0b1131ec88422f75e53976559d6b72e8",
"sha256": "e0eb8fce8d0170fc01469a9f8f2185d09eac1453897027cf189198d939f01735"
},
"downloads": -1,
"filename": "md_ref_checker-0.2.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0b1131ec88422f75e53976559d6b72e8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 14769,
"upload_time": "2024-12-23T02:39:11",
"upload_time_iso_8601": "2024-12-23T02:39:11.374495Z",
"url": "https://files.pythonhosted.org/packages/84/40/6bf93e54186b92f5de88598391e8453894e95c3120af6384d761ae973e20/md_ref_checker-0.2.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ae09c7740ece9b62dcfe6f24a5b1c3f393429109a1d8c86eef5c9a086a8aa75d",
"md5": "a29ec117b1ca92f78b20865d547947e0",
"sha256": "bc04876436bd6af6fab675768de62fb035b84b9d685a59b6f268b3e64cef9c92"
},
"downloads": -1,
"filename": "md_ref_checker-0.2.3.tar.gz",
"has_sig": false,
"md5_digest": "a29ec117b1ca92f78b20865d547947e0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 20911,
"upload_time": "2024-12-23T02:39:13",
"upload_time_iso_8601": "2024-12-23T02:39:13.427531Z",
"url": "https://files.pythonhosted.org/packages/ae/09/c7740ece9b62dcfe6f24a5b1c3f393429109a1d8c86eef5c9a086a8aa75d/md_ref_checker-0.2.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-23 02:39:13",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "chess99",
"github_project": "md-ref-checker",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "markdown-it-py",
"specs": [
[
">=",
"3.0.0"
]
]
},
{
"name": "pytest",
"specs": [
[
">=",
"7.0.0"
]
]
},
{
"name": "colorama",
"specs": [
[
">=",
"0.4.6"
]
]
}
],
"lcname": "md-ref-checker"
}