交流向实验性 QuickAdd 批量重命名小标题防止双链断裂

注:老代码了,请更多参考思路。


基本配置参 QuickAdd JS & Templater JS 简介及相互修改“QuickAdd Capture 加载内部代码”。

效果 GIF,点击展开

选区需覆盖标题前 # 号。全文替换 Ctrl A 全选即可。

20240222_110417

预填了一个格式化序号便于调试。实际使用多半用来批量改错别字。

第一个填空输入希望作用的标题级别或级别范围。第二个输入正则。第三个输入替换函数。

js quickadd 代码
let rgx = '/.*/', form = '`$&-${i+1}`'; const prompt = (str, holder, value)=> this.quickAddApi.inputPrompt(str, holder, value)
, { editor: Editor, file } = app.workspace.activeEditor, lv = await prompt('级别', '1-6', '1-6')
, confirm = async file=> { let r = []
  , repChan = (raw, isRef)=> { chans.map(chan=> {
    let rgx = new RegExp(isRef ? `\\[\\[.+?#${chan[0]}.*?]]` : `^#{${chan[2]}} ${chan[0]}$`, 'gm')
    raw = raw.replace(rgx, m=> m.replace(chan[0], chan[1])) }); return raw }, test = chans[0].heading
  do { rgx = await prompt(`正则`, rgx, rgx); if (!rgx) return; form = await prompt(`替换`, form, form) } while (!form)
  if (await this.quickAddApi.yesNoPrompt(test, [test].map((p, i)=> test.replace(eval(rgx), eval(form))))) {
    chans = chans.filter(p=> p.level >= lv.slice(0, 1) && p.level <= lv.slice(-1))
      .map((p, i)=> [p.heading, p.heading.replace(eval(rgx), eval(form)), p.level])
    app.fileManager.iterateAllRefs((rPath, rbj)=> {
      if (app.metadataCache.getFirstLinkpathDest(rbj.link.split('#')[0], rPath)?.path == file.path) r.includes(rPath) || r.push(rPath)
    }); r.map(async rPath=> await app.vault.process(app.vault.getAbstractFileByPath(rPath), raw=> repChan(raw, 1)))
    setTimeout(()=> Editor.replaceSelection(repChan(Editor.getSelection(), 0)), 50)
  } else confirm(file)
}, hds = app.metadataCache.getFileCache(file).headings; if (!hds) return; let chans = hds.filter(hd=>
  hd.position.end.line >= Editor.getCursor('from').line && hd.position.end.line <= Editor.getCursor('to').line
); if (!chans[0]) { new Notice('无选中', 1000); return }; confirm(file)

Ob“重命名当前小标题”命令无法做到的这个也无法做到。

比如同文档同名标题,引用时可以采用类似路径的格式做到区分,
【已解决】为什么引用文档内的同名标题永远显示第一个 #3

但重命名希望同步更新反向链接时,使用 Ob 内置“重命名当前小标题”命令无法区分,见下:

imageimage

测试结果能看到 Ob 内置的命令修改的是同文档同名二级标题的引用。

1 个赞

this表示的是当前对象 this.file就指在使用这段代码的文件 没有特别研究过ob 单纯从编程js编程语言角度来分析

谢谢,主要是不知道怎么上溯这些 this.。
有些能猜出来,比如截图中 n.fileManager.iterateAllRefs() 的 n 是 app。

截图来源开发控制台 - 源代码 Sources - obsidian.md - app.js。

目前感觉,Ob 官方的“重命名当前小标题”命令也是通过检索全库文档内容正则查找替换实现,并未存储额外的链接信息来控制,这可能是为什么对于同文档同名标题,即使引用时已链接到正确的标题,官方命令也无法重命名正确的引用链接。

若确实如此,#1 代码和官方的逻辑便是一致的。

但一是我不能肯定,二是官方的更有保障,谨慎点总没错。