65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
import { JSX } from 'solid-js'
|
|
import styles from '../styles/CodePreview.module.css'
|
|
|
|
/**
|
|
* Компонент для простого просмотра текста без подсветки syntax
|
|
* Убирает HTML теги и показывает чистый текст
|
|
*/
|
|
|
|
interface TextPreviewProps extends JSX.HTMLAttributes<HTMLPreElement> {
|
|
content: string
|
|
maxHeight?: string
|
|
showLineNumbers?: boolean
|
|
}
|
|
|
|
/**
|
|
* Убирает HTML теги и декодирует HTML entity
|
|
*/
|
|
function stripHtmlTags(text: string): string {
|
|
// Убираем HTML теги
|
|
let cleaned = text.replace(/<[^>]*>/g, '')
|
|
|
|
// Декодируем базовые HTML entity
|
|
cleaned = cleaned
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/&/g, '&')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, "'")
|
|
.replace(/ /g, ' ')
|
|
|
|
return cleaned.trim()
|
|
}
|
|
|
|
const TextPreview = (props: TextPreviewProps) => {
|
|
const cleanedContent = () => stripHtmlTags(props.content)
|
|
|
|
const contentWithLines = () => {
|
|
if (!props.showLineNumbers) return cleanedContent()
|
|
|
|
const lines = cleanedContent().split('\n')
|
|
return lines.map((line, index) => `${(index + 1).toString().padStart(3, ' ')} | ${line}`).join('\n')
|
|
}
|
|
|
|
return (
|
|
<pre
|
|
{...props}
|
|
class={`${styles.codePreview} ${props.class || ''}`}
|
|
style={`
|
|
max-height: ${props.maxHeight || '60vh'};
|
|
overflow-y: auto;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
font-size: 14px;
|
|
line-height: 1.6;
|
|
white-space: pre-wrap;
|
|
word-wrap: break-word;
|
|
${props.style || ''}
|
|
`}
|
|
>
|
|
<code class={styles.code}>{contentWithLines()}</code>
|
|
</pre>
|
|
)
|
|
}
|
|
|
|
export default TextPreview
|