Initial
This commit is contained in:
85
src/daily-notes.ts
Normal file
85
src/daily-notes.ts
Normal 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');
|
||||
}
|
||||
Reference in New Issue
Block a user