Obsidian插件篇-DataviewJS参考示例


Obsidian 插件篇 -DataviewJS 参考示例

在上文 Obsidian插件篇-DataviewJS基础知识 的基础上,本篇文章主要提供一些验证后的 DataviewJS 脚本供大家学习并仿写实践。

以下 DataviewJS 脚本,可以直接复制使用,标题即是脚本实现的功能。

汇总当前文件标题生成目录(文本)

dataviewjs
const startHeadingLevel = 0 // 起始标题级别
const file = app.workspace.getActiveFile()
const { headings } = app.metadataCache.getFileCache(file)
const lists = headings.map(p=>
  `${' '.repeat((p.level - startHeadingLevel) * 4)}- ${p.heading}`
) // 前导空格 + 列表格式
dv.paragraph(lists.join('\n')) // 输出

汇总指定文件夹位置生成目录

dataviewjs
const dFiles = dv.pages(`"3.Cards/Sh成长系统"`)
const startHeadingLevel = 0
dFiles.map(async dFile=> {
  const file = app.vault.getAbstractFileByPath(dFile.file.path)
  const { headings } = app.metadataCache.getFileCache(file)
  const lists = headings.filter(p=> p).map(p=>
    `${' '.repeat((p.level - startHeadingLevel) * 4)}- ${p.heading}`
  )
  dv.header(6, dFile.file.link)
  dv.paragraph(lists.join('\n'))
})

根据标题生成点击可跳转的目录

原文见:使用DV创建动态更新的笔记目录大纲(TOC) - 经验分享 - Obsidian 中文论坛

dataviewjs
dv.header(2,"目录");
// 标题级别,按需修改
const startHeadinglevel = 2;
const file = app.workspace.getActiveFile();
const { headings } = app.metadataCache.getFileCache(file);

// 全列表的形式
const raws = headings.map( p => {
    let repeatCount = Math.max((p.level - startHeadinglevel) * 4, 0);
    let spacesPrefix = ' '.repeat( repeatCount + 4 );
    let listSign = repeatCount > 0 ? '- ' : '';
    let linkText = `[[#${p.heading}]]`;
    let headingList = (p.level < startHeadinglevel) ? `- ${linkText}` : `${spacesPrefix}- ${linkText}`;
    return headingList;
  }
)

let result = raws.join('\n');
// 添加行距
dv.container.style.lineHeight = "1.5em";
dv.paragraph(result)
dataviewjs
// 一级列表单独显示的形式
// 标题级别,按需修改
const startHeadinglevel = 2;
const file = app.workspace.getActiveFile();
const { headings } = app.metadataCache.getFileCache(file);

let output = '';
const additionalAttr = {attr: {style: 'margin-block-start: 0 !important; margin-block-end: 0 !important;'}};

// 整个 dv 容器的样式调整
dv.container.style.marginBlockStart = "0em";

headings.forEach ( h => {
    if (h.level < startHeadinglevel) {
        // 先输出之前的子列表内容
        if (output) dv.paragraph(output, additionalAttr);

        // 将一级标题输出成单独的段落
        output = `[[#${h.heading}]]\n`;
        dv.paragraph(output);
        output = '';
    } else {
        output += `${' '.repeat((h.level - startHeadinglevel) * 4)}- [[#${h.heading}]]\n`;
    }
})

// 把最后的残余内容输出出来
if (output) dv.paragraph(output, additionalAttr);

按钮修改 yaml

dataviewjs
// 这个是按钮的点击函数
const {update,autoprop} = this.app.plugins.plugins["metaedit"].api;

const buttonMaker = (pn, pv, fpath) => {
	//  选项,值,路径
    const btn = this.container.createEl('button', {"text": pv});
    btn.addEventListener('click', async (evt) => {
        evt.preventDefault();
        //"新内容"要在Auto Properties中事先配置
		const newtext = await autoprop("新内容")
        await update(pn, newtext, fpath);
    });
    return btn;
}

dv.table(["文件","路径", "tags", "status"],
	dv.pages("#Linux")
	.map(t=>[t.file.link, t.file.folder,buttonMaker('tags',t.tags,t.file.path), buttonMaker('status', t.status, t.file.path)])
)

所有标签列表

dataviewjs
// 生成所有的标签且形成列表
dv.list(dv.pages("").file.tags.distinct())
dataviewjs
// 生成所有的标签且以 | 分割,修改时只需要修改 join(" | ") 里面的内容。
dv.paragraph(
  dv.pages("").file.tags.distinct().map(t => {return `[${t}](${t})`}).array().join(" | ")
)
dataviewjs
// 基于文件夹聚类所有的标签。
for (let group of dv.pages("").filter(p => p.file.folder != "").groupBy(p => p.file.folder.split("/")[0])) {
  dv.paragraph(`### ${group.key}`);
  dv.paragraph(
    dv.pages(`"${group.key}"`).file.tags.distinct().map(t => {return `[${t}](${t})`}).array().sort().join(" | "));
}

