Coalesce headings into one file?

Hello all,
I’m a relatively new Obsidian user and would really like to know if there’s a solution to this use case that doesn’t require too much customization. I think it could be helpful to others-

Use case or problem

I would like to use Obsidian as a general daily journaling tool. Something I have been doing in Notion that has been extremely helpful is creating columns for general topics in my life (Health, Work, etc.), and jot down quick notes from the day that I would like to review. After some time, I can simply concat all of the daily notes for a particular topic into one page to get a summary of that section over time.

The daily notes function is perfect for this, however I do not see a way to collect these subheadings over time.

Proposed solution

Functionality that lets me extract all text under headings into one note, while preserving the date of entry.

For example, let’s say there are many daily notes in a folder with ISO formatted dates as file names. Within these files might be sections: # Health, containing some text blocks.

I would like to run a query or command that searches all files in {path}, and extracts all text under specified {heading} into a new note, separating each extraction with the filename.

The results would look like this:

# 2022-12-01

Some text content under {heading}

# 2022-12-13

More text content in another file under {heading}

Current workaround (optional)

I can use the embedded query functionality to get this, however, there doesn’t seem to be a way to extract the query results as markdown content.

Linking to a page with {heading} is not useful, because the linked mentions pane does not allow exporting/pasting either. I’d also like not to use tags, since these are reserved for other purposes.

IMO, this functionality would be a powerful tool to turn unstructured notes into focused bullet journals. Thoughts?

PS - I found two related plugins, but I don’t think any of them match the exact functionality I described

You can do this with Dataview.

Here is a working demo vault which you can download to test with:

:floppy_disk: Download demo vault

It will collect the sections under each of your requested daily note headings, and summarise them by day inside a single note:


And here’s the how-to guide. The latest version of this guide can always be found here.

Step 1:

Install Dataview, and turn on Javascript queries:

Step 2:

Create a new note and paste this code:

```dataviewjs
// Headings you would like to summarise the text for
const headings = ['Health', 'Mood']

// You can update this to filter as you like.
// Here it is only returning results inside the "Daily notes" folder
const pages = dv.pages('"Daily notes"')

const output = {}
headings.forEach(x => output[x] = [])
for (const page of pages) {
  const file = app.vault.getAbstractFileByPath(page.file.path)
  // Read the file contents
  const contents = await app.vault.read(file)
  for (let heading of headings) {
    // Sanitise the provided heading to use in a regex
    heading = heading.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&')
    const regex = `(^|\n)#+ ${heading}\r?\n(.*?)(\n#+ |\n---|$)`
    // Extract the summary
    for (const block of contents.match(new RegExp(regex, 'isg')) || []) {
      const match = block.match(new RegExp(regex, 'is'))
      output[heading].push({
        title: file.basename,
        text: match[2].trim()
      })
    }
  }
}
Object.keys(output).forEach(heading => {
  dv.header(1, heading)
  output[heading].forEach(entry => {
    dv.header(4, entry.title)
    dv.paragraph(entry.text)
  })
})
```

You’ll need to update the two variables headings and pages at the top to match the location and format of your own files.

2 Likes

Thank you for the quick and very helpful response! Your solution worked great and seems that with a little more js knowledge, bet I could add more search criteria and reformat it to whichever need.

Do you think this is worth pitching as a plugin feature? I could see it being very useful for folks who aren’t great with the js api

Personally I wouldn’t bother. It’s the kind of thing which is so specific to the individual user case that modifying the Javascript code directly is likely going to produce the best result. There’s also the fact that plugins need to be maintained to keep up-to-date with new Obsidian versions. (Dataview is highly likely to be maintained.)

Plus it’s a great excuse to learn a little bit of Javascript, which is always going to be a valuable addition to your skillset :wink: Codecademy is a great resource.

3 Likes

Hi this is fantastic! Thanks for putting it up here. From looking through forums a lot of people have been looking for something like this for ages. I don’t know much about dataviewjs but do you know if it’d be easy to turn the filenames into clickable links like with dataview lists?

Very easy :slight_smile: Just replace the current title with a markdown link:

output[heading].push({
  title: '[[' + file.basename + ']]',

This will output [[Note title]] just like any link you’d use in any note. It’s not complex at all to work with Javascript once you know the basics, and I do recommend the course linked above.

You can make it more explicit if you have notes with duplicate titles by using the full path and then the | character to add an alias:

output[heading].push({
  title: '[[' + file.path + '|' + file.basename + ']]',

That will output [[Full/Path/To/File.md|Note title]] just like you would create any normal link in your notes.

2 Likes

This is great, thanks a lot! Definitely interesting stuff!