Skip to content

Commit a0bfc5b

Browse files
authored
Merge pull request #25 from ChiantiScarlett/add/latex-support
Add LaTeX Support for Test Cases
2 parents ccbc2e8 + 39c87b1 commit a0bfc5b

3 files changed

Lines changed: 111 additions & 20 deletions

File tree

apps/landing/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
"next": "15.3.3",
1919
"react": "^19.1.0",
2020
"react-dom": "^19.1.0",
21+
"react-latex-next": "^3.0.0",
2122
"react-syntax-highlighter": "15.6.1"
2223
},
2324
"devDependencies": {
2425
"@devup-ui/next-plugin": "^1.0.2",
2526
"@types/node": "^24",
2627
"@types/react": "^19",
2728
"@types/react-dom": "^19",
28-
"typescript": "^5",
29-
"@types/react-syntax-highlighter": "^15.5.13"
29+
"@types/react-syntax-highlighter": "^15.5.13",
30+
"typescript": "^5"
3031
}
3132
}

apps/landing/src/app/test-case/page.tsx

Lines changed: 78 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import 'katex/dist/katex.min.css'
2+
13
import { Box, Grid, Text, VStack } from '@devup-ui/react'
24
import { readFile } from 'fs/promises'
35
import { Metadata } from 'next'
6+
import Latex from 'react-latex-next'
47

58
import TestCaseCircle from '@/components/test-case/TestCaseCircle'
69

@@ -81,24 +84,34 @@ export default async function TestCasePage() {
8184
gridTemplateColumns="repeat(auto-fill, minmax(16px, 1fr))"
8285
>
8386
{testStatus[key][2].map(
84-
([text, expected, actual, isSuccess], idx) => (
85-
<TestCaseCircle key={text + idx} isSuccess={isSuccess}>
86-
<Text
87-
color="#FFF"
88-
typography="body"
89-
whiteSpace="nowrap"
90-
wordBreak="keep-all"
91-
>
92-
{text}
93-
<br />
94-
정답 : {expected}
95-
<br />
96-
결과 : {actual}
97-
<br />
98-
{isSuccess ? '✅ 테스트 성공' : '❌ 테스트 실패'}
99-
</Text>
100-
</TestCaseCircle>
101-
),
87+
([text, expected, actual, isSuccess], idx) => {
88+
const textParts = parseTextWithLaTeX(text)
89+
90+
return (
91+
<TestCaseCircle key={text + idx} isSuccess={isSuccess}>
92+
<Text
93+
color="#FFF"
94+
typography="body"
95+
whiteSpace="nowrap"
96+
wordBreak="keep-all"
97+
>
98+
{textParts.map((part, partIdx) =>
99+
part.type === 'latex' ? (
100+
<Latex key={partIdx}>${part.content}$</Latex>
101+
) : (
102+
<span key={partIdx}>{part.content}</span>
103+
),
104+
)}
105+
<br />
106+
정답 : {expected}
107+
<br />
108+
결과 : {actual}
109+
<br />
110+
{isSuccess ? '✅ 테스트 성공' : '❌ 테스트 실패'}
111+
</Text>
112+
</TestCaseCircle>
113+
)
114+
},
102115
)}
103116
</Grid>
104117
</VStack>
@@ -107,3 +120,50 @@ export default async function TestCasePage() {
107120
</Box>
108121
)
109122
}
123+
124+
/**
125+
* This function parses text with LaTeX expressions and returns an array of parts.
126+
* It assumes that LaTeX is wrapped in double dollar delimiters ($$...$$).
127+
* Note that single dollar delimiters ($...$) are not rendered.
128+
* @param input - The input text to parse.
129+
* @returns An array of parts, where each part is either a text or a LaTeX expression.
130+
*/
131+
const parseTextWithLaTeX = (input: string) => {
132+
const parts: Array<{
133+
type: 'text' | 'latex'
134+
content: string
135+
}> = []
136+
const latexRegex = /\$\$([^$]+(?:\$(?!\$)[^$]*)*)\$\$/g
137+
let lastIndex = 0
138+
let match
139+
140+
while ((match = latexRegex.exec(input)) !== null) {
141+
// if there is text before the LaTeX expression, add it as a text part:
142+
if (match.index > lastIndex) {
143+
const textContent = input.slice(lastIndex, match.index)
144+
if (textContent) {
145+
parts.push({ type: 'text', content: textContent })
146+
}
147+
}
148+
149+
// add the LaTeX expression from double dollars:
150+
const latexContent = match[1]
151+
parts.push({ type: 'latex', content: latexContent })
152+
lastIndex = match.index + match[0].length
153+
}
154+
155+
// add remaining text after the last LaTeX expression:
156+
if (lastIndex < input.length) {
157+
const remainingText = input.slice(lastIndex)
158+
if (remainingText) {
159+
parts.push({ type: 'text', content: remainingText })
160+
}
161+
}
162+
163+
// if no LaTeX found, return the original text as a single text part:
164+
if (!parts.length) {
165+
parts.push({ type: 'text', content: input })
166+
}
167+
168+
return parts
169+
}

pnpm-lock.yaml

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)