test push

This commit is contained in:
jze9
2026-05-18 18:51:00 +05:00
parent a64d8469df
commit 5057a61d55
5 changed files with 271 additions and 177 deletions

View File

@@ -6,11 +6,9 @@ function fmt(iso) {
}
export default function ArticleModal({ article, onClose }) {
// Закрытие по Escape
useEffect(() => {
const handler = e => { if (e.key === 'Escape') onClose() }
window.addEventListener('keydown', handler)
// Блокируем скролл страницы под модалкой
document.body.style.overflow = 'hidden'
return () => {
window.removeEventListener('keydown', handler)
@@ -18,6 +16,8 @@ export default function ArticleModal({ article, onClose }) {
}
}, [onClose])
const isFullHtml = /^\s*<!DOCTYPE|^\s*<html/i.test(article.content ?? '')
return (
<div className="article-modal-overlay" onClick={onClose}>
<div className="article-modal" onClick={e => e.stopPropagation()}>
@@ -27,42 +27,67 @@ export default function ArticleModal({ article, onClose }) {
<img className="article-modal__cover" src={article.cover_url} alt={article.title} />
)}
<div className="article-modal__body">
<div className="article-meta">
{article.category && (
<span className="chip chip--primary">{article.category.name}</span>
{isFullHtml ? (
<>
<div className="article-modal__body" style={{ paddingBottom: 0 }}>
<div className="article-meta">
{article.category && (
<span className="chip chip--primary">{article.category.name}</span>
)}
{article.published_at && <span>{fmt(article.published_at)}</span>}
</div>
<h1 className="article-title">{article.title}</h1>
</div>
<iframe
srcDoc={article.content}
style={{ width: '100%', border: 'none', display: 'block', minHeight: '70vh' }}
title={article.title}
sandbox="allow-scripts allow-same-origin"
onLoad={e => {
const doc = e.target.contentDocument
if (doc) e.target.style.height = doc.documentElement.scrollHeight + 'px'
}}
/>
</>
) : (
<div className="article-modal__body">
<div className="article-meta">
{article.category && (
<span className="chip chip--primary">{article.category.name}</span>
)}
{article.published_at && <span>{fmt(article.published_at)}</span>}
</div>
<h1 className="article-title">{article.title}</h1>
<div
className="article-body"
style={article.font_family ? { fontFamily: article.font_family } : undefined}
dangerouslySetInnerHTML={{ __html: article.content ?? '' }}
/>
{article.tags?.length > 0 && (
<div className="article-tags">
{article.tags.map(t => (
<span key={t.id} className="chip chip--ghost">#{t.name}</span>
))}
</div>
)}
{article.source_url && (
<div className="article-source">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
</svg>
<span>Источник:</span>
<a href={article.source_url} target="_blank" rel="noopener noreferrer">
{article.source_url}
</a>
</div>
)}
<span>{fmt(article.published_at)}</span>
</div>
<h1 className="article-title">{article.title}</h1>
<div
className="article-body"
dangerouslySetInnerHTML={{ __html: article.content ?? '' }}
/>
{article.tags?.length > 0 && (
<div className="article-tags">
{article.tags.map(t => (
<span key={t.id} className="chip chip--ghost">#{t.name}</span>
))}
</div>
)}
{article.source_url && (
<div className="article-source">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
</svg>
<span>Источник:</span>
<a href={article.source_url} target="_blank" rel="noopener noreferrer">
{article.source_url}
</a>
</div>
)}
</div>
)}
</div>
</div>
)

View File

@@ -32,6 +32,28 @@ export default function NewsDetail() {
</div>
)
const isFullHtml = /^\s*<!DOCTYPE|^\s*<html/i.test(article.content ?? '')
if (isFullHtml) {
return (
<div>
<div style={{ padding: '0.5rem 1rem', background: 'var(--c-surface)', borderBottom: '1px solid var(--c-border)' }}>
<button className="back-btn" onClick={() => navigate(-1)}> Назад</button>
</div>
<iframe
srcDoc={article.content}
style={{ width: '100%', border: 'none', display: 'block' }}
title={article.title}
sandbox="allow-scripts allow-same-origin"
onLoad={e => {
const doc = e.target.contentDocument
if (doc) e.target.style.height = doc.documentElement.scrollHeight + 'px'
}}
/>
</div>
)
}
return (
<div className="article-page">
<button className="back-btn" onClick={() => navigate(-1)}> Назад</button>
@@ -49,7 +71,8 @@ export default function NewsDetail() {
<div
className="article-body"
dangerouslySetInnerHTML={{ __html: article.body ?? '' }}
style={article.font_family ? { fontFamily: article.font_family } : undefined}
dangerouslySetInnerHTML={{ __html: article.content ?? '' }}
/>
{article.tags?.length > 0 && (