Find and embed all slides (or headings + text) that have the same tag

Problem setup

I have a master set of slides in a note. Each slide needs to be presented to one of three audiences:

  • Only Group 1,
  • Only Group 2,
  • Groups 1 & 2, or
  • No group.

I am using tags in every slide to keep track of the assigned groups: group1 group2 etc.

What I’m trying to do

I want to

  • Create a new note where only #group1 slides are embedded such that:
    • If I add/edit slides to the master set, they are reflected automatically in the child note.
    • The slides in the child note are in the same order as in the master set
    • The child note must be presentable ie I can click ‘Start presentation’ and present from it.
  • Repeat the above for #group2 only and a third note for both groups.
  • Extend the search to all notes in the vault.

Things I have tried

  • Obsidian query feature does not embed an entire slide.
  • Dataview cannot retrieve Headings + Text which a slide contains.
  • The extension Tagtracker is tangential to my need - it finds all notes containing the search tag, not sections/slides. Additionally, it embeds the slides as one giant embed which cannot be presented a slide at a time.

I believe this may require some JS magic but that’s not my forte. Any help would be magnificent. Thank you!

Here’s why your initial attempts fell short, and how you can get around them:

  • Standard queries won’t work: Obsidian’s native query and even standard Dataview can retrieve entire notes or list items, but they cannot process a note’s content at the level of individual “slides” separated by ---. To do that, we have to access the note as a full string and process it with JavaScript.
  • Embeds are not the answer: You’re also right that using embeds (![[...]]) will not work for a live presentation. The Obsidian presentation plugin relies on the --- separator to treat each section as a separate slide. Embeds are simply displayed as a single block of content and are not recognized as individual slides.

The best solution is to use DataviewJS to generate a brand new note for each group presentation. This note will have the correct format and will be fully presentable. The only trade-off is that this isn’t a “live” solution—you’ll need to re-run the script to update the presentation notes whenever you make changes to your master slides.

Here is the complete script that automates this entire process for you. Just paste it into a new note and it will create your three presentations automatically.

// Define the tags to filter the "master" notes.
const candidateMasterTags = ["#master"];
// Define the output configurations: tags and file names.
const targets = [
    [["#group1"], "Group 1 presentation.md"],
    [["#group2"], "Group 2 presentation.md"],
    [["#group1", "#group2"], "Group 1 & 2 presentation.md"]
];

// An async function to read the full content of a note from disk.
async function readSource(sourcePath) {
    const sourceFile = app.vault.getAbstractFileByPath(sourcePath);
    if (!sourceFile) {
        // Return an empty string if the file doesn't exist
        return "";
    }
    return await app.vault.cachedRead(sourceFile);
}

// A function to filter slides that contain ALL of the required tags.
function filterSlidesByTags(slides, requiredTags) {
    // Return a new list containing only the slides that include all required tags.
    return slides.filter(slide =>
        requiredTags.every(tag => slide.includes(tag))
    );
}

// --- Main script logic ---

// Get the notes that have any of the master tags.
const masters = dv.pages().filter(p =>
    p.file.tags.some(tag => candidateMasterTags.includes(tag))
);

// Get promises to read the content of all master notes.
const readPromises = masters.map(p => readSource(p.file.path));

// Wait for all files to be read and get their full content.
const allContents = await Promise.all(readPromises);

// Split each note's content into individual slides and create a flat list.
const allSlides = allContents.flatMap(content =>
    content.split("\n---\n")
);

// Iterate through each target configuration and generate a new presentation.
for (const [requiredSlideTags, targetFileName] of targets) {
    // Filter the slides to keep only those that have all required tags for the current target.
    const filteredSlides = filterSlidesByTags(allSlides, requiredSlideTags);

    // Join the filtered slides to create the new presentation content.
    const newPresentationContent = filteredSlides.join("\n---\n");

    // Get the file handle for the target path.
    const targetFile = app.vault.getAbstractFileByPath(targetFileName);

    if (targetFile) {
        // If the file exists, modify its content.
        await app.vault.modify(targetFile, newPresentationContent);
    } else {
        // If the file doesn't exist, create a new one.
        await app.vault.create(targetFileName, newPresentationContent);
    }

    // Display a message confirming the action.
    dv.el("p", `Presentation created at **${targetFileName}** with ${filteredSlides.length} slides.`);
}

Instructions

  1. Tag Your Master Notes: Add the #master tag to any note you want to include in your presentations. A good place to do this is in the note’s frontmatter.
  2. Create the Builder: Create a new note titled Presentation Builder (or any other name you prefer). Paste the complete DataviewJS code block into this note.
  3. Run the Script: Simply open the Presentation Builder note. The script will automatically run, find all notes tagged with #master, and create the new presentation files in your vault.
  4. Customize: You can easily edit the output filenames and the required tags for each presentation in the targets list at the beginning of the script. The new presentations will be saved to the root of your vault by default.

Thank you, this worked!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.