11---
2- import { ViewTransitions } from ' astro:transitions ' ;
2+ import BaseLayout from ' ../../layouts/BaseLayout. astro' ;
33import { getCollection , type CollectionEntry } from ' astro:content' ;
44import readingTime from ' reading-time' ;
5- import LanguageToggle from ' ../LanguageToggle.astro' ;
6- import { COMMON_TEXT , NAV_TEXT , HOME_TEXT , POST_TEXT } from ' ../../i18n/ui' ;
7- import { getLocalePrefix , resolveLocale , type Locale } from ' ../../i18n/config' ;
8- import { isActiveLink as checkActiveLink } from ' ../../utils/linkUtils' ;
5+ import { HOME_TEXT , POST_TEXT } from ' ../../i18n/ui' ;
6+ import { getLocalePrefix , type Locale } from ' ../../i18n/config' ;
97import { formatDate } from ' ../../utils/dateFormatter' ;
10- import ' ../../styles/global.css' ;
11- import mainScript from ' ../../scripts/main.js?url' ;
128
139interface Props {
1410 locale: Locale ;
@@ -32,176 +28,51 @@ const postsWithContent = await Promise.all(
3228);
3329
3430const localePrefix = getLocalePrefix (locale );
35- const nav = NAV_TEXT [locale ];
36- const common = COMMON_TEXT [locale ];
3731const home = HOME_TEXT [locale ];
3832const postText = POST_TEXT [locale ];
3933const buildPath = (path : string ) => path .replace (/ \/ {2,} / g , ' /' );
40- const navLinks = [
41- { href: buildPath (` ${localePrefix || ' /' } ` ), label: nav .home },
42- { href: buildPath (` ${localePrefix }/archive ` ), label: nav .archive },
43- { href: buildPath (` ${localePrefix }/tags ` ), label: nav .tags },
44- ];
4534const tagsPageHref = buildPath (` ${localePrefix }/tags ` );
46- const currentPath = Astro .url .pathname ;
47- const isActiveLink = (href : string ) => checkActiveLink (href , currentPath );
4835---
4936
50- <!DOCTYPE html >
51- <html lang ={ locale } >
52- <head >
53- <meta charset =" UTF-8" />
54- <meta name =" viewport" content =" width=device-width, initial-scale=1.0" />
55- <title >{ home .siteTitle } </title >
56- <meta name =" description" content ={ home .siteDescription } />
57-
58- <!-- Fonts -->
59- <link rel =" preconnect" href =" https://fonts.googleapis.com" />
60- <link rel =" preconnect" href =" https://fonts.gstatic.com" crossorigin />
61- <link href =" https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&display=block" rel =" stylesheet" />
62- <link href =" https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@200..900&display=block" rel =" stylesheet" />
63- <link href =" https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&display=block" rel =" stylesheet" />
64-
65- <!-- Icons -->
66- <link rel =" icon" type =" image/x-icon" href =" /static/favicon.ico" />
67- <link rel =" icon" type =" image/png" sizes =" 16x16" href =" /static/favicon-16x16.png" />
68- <link rel =" icon" type =" image/png" sizes =" 32x32" href =" /static/favicon-32x32.png" />
69-
70- <!-- RSS -->
71- <link rel =" alternate" type =" application/rss+xml" title =" Code Brewer RSS Feed" href =" /feed.xml" />
37+ <BaseLayout title ={ home .siteTitle } description ={ home .siteDescription } >
38+ { postsWithContent .map (({ post , Content , readingTime , pathSlug }, index ) => {
39+ const formattedDate = formatDate (post .data .date , locale );
7240
73- <ViewTransitions />
74- </head >
75- <body >
76- <!-- Mobile Header -->
77- <header class =" mobile-header" >
78- <button
79- id =" mobile-nav-toggle"
80- class =" mobile-site-title"
81- type =" button"
82- aria-expanded =" false"
83- aria-controls =" mobile-nav-menu"
41+ const readingMinutes = Math .ceil (readingTime );
42+ const readingTimeText = locale === ' ko'
43+ ? ` ${readingMinutes }${postText .readingTime } `
44+ : ` ${readingMinutes } ${postText .readingTime } ` ;
45+ const postHref = ` ${localePrefix }/posts/${pathSlug } ` .replace (/ \/\/ / g , ' /' );
46+ return (
47+ <article
48+ class = " post-article"
49+ id = { pathSlug }
50+ data-index = { index }
51+ data-lang = { locale }
52+ data-translation-key = { post .data .translationKey || ' ' }
8453 >
85- { home .siteTitle }
86- <span class =" mobile-nav-caret" >▾</span >
87- </button >
88- <div class =" mobile-controls" >
89- <LanguageToggle class =" mobile-lang-toggle" />
90- <button class =" theme-toggle mobile-theme-toggle" type =" button" aria-label ={ common .themeToggle } >
91- <span id =" mobile-theme-icon" >○</span >
92- </button >
93- </div >
94- </header >
95- <nav class =" mobile-nav-menu" id =" mobile-nav-menu" hidden >
96- <ul >
97- { navLinks .map ((link ) => {
98- const isActive = isActiveLink (link .href );
99- return (
100- <li >
101- <a href = { link .href } class = { isActive ? ' mobile-nav-link active' : ' mobile-nav-link' } >{ link .label } </a >
102- </li >
103- );
104- })}
105- </ul >
106- </nav >
107-
108- <div class =" layout-container" >
109- <!-- Left Sidebar -->
110- <aside class =" sidebar" >
111- <div class =" sidebar-header" >
112- <h1 class =" site-title" >
113- <a href ={ ` ${localePrefix || ' /' } ` } >{ home .siteTitle } </a >
54+ <header class = " post-header" >
55+ <h1 >
56+ <a href = { postHref } class = " post-title-link" >{ post .data .title } </a >
11457 </h1 >
115- </div >
116-
117- <!-- Main Navigation Menu -->
118- <nav class =" main-nav" >
119- <div class =" nav-section" >
120- <h3 class =" nav-section-title" >{ nav .navigate } </h3 >
121- <ul class =" nav-links" >
122- { navLinks .map ((link ) => (
123- <li >
124- <a href = { link .href } class = { isActiveLink (link .href ) ? ' nav-link nav-link-active' : ' nav-link' } >
125- { link .label }
126- </a >
127- </li >
128- ))}
129- </ul >
58+ <div class = " post-meta" >
59+ <time datetime = { post .data .date .toISOString ()} >{ formattedDate } </time >
60+ <span class = " reading-time" >{ readingTimeText } </span >
13061 </div >
131-
132- <div class =" nav-section" >
133- <h3 class =" nav-section-title" >{ nav .links } </h3 >
134- <ul class =" nav-links" >
135- <li >
136- <a href =" https://github.com/hwisu" target =" _blank" rel =" noopener" class =" nav-link" >
137- { nav .github }
138- <span class =" external-indicator" aria-hidden =" true" >↗</span >
139- </a >
140- </li >
141- <li >
142- <a href =" https://www.linkedin.com/in/hwisu/" target =" _blank" rel =" noopener" class =" nav-link" >
143- { nav .linkedin }
144- <span class =" external-indicator" aria-hidden =" true" >↗</span >
145- </a >
146- </li >
147- </ul >
62+ <div class = " post-tags" >
63+ { post .data .tags .map (tag => {
64+ const tagSearchHref = ` ${tagsPageHref }?q=${encodeURIComponent (tag )} ` ;
65+ return (
66+ <a href = { tagSearchHref } class = " tag" >{ tag } </a >
67+ );
68+ })}
14869 </div >
149- </nav >
150- </aside >
70+ </header >
15171
152- <!-- Right Content Area -->
153- <main class =" content-area" >
154- <div class =" content-shell" >
155- <div class =" content-controls" >
156- <LanguageToggle />
157- <button class =" theme-toggle" type =" button" aria-label ={ common .themeToggle } >
158- <span id =" theme-icon" >○</span >
159- </button >
160- </div >
161- { postsWithContent .map (({ post , Content , readingTime , pathSlug }, index ) => {
162- const formattedDate = formatDate (post .data .date , locale );
163-
164- const readingMinutes = Math .ceil (readingTime );
165- const readingTimeText = locale === ' ko'
166- ? ` ${readingMinutes }${postText .readingTime } `
167- : ` ${readingMinutes } ${postText .readingTime } ` ;
168- const postHref = ` ${localePrefix }/posts/${pathSlug } ` .replace (/ \/\/ / g , ' /' );
169- return (
170- <article
171- class = " post-article"
172- id = { pathSlug }
173- data-index = { index }
174- data-lang = { locale }
175- data-translation-key = { post .data .translationKey || ' ' }
176- >
177- <header class = " post-header" >
178- <h1 >
179- <a href = { postHref } class = " post-title-link" >{ post .data .title } </a >
180- </h1 >
181- <div class = " post-meta" >
182- <time datetime = { post .data .date .toISOString ()} >{ formattedDate } </time >
183- <span class = " reading-time" >{ readingTimeText } </span >
184- </div >
185- <div class = " post-tags" >
186- { post .data .tags .map (tag => {
187- const tagSearchHref = ` ${tagsPageHref }?q=${encodeURIComponent (tag )} ` ;
188- return (
189- <a href = { tagSearchHref } class = " tag" >{ tag } </a >
190- );
191- })}
192- </div >
193- </header >
194-
195- <div class = " post-content" >
196- <Content />
197- </div >
198- </article >
199- );
200- })}
72+ <div class = " post-content" >
73+ <Content />
20174 </div >
202- </main >
203- </div >
204-
205- <script is:inline type =" module" src ={ mainScript } ></script >
206- </body >
207- </html >
75+ </article >
76+ );
77+ })}
78+ </BaseLayout >
0 commit comments