summaryrefslogtreecommitdiffhomepage
path: root/src/calendar/daily-notes.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/calendar/daily-notes.ts')
-rw-r--r--src/calendar/daily-notes.ts223
1 files changed, 0 insertions, 223 deletions
diff --git a/src/calendar/daily-notes.ts b/src/calendar/daily-notes.ts
deleted file mode 100644
index 2e66834..0000000
--- a/src/calendar/daily-notes.ts
+++ /dev/null
@@ -1,223 +0,0 @@
-import { App, TFile, Vault, WorkspaceLeaf } from "obsidian";
-import type { Moment } from "moment";
-
-const DATE_FORMAT = "YYYY-MM-DD";
-
-/**
- * Computes the vault-relative path for a daily note.
- * Format: {rootFolder}/{YYYY}/{MM}/{DD}/{YYYY-MM-DD}.md
- */
-export function getDailyNotePath(date: Moment, rootFolder: string): string {
- const year = date.format("YYYY");
- const month = date.format("MM");
- const day = date.format("DD");
- const filename = date.format(DATE_FORMAT);
- return `${rootFolder}/${year}/${month}/${day}/${filename}.md`;
-}
-
-/**
- * Looks up an existing daily note in the vault for the given date.
- * Returns null if the file does not exist.
- */
-export function getDailyNote(
- app: App,
- date: Moment,
- rootFolder: string,
-): TFile | null {
- const path = getDailyNotePath(date, rootFolder);
- return app.vault.getFileByPath(path);
-}
-
-/**
- * Creates a new daily note for the given date.
- * Creates parent folders ({rootFolder}/{YYYY}/{MM}/{DD}/) if they don't exist.
- * If a template path is provided and the template file exists, its content is
- * used with `{{date}}` placeholders replaced by the ISO date string.
- * Otherwise, a minimal file with date frontmatter is created.
- */
-export async function createDailyNote(
- app: App,
- date: Moment,
- rootFolder: string,
- template?: string,
-): Promise<TFile> {
- const path = getDailyNotePath(date, rootFolder);
- const dateStr = date.format(DATE_FORMAT);
-
- // Ensure parent folders exist
- const folderPath = path.substring(0, path.lastIndexOf("/"));
- await ensureFolderExists(app.vault, folderPath);
-
- // Resolve content
- let content: string;
- if (template !== undefined && template !== "") {
- const templateFile = app.vault.getFileByPath(template);
- if (templateFile !== null) {
- const raw = await app.vault.cachedRead(templateFile);
- content = raw.replace(/\{\{date\}\}/g, dateStr);
- } else {
- content = defaultDailyNoteContent(dateStr);
- }
- } else {
- content = defaultDailyNoteContent(dateStr);
- }
-
- return app.vault.create(path, content);
-}
-
-/**
- * Opens an existing daily note or creates one first, then opens it.
- * When `newLeaf` is true, opens in a new tab; otherwise reuses the current leaf.
- */
-export async function openDailyNote(
- app: App,
- date: Moment,
- rootFolder: string,
- opts: { newLeaf: boolean },
- template?: string,
-): Promise<void> {
- let file = getDailyNote(app, date, rootFolder);
- if (file === null) {
- file = await createDailyNote(app, date, rootFolder, template);
- }
-
- const leaf: WorkspaceLeaf = app.workspace.getLeaf(opts.newLeaf);
- await leaf.openFile(file);
-}
-
-/**
- * Scans the calendar root folder recursively and builds an index of all
- * daily notes, keyed by their ISO date string ("YYYY-MM-DD").
- *
- * Only files that match the expected `{YYYY}/{MM}/{DD}/{YYYY-MM-DD}.md`
- * structure within the root folder are included.
- */
-export function indexDailyNotes(
- app: App,
- rootFolder: string,
-): Map<string, TFile> {
- const index = new Map<string, TFile>();
- const root = app.vault.getFolderByPath(rootFolder);
- if (root === null) {
- return index;
- }
-
- // Pattern: rootFolder/YYYY/MM/DD/YYYY-MM-DD.md
- // After stripping rootFolder prefix, remainder is: YYYY/MM/DD/YYYY-MM-DD.md
- const datePathRegex = /^(\d{4})\/(\d{2})\/(\d{2})\/(\d{4}-\d{2}-\d{2})\.md$/;
-
- Vault.recurseChildren(root, (abstractFile) => {
- if (!(abstractFile instanceof TFile)) {
- return;
- }
- if (abstractFile.extension !== "md") {
- return;
- }
-
- const relativePath = abstractFile.path.substring(rootFolder.length + 1);
- const match = datePathRegex.exec(relativePath);
- if (match === null) {
- return;
- }
-
- const [, year, month, day, filename] = match;
- if (
- year === undefined ||
- month === undefined ||
- day === undefined ||
- filename === undefined
- ) {
- return;
- }
-
- // Verify the folder components match the filename
- const expectedFilename = `${year}-${month}-${day}`;
- if (filename !== expectedFilename) {
- return;
- }
-
- // Validate it's a real date
- const m = window.moment(filename, DATE_FORMAT, true);
- if (!m.isValid()) {
- return;
- }
-
- index.set(filename, abstractFile);
- });
-
- return index;
-}
-
-/**
- * Given a TFile, determines whether it lives in the daily note folder
- * structure and extracts the date if so.
- * Returns null if the file is not a recognized daily note.
- */
-export function getDateFromDailyNote(
- file: TFile,
- rootFolder: string,
-): Moment | null {
- // File must be under the root folder
- if (!file.path.startsWith(rootFolder + "/")) {
- return null;
- }
-
- const relativePath = file.path.substring(rootFolder.length + 1);
- const datePathRegex = /^(\d{4})\/(\d{2})\/(\d{2})\/(\d{4}-\d{2}-\d{2})\.md$/;
- const match = datePathRegex.exec(relativePath);
- if (match === null) {
- return null;
- }
-
- const [, year, month, day, filename] = match;
- if (
- year === undefined ||
- month === undefined ||
- day === undefined ||
- filename === undefined
- ) {
- return null;
- }
-
- const expectedFilename = `${year}-${month}-${day}`;
- if (filename !== expectedFilename) {
- return null;
- }
-
- const m = window.moment(filename, DATE_FORMAT, true);
- if (!m.isValid()) {
- return null;
- }
-
- return m;
-}
-
-// ---------------------------------------------------------------------------
-// Internal helpers
-// ---------------------------------------------------------------------------
-
-/**
- * Recursively creates folders for the given path if they don't already exist.
- */
-async function ensureFolderExists(vault: Vault, folderPath: string): Promise<void> {
- if (vault.getFolderByPath(folderPath) !== null) {
- return;
- }
-
- // Walk from root to deepest folder, creating each segment
- const segments = folderPath.split("/");
- let current = "";
- for (const segment of segments) {
- current = current === "" ? segment : `${current}/${segment}`;
- if (vault.getFolderByPath(current) === null) {
- await vault.createFolder(current);
- }
- }
-}
-
-/**
- * Returns the default content for a new daily note with date frontmatter.
- */
-function defaultDailyNoteContent(dateStr: string): string {
- return `---\ndate: ${dateStr}\n---\n`;
-}