name: obsidian-bases
description: 创建和编辑 Obsidian 基础文件(.base 文件),包含视图、过滤器、公式和摘要。在操作 .base 文件、创建笔记的类数据库视图,或用户提及 Bases、表格视图、卡片视图、过滤器或公式时使用。
Obsidian Bases 技能
此技能使技能兼容的代理能够创建和编辑有效的 Obsidian Bases(.base 文件),包括视图、过滤器、公式和所有相关配置。
概述
Obsidian Bases 是基于 YAML 的文件,用于定义 Obsidian 仓库中笔记的动态视图。一个 Base 文件可以包含多个视图、全局过滤器、公式、属性配置和自定义摘要。
文件格式
Base 文件使用 .base 扩展名,并包含有效的 YAML。它们也可以嵌入到 Markdown 代码块中。
完整模式
# 全局过滤器适用于基础中的所有视图
filters:
# 可以是单个过滤器字符串
# 或者具有 and/or/not 的递归过滤器对象
and: []
or: []
not: []
# 定义可在所有视图中使用的公式属性
formulas:
formula_name: 'expression'
# 配置属性的显示名称和设置
properties:
property_name:
displayName: "显示名称"
formula.formula_name:
displayName: "公式显示名称"
file.ext:
displayName: "扩展名"
# 定义自定义摘要公式
summaries:
custom_summary_name: 'values.mean().round(3)'
# 定义一个或多个视图
views:
- type: table | cards | list | map
name: "视图名称"
limit: 10 # 可选:限制结果
groupBy: # 可选:分组结果
property: property_name
direction: ASC | DESC
filters: # 视图特定过滤器
and: []
order: # 按顺序显示的属性
- file.name
- property_name
- formula.formula_name
summaries: # 映射属性到摘要公式
property_name: Average
过滤器语法
过滤器缩小结果范围。它们可以全局应用或按视图应用。
过滤器结构
# 单个过滤器
filters: 'status == "done"'
# AND - 所有条件必须为真
filters:
and:
- 'status == "done"'
- 'priority > 3'
# OR - 任何条件可以为真
filters:
or:
- 'file.hasTag("book")'
- 'file.hasTag("article")'
# NOT - 排除匹配项
filters:
not:
- 'file.hasTag("archived")'
# 嵌套过滤器
filters:
or:
- file.hasTag("tag")
- and:
- file.hasTag("book")
- file.hasLink("Textbook")
- not:
- file.hasTag("book")
- file.inFolder("Required Reading")
过滤器操作符
| 操作符 |
描述 |
== |
等于 |
!= |
不等于 |
> |
大于 |
< |
小于 |
>= |
大于或等于 |
<= |
小于或等于 |
&& |
逻辑与 |
|| |
逻辑或 |
| <code>!</code> |
逻辑非 |
属性
三种属性类型
- 笔记属性 - 来自 frontmatter:
note.author 或仅 author
- 文件属性 - 文件元数据:
file.name, file.mtime 等
- 公式属性 - 计算值:
formula.my_formula
文件属性参考
| 属性 |
类型 |
描述 |
file.name |
字符串 |
文件名 |
file.basename |
字符串 |
无扩展名的文件名 |
file.path |
字符串 |
文件的完整路径 |
file.folder |
字符串 |
父文件夹路径 |
file.ext |
字符串 |
文件扩展名 |
file.size |
数字 |
文件大小(字节) |
file.ctime |
日期 |
创建时间 |
file.mtime |
日期 |
修改时间 |
file.tags |
列表 |
文件中的所有标签 |
file.links |
列表 |
文件中的内部链接 |
file.backlinks |
列表 |
链接到此文件的文件 |
file.embeds |
列表 |
笔记中的嵌入 |
file.properties |
对象 |
所有 frontmatter 属性 |
this 关键字
- 在主内容区域:引用基础文件本身
- 嵌入时:引用嵌入文件
- 在侧边栏:引用主内容中的活动文件
公式语法
公式从属性计算值。在 formulas 部分定义。
formulas:
# 简单算术
total: "price * quantity"
# 条件逻辑
status_icon: 'if(done, "✅", "⏳")'
# 字符串格式化
formatted_price: 'if(price, price.toFixed(2) + " dollars")'
# 日期格式化
created: 'file.ctime.format("YYYY-MM-DD")'
# 复杂表达式
days_old: '((now() - file.ctime) / 86400000).round(0)'
函数参考
全局函数
| 函数 |
签名 |
描述 |
date() |
date(string): date |
将字符串解析为日期。格式:YYYY-MM-DD HH:mm:ss |
duration() |
duration(string): duration |
解析持续时间字符串 |
now() |
now(): date |
当前日期和时间 |
today() |
today(): date |
当前日期(时间 = 00:00:00) |
if() |
if(condition, trueResult, falseResult?) |
条件 |
min() |
min(n1, n2, ...): number |
最小数字 |
max() |
max(n1, n2, ...): number |
最大数字 |
number() |
number(any): number |
转换为数字 |
link() |
link(path, display?): Link |
创建链接 |
list() |
list(element): List |
如果还不是列表,则包装为列表 |
file() |
file(path): file |
获取文件对象 |
image() |
image(path): image |
创建图像用于渲染 |
icon() |
icon(name): icon |
通过名称获取 Lucide 图标 |
html() |
html(string): html |
渲染为 HTML |
escapeHTML() |
escapeHTML(string): string |
转义 HTML 字符 |
任意类型函数
| 函数 |
签名 |
描述 |
isTruthy() |
any.isTruthy(): boolean |
强制转换为布尔值 |
isType() |
any.isType(type): boolean |
检查类型 |
toString() |
any.toString(): string |
转换为字符串 |
日期函数和字段
字段: date.year, date.month, date.day, date.hour, date.minute, date.second, date.millisecond
| 函数 |
签名 |
描述 |
date() |
date.date(): date |
移除时间部分 |
format() |
date.format(string): string |
使用 Moment.js 模式格式化 |
time() |
date.time(): string |
获取时间为字符串 |
relative() |
date.relative(): string |
人类可读的相对时间 |
isEmpty() |
date.isEmpty(): boolean |
日期始终为 false |
日期算术
# 持续时间单位:y/year/years, M/month/months, d/day/days,
# w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
# 添加/减去持续时间
"date + \"1M\"" # 添加 1 个月
"date - \"2h\"" # 减去 2 小时
"now() + \"1 day\"" # 明天
"today() + \"7d\"" # 从今天起一周后
# 减去日期以获取毫秒差
"now() - file.ctime"
# 复杂持续时间算术
"now() + (duration('1d') * 2)"
字符串函数
字段: string.length
| 函数 |
签名 |
描述 |
contains() |
string.contains(value): boolean |
检查子字符串 |
containsAll() |
string.containsAll(...values): boolean |
所有子字符串存在 |
containsAny() |
string.containsAny(...values): boolean |
任何子字符串存在 |
startsWith() |
string.startsWith(query): boolean |
以查询开头 |
endsWith() |
string.endsWith(query): boolean |
以查询结尾 |
isEmpty() |
string.isEmpty(): boolean |
为空或不存在 |
lower() |
string.lower(): string |
转换为小写 |
title() |
string.title(): string |
转换为标题大小写 |
trim() |
string.trim(): string |
移除空白 |
replace() |
string.replace(pattern, replacement): string |
替换模式 |
repeat() |
string.repeat(count): string |
重复字符串 |
reverse() |
string.reverse(): string |
反转字符串 |
slice() |
string.slice(start, end?): string |
子字符串 |
split() |
string.split(separator, n?): list |
拆分为列表 |
数字函数
| 函数 |
签名 |
描述 |
abs() |
number.abs(): number |
绝对值 |
ceil() |
number.ceil(): number |
向上取整 |
floor() |
number.floor(): number |
向下取整 |
round() |
number.round(digits?): number |
四舍五入到指定位数 |
toFixed() |
number.toFixed(precision): string |
固定点表示法 |
isEmpty() |
number.isEmpty(): boolean |
不存在 |
列表函数
字段: list.length
| 函数 |
签名 |
描述 |
contains() |
list.contains(value): boolean |
元素存在 |
containsAll() |
list.containsAll(...values): boolean |
所有元素存在 |
containsAny() |
list.containsAny(...values): boolean |
任何元素存在 |
filter() |
list.filter(expression): list |
按条件过滤(使用 value, index) |
map() |
list.map(expression): list |
转换元素(使用 value, index) |
reduce() |
list.reduce(expression, initial): any |
减少为单个值(使用 value, index, acc) |
flat() |
list.flat(): list |
展平嵌套列表 |
join() |
list.join(separator): string |
连接为字符串 |
reverse() |
list.reverse(): list |
反转顺序 |
slice() |
list.slice(start, end?): list |
子列表 |
sort() |
list.sort(): list |
升序排序 |
unique() |
list.unique(): list |
移除重复项 |
isEmpty() |
list.isEmpty(): boolean |
无元素 |
文件函数
| 函数 |
签名 |
描述 |
asLink() |
file.asLink(display?): Link |
转换为链接 |
hasLink() |
file.hasLink(otherFile): boolean |
有链接到文件 |
hasTag() |
file.hasTag(...tags): boolean |
有任何标签 |
hasProperty() |
file.hasProperty(name): boolean |
有属性 |
inFolder() |
file.inFolder(folder): boolean |
在文件夹或子文件夹中 |
链接函数
| 函数 |
签名 |
描述 |
asFile() |
link.asFile(): file |
获取文件对象 |
linksTo() |
link.linksTo(file): boolean |
链接到文件 |
对象函数
| 函数 |
签名 |
描述 |
isEmpty() |
object.isEmpty(): boolean |
无属性 |
keys() |
object.keys(): list |
键列表 |
values() |
object.values(): list |
值列表 |
正则表达式函数
| 函数 |
签名 |
描述 |
matches() |
regexp.matches(string): boolean |
测试是否匹配 |
视图类型
表格视图
views:
- type: table
name: "我的表格"
order:
- file.name
- status
- due_date
summaries:
price: Sum
count: Average
卡片视图
views:
- type: cards
name: "画廊"
order:
- file.name
- cover_image
- description
列表视图
views:
- type: list
name: "简单列表"
order:
- file.name
- status
地图视图
需要纬度/经度属性和 Maps 社区插件。
views:
- type: map
name: "位置"
# 地图特定设置,用于 lat/lng 属性
默认摘要公式
| 名称 |
输入类型 |
描述 |
Average |
数字 |
数学平均值 |
Min |
数字 |
最小数字 |
Max |
数字 |
最大数字 |
Sum |
数字 |
所有数字的总和 |
Range |
数字 |
最大 - 最小 |
Median |
数字 |
数学中位数 |
Stddev |
数字 |
标准偏差 |
Earliest |
日期 |
最早日期 |
Latest |
日期 |
最晚日期 |
Range |
日期 |
最晚 - 最早 |
Checked |
布尔值 |
真值计数 |
Unchecked |
布尔值 |
假值计数 |
Empty |
任意 |
空值计数 |
Filled |
任意 |
非空值计数 |
Unique |
任意 |
唯一值计数 |
完整示例
任务跟踪基础
filters:
and:
- file.hasTag("task")
- 'file.ext == "md"'
formulas:
days_until_due: 'if(due, ((date(due) - today()) / 86400000).round(0), "")'
is_overdue: 'if(due, date(due) < today() && status != "done", false)'
priority_label: 'if(priority == 1, "🔴 High", if(priority == 2, "🟡 Medium", "🟢 Low"))'
properties:
status:
displayName: 状态
formula.days_until_due:
displayName: "到期天数"
formula.priority_label:
displayName: 优先级
views:
- type: table
name: "活跃任务"
filters:
and:
- 'status != "done"'
order:
- file.name
- status
- formula.priority_label
- due
- formula.days_until_due
groupBy:
property: status
direction: ASC
summaries:
formula.days_until_due: Average
- type: table
name: "已完成"
filters:
and:
- 'status == "done"'
order:
- file.name
- completed_date
阅读列表基础
filters:
or:
- file.hasTag("book")
- file.hasTag("article")
formulas:
reading_time: 'if(pages, (pages * 2).toString() + " min", "")'
status_icon: 'if(status == "reading", "📖", if(status == "done", "✅", "📚"))'
year_read: 'if(finished_date, date(finished_date).year, "")'
properties:
author:
displayName: 作者
formula.status_icon:
displayName: ""
formula.reading_time:
displayName: "预计时间"
views:
- type: cards
name: "图书馆"
order:
- cover
- file.name
- author
- formula.status_icon
filters:
not:
- 'status == "dropped"'
- type: table
name: "阅读列表"
filters:
and:
- 'status == "to-read"'
order:
- file.name
- author
- pages
- formula.reading_time
项目笔记基础
filters:
and:
- file.inFolder("Projects")
- 'file.ext == "md"'
formulas:
last_updated: 'file.mtime.relative()'
link_count: 'file.links.length'
summaries:
avgLinks: 'values.filter(value.isType("number")).mean().round(1)'
properties:
formula.last_updated:
displayName: "更新"
formula.link_count:
displayName: "链接"
views:
- type: table
name: "所有项目"
order:
- file.name
- status
- formula.last_updated
- formula.link_count
summaries:
formula.link_count: avgLinks
groupBy:
property: status
direction: ASC
- type: list
name: "快速列表"
order:
- file.name
- status
每日笔记索引
filters:
and:
- file.inFolder("Daily Notes")
- '/^\\d{4}-\\d{2}-\\d{2}$/.matches(file.basename)'
formulas:
word_estimate: '(file.size / 5).round(0)'
day_of_week: 'date(file.basename).format("dddd")'
properties:
formula.day_of_week:
displayName: "星期"
formula.word_estimate:
displayName: "~字数"
views:
- type: table
name: "近期笔记"
limit: 30
order:
- file.name
- formula.day_of_week
- formula.word_estimate
- file.mtime
嵌入基础
嵌入到 Markdown 文件中:
![[MyBase.base]]
<!-- 特定视图 -->
![[MyBase.base#View Name]]
YAML 引用规则
- 对于包含双引号的公式,使用单引号:
'if(done, "Yes", "No")'
- 对于简单字符串,使用双引号:
"My View Name"
- 在复杂表达式中正确转义嵌套引号
常见模式
按标签过滤
filters:
and:
- file.hasTag("project")
按文件夹过滤
filters:
and:
- file.inFolder("Notes")
按日期范围过滤
filters:
and:
- 'file.mtime > now() - "7d"'
按属性值过滤
filters:
and:
- 'status == "active"'
- 'priority >= 3'
组合多个条件
filters:
or:
- and:
- file.hasTag("important")
- 'status != "done"'
- and:
- 'priority == 1'
- 'due != ""'
参考文献