仓库统计

dataviewjs
dv.header(2,"文章统计");
let ftMd = dv.pages("").file.sort(t => t.cday)[0]
let total = parseInt([new Date() - ftMd.ctime] / (60*60*24*1000))
let totalDays = "使用 *Obsidian* "+"**"+total+"**天,"
dv.paragraph(totalDays)
//.length统计数量
let i = [dv.pages('!"4.Extra/Template"').length,dv.pages(`"2.Calendar"`).length,dv.pages(`"4.Extra"`).length,
         dv.pages().file.etags.distinct().length]
// console.log(dv.pages())
dv.paragraph(`共有 **${i[0]}** 篇笔记,Calendar笔记 **${i[1]}** 篇,附件 **${i[2]}** 个,标签 **${i[3]}** 个`)
dataviewjs
let ftMd = dv.pages("").file.sort(t => t.cday)[0]
let total = parseInt([new Date() - ftMd.ctime] / (60*60*24*1000))
let totalDays = "您已使用 ***Obsidian*** "+total+" 天,"
let nofold = '!"misc/templates"'
let allFile = dv.pages(nofold).file
let totalMd = "共创建 "+ allFile.length+" 篇笔记"
let totalTag = allFile.etags.distinct().length+" 个标签"
let totalTask = allFile.tasks.length+"个待办。 "
dv.paragraph(
	totalDays + totalMd + "、" + totalTag + "、" + totalTask
)

所有带关键词的行

dataviewjs
//输出所有带有关键词的行
//使用时修改关键词即可
const term = "ACID"
const files = app.vault.getMarkdownFiles()
const arr = files.map(async ( file) => {
	const content = await app.vault.cachedRead(file)
	const lines = content.split("\n").filter(line => line.contains(term))
	return lines
})
Promise.all(arr).then(values => dv.list(values.flat()))

倒计时

dataviewjs
// 修改其中的时间,可以输出当前离倒计时的时间差。
const setTime = new Date("2024/6/15 08:00:00");
const nowTime = new Date();
const restSec = setTime.getTime() - nowTime.getTime();
const day = parseInt(restSec / (60*60*24*1000));
const str = day + "天"
dv.paragraph(str);

Todo 文件一行输出

dataviewjs
//控制台调试
console.log(dv.pages("#Todo"))
//dv.paragraph生成段落
dv.paragraph(`${dv.pages("#Todo").file.link}`)

任务列表

dataviewjs
//dv.taskList生成任务列表
//console.log(dv.pages("#Task"))
dv.taskList(dv.pages("#Task").file.tasks) 

待办列表

dataviewjs
dv.header(3,"待办列表");
//dv.list生成列表
dv.list(dv.pages("#Todo").map(p=>p.file.link));

最近一周文件列表

dataviewjs
//查询结果有误
dv.header(5,"最近一周");
dv.list(
	dv.pages(``)
	.filter(p=>moment(p.created).diff(moment(),'days')<=7)
	.map(p=>p.file.link+' - '+p.created));

2024 年 8 月文件列表

dataviewjs
dv.header(3,"2024年7月文件列表");
//2024年文件
//dv.list()生成List
dv.list(
	//获取符合条件的文件数组
	dv.pages(``)
		//筛选符合条件的子数组
		.filter(p=>moment(Number(p.file.cday)).get("year")==2024 
		&& moment(Number(p.file.cday)).get("month")==7)
		//降序排序
		.sort(p=>p.file.cday,'desc')
		//.map()类似for循环
		.map(p=>moment(Number(p.file.cday)).format('yyyy-MM-DD')+' >> '+p.file.link)
)

某年某月文件列表

dataviewjs
dv.header(3,"2024年8月文件列表");
dv.list(
    // 获取符合条件的文件数组
    dv.pages("")
        // 筛选符合条件的子数组(将 'file.cday' 转换为日期格式)
        .filter(p => {
            const date = moment(p.created);
            // 筛选符合条件的子数组(将 'file.cday' 转换为日期格式)
            // 月份比较不准,总是大一,问题未知(24年1月)
            return date.year() ==2024 && date.month() ==0;
        })
        // 降序排序
        .sort(p => p.created, 'desc')
        // 使用 map 转换输出格式并处理日期(确保使用 `format` 方法正确解析)
        .map(p => {
            const formattedDate = moment(p.created).format('YYYY-MM-DD');
            return `${formattedDate} >> ${p.file.link}`;
        })
)

文件夹下文件列表

