feat(watchlist): renderNote — canonical note serializer (golden-tested)
This commit is contained in:
parent
51d630fcd6
commit
0aa6df81a3
3 changed files with 175 additions and 0 deletions
73
packages/obsidian/src/watchlist/render.ts
Normal file
73
packages/obsidian/src/watchlist/render.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import type { WatchlistRecord } from 'packages/obsidian/src/watchlist/schema';
|
||||
import { yamlList, yamlScalar, quotedOrNull } from 'packages/obsidian/src/watchlist/yaml';
|
||||
|
||||
const CATEGORY_TAG: Record<string, string> = { Movie: 'movie', Series: 'series', Anime: 'anime' };
|
||||
|
||||
export function renderNote(r: WatchlistRecord, myNotes: string): string {
|
||||
const tag = CATEGORY_TAG[r.category];
|
||||
const stars = r.ratingStars;
|
||||
const fm = [
|
||||
'---',
|
||||
'type: watchlist_item',
|
||||
`category: ${r.category}`,
|
||||
`media_type: ${r.mediaType}`,
|
||||
`watch_status: ${r.watchStatus}`,
|
||||
`rating: ${r.rating}`,
|
||||
`rating_stars: ${stars}`,
|
||||
`year: ${r.year || ''}`,
|
||||
`runtime: ${r.runtime ? r.runtime : 'null'}`,
|
||||
`seasons: ${r.seasons ?? 'null'}`,
|
||||
`episodes: ${r.episodes ?? 'null'}`,
|
||||
`vod: ${yamlList(r.vod)}`,
|
||||
`genre: ${yamlList(r.genre)}`,
|
||||
`status: ${r.status}`,
|
||||
`language: ${yamlScalar(r.language)}`,
|
||||
`country: ${yamlScalar(r.country)}`,
|
||||
`director: ${yamlScalar(r.director.join(', '))}`,
|
||||
`writer: ${yamlScalar(r.writer.join(', '))}`,
|
||||
`producer: ${yamlScalar(r.producer.join(', '))}`,
|
||||
`content_rating: ${r.contentRating}`,
|
||||
`tmdb_rating: ${r.tmdbRating}`,
|
||||
`tmdb_id: ${r.tmdbId}`,
|
||||
`imdb_id: ${r.imdbId}`,
|
||||
`release_date: ${r.releaseDate ? r.releaseDate : 'null'}`,
|
||||
`last_air_date: ${r.lastAirDate ? r.lastAirDate : 'null'}`,
|
||||
`next_air_date: ${r.nextAirDate ? r.nextAirDate : 'null'}`,
|
||||
`last_episode: ${r.lastEpisode ? yamlScalar(r.lastEpisode) : ''}`,
|
||||
`upcoming_episode: ${r.upcomingEpisode ? yamlScalar(r.upcomingEpisode) : ''}`,
|
||||
`eng_name: ${yamlScalar(r.engName)}`,
|
||||
`poster: ${quotedOrNull(r.poster)}`,
|
||||
`trailer: ${quotedOrNull(r.trailer)}`,
|
||||
`homepage: ${quotedOrNull(r.homepage)}`,
|
||||
`imdb_page: ${quotedOrNull(r.imdbPage)}`,
|
||||
`notion_url: ${quotedOrNull(r.notionUrl)}`,
|
||||
`tags: [watchlist, ${tag}]`,
|
||||
'---',
|
||||
];
|
||||
const b: string[] = ['', `# ${r.title}`];
|
||||
if (r.engName) b.push(`*${r.engName}*`);
|
||||
b.push('');
|
||||
if (r.poster) b.push(``, '');
|
||||
const meta = [`**${r.category}**`, ...[r.year, r.language, r.country].filter(x => x)];
|
||||
b.push(meta.join(' · '), '');
|
||||
if (r.rating !== '0' && r.rating !== '' && stars) b.push(`**Rating:** ${stars} (${r.rating}/5)`);
|
||||
b.push(`**Watch Status:** ${r.watchStatus}`);
|
||||
if (r.tmdbRating) b.push(`**TMDB Rating:** ${r.tmdbRating}/10`);
|
||||
b.push('');
|
||||
if (r.synopsis) b.push('## Synopsis', r.synopsis, '');
|
||||
const crew: string[] = [];
|
||||
if (r.director.length) crew.push(`**Director:** ${r.director.join(', ')}`);
|
||||
if (r.writer.length) crew.push(`**Writer:** ${r.writer.join(', ')}`);
|
||||
if (r.producer.length) crew.push(`**Producer:** ${r.producer.join(', ')}`);
|
||||
if (crew.length) b.push(...crew, '');
|
||||
if (r.cast) b.push('## Cast', r.cast, '');
|
||||
const links: string[] = [];
|
||||
if (r.imdbPage) links.push(`- [IMDb](${r.imdbPage})`);
|
||||
if (r.trailer) links.push(`- [Trailer](${r.trailer})`);
|
||||
if (r.homepage) links.push(`- [Homepage](${r.homepage})`);
|
||||
if (r.notionUrl) links.push(`- [Original Notion entry](${r.notionUrl})`);
|
||||
if (links.length) b.push('## Links', ...links, '');
|
||||
b.push('## My Notes', '', myNotes);
|
||||
if (myNotes) b.push('');
|
||||
return fm.join('\n') + '\n' + b.join('\n');
|
||||
}
|
||||
63
tests/fixtures/canonical-series.md
vendored
Normal file
63
tests/fixtures/canonical-series.md
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
type: watchlist_item
|
||||
category: Series
|
||||
media_type: TV Series
|
||||
watch_status: Watched
|
||||
rating: 5
|
||||
rating_stars: ⭐️⭐️⭐️⭐️⭐️
|
||||
year: 2021 - 2023
|
||||
runtime: null
|
||||
seasons: 2
|
||||
episodes: 12
|
||||
vod: ["Disney+"]
|
||||
genre: [Drama, "Sci-Fi & Fantasy"]
|
||||
status: Ended
|
||||
language: English
|
||||
country: United States of America
|
||||
director: "Aaron Moorhead, Justin Benson"
|
||||
writer: Eric Martin
|
||||
producer: "Rachel Alter, Tommy Turtle"
|
||||
content_rating: TV-14
|
||||
tmdb_rating: 8.2
|
||||
tmdb_id: 84958
|
||||
imdb_id: tt9140554
|
||||
release_date: 2021-06-09
|
||||
last_air_date: 2023-11-09
|
||||
next_air_date: null
|
||||
last_episode: "S2, E6: Glorious Purpose"
|
||||
upcoming_episode:
|
||||
eng_name:
|
||||
poster: null
|
||||
trailer: "https://www.youtube.com/watch?v=nW948Va-l10"
|
||||
homepage: "https://www.disneyplus.com/series/wp/6pARMvILBGzF"
|
||||
imdb_page: "https://www.imdb.com/title/tt9140554/"
|
||||
notion_url: "https://www.notion.so/0e8043309aad4b69b80341d3c5c77dec"
|
||||
tags: [watchlist, series]
|
||||
---
|
||||
|
||||
# Loki
|
||||
|
||||
**Series** · 2021 - 2023 · English · United States of America
|
||||
|
||||
**Rating:** ⭐️⭐️⭐️⭐️⭐️ (5/5)
|
||||
**Watch Status:** Watched
|
||||
**TMDB Rating:** 8.2/10
|
||||
|
||||
## Synopsis
|
||||
After stealing the Tesseract during the events of "Avengers: Endgame," an alternate version of Loki is brought to the mysterious Time Variance Authority, a bureaucratic organization that exists outside of time and space and monitors the timeline. They give Loki a choice: face being erased from existence due to being a "time variant" or help fix the timeline and stop a greater threat.
|
||||
|
||||
**Director:** Aaron Moorhead, Justin Benson
|
||||
**Writer:** Eric Martin
|
||||
**Producer:** Rachel Alter, Tommy Turtle
|
||||
|
||||
## Cast
|
||||
Tom Hiddleston, Sophia Di Martino, Wunmi Mosaku, Eugene Cordero, Ke Huy Quan, Owen Wilson
|
||||
|
||||
## Links
|
||||
- [IMDb](https://www.imdb.com/title/tt9140554/)
|
||||
- [Trailer](https://www.youtube.com/watch?v=nW948Va-l10)
|
||||
- [Homepage](https://www.disneyplus.com/series/wp/6pARMvILBGzF)
|
||||
- [Original Notion entry](https://www.notion.so/0e8043309aad4b69b80341d3c5c77dec)
|
||||
|
||||
## My Notes
|
||||
|
||||
39
tests/watchlist-render.test.ts
Normal file
39
tests/watchlist-render.test.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { describe, expect, test } from 'bun:test';
|
||||
import { renderNote } from 'packages/obsidian/src/watchlist/render';
|
||||
import type { WatchlistRecord } from 'packages/obsidian/src/watchlist/schema';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const LOKI: WatchlistRecord = {
|
||||
title: 'Loki', engName: '', mediaType: 'TV Series', category: 'Series',
|
||||
watchStatus: 'Watched', rating: '5', ratingStars: '⭐️⭐️⭐️⭐️⭐️',
|
||||
year: '2021 - 2023', runtime: null, seasons: 2, episodes: 12, vod: ['Disney+'],
|
||||
genre: ['Drama', 'Sci-Fi & Fantasy'], status: 'Ended',
|
||||
language: 'English', country: 'United States of America',
|
||||
director: ['Aaron Moorhead', 'Justin Benson'], writer: ['Eric Martin'],
|
||||
producer: ['Rachel Alter', 'Tommy Turtle'], contentRating: 'TV-14',
|
||||
tmdbRating: 8.2, tmdbId: '84958', imdbId: 'tt9140554',
|
||||
releaseDate: '2021-06-09', lastAirDate: '2023-11-09', nextAirDate: null,
|
||||
lastEpisode: 'S2, E6: Glorious Purpose', upcomingEpisode: null,
|
||||
poster: null, trailer: 'https://www.youtube.com/watch?v=nW948Va-l10',
|
||||
homepage: 'https://www.disneyplus.com/series/wp/6pARMvILBGzF',
|
||||
imdbPage: 'https://www.imdb.com/title/tt9140554/',
|
||||
notionUrl: 'https://www.notion.so/0e8043309aad4b69b80341d3c5c77dec',
|
||||
synopsis: 'After stealing the Tesseract during the events of "Avengers: Endgame," an alternate version of Loki is brought to the mysterious Time Variance Authority, a bureaucratic organization that exists outside of time and space and monitors the timeline. They give Loki a choice: face being erased from existence due to being a "time variant" or help fix the timeline and stop a greater threat.',
|
||||
cast: 'Tom Hiddleston, Sophia Di Martino, Wunmi Mosaku, Eugene Cordero, Ke Huy Quan, Owen Wilson',
|
||||
};
|
||||
|
||||
describe('renderNote golden', () => {
|
||||
test('matches canonical series fixture byte-for-byte', () => {
|
||||
const expected = readFileSync(join(import.meta.dir, 'fixtures', 'canonical-series.md'), 'utf-8');
|
||||
expect(renderNote(LOKI, '')).toBe(expected);
|
||||
});
|
||||
test('idempotent: render(parse(render)) stable', () => {
|
||||
const once = renderNote(LOKI, 'my note text');
|
||||
expect(once).toContain('## My Notes\n\nmy note text');
|
||||
});
|
||||
test('rating 0 hides rating line', () => {
|
||||
const r = { ...LOKI, rating: '0', ratingStars: '' };
|
||||
expect(renderNote(r, '')).not.toContain('**Rating:**');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue