Note: for my purposes, a MOC is just a table of contents. I’m organizing my vault w/ a very basic IMF structure:
- each directory has a MOC which contains a list of internal links to notes in the same directory and/or other MOCs in child directories.
I got tired of updating my MOCs every time I added a new note or MOC so I wrote some code to update them for me (Note: I didn’t really write a whole plugin, I just pulled the code for the very awesome Templater plugin and added to it.
Here’s the Templater function I added code to:
async append_template_to_active_file(template_file: TFile): Promise<void> {
const active_view =
this.app.workspace.getActiveViewOfType(MarkdownView);
if (active_view === null) {
log_error(
new TemplaterError("No active view, can't append templates.")
);
return;
}
const running_config = this.create_running_config(
template_file,
active_view.file,
RunMode.AppendActiveFile
);
const output_content = await errorWrapper(
async () => this.read_and_parse_template(running_config),
"Template parsing error, aborting."
);
// errorWrapper failed
if (output_content == null) {
return;
}
const editor = active_view.editor;
const doc = editor.getDoc();
doc.replaceSelection(output_content);
// CODE I ADDED
const newFileIsMOC = template_file.name.includes("MOC")
let mocToUpdate
if (newFileIsMOC) {
mocToUpdate = active_view.file.parent.parent.children.filter(f => f.name.includes("MOC"))[0]
} else {
mocToUpdate = active_view.file.parent.children.filter(f => f.name.includes("MOC"))[0]
}
if (mocToUpdate) {
const linkTitle = newFileIsMOC ? active_view.file.basename.split('-')[1].trim() : active_view.file.basename
const linkPath = active_view.file.path
const mocToUpdateContent = (await this.app.vault.read(mocToUpdate)).trimEnd()
const shouldAddNewLine = !((mocToUpdateContent.slice(mocToUpdateContent.length - 2)).match(/\d+\./))
const newMocListItem = `${ shouldAddNewLine ? "\n1." : ""} [[${linkPath}|${linkTitle}]]`
const newMocToUpdateContent = mocToUpdateContent + newMocListItem
try {
await this.app.vault.modify(mocToUpdate, newMocToUpdateContent)
new Notice(`updated ${mocToUpdate.name}`)
} catch(e) {
new Notice(`error updating MOC: ${e}`)
}
}
// END OF CODE I ADDED
await this.plugin.editor_handler.jump_to_next_cursor_location(active_view.file, true);
}
This works fine but I wonder if any folks have ideas for how I might improve it.
- I chose to tack this functionality onto the action of applying a template to file b/c at that point I know if the new file is meant to be a note or a MOC. Is there another point when I could make that determination? Like maybe I could setup some kind of pre-commit hook that would update the MOCs everytime I commit changes to my vault? Any other ideas?
- I would like to extract this functionality from Templater if possible (i.e. so I don’t have to re-insert it everytime I update the plugin), is there an event I could listen for to trigger the MOC update? Maybe I could fire an event in Templater and listen for the event in a different plugin?
Any thoughts/feedback would be appreciated!