test push
This commit is contained in:
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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 && (
|
||||
|
||||
Reference in New Issue
Block a user