diff --git a/src/components/markdown-content.tsx b/src/components/markdown-content.tsx
index c5af425..773098b 100644
--- a/src/components/markdown-content.tsx
+++ b/src/components/markdown-content.tsx
@@ -9,6 +9,20 @@ type MarkdownContentProps = Readonly<{
html: SanitizedHtml
}>
+const DEFAULT_KATEX_CSS_PATH = "/katex/katex.min.css"
+
+/**
+ * GitHub Pages 서브경로(e.g. /repo/) 배포 환경을 지원하기 위해
+ * 환경변수 NEXT_PUBLIC_BASE_PATH 가 지정된 경우 KaTeX 스타일시트 경로 앞에 접두사로 조합합니다.
+ */
+export function getKatexStylesheetUrl(): string {
+ // biome-ignore lint/complexity/useLiteralKeys: tsconfig noPropertyAccessFromIndexSignature requires bracket access
+ const basePath = process.env["NEXT_PUBLIC_BASE_PATH"]?.trim() ?? ""
+ const normalizedBasePath = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath
+
+ return `${normalizedBasePath}${DEFAULT_KATEX_CSS_PATH}`
+}
+
const markdownContentClassName = cn(
"prose prose-neutral max-w-none text-foreground dark:prose-invert",
"prose-a:text-foreground prose-a:decoration-border prose-a:underline-offset-4",
@@ -30,7 +44,9 @@ export function MarkdownContent({ contentKey, hasDiagram, hasMath, html }: Markd
return (
<>
- {hasMath ? : null}
+ {hasMath ? (
+
+ ) : null}
{
+ const originalEnv = process.env
+
+ beforeEach(() => {
+ process.env = { ...originalEnv }
+ })
+
+ afterEach(() => {
+ process.env = originalEnv
+ })
+
it("Given repository-owned KaTeX assets When checking the public directory Then includes CSS and its license", () => {
expect(existsSync(stylesheetPath)).toBe(true)
expect(existsSync(licensePath)).toBe(true)
@@ -34,4 +45,18 @@ describe("local KaTeX assets", () => {
expect(packageJson).not.toMatch(/^\s*"katex":/m)
expect(packageJson).not.toContain("copy-katex-assets")
})
+
+ describe("getKatexStylesheetUrl", () => {
+ it("Given no NEXT_PUBLIC_BASE_PATH When resolving Then returns root stylesheet path", () => {
+ // biome-ignore lint/complexity/useLiteralKeys: tsconfig noPropertyAccessFromIndexSignature requires bracket access
+ delete process.env["NEXT_PUBLIC_BASE_PATH"]
+ expect(getKatexStylesheetUrl()).toBe("/katex/katex.min.css")
+ })
+
+ it("Given NEXT_PUBLIC_BASE_PATH When resolving Then prepends base path with normalized slashes", () => {
+ // biome-ignore lint/complexity/useLiteralKeys: tsconfig noPropertyAccessFromIndexSignature requires bracket access
+ process.env["NEXT_PUBLIC_BASE_PATH"] = "/my-blog/"
+ expect(getKatexStylesheetUrl()).toBe("/my-blog/katex/katex.min.css")
+ })
+ })
})