|
1 | 1 | <script> |
| 2 | + import { onMount } from "svelte"; |
2 | 3 | import { blogs } from "../data/blogs.js"; |
3 | 4 |
|
4 | 5 | let { slug } = $props(); |
5 | 6 |
|
6 | 7 | let post = $derived(blogs.find(b => b.slug === slug)); |
| 8 | + let contentEl = $state(null); |
7 | 9 |
|
8 | 10 | function formatDate(dateStr) { |
9 | 11 | return new Date(dateStr).toLocaleDateString("en-US", { |
|
12 | 14 | day: "numeric", |
13 | 15 | }); |
14 | 16 | } |
| 17 | +
|
| 18 | + async function highlightCode() { |
| 19 | + if (!contentEl) return; |
| 20 | + const hljs = (await import("highlight.js/lib/core")).default; |
| 21 | + const cpp = (await import("highlight.js/lib/languages/cpp")).default; |
| 22 | + const python = (await import("highlight.js/lib/languages/python")).default; |
| 23 | + const go = (await import("highlight.js/lib/languages/go")).default; |
| 24 | + hljs.registerLanguage("cpp", cpp); |
| 25 | + hljs.registerLanguage("python", python); |
| 26 | + hljs.registerLanguage("go", go); |
| 27 | + contentEl.querySelectorAll("pre code").forEach(block => { |
| 28 | + hljs.highlightElement(block); |
| 29 | + }); |
| 30 | + } |
| 31 | +
|
| 32 | + onMount(() => { |
| 33 | + highlightCode(); |
| 34 | + }); |
| 35 | +
|
| 36 | + $effect(() => { |
| 37 | + slug; |
| 38 | + if (contentEl) highlightCode(); |
| 39 | + }); |
15 | 40 | </script> |
16 | 41 |
|
17 | 42 | <svelte:head> |
|
31 | 56 | </div> |
32 | 57 | <h1>{post.title}</h1> |
33 | 58 | </header> |
34 | | - <div class="article-content"> |
| 59 | + <div class="article-content" bind:this={contentEl}> |
35 | 60 | {@html post.content} |
36 | 61 | </div> |
37 | 62 | <footer class="article-footer"> |
|
94 | 119 | } |
95 | 120 |
|
96 | 121 | .article-meta h1 { |
| 122 | + font-family: "Epilogue", var(--font-heading); |
97 | 123 | font-size: clamp(1.75rem, 4vw, 2.5rem); |
98 | 124 | line-height: 1.2; |
99 | 125 | letter-spacing: -0.03em; |
100 | 126 | } |
101 | 127 |
|
102 | 128 | .article-content :global(h2) { |
103 | | - font-family: var(--font-heading); |
| 129 | + font-family: "Epilogue", var(--font-heading); |
104 | 130 | font-size: 1.5rem; |
105 | 131 | font-weight: 600; |
106 | 132 | margin-top: 48px; |
|
109 | 135 | } |
110 | 136 |
|
111 | 137 | .article-content :global(h3) { |
112 | | - font-family: var(--font-heading); |
| 138 | + font-family: "Epilogue", var(--font-heading); |
113 | 139 | font-size: 1.25rem; |
114 | 140 | font-weight: 500; |
115 | 141 | margin-top: 32px; |
|
133 | 159 | line-height: 1.6; |
134 | 160 | } |
135 | 161 |
|
| 162 | + .article-content :global(pre code) { |
| 163 | + background: none; |
| 164 | + border: none; |
| 165 | + padding: 0; |
| 166 | + } |
| 167 | +
|
136 | 168 | .article-content :global(code) { |
137 | 169 | font-family: var(--font-mono); |
138 | 170 | font-size: 0.875em; |
|
183 | 215 | font-style: italic; |
184 | 216 | } |
185 | 217 |
|
| 218 | + .article-content :global(.hljs) { |
| 219 | + background: transparent; |
| 220 | + color: var(--text-primary); |
| 221 | + } |
| 222 | +
|
| 223 | + .article-content :global(.hljs-keyword), |
| 224 | + .article-content :global(.hljs-built_in), |
| 225 | + .article-content :global(.hljs-type) { |
| 226 | + color: var(--accent); |
| 227 | + font-weight: 500; |
| 228 | + } |
| 229 | +
|
| 230 | + .article-content :global(.hljs-string), |
| 231 | + .article-content :global(.hljs-attr) { |
| 232 | + color: #b56b45; |
| 233 | + } |
| 234 | +
|
| 235 | + .article-content :global(.hljs-number), |
| 236 | + .article-content :global(.hljs-literal) { |
| 237 | + color: #8f6cc4; |
| 238 | + } |
| 239 | +
|
| 240 | + .article-content :global(.hljs-comment) { |
| 241 | + color: var(--text-muted); |
| 242 | + font-style: italic; |
| 243 | + } |
| 244 | +
|
| 245 | + .article-content :global(.hljs-function) { |
| 246 | + color: var(--text-primary); |
| 247 | + } |
| 248 | +
|
| 249 | + .article-content :global(.hljs-title) { |
| 250 | + color: #3a7cc2; |
| 251 | + } |
| 252 | +
|
| 253 | + .article-content :global(.hljs-params) { |
| 254 | + color: var(--text-secondary); |
| 255 | + } |
| 256 | +
|
| 257 | + .article-content :global(.hljs-meta) { |
| 258 | + color: var(--text-muted); |
| 259 | + } |
| 260 | +
|
186 | 261 | .article-footer { |
187 | 262 | margin-top: 64px; |
188 | 263 | padding-top: 32px; |
|
0 commit comments