我在确认一下吧,其实我用getAllLoadedFiles 的目的是希望把文件和目录分离出来,分别统计多少文件发生变化,哪些目录(因为其中文件变化)而发生变化。
真是奇怪的需求啊 ,我还是有点晕,文件和文件夹是分两个表,分别按时间排序吗
是的,我的需求就是分成两个表来统计啊,不是在同一个表里的。
现在的统计文件的代码和效果图如下:
const afiles = await app.vault.getFiles();
const files = dv.array(afiles).filter(p=> p.extension != 'md').sort(p=>moment(p.stat.mtime),'desc');
dv.table(["文件名("+files.length+"个)","文件夹","文件链接","修改时间","距离今天"], files.map(p=>[p.name,p.parent.path,dv.fileLink(p.path,false,p.basename),moment(p.stat.mtime).format("LL"),new moment().diff(moment(p.stat.mtime),'days')]))
大神指导一下,文件夹监控怎么写?
注释dataviewjs loop下面一行的p.file.frontmatter.date换成p.date试试
这样看看行不行吧
let afiles = dv.array(app.vault.getFiles()).filter(p=> p.extension != 'md').sort(p=>moment(p.stat.mtime),'desc');
dv.table(["文件名("+afiles.length+"个)","文件夹","文件链接","修改时间","距离今天"], afiles.map(p=>[p.name,p.parent.path,dv.fileLink(p.path,false,p.basename),moment(p.stat.mtime).format("LL"),moment().diff(moment(p.stat.mtime),'days')]))
// dv.table(["文件名("+afiles.length+"个)","文件夹","修改时间","距离今天"], afiles.map(p=>[dv.fileLink(p.path,false,p.name),p.parent.path,moment(p.stat.mtime).format("LL"),moment().diff(moment(p.stat.mtime),'days')]))
let folders = [];
let time = [];
afiles.forEach(p=>{
if(!folders.includes(p.parent.path)){
folders.push(p.parent.path)
time.push(p.stat.mtime)
}
})
dv.table(["文件夹("+folders.length+"个)","修改时间","距离今天"],folders.map(p=>app.vault.getAbstractFileByPath(p)).map((p,i)=>[p.name,moment(time[i]).format("LL"),moment().diff(moment(time[i]),'days')]))
文件夹的时间用的是该文件夹里时间最近的文件,因为昨天看错了,文件夹确实没有.stat.mtime 属性,昨天金工实习眼睛都干花了
感谢大佬回复,但这个方法不行。我又尝试了你以前的回复,问题解决了
dv.span("😍")
const calendarData = {
year: 2023,
colors: {
blue: ["#8cb9ff","#69a3ff","#428bff","#1872ff","#0058e2"], // first entry is considered default if supplied
green: ["#c6e48b","#7bc96f","#49af5d","#2e8840","#196127"], }, showCurrentDayBorder: true, // (optional) defaults to true
defaultEntryIntensity: 1, // (optional) defaults to 4
intensityScaleStart: 1, // (optional) defaults to lowest value passed to entries.intensity
intensityScaleEnd: 66, // (optional) defaults to highest value passed to entries.intensity
entries: [] }
for(let page of dv.pages('').groupBy(p=>moment(Number(p.file.cday)).format('YYYY-MM-DD'))){
calendarData.entries.push({
date: page.key,
color: "green",
intensity: page.rows.length,
content: page.rows.length }) }
renderHeatmapCalendar(this.container, calendarData)
嗯,确实是疏漏了,不能直接拿这玩意分组。
如果你想用yaml的自定义的时间属性可以用 moment(p.date.ts).format(‘YYYY-MM-DD’) 或 moment(Number(p.date)).format(‘YYYY-MM-DD’)
感谢感谢,这样显示的是对的。
如果要筛选指定二级标题下的tasks且不用正则,我一开始想的是用tasks.section.subpath去和.heading获取的所有level 2+标题比对,然后看比对到的标题是否是目标标题或它的次级标题。但是因为subpath只能拿到这个task直属section的标题,看不到更高level的父级标题,所以如果不同父标题下出现了同名的次级标题,筛选就会有误。大佬有更好的建议么
谢谢大佬的提议,我不太在意是不是在子标题下。按这个方向写了一版,目前看起来可以正常工作,就是啰嗦了点
let files = dv.pages('"02-Daily Notes" or "03-Meetings"')
.filter(p=>p.file.tasks.where(t => !t.completed).length!=0)
.sort(p => p.file.name)
function isWithinRanges(num, arr) {
for (let i = 0; i < arr.length; i += 2) {
if (num >= arr[i] && num <= arr[i + 1]) {
return true;
}
}
return false;
}
let targetHeader = `[[${dv.current().file.name}]]`
let tks = files.map(p => {
let tf = app.vault.getAbstractFileByPath(p.file.path)
let header = app.metadataCache.getFileCache(tf)
.headings
if (!header) return
let hRange = [] // 目标标题覆盖范围的始末行数
let t = [] // 目标标题下的task
let b = false
for (let i of header) {
if (b && i.level == 2) {
hRange.push(i.position.start.line)
b = false
}
if (i.heading == targetHeader && i.level == 2) {
hRange.push(i.position.start.line)
b = true
}
}
if (hRange.length > 0) {
if (hRange.length % 2 == 1) hRange.push(100000000)
let tasks = p.file.tasks
for (let j of tasks) {
if (isWithinRanges(j.line, hRange)) t.push(j)
}
}
return t.length == 0 ? false : [p.file.link, t]
})
.filter(p => p)
dv.table(['Date','Tasks'],files.map(p=>{
let div = dv.container.createEl('div');
if (tks.length > 0) {
for (let t of tks) {
if (t[0] == p.file.link) {
dv.api.taskList(t[1], 0, div, this.component, this.currentFilePath);
return [p.file.link,div];
}
}
}
}))
能实现就很好了,越是定制化的功能,代码就越麻烦。
请问图片如果有进行大小调整需要怎么修改吗?
例如
![[99-Attachment/local_images/1.jpeg]]可以渲染出来
![[99-Attachment/local_images/1.jpeg|500]]就无法渲染了
噢噢我知晓了,根据gpt给的方案,将正则修改为
x = x.replace(/![[(.+?)(?:|(\d+))?]]/g, function(match, p1)
就可以解决原先提出的问题
同时修改返回值,加入 height="400",可以固定渲染出来的图片的高度(如果宽度width)
return "<img src=\""+app.vault.adapter.basePath+"/"+p1+"\" height=\"400\">"
是的是的,我之前没有放在格式框内,显示有问题。修改了一下。
目前是通过dv.paragraph进行渲染,请问这个可以和dv.table或者dv.list相结合吗?
类似dv.table(file.name,file.figure)的效果?或者包含其他YAML区中的信息?
例如,
文件1 文件1.infor 文件1.figure
文件2 文件2.infor 文件2.figure
…
目前的显示效果是一股脑的图片,没有文件信息
文件1.figure
文件2.figure
…
需要这个功能的场景:监控文件变化后,对于新接收的pdf文件,我会根据需要用acrobat打开文件并进行标注。
通过dataviewjs检索文件后,如何才能实现“使用默认应用中打开文件”这个功能呢?
就像在文件列表的文件上调用“使用默认应用中打开”。
测试一个折中做法,直接在文件链接上可以使用右键命令,和文件列表上使用效果是一样的。
let afiles = dv.array(app.vault.getFiles()).filter(p=> p.extension != 'md').sort(p=>moment(p.stat.mtime),'desc');
dv.table(["文件名("+afiles.length+"个)","文件夹","默认打开","修改时间","距离今天"], afiles.map(p=>{
let div = dv.container.createEl('div',{text:'打开'})
div.onclick=()=>app.openWithDefaultApp(p.path)
return [dv.fileLink(p.path,false,p.name),p.parent.path,div,moment(p.stat.mtime).format("LL"),moment().diff(moment(p.stat.mtime),'days')]
}))
let folders = [];
let time = [];
afiles.forEach(p=>{
if(!folders.includes(p.parent.path)){
folders.push(p.parent.path)
time.push(p.stat.mtime)
}
})
dv.table(["文件夹("+folders.length+"个)","修改时间","距离今天"],folders.map(p=>app.vault.getAbstractFileByPath(p)).map((p,i)=>[p.name,moment(time[i]).format("LL"),moment().diff(moment(time[i]),'days')]))
有点丑陋,你可以加点css进去,反正默认打开的方法是 app.openWithDefaultApp(p.path)
非常感谢。
我还利用Obsidian的书签功能给关注的文件进行了标记,Obsidian的 书签功能 还是挺好用的,可以标记文件(含MD和非markdown文件)、文件夹、markdown文件中的标题。
新的问题来了,如何筛选打过书签的文件呢?
通过查阅dataview提供的页面文件的元数据说明,通过dv.pages().filter(f=>f.file.starred)
可以得到打过书签的笔记文件,但是附件文件(非markdown)是通过app.vault.getFiles().filter(f=>f.extension != 'md')
得到的,他们没有相应属性或者方法。
请问,有Obsidian内部函数或者属性来判断文件是否打过书签吗?