To get to the heading of your choice, you’ve got a least two options, and that is either to read the entire file scanning for the heading syntax, and then matching against your wanted heading, or use the metadata.
If you use getCache(filepath), you get access to the CachedMetadata, where you could get a record like the following:
This now shows that there is a heading at line 50, which you can easily get to when you’ve got a Editor view of your file. You could use getRange to find the heading text, and if you in addition also get the starting line of the next heading you know where to insert your text in front of, or where to set the cursor position with some accuracy.
Example showing code blocks
This code snippet is not directly related, but it could help you get started at navigating the metadata. In this variant I scan all of the files (picking out the first 15) and the show where there are code blocks in those files.
```dataviewjs
const result = []
for (let [fname, fcache] of Object.entries(dv.app.metadataCache.fileCache)) {
// fname is the filename
// fcache is the entry from metadataCache.fileCache
// mcache is the actual metadataCache.metadataCache entry
const mcache = dv.app.metadataCache.metadataCache[fcache.hash]
console.log(fcache)
// console.log(mcache.sections)
if ( mcache && !mcache.frontmatter &&
mcache.hasOwnProperty("sections") &&
mcache["sections"].some(s => s.type == "code")
) {
for (const section of mcache["sections"]) {
if (section.type == "code")
result.push([fname, section.position.start.line, section.position.end.line])
}
// console.log(mcache.sections)
}
//console.log(fname, " » ", fcache, "\n »» ", mcache)
// Bail out after the first 15 entries
if (result.length > 15) break
}
dv.table(["Filename", "Code start line", "Code end line"], result)
```
Example on changing a line
As part of a multi-menu of mine, I need to change the status of a given line (using a position object, orgPos
), where I also set the clipboard to the old line. It showcases one way of changing a line. Similar code could be used to set the cursor position at a given liven.
async function migrateTask(params, selected) {
const dv = params.app.plugins.plugins.dataview.api
const currFile = await params.app.workspace.getActiveFile()
const activeView = app.workspace.getActiveViewOfType(params.obsidian.MarkdownView)
if ( !activeView || !currFile ) {
window.alert("Couldn't find an active file/editor")
return -1
}
let orgPos = activeView.editor.getCursor()
const orgLine = activeView.editor.getLine(orgPos.line)
const today = moment().format("YYYY-MM-DD")
activeView.editor.setLine(orgPos.line,
orgLine.replace(/^(\s*-\s*)\[.\](.*?)\s*?/, "$1[" + selected.status + "]$2") + ` [[${ today }|🔜]]`)
params.quickAddApi.utility.setClipboard(
"\n" + orgLine + " " + dv.fileLink(currFile.path, false, "🔙").toString())
return " "
}
The last two lines of setting the clipboard, and returning " "
is just part of the inner workings of my multi-menu, so they can be ignored.
I’m glad to see that you’re finding your way, and please feel free to ask if there is something in particular you’re stuck on doing.