'use strict'; // Checklist items (`- [ ] text`) across the notes, and ticking one from outside its page. // A task is identified by its page and line number in the page's body (what vault.read returns), plus its text, // so a file that changed since the list was made is never edited blindly. const TASK = /^(\s*(?:>\s*)*[-*+]\s+)\[([ xX])\](\s+)(.*)$/; const DUE = /(?:📅|\bdue:|\[due::)\s*(\d{4}-\d{2}-\d{2})/; const TAG = /(?:^|\s)#([\p{L}\p{N}_/-]*[\p{L}_/-][\p{L}\p{N}_/-]*)/gu; // Line indexes inside ``` / ~~~ fences are not tasks. function* lines(body) { let fence = null; const all = String(body || '').split('\n'); for (let i = 0; i < all.length; i++) { const f = all[i].match(/^\s*(```|~~~)/); if (f) { fence = fence === f[1] ? null : fence || f[1]; continue; } if (!fence) yield [i, all[i]]; } } // [{ id, title, icon, line, done, text, due, tags, depth }] for every task on every page (boards and canvases excluded: // a board's cards are its own thing). function findTasks(pages) { const out = []; for (const p of pages) { if (!p.exists || p.kind === 'canvas' || /\.canvas$/i.test(p.id)) continue; if (p.props && p.props['kanban-plugin']) continue; for (const [line, text] of lines(p.body)) { const m = text.match(TASK); if (!m) continue; const body = m[4].trim(); if (!body) continue; const tags = new Set((p.tags || []).map(String)); for (const t of body.matchAll(TAG)) tags.add(t[1]); const due = body.match(DUE); out.push({ id: p.id, title: p.title, icon: p.icon || null, line, done: m[2] !== ' ', text: body, due: due ? due[1] : '', tags: [...tags], depth: Math.floor((m[1].match(/^\s*/)[0].replace(/\t/g, ' ').length) / 2) }); } } return out; } // The body with the task at `line` ticked or unticked; null if the line is no longer that task. function setTask(body, line, text, done) { const all = String(body || '').split('\n'); const m = all[line] && all[line].match(TASK); if (!m || m[4].trim() !== String(text).trim()) return null; all[line] = m[1] + (done ? '[x]' : '[ ]') + m[3] + m[4]; return all.join('\n'); } module.exports = { findTasks, setTask };