【文章汇总】Moy的OB分享(兼答疑贴)

感觉可以先看一下 轻量数据库 的实现方案。

基础格式和你列举的很相似:

  • 二级标题
  • 标题下面一行 inline property 内联属性
  • 然后写链接
  • 正文

用 Dataview 可以把它们提取出来并显示成一个表格。
而且不需要拆分很多个页面,单个 md 内就可以。

效果像是这样:


更新版的脚本在这里:

const useList = false;
const curNote = dv.current();

const showLink = input?.showLink ?? true;
const showImage = input?.showImage ?? true;

if (!curNote){
    dv.span("当前文档未加载,请重新打开");
    return;
}

let tarFile = await app.vault.getAbstractFileByPath(curNote.file.path);

// 获取当前文件的 meta 数据
const curFileMeta = app.metadataCache.getFileCache(tarFile);
const headings = curFileMeta.headings;

const headingsList = headings.map( k => k.heading )

// 获取当前文章的文本内容
const curFilePath = curNote.file.path;
const curTFile = await app.vault.getFileByPath(curFilePath)
const content = await app.vault.cachedRead(curTFile);

if (!headings) {
  dv.span("当前文档缺少标题");
  return;
}

const meta = content.matchAll(/#+ (.*)\n+(\[.*\:.*\])\n+(\[.*\]\(.*\))\n+(\!\[\[.*\]\])\n/gm);

// 标题作为 key,元数据作为 value,做成 DV 表格
let tableHeads = ["标题"]

// 先存成一个 dict
let metaValues = []

if (showLink) {
    tableHeads.push("链接")
}

if (showImage) {
    tableHeads.push("图片")
}

if (meta) {
    for (let m of meta) {
        let title = m[1]

        // 检查 title 是否在 headings 内(避免把一些代码块内的内容也当作元数据)
        if (headingsList.indexOf(title) == -1) {
            continue
        }

        let metaList = m[2].split("  ")
        let metaDict = {}


        if (showImage) {
            let image = m[4] ?? ""
            let imageHtml = ""
            if (image) {
                // 把图片的displaytext 换成 📸
                // image = dv.embed(image)
                let imageLink = image.match(/\[\[(.*?)\]\]/)
                let imageFullPath = app.metadataCache.getFirstLinkpathDest(imageLink[1], imageLink[1]).path
                let resPath = app.vault.adapter.getResourcePath(imageFullPath)
                imageHtml = `<img src="${resPath}"  style="max-width: 300px;"  />`
            }
            metaDict["图片"] = imageHtml
        }

        // 添加元数据的 key 到表头
        for (let i = 0; i < metaList.length; i++) {
            let keyValue = metaList[i].replace("[", "").replace("]", "").split("::")
            // console.log(metaList[i], keyValue)

            let key = keyValue[0].trim()
            if (tableHeads.indexOf(key) == -1) {
                tableHeads.push(key)
            }

            if (useList){
                // 1. 列表形式,重复属性会合并
                let value = [keyValue[1]]
                metaDict[key] = metaDict[key] ? metaDict[key].concat(value) : value
            } else {
                // 2. 文本形式,重复属性会使用最新的
                let value = keyValue[1]
                metaDict[key] = metaDict[key] ? metaDict[key] + `,${value}` : value
            }
        }

        // 添加 URL 进元数据
        if (showLink) { 
            let url = m[3]??""
            if (url) {
                // 把链接的displaytext 换成 🔗
                url = url.replace(/\[(.*?)\]/, "[🔗]")
            }
            metaDict["链接"] = url
        }

        let returnValuesList = []

        for (let i = 0; i < tableHeads.length; i++) {
            if (i == 0) {
                returnValuesList.push(`[[#${m[1]}]]`)
            } else {
                returnValuesList.push(metaDict[tableHeads[i]] ? metaDict[tableHeads[i]] : "")
            }
        }


        metaValues.push(returnValuesList)
    }
}

dv.table(
    tableHeads,
    metaValues.map( k => k )
)


用法见 【Dataview 入门介绍】DV 脚本是什么?怎么用? - 经验分享 - Obsidian 中文论坛

例图里对应的文本源代码为:


### DOIO

[按键::16]  [旋钮::1]   [连接::蓝牙双模]  [价格::378]

[DOIO 16键设计师小键盘 客制化 蓝牙双模 无线 机械键盘 KB16B-02-tmall.com天猫](https://detail.tmall.com/item.htm...)

![[250427_单手小键盘选购-img-250427_094128.webp]]

需要注意的是,列表类型的属性直接写到一起就可以,像是 [关键字::A,B] 这样。

脚本本身也有一些开关选项,可以询问 AI 进行调整。