Dataview插件功能强大毋庸置疑,然而DataviewJS 脚本的编写却存在一定难度,学习成本也很高。本篇文章旨在从实际需求出发分享指定目录下文件分组自定义排序统计的Dataviewjs 脚本。
结果预览
如下图所示,此脚本统计出了本地知识库“1.Projects”文件夹下的文件数量、标签数量、显示标签内容,并将文件按照子文件夹分组排序输出成了表格形式方便查看。
dataview脚本分享
以下脚本基于个人知识库本地测试验证后,可以正常使用,遂分享供大家学习借鉴。
dv.header(2,"文章统计情况");
let path="1.Projects"; // 设置根目录路径,请替换 "1.Projects" 为您实际的根目录
let paths = dv.pagePaths(`"${path}"`); // 获取根目录下所有页面的路径
let filePaths=paths.groupBy(p=>p.split("/")[1]); // 按第一级子文件夹名称分组路径,可替换 "1" 为您实际层次目录
let pages = dv.pages(`"${path}"`);//获取根目录下所有文件
let publishPages=pages.filter(a => a.publish == true);//已发布,可替换 "publish" 为您实际yaml属性
let toPublishPages=pages.filter(a => a.publish == false);//未发布,可替换 "publish" 为您实际yaml属性
let loopCount = 1;// 初始化循环计数器
let cols=['文件名','是否发布','标签', '状态','创建天数', '创建日期'];//预设的输出table表头,可替换
//自定义排序部分
let letters = "*abcdefghjklmnopqrstwxyz".toLocaleUpperCase().split('');
let zh = "阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀".split('');
var isNumber = function(temp){
let re = /[0-9]/;
return re.test(temp);
};
var isChar = function(temp){
let re = /[a-zA-Z]/;
return re.test(temp);
};
var isChinese = function(temp){
let re = /[^\u4E00-\u9FA5]/;
return re.test(temp) ? false : true;
};
// mySort 函数,将文件按照文件名排序,优先数字,其次字母,最后汉字
function mySort(dvPages, letters, zh) {
let sortedPages = [];
letters.forEach((e,i) => {
let key = (e == "*") ? "0~9" : e;
let currData = new Array();
dvPages.forEach(b => {
let fileName = b.file.name;
if (fileName) {
let initial = fileName.charAt(0);
if(i == 0 && isNumber(initial)){
currData.push(b);
} else if (i != 0 && isChar(initial) && e == initial.toLocaleUpperCase()){
currData.push(b);
} else if (i != 0 && isChinese(initial)){
if(initial.localeCompare(zh[i]) == -1 && (!zh[i-1] || zh[i-1].localeCompare(initial) <= 0)){
currData.push(b);
}
}
}
});
if(currData.length > 0){
currData.sort((a, b) => { // 修改后的排序函数
let fileNameA = a.file.name;
let fileNameB = b.file.name;
// 提取文件名中的数字部分进行数值比较
let numA = parseInt(fileNameA.match(/^(\d+)/)?.[1]); // 正则提取文件名开头的数字
let numB = parseInt(fileNameB.match(/^(\d+)/)?.[1]); // 正则提取文件名开头的数字
// 如果都能提取到数字,则进行数值比较
if (!isNaN(numA) && !isNaN(numB)) {
return numA - numB; // 数值升序排序
} else {
// 如果无法提取数字,则 Fallback 到字符串排序 (字典序)
if (fileNameA < fileNameB) return -1;
if (fileNameA > fileNameB) return 1;
return 0;
}
});
sortedPages = sortedPages.concat(currData);
}
});
return sortedPages;
}
//数量统计部分
let i = [pages.length,
toPublishPages.length,
publishPages.length,
pages.file.etags.distinct().length];
dv.paragraph(`共有 **${i[0]}** 篇相关笔记,未发布**${i[1]}** 篇,已发布**${i[2]}** 篇,标签 **${i[3]}** 个`);
// 所有的标签
dv.paragraph(pages.file.tags.distinct()
.map(t => {return `[${t}](${t})`})
.array().sort().join(" | "));
// 按照层级循环遍历根目录下的子文件夹
for (const i of filePaths) {
// 输出三级标题,有序显示当前子文件夹名称
dv.header(3, `${loopCount} : ${i.key}`);
// 动态查询每个子文件夹下的已发布页面
let currentDvPages = dv.pages(`"${path}/${i.key}"`).filter(a => a.publish == true);
// 调用 mySort 函数对当前子文件夹的页面进行排序
const sortedPages = mySort(currentDvPages, letters, zh);
// 输出当前子文件夹的排序结果
if (sortedPages.length > 0) {
table(cols,sortedPages);
} else {
dv.paragraph(` ${i.key} 下没有符合条件的文件`);
}
dv.paragraph("---"); // 添加分隔线,区分不同子文件夹的输出
// 循环计数器递增
loopCount++;
}
//输出表格,可替换成您实际yaml属性
function table(cols,pages) {
dv.table(cols,pages
.map(p => ([
p.file.link,
p.publish,
p.tags,
p.status,
moment().diff(moment(p.created), 'days'),
p.created
]))
);
}
脚本功能总结
- 统计指定目录下文件数量
- 统计标签数量并显示标签内容
- 文件按照子文件夹分组显示
- 文件自定义排序(优先数字,然后字母,最后汉字)
- 文件信息表格化输出,一览无余
- 计算出笔记创建天数
自定义修改
以上脚本根据本人的知识库编写,如需自定义,可参照注释自行修改。