Within a note, embed the paragraphs from other notes that link to it

Hello,

I wanted to share a datawiew snippet that has helped me a lot. With this snippet placed in a note, I am able to embed automatically the paragraphs from other notes that link to this note.

My current use case is the following.

I use daily notes. I store them as follows:

/Diary/YYYY/Notes/YYYY-MM-DD.md

During the day, if I do something regarding some project, or there is some random thing I want to write it down regarding some project, I add it to the daily note as follows:

- [[Link to project 1]]
    - Some thing regarding that project
        - Subpoint 
        - Subpoint
    - Another thing regarding the project

- [[Link to project 2]]
    - Some thing about project 2
    - Some thing extra about project 2

In my Vault, I have a folder for projects, as follows:
.
β”œβ”€β”€ Diary
β”‚ └── 2025
β”‚ └── Notes
β”‚ β”œβ”€β”€ 2025-05-07.md
β”‚ └── 2025-05-08.md
└── Projects
β”œβ”€β”€ P001-My Project 1
β”‚ β”œβ”€β”€ My Project 1.md
β”‚ └── Notes
β”‚ β”œβ”€β”€ Specific note related with project 1.md
β”‚ └── Another note specific of project 1.md
└── P002-My Project 2
β”œβ”€β”€ My Project 2.md
└── Notes
β”œβ”€β”€ Specific note related with project 2.md
└── Another note specific of project 2.md

The main note of a project is the note with the actual name of the project. For example: β€œMy Project 1.md”
Unrelated: The subfolder β€œNotes” of the Project is where I place some notes that are specific for that project and that have some entity.

In each project, the main note acts as an index. For example, it has a description of the project, the index of Tasks, and the β€œLogBook” of this project. In this section β€œLogBook” is where I use the snippet. What I want is to be able to read all the specific parts of the daily notes that I have written regarding that project. In descing order. In addition, if the paragraph is under another bullet point, it will show the full list of ancestors.

Example

Dataview Snippet

// Actual Note (complete relative path and name)
const currentFilePath = dv.current().file.path.replace('.md', '');
const currentFileName = dv.current().file.name;

// Search in folders with format: Diary/####/Notes
const notes = dv.pages('"Diary"').filter(n => /^Diary\/\d{4}\/Notes/.test(n.file.path)).sort(n => n.file.name, 'desc');

// Obtain specific context of bullet points (only parents and children of link)
async function getContexts(file, possibleLinks) {
    const content = await dv.io.load(file.path);
    if (!content) return [];

    const lines = content.split("\n");
    const contexts = [];

    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        const hasLink = possibleLinks.some(link => line.includes(`[[${link}]]`) || line.includes(`[[${link}|`));

        if (hasLink) {
            if (/^\s*[-*+]\s/.test(line)) {
                let currentIndent = line.match(/^\s*/)[0].length;

                // Capture only previous parents
                const parents = [];
                let indentTracker = currentIndent;
                for (let j = i - 1; j >= 0; j--) {
                    const parentLine = lines[j];
                    const parentIndent = parentLine.match(/^\s*/)[0].length;
                    if (/^\s*[-*+]\s/.test(parentLine) && parentIndent < indentTracker) {
                        parents.unshift(parentLine);
                        indentTracker = parentIndent;
                    }
                    if (parentIndent === 0) break;
                }

                // Capture current bullet and children
                const descendants = [line];
                const baseIndent = currentIndent;
                for (let j = i + 1; j < lines.length; j++) {
                    const childLine = lines[j];
                    const childIndent = childLine.match(/^\s*/)[0].length;
                    if (/^\s*[-*+]\s/.test(childLine)) {
                        if (childIndent > baseIndent) {
                            descendants.push(childLine);
                        } else if (childIndent <= baseIndent) {
                            break;
                        }
                    } else {
                        break;
                    }
                }

                contexts.push([...parents, ...descendants].join("\n"));
            } else if (line.trim() !== "") {
                let para = [line];
                let j = i - 1;
                while (j >= 0 && lines[j].trim() !== "") para.unshift(lines[j--]);
                j = i + 1;
                while (j < lines.length && lines[j].trim() !== "") para.push(lines[j++]);
                contexts.push(para.join("\n"));
            }
        }
    }

    return contexts;
}

// Possible link
const possibleLinks = [currentFileName, currentFilePath];

// Embed notes
const embeds = [];
for (let note of notes) {
    const contexts = await getContexts(note.file, possibleLinks);
    contexts.forEach(context => {
        embeds.push(`[[${note.file.path}|${note.file.name}]]\n> ${context.replace(/\n/g, "\n> ")}`);
    });
}

// Show results
dv.paragraph(embeds.length ? embeds.join('\n\n') : "_There are 0 references._");

I suggest you change this into Dataview JS Snippet, as it is JS and not DQL.

Otherwise - good job! :clap:

Cheers, Marko :nerd_face:

Sorry, but I can’t edit my post. I don’t see the option to do that.

1 Like

It’s not a problem. This is one of the form safety features: after a few posts, you get this β€œgod mode” :slight_smile: … one of the moderators will help and rename this for you.

Want you, friendly moderators? :slight_smile:

Cheers, Marko :nerd_face: