@@ -3,6 +3,23 @@ import { DailyNote, getDaysAgo, } from "../types/note";
33import { resolveMarkdownImages , unresolveMarkdownImages , } from "./images" ;
44import { getNoteDir , getNotePath , } from "./paths" ;
55
6+ const FRONTMATTER_RE = / ^ - - - \n ( [ \s \S ] * ?) \n - - - \n ? / ;
7+
8+ function parseFrontmatter ( raw : string , ) : { city : string | null ; body : string ; } {
9+ const match = raw . match ( FRONTMATTER_RE , ) ;
10+ if ( ! match ) return { city : null , body : raw , } ;
11+ const cityMatch = match [ 1 ] . match ( / ^ c i t y : \s * ( .+ ) $ / m, ) ;
12+ return {
13+ city : cityMatch ? cityMatch [ 1 ] . trim ( ) : null ,
14+ body : raw . slice ( match [ 0 ] . length , ) ,
15+ } ;
16+ }
17+
18+ function buildFrontmatter ( city : string | null | undefined , body : string , ) : string {
19+ if ( ! city ) return body ;
20+ return `---\ncity: ${ city } \n---\n${ body } ` ;
21+ }
22+
623async function ensureDir ( dir : string , ) {
724 const dirExists = await exists ( dir , ) ;
825 if ( ! dirExists ) {
@@ -42,9 +59,9 @@ export async function saveDailyNote(note: DailyNote,): Promise<void> {
4259 await ensureDir ( noteDir , ) ;
4360 const filepath = await getNotePath ( note . date , ) ;
4461 // Convert asset:// URLs back to relative paths, strip ZWSP, normalize blanks
45- let markdown = normalizeForSave ( stripNbsp ( unresolveMarkdownImages ( note . content , ) , ) , ) ;
46- if ( ! markdown . endsWith ( "\n" , ) ) markdown += "\n" ;
47- await writeTextFile ( filepath , markdown , ) ;
62+ let body = normalizeForSave ( stripNbsp ( unresolveMarkdownImages ( note . content , ) , ) , ) ;
63+ if ( ! body . endsWith ( "\n" , ) ) body += "\n" ;
64+ await writeTextFile ( filepath , buildFrontmatter ( note . city , body , ) , ) ;
4865}
4966
5067export async function loadDailyNote ( date : string , ) : Promise < DailyNote | null > {
@@ -56,11 +73,12 @@ export async function loadDailyNote(date: string,): Promise<DailyNote | null> {
5673 }
5774
5875 const raw = await readTextFile ( filepath , ) ;
76+ const { city, body, } = parseFrontmatter ( raw , ) ;
5977 // Strip from existing files, resolve asset paths, then
6078 // convert blank lines into ZWSP paragraphs so TipTap shows them.
61- const resolved = await resolveMarkdownImages ( stripNbsp ( raw , ) , ) ;
79+ const resolved = await resolveMarkdownImages ( stripNbsp ( body , ) , ) ;
6280 const content = preserveBlankLines ( resolved , ) ;
63- return { date, content, } ;
81+ return { date, content, city , } ;
6482}
6583
6684export async function createEmptyDailyNote ( date : string , ) : Promise < DailyNote > {
0 commit comments