From a35ee25f4c92148d0e09b7d17915588fbbf04bcc Mon Sep 17 00:00:00 2001 From: summerscar Date: Tue, 17 Dec 2024 18:35:39 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(article):=20sbs=20news?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../article/[slug]/_components/text.tsx | 9 +++++++-- app/(home)/article/[slug]/page.tsx | 4 ++-- app/(home)/article/page.tsx | 11 +++++++---- app/api/cron/sbs-news/route.ts | 19 ++++++++++++++++--- app/api/cron/sbs-news/template.ts | 4 ++-- app/components/home-status/display-name.tsx | 2 +- app/components/render-md-server.tsx | 16 ++++++++++++++++ app/styles/_markdown.css | 8 ++++++++ app/utils/render-md-server.tsx | 12 ------------ 9 files changed, 59 insertions(+), 26 deletions(-) create mode 100644 app/components/render-md-server.tsx delete mode 100644 app/utils/render-md-server.tsx diff --git a/app/(home)/article/[slug]/_components/text.tsx b/app/(home)/article/[slug]/_components/text.tsx index ea2240f..e09fb7c 100644 --- a/app/(home)/article/[slug]/_components/text.tsx +++ b/app/(home)/article/[slug]/_components/text.tsx @@ -1,11 +1,16 @@ +import { RenderMDTextServer } from "@/components/render-md-server"; import { SelectToSearch } from "@/hooks/use-select-to-search"; -import { renderMDTextServer } from "@/utils/render-md-server"; +import { notoKR } from "@/utils/fonts"; +import clsx from "clsx"; const Text = ({ content }: { content: string }) => { const resolvedContent = content.replace("frameborder", "frameBorder"); return ( - {renderMDTextServer(resolvedContent)} + ); }; diff --git a/app/(home)/article/[slug]/page.tsx b/app/(home)/article/[slug]/page.tsx index 0ad2979..7eb05bc 100644 --- a/app/(home)/article/[slug]/page.tsx +++ b/app/(home)/article/[slug]/page.tsx @@ -4,10 +4,10 @@ import { articleRevalidateKey, getArticleRevalidateKey, } from "@/actions/user-dict-utils"; +import { RenderMDTextServer } from "@/components/render-md-server"; import type { SubtitleCues, SubtitleSeries } from "@/types/article"; import { notoKR } from "@/utils/fonts"; import { getBaseURL } from "@/utils/get-base-url"; -import { renderMDTextServer } from "@/utils/render-md-server"; import clsx from "clsx"; import { getTranslations } from "next-intl/server"; import { unstable_cache } from "next/cache"; @@ -119,7 +119,7 @@ const SlugPage = async ({ viewTransitionName: `article-description-${article.id}`, }} > - {renderMDTextServer(article.description)} + {article.type === "MOVIE" && } diff --git a/app/(home)/article/page.tsx b/app/(home)/article/page.tsx index ab6cdf9..d84f24b 100644 --- a/app/(home)/article/page.tsx +++ b/app/(home)/article/page.tsx @@ -1,6 +1,6 @@ import { getArticles } from "@/actions/article-actions"; +import { RenderMDTextServer } from "@/components/render-md-server"; import { notoKR } from "@/utils/fonts"; -import { renderMDTextServer } from "@/utils/render-md-server"; import { getTranslations } from "next-intl/server"; import { Link } from "next-view-transitions"; @@ -14,11 +14,14 @@ export const generateMetadata = async () => { const ArticlePage = async () => { const articles = await getArticles(); + const sortedArticles = articles.toSorted((a, b) => + a.type === "MOVIE" ? -1 : b.type === "MOVIE" ? 1 : 0, + ); return (
- {articles.map(async (article) => ( + {sortedArticles.map(async (article) => (
{

{ viewTransitionName: `article-description-${article.id}`, }} > - {await renderMDTextServer(article.description)} +

diff --git a/app/api/cron/sbs-news/route.ts b/app/api/cron/sbs-news/route.ts index bb37425..54571ce 100644 --- a/app/api/cron/sbs-news/route.ts +++ b/app/api/cron/sbs-news/route.ts @@ -10,6 +10,17 @@ const channelId = "UCkinYTS9IHqOEwR1Sze2JTw"; // Ensure you set this as an environment variable const YOUTUBE_API_KEY = process.env.YOUTUBE_API_KEY; +function decodeHtmlEntities(text: string | null | undefined): string { + if (!text) return ""; + return text + .replace(/'/g, "'") + .replace(/"/g, '"') + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">"); +} + +// When setting the title or description export async function GET() { try { if (!YOUTUBE_API_KEY) { @@ -49,11 +60,13 @@ export async function GET() { const videoStats = statsResponse.data.items?.[0]?.statistics; const fullSnippet = statsResponse.data.items?.[0]?.snippet; - console.log("item.snippet?.thumbnails", item.snippet?.thumbnails); + return { videoId, - title: item.snippet?.title, - description: fullSnippet?.description || item.snippet?.description, + title: decodeHtmlEntities(item.snippet?.title), + description: decodeHtmlEntities( + fullSnippet?.description || item.snippet?.description, + ), publishedAt: item.snippet?.publishedAt, viewCount: Number(videoStats?.viewCount || 0), thumbnailUrl: item.snippet?.thumbnails?.high?.url, diff --git a/app/api/cron/sbs-news/template.ts b/app/api/cron/sbs-news/template.ts index a16c8e6..725a15d 100644 --- a/app/api/cron/sbs-news/template.ts +++ b/app/api/cron/sbs-news/template.ts @@ -13,12 +13,12 @@ const buildContent = (video: Video) => { width="560" height="315" src="https://www.youtube.com/embed/${video.videoId}" - title="${video.title}" + title="${video.title?.replace(/"/g, '\\"')}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" /> - +--- ${video.description} diff --git a/app/components/home-status/display-name.tsx b/app/components/home-status/display-name.tsx index 875033c..1911da8 100644 --- a/app/components/home-status/display-name.tsx +++ b/app/components/home-status/display-name.tsx @@ -1,3 +1,4 @@ +import { Pronunciation } from "@/components/pronunciation"; import { useDevice } from "@/hooks/use-device"; import { useHoverToSearch } from "@/hooks/use-hover-to-search"; import type { DictItem } from "@/types/dict"; @@ -5,7 +6,6 @@ import { notoKR } from "@/utils/fonts"; import { generateWordSuggestionPrompt } from "@/utils/prompts"; import clsx from "clsx"; import { romanize, standardizePronunciation } from "es-hangul"; -import { Pronunciation } from "../pronunciation"; import { Star } from "./star"; const DisplayName = ({ diff --git a/app/components/render-md-server.tsx b/app/components/render-md-server.tsx new file mode 100644 index 0000000..5a048c6 --- /dev/null +++ b/app/components/render-md-server.tsx @@ -0,0 +1,16 @@ +import { components } from "@/components/markdown-render"; +import clsx from "clsx"; +import { compileMDX } from "next-mdx-remote/rsc"; + +const RenderMDTextServer = async ({ + text, + className, +}: { text: string; className?: string }) => { + const { content } = await compileMDX({ + source: text, + components: { ...components }, + }); + return
{content}
; +}; + +export { RenderMDTextServer }; diff --git a/app/styles/_markdown.css b/app/styles/_markdown.css index 80aa2ac..7c3152a 100644 --- a/app/styles/_markdown.css +++ b/app/styles/_markdown.css @@ -52,4 +52,12 @@ li > pre { @apply mobile:max-w-[calc(100vw-7rem)]; } + + hr { + @apply !h-0.5 + } + + iframe { + @apply !w-[-webkit-fill-available] !h-auto !aspect-video; + } } diff --git a/app/utils/render-md-server.tsx b/app/utils/render-md-server.tsx deleted file mode 100644 index 8c481ce..0000000 --- a/app/utils/render-md-server.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { components } from "@/components/markdown-render"; -import { compileMDX } from "next-mdx-remote/rsc"; - -const renderMDTextServer = async (text: string) => { - const { content } = await compileMDX({ - source: text, - components: { ...components }, - }); - return
{content}
; -}; - -export { renderMDTextServer };