A note-taking app inspired by nb
at main 107 lines 2.4 kB view raw
1import * as frontMatter from "@std/front-matter"; 2import { Notebook } from "./notebook.ts"; 3 4export interface BaseEntry { 5 notebook: Notebook; 6 folders: string[]; 7 filename: string; 8 title: string; 9 lastModified: Date; 10 pinned: boolean; 11} 12 13export interface TodoEntry extends BaseEntry { 14 type: "todo"; 15 status: "open" | "closed"; 16} 17 18export type GenericEntryType = 19 | "note" 20 | "directory" 21 | "bookmark" 22 | "image" 23 | "file"; 24export interface GenericEntry extends BaseEntry { 25 type: GenericEntryType; 26} 27 28export type EntryType = GenericEntryType | "todo"; 29export type Entry = TodoEntry | GenericEntry; 30 31export interface NoteContents { 32 // deno-lint-ignore no-explicit-any 33 attrs?: any; 34 body: string; 35} 36 37export function suffixFor(filename: string): string { 38 switch (inferredType(filename)) { 39 case "bookmark": 40 return ".bookmark.md"; 41 case "todo": 42 return ".todo.md"; 43 default: 44 return ".md"; 45 } 46} 47 48export function inferredType(filename: string): EntryType { 49 if (filename.endsWith(".bookmark.md")) { 50 return "bookmark"; 51 } else if (filename.endsWith(".todo.md")) { 52 return "todo"; 53 } else if ( 54 [".jpg", ".jpeg", ".png", ".gif"].some((ext) => filename.endsWith(ext)) 55 ) { 56 return "image"; 57 } else { 58 return "note"; 59 } 60} 61 62export function getRawTitle(content: string): string | null { 63 if (frontMatter.test(content)) { 64 const extract = frontMatter.extractYaml(content); 65 const title = (extract.attrs as { title?: string }).title; 66 if (title != null) return title; 67 } 68 const [firstLine] = content.split("\n", 1); 69 if (firstLine.startsWith("# ")) { 70 return firstLine.slice(2); 71 } 72 return null; 73} 74 75export function getTitleFor(item: string, content: string): string { 76 return getRawTitle(content) ?? 77 `${item} · "${content.split("\n", 1)[0]}"`; 78} 79 80export function iconForEntry(entry: Entry): string { 81 let icon = ""; 82 if (entry.pinned) { 83 icon = "📌 "; 84 } 85 switch (entry.type) { 86 case "bookmark": 87 icon += "🔖 "; 88 break; 89 case "directory": 90 icon += "📂 "; 91 break; 92 case "todo": 93 icon += entry.status === "open" ? "✔️ " : "✅ "; 94 break; 95 case "note": 96 break; 97 case "image": 98 icon += "🖼️ "; 99 break; 100 case "file": 101 icon += "📄 "; 102 break; 103 default: 104 entry satisfies never; 105 } 106 return icon; 107}