```` --- players: - "[[player1]]" - '[[player 2]]' - "[[player 3]]" - "[[player 4]]" adventure: Example Adventure --- # 📜 Adventures in Templating - Adventure Hub ## 📚 Chapter Links ```dataviewjs const currentFolder = dv.current().file.folder; const adventureFolder = `${currentFolder}/Adventure`; // Fetch pages from the "Adventure" folder const pages = dv.pages(`"${adventureFolder}"`).sort(p => p.file.name); // Output each note as an H4 link pages.forEach(p => dv.header(4, p.file.link)); ``` >[!success] Current Session: > ```dataviewjs > const pages = dv.pages('"Adventures/Example Adventure/Session Notes"') > .sort(p => p.file.ctime, 'desc') > .limit(1); > if (pages.length) { > dv.header(4, pages[0].file.link); > } > > > ``` ![[example_quicknotes]] ## 👥 Player Characters ```dataviewjs const players = dv.current().players; if (!players || players.length === 0) { dv.paragraph("No players found."); } else { const playerPages = players .map(player => dv.page(player)) .filter(p => p); dv.table( ["Player", "Species", "Class", "Level", "Max HP", "AC", "STR", "DEX", "CON", "INT", "WIS", "CHA"], playerPages.map(p => [ p.file.link, p.Species, p.Class, p.level, p.hp, p.ac, p.Strength, p.Dexterity, p.Constitution, p.Intelligence, p.Wisdom, p.Charisma ]) ); } ``` ## ⏳️ Takeaways ```dataviewjs const folderPath = "Adventures/Example Adventure/Session Notes"; // Function to extract text between specific headers const extractTakeaways = (content, startHeader, endHeader) => { const startPattern = new RegExp(`^#+\\s*${startHeader}\\s*`, "im"); const endPattern = new RegExp(`^#+\\s*${endHeader}\\s*`, "im"); const startMatch = content.match(startPattern); const endMatch = content.match(endPattern); if (!startMatch) return null; const startIndex = startMatch.index + startMatch[0].length; const endIndex = endMatch ? endMatch.index : content.length; return content.slice(startIndex, endIndex).replace(/^(#+.*|Notes last touched.*)$/gim, "").trim() || null; }; // Collect notes, extract takeaways, sort them, and build the table (async () => { let tableData = await Promise.all(dv.pages(`"${folderPath}"`) .map(async page => { const content = await dv.io.load(page.file.path); const takeaway = content ? extractTakeaways(content, "Takeaways", "Next Session") : null; return takeaway ? [page.file.name, takeaway] : null; })); // Filter out any null entries tableData = tableData.filter(row => row !== null); // Sort the sessions by the session number extracted from the file name (assuming "Session XX - Date" format) tableData.sort((a, b) => { const sessionNumberA = parseInt(a[0].match(/Session (\d+)/)?.[1] || 0, 10); const sessionNumberB = parseInt(b[0].match(/Session (\d+)/)?.[1] || 0, 10); return sessionNumberB - sessionNumberA; // Sort in descending order }); // Slice to get the latest 5 entries after sorting tableData = tableData.slice(0, 5); if (tableData.length > 0) dv.table(["Note", "Takeaway"], tableData); })(); ```