Update TaskWorkspace component to integrate ReactMarkdown for enhanced task description rendering. Add remark-gfm support for GitHub Flavored Markdown, improving text formatting and presentation. Update package dependencies in package.json and package-lock.json to include react-markdown and remark-gfm.
Some checks failed
platform/bro-js/challenge-pl/pipeline/head There was a failure building this commit

This commit is contained in:
2025-12-12 15:03:27 +03:00
parent 25baea7447
commit 0965318bca
3 changed files with 1643 additions and 16 deletions

1479
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -35,8 +35,10 @@
"globals": "^15.9.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-markdown": "^10.1.0",
"react-redux": "^9.2.0",
"react-router-dom": "^6.23.1",
"remark-gfm": "^4.0.1",
"typescript-eslint": "^8.6.0"
}
}

View File

@@ -8,6 +8,8 @@ import {
Textarea,
VStack,
} from '@chakra-ui/react'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import type { ChallengeTask } from '../../__data__/types'
import { useChallenge } from '../../context/ChallengeContext'
@@ -24,7 +26,6 @@ export const TaskWorkspace = ({ task, onTaskComplete }: TaskWorkspaceProps) => {
taskId: task.id,
})
const descriptionBg = 'gray.50'
const isChecking = !!queueStatus || isSubmitting
const isAccepted = finalSubmission?.status === 'accepted'
const needsRevision = finalSubmission?.status === 'needs_revision'
@@ -37,13 +38,178 @@ export const TaskWorkspace = ({ task, onTaskComplete }: TaskWorkspaceProps) => {
return (
<VStack align="stretch" gap={3}>
<Box borderWidth="1px" borderRadius="md" borderColor="gray.200" p={3} bg={descriptionBg}>
<Text fontSize="md" fontWeight="semibold" mb={1}>
<Box borderWidth="1px" borderRadius="md" borderColor="gray.200" p={4} bg="white" shadow="sm">
<Text fontSize="lg" fontWeight="bold" mb={3} color="gray.800">
{task.title}
</Text>
<Text whiteSpace="pre-line" color="gray.700" fontSize="sm">
{task.description}
</Text>
<Box
color="gray.700"
fontSize="sm"
lineHeight="1.7"
css={{
// Заголовки
'& h1': {
fontSize: '1.75em',
fontWeight: '700',
marginTop: '1.2em',
marginBottom: '0.6em',
color: '#2D3748',
borderBottom: '2px solid #E2E8F0',
paddingBottom: '0.3em'
},
'& h2': {
fontSize: '1.5em',
fontWeight: '600',
marginTop: '1em',
marginBottom: '0.5em',
color: '#2D3748'
},
'& h3': {
fontSize: '1.25em',
fontWeight: '600',
marginTop: '0.8em',
marginBottom: '0.4em',
color: '#2D3748'
},
'& h4': {
fontSize: '1.1em',
fontWeight: '600',
marginTop: '0.6em',
marginBottom: '0.3em',
color: '#4A5568'
},
// Параграфы
'& p': {
marginTop: '0.75em',
marginBottom: '0.75em',
lineHeight: '1.8'
},
// Списки
'& ul, & ol': {
marginLeft: '1.5em',
marginTop: '0.75em',
marginBottom: '0.75em',
paddingLeft: '0.5em'
},
'& li': {
marginTop: '0.4em',
marginBottom: '0.4em',
lineHeight: '1.7'
},
'& li > p': {
marginTop: '0.25em',
marginBottom: '0.25em'
},
// Инлайн-код
'& code': {
backgroundColor: '#EDF2F7',
color: '#C53030',
padding: '0.15em 0.4em',
borderRadius: '4px',
fontSize: '0.9em',
fontFamily: 'Monaco, Consolas, "Courier New", monospace',
fontWeight: '500'
},
// Блоки кода
'& pre': {
backgroundColor: '#1A202C',
color: '#E2E8F0',
padding: '1em 1.2em',
borderRadius: '8px',
overflowX: 'auto',
marginTop: '1em',
marginBottom: '1em',
border: '1px solid #2D3748',
fontSize: '0.9em',
lineHeight: '1.6'
},
'& pre code': {
backgroundColor: 'transparent',
color: '#E2E8F0',
padding: '0',
fontFamily: 'Monaco, Consolas, "Courier New", monospace'
},
// Цитаты
'& blockquote': {
borderLeft: '4px solid #4299E1',
paddingLeft: '1em',
paddingTop: '0.5em',
paddingBottom: '0.5em',
marginLeft: '0',
marginTop: '1em',
marginBottom: '1em',
fontStyle: 'italic',
color: '#4A5568',
backgroundColor: '#EBF8FF',
borderRadius: '0 4px 4px 0'
},
'& blockquote p': {
marginTop: '0.25em',
marginBottom: '0.25em'
},
// Ссылки
'& a': {
color: '#3182CE',
textDecoration: 'underline',
fontWeight: '500',
transition: 'color 0.2s',
'&:hover': {
color: '#2C5282'
}
},
// Горизонтальная линия
'& hr': {
border: 'none',
borderTop: '2px solid #E2E8F0',
marginTop: '1.5em',
marginBottom: '1.5em'
},
// Таблицы
'& table': {
borderCollapse: 'collapse',
width: '100%',
marginTop: '1em',
marginBottom: '1em',
fontSize: '0.95em'
},
'& table thead': {
backgroundColor: '#F7FAFC'
},
'& table th': {
border: '1px solid #E2E8F0',
padding: '0.75em 1em',
textAlign: 'left',
fontWeight: '600',
color: '#2D3748'
},
'& table td': {
border: '1px solid #E2E8F0',
padding: '0.75em 1em',
textAlign: 'left'
},
'& table tr:nth-of-type(even)': {
backgroundColor: '#F7FAFC'
},
// Выделение (strong, em)
'& strong': {
fontWeight: '600',
color: '#2D3748'
},
'& em': {
fontStyle: 'italic'
},
// Изображения
'& img': {
maxWidth: '100%',
height: 'auto',
borderRadius: '8px',
marginTop: '1em',
marginBottom: '1em'
}
}}
>
<ReactMarkdown remarkPlugins={[remarkGfm]}>{task.description}</ReactMarkdown>
</Box>
</Box>
{/* Статус проверки */}