dataviewjs
//写法1
//dv.pagePaths()获取文件目录数组
for(let i of dv.pagePaths(`"1.Atlas"`).groupBy(p=>p.split("/")[1])){
	let a = dv.pages(`"1.Atlas/${i.key}"`).length
	dv.paragraph(`### ${i.key} --**${a}**篇`);
	dv.list(
		dv.pages(`"1.Atlas"`)
			.filter(p=>p.file.folder.split("/")[1]==i.key)
			//cday写法 .map(p=>moment(Number(p.file.cday)).format('yyyy-MM-DD')+' >> '+p.file.link)
			.map(p=> p.file.link + '>>' +p.created +' - '+moment().diff(moment(p.created),'days')+'天')
	);
}
dataviewjs
//写法2,优先使用
let pageGroups = dv.pagePaths(`"1.Atlas"`).groupBy(p => p.split("/")[1]);
for (let i of pageGroups) {
    let pagesInGroup = dv.pages(`"1.Atlas/${i.key}"`);
    // 使用 pagesInGroup 替换重复的获取操作
    dv.paragraph(`### ${i.key} --**${pagesInGroup.length}**篇`);
    dv.list(pagesInGroup.map(p => {
        let daysSince = moment(p.created).diff(moment(), 'days');
        return p.file.link + '>>' +p.created + ' - ' + `${daysSince}` + '天';
    }));
}

MySQL 文件夹列表

dataviewjs
//MySQL文件夹总览
let pageGroups = dv.pagePaths(`"2.Calendar/7.todo/1.Study/MySQL"`).groupBy(p => p.split("/")[4]);
console.log(pageGroups);
for (let i of pageGroups) {
    let pagesInGroup = dv.pages(`"2.Calendar/7.todo/1.Study/MySQL/${i.key}"`);
    // 使用 pagesInGroup 替换重复的获取操作
    dv.paragraph(`### ${i.key} --**${pagesInGroup.length}**篇`);
    dv.list(pagesInGroup.map(p => {
        let daysSince = moment(p.created).diff(moment(), 'days');
        return p.file.link + '>>' +p.created + ' - ' + `${daysSince}` + '天';
    }));
}

Atlas 文件夹 Table

dataviewjs
dv.header(1,"table任务");
// 首先获取所有页面的路径
let allPaths = dv.pagePaths(`"1.Atlas"`);

// 对文件夹进行分组并处理每个子集
for(let i of allPaths.groupBy(p=>p.split("/")[1])){
    let a = dv.pages(`"1.Atlas/${i.key}"`).length;
    dv.paragraph(`### ${i.key} --**${a}**篇`);
    // 过滤当前文件夹下的页面,并计算从创建以来的天数和获取实际创建日期
    let pageData = dv.pages(`"1.Atlas"`)
                        .filter(p => p.file.folder.split("/")[1] == i.key)
                        .map(p => ({
                            title: i.key,
                            pageName: p.file.link,
                            sinceCreated: moment().diff(moment(p.created), 'days'),
                            created: p.created
                        }));
    // 创建并展示一个表格,用于当前文件夹下的页面数据
    dv.table(['文件夹', '文件名', '创建天数', '创建日期'],
    [[pageData.title,pageData.pageName,pageData.sinceCreated,pageData.created]]);   
}

指定多个文件夹 Table

dataviewjs
{
dv.header(1,"指定多个文件夹Table");
// 首先获取所有页面的路径
let allPaths = [
    { key: "1.Atlas" },
    { key: "4.Extra" }
];
// 对文件夹进行分组并处理每个子集
for(let i of allPaths){
    let a = dv.pages(`"${allPaths[0].key}"`).length;
    dv.paragraph(`### ${i.key} --**${a}**篇`);
    // 过滤当前文件夹下的页面,并计算从创建以来的天数和获取实际创建日期
    let pageData = dv.pages(``)
                        .filter(p => p.file.folder.split("/")[0] == i.key)
                        .map(p => ({
                            pageName: p.file.link,
                            path: p.file.folder,
                            sinceCreated: moment().diff(moment(p.created), 'days'),
                            created: p.created
                        }));
    // 创建并展示一个表格,用于当前文件夹下的页面数据
    dv.table(['文件名','文件路径','创建天数', '创建日期'],
    [[pageData.pageName,pageData.path,pageData.sinceCreated,pageData.created]]);   
}}

仓库文件夹 Table

dataviewjs
dv.header(1,"仓库文件夹Table");
// 首先获取所有页面的路径
let allPaths = dv.pagePaths(``);
// 对文件夹进行分组并处理每个子集
for(let i of allPaths.groupBy(p=>p.split("/")[0])){
    let a = dv.pages(`"${i.key}"`).length;
    dv.paragraph(`### ${i.key} --**${a}**篇`);
    // 过滤当前文件夹下的页面,并计算从创建以来的天数和获取实际创建日期
    let pageData = dv.pages(``)
                        .filter(p => p.file.folder.split("/")[0] == i.key)
                        .map(p => ({
                            pageName: p.file.link,
                            path: p.file.folder,
                            sinceCreated: moment().diff(moment(p.created), 'days'),
                            created: p.created
                        }));
    // 创建并展示一个表格,用于当前文件夹下的页面数据
    dv.table(['文件名', '文件路径','创建天数', '创建日期'],
    [[pageData.pageName,pageData.path,pageData.sinceCreated,pageData.created]]);   
}

文章作者: huan
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 huan !
  目录