Instantly share code, notes, and snippets.
Created
April 5, 2023 03:19
-
Star
(2)
2
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save eoureo/6068f4bf262f2d87d117c805b861fc0f to your computer and use it in GitHub Desktop.
Obsidian Templater - Change tags of multiple notes at once. 옵시디언 Templater - 한꺼번에 여러 노트의 태그들을 바꾸기(Feat. Dataview)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%_* | |
/* | |
@2023-04-05 12:00:00 | |
Obsidian Templater - Change tags of multiple notes at once. | |
1. Make a table with dataviewjs. | |
```dataviewjs | |
dv.table(["✓", "File", "mtime", "ctime", "tags", "folder"], dv.pages("#book") | |
.where(p => p.rating > 4) | |
.sort(b => b.file.mtime, "desc") | |
.map(b => ["<input type='checkbox'>", b.file.link, b.file.mtime, b.file.ctime, b.tags, b.file.folder])) | |
``` | |
2. Check the files to change tags. | |
3. Run Templater. | |
*/ | |
let files = []; | |
let trs = Array.from(app.workspace.activeLeaf.containerEl.querySelectorAll("tr")); | |
for(var ti = 0; ti < trs.length; ti++) { | |
let tr = trs[ti]; | |
if(tr.querySelector("input")?.checked) { | |
let href = tr.querySelector("a")?.getAttribute("href"); | |
if(href) { | |
let path = tp.obsidian.normalizePath(href); | |
files.push(path); | |
} | |
} | |
} | |
// import { App, Modal, Setting } from "obsidian"; | |
const Modal = tp.obsidian.Modal; | |
const Setting = tp.obsidian.Setting; | |
if(files.length < 1) { | |
let modal = new Modal(app); | |
modal.titleEl.setText("⚠ 에러 - 선택된 파일이 없습니다."); | |
modal.contentEl.setText("dataviewjs 코드 블록으로 리스트를 만들고 파일에 체크해야 합니다."); | |
modal.open(); | |
return; // 아무 것도 하지 않고 마치기 | |
} | |
class TagsModal extends Modal { | |
constructor(app, onSubmit) { | |
super(app); | |
this.onSubmit = onSubmit; | |
} | |
onOpen() { | |
const { contentEl } = this; | |
contentEl.createEl("h1", { text: "Change Tags of Notes" }); | |
contentEl.createDiv({ text: `Tags must be separated by ",".` }); | |
new Setting(contentEl) | |
.setName("Tags to add") | |
.addText((text) => { | |
text.inputEl.setAttribute("style", "width:100%"); | |
text.onChange((value) => { | |
this.tags_add = value | |
}) | |
}); | |
new Setting(contentEl) | |
.setName("Tags to delete") | |
.addText((text) => { | |
text.inputEl.setAttribute("style", "width:100%"); | |
text.onChange((value) => { | |
this.tags_del = value | |
}) | |
}); | |
new Setting(contentEl) | |
.addButton((btn) => | |
btn | |
.setButtonText("Cancel") | |
.setCta() | |
.onClick(() => { | |
this.close(); | |
})) | |
.addButton((btn) => | |
btn | |
.setButtonText("Change Tags") | |
.setCta() | |
.onClick(() => { | |
this.onChangeTags(); | |
})); | |
contentEl.createEl("h3", { text: "selected files: " + files.length }); | |
let dropDown = new tp.obsidian.DropdownComponent(contentEl); | |
dropDown.selectEl.setAttribute("style", "width:100%"); | |
for(var fi = 0; fi < files.length; fi++) { | |
dropDown.addOption(fi, (fi + 1) + " " + files[fi]); | |
} | |
this.dropDown = dropDown; | |
this.progress = contentEl.createEl("progress", {attr: {style:"width:100%", value:0, max: files.length}}); | |
let textarea = new tp.obsidian.TextAreaComponent(contentEl); | |
console.log("textarea"); | |
console.dir(textarea); | |
textarea.inputEl.setAttribute("style", "width:100%;height:5em;"); | |
this.textarea = textarea; | |
} | |
onClose() { | |
let { contentEl } = this; | |
contentEl.empty(); | |
} | |
async onChangeTags() { | |
if(!this?.tags_add && !this?.tags_del) { | |
new Notice(`Input tags!`); | |
return; | |
} | |
let tags_add = []; | |
if(this?.tags_add) { | |
tags_add = this.tags_add.split(",").map(tag => tag.trim()); | |
} | |
let tags_del = []; | |
if(this?.tags_del) { | |
tags_del = this.tags_del.split(",").map(tag => tag.trim()); | |
} | |
let log = "====================\n"; | |
log += "tags add: " + tags_add.join(", ") + "\n"; | |
log += "tags del: " + tags_del.join(", ") + "\n"; | |
log += "--------------------\n" | |
log += "Start: " +new Date().toString() + "\n"; | |
this.textarea.inputEl.value += log; | |
for(var fi = 0; fi < files.length; fi++) { | |
this.dropDown.setValue(fi); | |
let path = files[fi]; | |
let tfile = app.vault.getAbstractFileByPath(path); | |
await app.fileManager.processFrontMatter(tfile, (fm) => { | |
let tags = fm["tags"] ? fm["tags"] : []; | |
let tags_changed = false; | |
// 태그 더하기. | |
tags_add.forEach(tag => { | |
if (!tags.includes(tag)) { | |
tags.push(tag); | |
tags_changed = true; | |
} | |
}); | |
// 태그 지우기. | |
tags_del.forEach(tag => { | |
let index = tags.indexOf(tag); | |
if (index > -1) { | |
tags.splice(index, 1); | |
tags_changed = true; | |
} | |
}); | |
if (tags_changed) { | |
fm["tags"] = tags; | |
} | |
}); | |
this.progress.value = fi + 1; | |
// await sleep(1000); | |
} | |
this.textarea.inputEl.value += "End: " +new Date().toString() + "\n"; | |
} | |
} | |
new TagsModal(this.app, async (result) => { | |
return; | |
}).open(); | |
return // 지금 노트에 변화 없이 끝냄 | |
-%> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
여러 노트 파일을 선택하여 frontmatter tags 키 값에 한꺼번에 새 태그들을 넣거나 이미 있는 태그들을 지울 수 있도록 했습니다.
데이터뷰로 노트 목록(체크 박스를 넣음)을 만들고 템플레이터로 태그를 바꾸는 방법이 나을 것 같아 만들어 봤습니다.
옵시디언 - 한꺼번에 여러 노트의 태그들을 바꾸기(Feat. 템플레이터 & 데이터뷰)
https://eoureo.tistory.com/14
제 블로그에서 자세한 내용을 볼 수 있습니다.