This commit is contained in:
2026-03-28 10:55:42 -04:00
commit 6a2d0cffd6
21 changed files with 2175 additions and 0 deletions

85
src/daily-notes.ts Normal file
View File

@ -0,0 +1,85 @@
import { App, Notice, TFile } from 'obsidian';
import type { Task } from './types';
import { DAILY_NOTE_TASKS_HEADING } from './constants';
// obsidian-daily-notes-interface re-exports moment from Obsidian's bundle.
// We import it this way so esbuild treats moment as external.
declare const moment: (date?: unknown) => {
format(fmt: string): string;
};
interface DailyNotesInterface {
appHasDailyNotesPluginLoaded(app: App): boolean;
getDailyNote(
date: ReturnType<typeof moment>,
notes: Record<string, TFile>
): TFile | null;
createDailyNote(date: ReturnType<typeof moment>): Promise<TFile>;
getAllDailyNotes(): Record<string, TFile>;
}
let dni: DailyNotesInterface | null = null;
async function getDni(): Promise<DailyNotesInterface> {
if (!dni) {
dni = await import('obsidian-daily-notes-interface') as unknown as DailyNotesInterface;
}
return dni;
}
/**
* Append a completed task (and its notes) to the `#### Tasks` section
* of today's daily note, creating the section and/or the note if needed.
*/
export async function appendTaskToDailyNote(task: Task, app: App): Promise<void> {
const lib = await getDni();
if (!lib.appHasDailyNotesPluginLoaded(app)) {
new Notice(
'YAOTP: Daily Notes plugin is not enabled. ' +
'Please enable it in Settings → Core plugins.'
);
return;
}
const all = lib.getAllDailyNotes();
// moment is available as a global in Obsidian's runtime
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const today = (window as any).moment();
let file: TFile | null = lib.getDailyNote(today, all);
if (!file) {
file = await lib.createDailyNote(today);
}
const existing = await app.vault.read(file);
const appended = buildAppendedContent(existing, task);
await app.vault.modify(file, appended);
}
function buildAppendedContent(existing: string, task: Task): string {
const taskLine = `- [x] ${task.text}`;
const notesBlock =
task.notes.length > 0 ? '\n\n' + task.notes.join('\n') : '';
const entry = taskLine + notesBlock;
const headingIndex = existing.lastIndexOf(DAILY_NOTE_TASKS_HEADING);
if (headingIndex === -1) {
// Section doesn't exist — append it at the end
const base = existing.trimEnd();
return base + (base.length > 0 ? '\n\n' : '') + DAILY_NOTE_TASKS_HEADING + '\n\n' + entry + '\n';
}
// Section exists — insert after heading and any existing items
const afterHeading = existing.slice(headingIndex + DAILY_NOTE_TASKS_HEADING.length);
// Find where the next same-or-higher-level heading starts (if any)
const nextHeadingMatch = afterHeading.match(/\n#{1,4} /);
const insertionRelative = nextHeadingMatch?.index ?? afterHeading.length;
const before = existing.slice(0, headingIndex + DAILY_NOTE_TASKS_HEADING.length);
const sectionContent = afterHeading.slice(0, insertionRelative).trimEnd();
const after = afterHeading.slice(insertionRelative);
return before + sectionContent + '\n\n' + entry + (after.length > 0 ? '\n' + after : '\n');
}