A powerful block-based markup language parser and query API, fully compatible with Markdown
Project description
BlockMD 查询 API
一个功能强大的 BlockMD 文档链式查询 API,支持过滤、排序和多种视图格式。
特性
✅ 链式 API - 流畅的方法链式调用,支持复杂查询
✅ 文件/目录加载 - 从单个文件或整个目录加载
✅ 灵活过滤 - 按属性、层级、内容、自定义条件过滤
✅ Lambda 支持 - 使用 lambda 函数进行复杂条件判断
✅ 排序功能 - 按字段或自定义 lambda 函数排序
✅ 多种视图 - 树形、表格和列表输出格式
✅ 字段提取 - 提取特定字段为字典
安装
# 克隆仓库
git clone <repo-url>
cd wesleysbmd
# 运行测试
python tests/test_query_builder.py
快速开始
from query import query
# 加载并查询 BlockMD 文件
results = (query()
.from_path('docs/spec.bmd')
.where(level=lambda l: l >= 2)
.contains('TODO')
.order_by('title')
.view('table')
)
print(results)
API 参考
加载数据
from_path(path: str | Path) -> QueryBuilder
从文件或目录加载区块。
# 加载单个文件
query().from_path('document.bmd')
# 加载目录中所有 .bmd 文件
query().from_path('docs/')
from_blocks(blocks: List[Block]) -> QueryBuilder
从现有 Block 对象初始化。
from parser import parse_blockmd
blocks = parse_blockmd(text)
query().from_blocks(blocks)
过滤
where(**conditions) -> QueryBuilder
按属性条件过滤区块。
# 精确匹配
query().where(status='done', level=2)
# Lambda 函数
query().where(level=lambda l: l >= 2)
# 多个值
query().where(status=['todo', 'doing'])
# 特殊字段: title, level
query().where(title='Introduction')
has_property(*keys: str) -> QueryBuilder
过滤具有指定属性的区块。
# 单个属性
query().has_property('status')
# 多个属性 (AND)
query().has_property('status', 'priority')
contains(keyword: str, case_sensitive: bool = False) -> QueryBuilder
过滤内容包含关键词的区块。
# 不区分大小写 (默认)
query().contains('TODO')
# 区分大小写
query().contains('FIXME', case_sensitive=True)
filter(predicate: Callable[[Block], bool]) -> QueryBuilder
使用自定义条件函数过滤。
# 有子节点的区块
query().filter(lambda b: len(b.children) > 0)
# 叶子节点
query().filter(lambda b: b.is_leaf())
# 长内容
query().filter(lambda b: len(b.get_content_text()) > 100)
排序
order_by(key: str | Callable, reverse: bool = False) -> QueryBuilder
按字段或函数对区块排序。
# 按字段名排序
query().order_by('title')
query().order_by('level', reverse=True)
# 按属性排序
query().order_by('priority')
# 按 lambda 排序
query().order_by(lambda b: len(b.title))
query().order_by(lambda b: b.get_depth())
可用字段名:
title- 区块标题level- 标题层级 (1-6)depth- 树深度- 任何属性键
限制
limit(count: int) -> QueryBuilder
限制结果数量。
# 获取前 10 个结果
query().limit(10)
# 按优先级排序取前 5 个
query().order_by('priority').limit(5)
输出
view(format: 'tree' | 'table' | 'list', fields: List[str] = None) -> str
格式化结果以供显示。
# 树形视图 - 层级结构
print(query().view('tree'))
# └── Root [prop=value]
# ├── Child A
# └── Child B
# 表格视图 - 结构化列
print(query().view('table', fields=['title', 'level', 'status']))
# title | level | status
# ------+-------+--------
# Block | 2 | done
# 列表视图 - 简单编号列表
print(query().view('list', fields=['title', 'status']))
# 1. Block | status=done
# 2. Other | status=todo
select(*fields: str) -> List[dict]
提取特定字段为字典。
results = query().select('title', 'level', 'content')
# [
# {'title': 'Intro', 'level': 1, 'content': '...'},
# {'title': 'Overview', 'level': 2, 'content': '...'}
# ]
可用字段名:
title,level,content,path,depthid(来自属性)- 任何属性键
execute() -> List[Block]
获取匹配的 Block 对象列表。
blocks = query().where(status='done').execute()
for block in blocks:
print(block.title, block.level)
count() -> int
统计匹配的区块数量。
total = query().contains('TODO').count()
print(f"Found {total} TODOs")
示例
基础过滤
# 所有二级标题
query().from_path('doc.bmd').where(level=2)
# 已完成的任务
query().from_path('tasks.bmd').where(status='complete')
# 高优先级项目
query().from_path('tasks.bmd').where(priority='high')
Lambda 条件
# 二级或更高层级
query().where(level=lambda l: l >= 2)
# 多个状态值
query().where(status=['todo', 'doing'])
# 复杂条件
query().filter(lambda b:
b.level <= 3 and
len(b.children) > 0 and
'TODO' in b.get_content_text()
)
内容搜索
# 查找所有 TODOs
query().contains('TODO')
# 查找 FIXMEs (区分大小写)
query().contains('FIXME', case_sensitive=True)
# 提及 "database" 的区块
query().contains('database').where(level=2)
排序
# 按标题字母顺序
query().order_by('title')
# 按深度 (最深优先)
query().order_by('depth', reverse=True)
# 按内容长度
query().order_by(lambda b: len(b.get_content_text()))
# 按子节点数量
query().order_by(lambda b: len(b.children), reverse=True)
复杂链式调用
# 查找 2 级以上未完成的高优先级任务
results = (query()
.from_path('project/')
.where(
status='todo',
priority='high',
level=lambda l: l >= 2
)
.order_by('priority')
.limit(10)
.view('table', fields=['title', 'priority', 'status'])
)
# 搜索 TODOs,按层级过滤,按深度排序
results = (query()
.from_path('docs/')
.contains('TODO')
.where(level=lambda l: 2 <= l <= 3)
.order_by('depth')
.view('tree')
)
# 获取有子节点的模块,按名称排序
modules = (query()
.from_path('specs/')
.where(type='module')
.filter(lambda b: len(b.children) > 0)
.order_by('title')
.select('title', 'children_count')
)
视图格式
# 树形视图 - 查看层级结构
print(query()
.from_path('project.bmd')
.where(level=lambda l: l <= 2)
.view('tree')
)
# 表格视图 - 结构化数据
print(query()
.from_path('tasks.bmd')
.where(status='todo')
.view('table', fields=['title', 'priority', 'status'])
)
# 列表视图 - 简单输出
print(query()
.from_path('docs.bmd')
.has_property('section')
.view('list', fields=['title', 'section'])
)
统计
# 按状态统计
q = query().from_path('tasks.bmd')
print(f"总数: {q.count()}")
print(f"已完成: {q.where(status='done').count()}")
print(f"待办: {q.where(status='todo').count()}")
# 按层级统计区块
for level in range(1, 4):
count = q.where(level=level).count()
print(f"层级 {level}: {count} 个区块")
高级用法
从多个源加载
# 加载多个文件
q = query()
q.from_path('specs/api.bmd')
q.from_path('specs/database.bmd')
results = q.where(type='function').execute()
# 加载整个目录
q = query().from_path('docs/') # 递归 *.bmd
自定义过滤器
# 标题较长的区块
query().filter(lambda b: len(b.title) > 50)
# 特定深度的区块
query().filter(lambda b: b.get_depth() == 2)
# 有特定祖先的区块
def has_ancestor(block, title):
current = block.parent
while current:
if current.title == title:
return True
current = current.parent
return False
query().filter(lambda b: has_ancestor(b, 'API'))
属性继承
BlockMD 支持使用 key* 语法的属性继承:
# Parent
`status`: active
## Child
`status*`: working
结果: Child 的 status="active/working"
查询继承的属性:
# 查找具有继承状态的区块
query().filter(lambda b: '/' in b.get_property('status', ''))
运行测试
# 测试 QueryBuilder API
python tests/test_query_builder.py
# 运行所有解析器测试
python tests/test_parser.py
示例
查看 examples/query_demo.py 获取所有特性的完整示例:
python examples/query_demo.py
API 使用
# 链式、流畅的接口
query()
.from_path('docs/')
.where(level=lambda l: l >= 2)
.contains('TODO')
.order_by('title')
.view('table')
BlockMD 格式说明
什么是 BlockMD?
BlockMD 是一种与 Markdown 完全兼容的块状标记语言,为标准 Markdown 文件增加了结构化和元数据功能。
基本语法
# 区块标题
`property`: value
`status`: active
区块内容可以包含任何标准 Markdown 格式。
## 子区块
`status*`: working
子区块继承父区块的属性。
核心概念
- 区块(Block):由 Markdown 标题(
#、##等)定义 - 层级(Level):标题的
#数量(1-6)决定嵌套层级 - 属性(Properties):
`key`: value格式的键值对元数据 - 继承(Inheritance):
`key*`: value语法从父区块继承属性 - 内容(Content):标准 Markdown 文本
许可证
MIT
贡献
欢迎贡献!提交 PR 前请确保测试通过。
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wesleysbmd-0.1.0.tar.gz.
File metadata
- Download URL: wesleysbmd-0.1.0.tar.gz
- Upload date:
- Size: 23.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37cef22c1bcc6182a315c5aa9330c8d522d00c77befaf24fdaa428d81b042351
|
|
| MD5 |
76b11e3c31debc9c6b87648fc52531af
|
|
| BLAKE2b-256 |
7e7b68fecee8f39af254951124e6669cfe56c50fd9ad89bc56eed892c52e3c0a
|
File details
Details for the file wesleysbmd-0.1.0-py3-none-any.whl.
File metadata
- Download URL: wesleysbmd-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5586aa115bbc485b378fd7c8a9cc58a2ce28ff264b1edd52ec77735ae9138bb2
|
|
| MD5 |
f189f9994ac7783a36e1f1af83ddff85
|
|
| BLAKE2b-256 |
8beb6b68f266cc70ef4db0e20ca2ca1724d0696e4b1745798578357aaa9d4c6b
|