From e8cb9b93fef622a754d7b40408f46cd97f04d908 Mon Sep 17 00:00:00 2001 From: afiqzudinhadi Date: Thu, 30 Jul 2026 12:37:52 +0800 Subject: [PATCH] fix(watchlist): strip surrounding quotes from prev user fields (notion_url round-trip) --- packages/obsidian/src/watchlist/build.ts | 9 +++++---- packages/obsidian/src/watchlist/parse.ts | 2 +- tests/watchlist-build.test.ts | 10 ++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/obsidian/src/watchlist/build.ts b/packages/obsidian/src/watchlist/build.ts index 4c994a4..e399f7b 100644 --- a/packages/obsidian/src/watchlist/build.ts +++ b/packages/obsidian/src/watchlist/build.ts @@ -1,4 +1,5 @@ import type { WatchlistRecord } from 'packages/obsidian/src/watchlist/schema'; +import { stripQuotes } from 'packages/obsidian/src/watchlist/parse'; export type TmdbDetail = Record; @@ -136,10 +137,10 @@ export function buildRecord(details: TmdbDetail, isMovie: boolean, prev: Record< } // ---- preserve user-managed fields ---- - let watchStatus = prev['watch_status'] || 'Unwatched'; - const rating = prev['rating'] || '0'; - const ratingStars = prev['rating_stars'] ?? ''; - const rawNotionUrl = prev['notion_url'] || ''; + let watchStatus = stripQuotes(prev['watch_status']) || 'Unwatched'; + const rating = stripQuotes(prev['rating']) || '0'; + const ratingStars = stripQuotes(prev['rating_stars']); + const rawNotionUrl = stripQuotes(prev['notion_url']); const notionUrl = rawNotionUrl === 'null' ? '' : rawNotionUrl; // quotedOrNull renders empty as literal `null` — don't round-trip it as a value // ---- TV watch-status rule: new episode aired since last sync ---- diff --git a/packages/obsidian/src/watchlist/parse.ts b/packages/obsidian/src/watchlist/parse.ts index 29a2eb8..041e484 100644 --- a/packages/obsidian/src/watchlist/parse.ts +++ b/packages/obsidian/src/watchlist/parse.ts @@ -22,7 +22,7 @@ export function extractMyNotes(body: string): string { return m ? m[1].trim() : ''; } -function stripQuotes(s: string | undefined): string { +export function stripQuotes(s: string | undefined): string { return (s ?? '').trim().replace(/^"|"$/g, ''); } diff --git a/tests/watchlist-build.test.ts b/tests/watchlist-build.test.ts index 14389a4..44d3780 100644 --- a/tests/watchlist-build.test.ts +++ b/tests/watchlist-build.test.ts @@ -80,6 +80,16 @@ describe('user-field preservation', () => { expect(r.ratingStars).toBe('⭐️⭐️⭐️⭐️'); expect(r.notionUrl).toBe('https://notion.so/x'); }); + test('quoted notion_url from raw frontmatter capture → quotes stripped', () => { + const prev = { notion_url: '"https://www.notion.so/x"' }; + const r = buildRecord(tvDetail, false, prev); + expect(r.notionUrl).toBe('https://www.notion.so/x'); + }); + test('null-sentinel notion_url still normalizes to empty', () => { + const prev = { notion_url: 'null' }; + const r = buildRecord(tvDetail, false, prev); + expect(r.notionUrl).toBe(''); + }); }); describe('watch-status rule (TV)', () => {