Docker
This commit is contained in:
@@ -1,163 +1,176 @@
|
||||
import React from 'react'
|
||||
import { BlogPost } from '@/data/blogPosts'
|
||||
import React from 'react'
|
||||
import { resolveMediaUrl } from '@/lib/media'
|
||||
import { BlogPost, BlogPostSection } from '@/types/blog'
|
||||
|
||||
interface BlogPostCardProps {
|
||||
post: BlogPost
|
||||
onReadMore: (post: BlogPost) => void
|
||||
isLatest: boolean
|
||||
}
|
||||
|
||||
export function BlogPostCard({ post, onReadMore }: BlogPostCardProps) {
|
||||
const formatDate = (date: Date) => {
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
}).format(date)
|
||||
const cardStyles = {
|
||||
container: {
|
||||
position: 'relative' as const,
|
||||
backgroundColor: 'white',
|
||||
border: '2px solid #8B7D6B',
|
||||
padding: '24px',
|
||||
marginBottom: '32px',
|
||||
boxShadow: '4px 4px 0 rgba(139, 125, 107, 0.2)'
|
||||
},
|
||||
imageWrapper: {
|
||||
marginBottom: '24px',
|
||||
marginLeft: '-24px',
|
||||
marginRight: '-24px',
|
||||
marginTop: '-24px',
|
||||
height: '280px',
|
||||
backgroundSize: 'cover',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: 'center',
|
||||
backgroundColor: 'white',
|
||||
borderBottom: '2px solid #8B7D6B'
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Abril Fatface, serif',
|
||||
fontSize: '28px',
|
||||
fontWeight: 900,
|
||||
color: '#1E1A17',
|
||||
marginBottom: '16px',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
excerpt: {
|
||||
fontFamily: 'Spectral, serif',
|
||||
fontSize: '16px',
|
||||
color: '#4A4A4A',
|
||||
lineHeight: 1.6,
|
||||
marginBottom: '20px'
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate(timestamp: string) {
|
||||
const date = new Date(timestamp)
|
||||
return date.toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
})
|
||||
}
|
||||
|
||||
export function BlogPostCard({ post, onReadMore, isLatest }: BlogPostCardProps) {
|
||||
const previewUrl = resolveMediaUrl(post.previewImage)
|
||||
|
||||
return (
|
||||
<article style={{
|
||||
backgroundColor: 'white',
|
||||
border: '2px solid #8B7D6B',
|
||||
padding: '24px',
|
||||
marginBottom: '32px',
|
||||
position: 'relative',
|
||||
boxShadow: '4px 4px 0 rgba(139, 125, 107, 0.2)'
|
||||
}}>
|
||||
{/* Featured Badge */}
|
||||
{post.featured && (
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
top: '-12px',
|
||||
right: '24px',
|
||||
backgroundColor: '#C89C2B',
|
||||
color: '#F7F1E1',
|
||||
padding: '4px 12px',
|
||||
fontFamily: 'Pacifico, cursive',
|
||||
fontSize: '14px',
|
||||
transform: 'rotate(3deg)',
|
||||
boxShadow: '2px 2px 4px rgba(0,0,0,0.2)'
|
||||
}}>
|
||||
Featured
|
||||
<article style={cardStyles.container}>
|
||||
{post.isEditorsPick && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '32px',
|
||||
left: '-60px',
|
||||
padding: '8px 64px',
|
||||
backgroundColor: '#C89C2B',
|
||||
color: '#F7F1E1',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
letterSpacing: '0.2em',
|
||||
textTransform: 'uppercase',
|
||||
transform: 'rotate(-45deg)',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.2)'
|
||||
}}
|
||||
>
|
||||
Editor's Pick
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Header Image */}
|
||||
{(post.previewImage || post.images[0]) && (
|
||||
<div style={{
|
||||
marginBottom: '24px',
|
||||
marginLeft: '-24px',
|
||||
marginRight: '-24px',
|
||||
marginTop: '-24px',
|
||||
height: '300px',
|
||||
backgroundImage: `url('${post.previewImage || post.images[0]}')`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: 'center',
|
||||
backgroundColor: 'white',
|
||||
borderBottom: '2px solid #8B7D6B'
|
||||
}} />
|
||||
{isLatest && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '16px',
|
||||
right: '16px',
|
||||
backgroundColor: '#1E1A17',
|
||||
color: '#F7F1E1',
|
||||
padding: '6px 12px',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
letterSpacing: '0.15em',
|
||||
textTransform: 'uppercase'
|
||||
}}
|
||||
>
|
||||
Last Blog Post
|
||||
</div>
|
||||
)}
|
||||
|
||||
{previewUrl && (
|
||||
<div
|
||||
style={{
|
||||
...cardStyles.imageWrapper,
|
||||
backgroundImage: `url('${previewUrl}')`
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Category & Date */}
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: '16px'
|
||||
marginBottom: '12px'
|
||||
}}>
|
||||
<span style={{
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.15em',
|
||||
color: '#C89C2B',
|
||||
fontWeight: 'bold'
|
||||
}}>
|
||||
{post.category}
|
||||
</span>
|
||||
<span style={{
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
color: '#8B7D6B'
|
||||
}}>
|
||||
{formatDate(post.datePublished)}
|
||||
{formatDate(post.createdAt)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<h2 style={{
|
||||
fontFamily: 'Abril Fatface, serif',
|
||||
fontSize: '28px',
|
||||
fontWeight: '900',
|
||||
color: '#1E1A17',
|
||||
marginBottom: '16px',
|
||||
lineHeight: '1.2'
|
||||
}}>
|
||||
{post.title}
|
||||
</h2>
|
||||
<h2 style={cardStyles.title}>{post.title}</h2>
|
||||
|
||||
{/* Excerpt */}
|
||||
<p style={{
|
||||
fontFamily: 'Spectral, serif',
|
||||
fontSize: '16px',
|
||||
color: '#4A4A4A',
|
||||
lineHeight: '1.6',
|
||||
marginBottom: '20px'
|
||||
}}>
|
||||
{post.excerpt}
|
||||
</p>
|
||||
{post.linkUrl && (
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<a
|
||||
href={post.linkUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
backgroundColor: '#1E1A17',
|
||||
color: '#F7F1E1',
|
||||
padding: '10px 18px',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
letterSpacing: '0.15em',
|
||||
textTransform: 'uppercase',
|
||||
border: '2px solid #8B7D6B'
|
||||
}}
|
||||
>
|
||||
To Produkt
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Tags */}
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
gap: '8px',
|
||||
marginBottom: '20px'
|
||||
}}>
|
||||
{post.tags.slice(0, 3).map(tag => (
|
||||
<span key={tag} style={{
|
||||
backgroundColor: '#F7F1E1',
|
||||
border: '1px solid #8B7D6B',
|
||||
padding: '4px 8px',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '11px',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.05em',
|
||||
color: '#8B7D6B'
|
||||
}}>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
{post.excerpt && <p style={cardStyles.excerpt}>{post.excerpt}</p>}
|
||||
|
||||
{/* Read More Button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onReadMore(post)}
|
||||
style={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
padding: '12px 18px',
|
||||
border: '2px solid #8B7D6B',
|
||||
backgroundColor: 'transparent',
|
||||
border: '2px solid #C89C2B',
|
||||
color: '#C89C2B',
|
||||
padding: '12px 24px',
|
||||
fontFamily: 'Staatliches, sans-serif',
|
||||
fontSize: '16px',
|
||||
letterSpacing: '0.1em',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
letterSpacing: '0.15em',
|
||||
textTransform: 'uppercase',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.3s ease',
|
||||
position: 'relative',
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.backgroundColor = '#C89C2B'
|
||||
e.currentTarget.style.color = '#F7F1E1'
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.backgroundColor = 'transparent'
|
||||
e.currentTarget.style.color = '#C89C2B'
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Read Full Article →
|
||||
Read More
|
||||
</button>
|
||||
</article>
|
||||
)
|
||||
@@ -168,350 +181,198 @@ interface BlogPostModalProps {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export function BlogPostModal({ post, onClose }: BlogPostModalProps) {
|
||||
const formatDate = (date: Date) => {
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
}).format(date)
|
||||
}
|
||||
function renderSection(section: BlogPostSection) {
|
||||
const imageUrl = resolveMediaUrl(section.image)
|
||||
|
||||
// Convert markdown-style formatting to HTML
|
||||
const formatContent = (content: string) => {
|
||||
return content
|
||||
.split('\n\n')
|
||||
.map((paragraph, index) => {
|
||||
// Handle headers
|
||||
if (paragraph.startsWith('## ')) {
|
||||
return (
|
||||
<h3 key={index} style={{
|
||||
fontFamily: 'Abril Fatface, serif',
|
||||
fontSize: '24px',
|
||||
fontWeight: '900',
|
||||
color: '#1E1A17',
|
||||
marginTop: '32px',
|
||||
marginBottom: '16px'
|
||||
}}>
|
||||
{paragraph.replace('## ', '')}
|
||||
</h3>
|
||||
)
|
||||
}
|
||||
if (paragraph.startsWith('### ')) {
|
||||
return (
|
||||
<h4 key={index} style={{
|
||||
fontFamily: 'Staatliches, sans-serif',
|
||||
fontSize: '20px',
|
||||
color: '#C89C2B',
|
||||
marginTop: '24px',
|
||||
marginBottom: '12px'
|
||||
}}>
|
||||
{paragraph.replace('### ', '')}
|
||||
</h4>
|
||||
)
|
||||
}
|
||||
|
||||
// Handle lists
|
||||
if (paragraph.startsWith('- ')) {
|
||||
const items = paragraph.split('\n').filter(line => line.startsWith('- '))
|
||||
return (
|
||||
<ul key={index} style={{
|
||||
marginBottom: '16px',
|
||||
paddingLeft: '24px'
|
||||
}}>
|
||||
{items.map((item, i) => (
|
||||
<li key={i} style={{
|
||||
fontFamily: 'Spectral, serif',
|
||||
fontSize: '16px',
|
||||
color: '#4A4A4A',
|
||||
lineHeight: '1.8',
|
||||
marginBottom: '8px'
|
||||
}}>
|
||||
{item.replace('- ', '').replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
||||
// Regular paragraphs with bold text support
|
||||
const formattedText = paragraph.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||
return (
|
||||
<p key={index} style={{
|
||||
return (
|
||||
<div key={section.id} style={{ marginBottom: '32px' }}>
|
||||
{section.text && (
|
||||
<p
|
||||
style={{
|
||||
fontFamily: 'Spectral, serif',
|
||||
fontSize: '16px',
|
||||
color: '#4A4A4A',
|
||||
lineHeight: '1.8',
|
||||
marginBottom: '16px'
|
||||
}} dangerouslySetInnerHTML={{ __html: formattedText }} />
|
||||
)
|
||||
})
|
||||
}
|
||||
lineHeight: 1.8,
|
||||
marginBottom: imageUrl ? '18px' : 0
|
||||
}}
|
||||
>
|
||||
{section.text}
|
||||
</p>
|
||||
)}
|
||||
{imageUrl && (
|
||||
<div
|
||||
style={{
|
||||
border: '2px solid #8B7D6B',
|
||||
backgroundColor: 'white',
|
||||
padding: '6px',
|
||||
maxWidth: '420px',
|
||||
width: '100%',
|
||||
margin: '0 auto'
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={imageUrl}
|
||||
alt="Blog section"
|
||||
style={{
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
height: 'auto',
|
||||
backgroundColor: '#F7F1E1'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function BlogPostModal({ post, onClose }: BlogPostModalProps) {
|
||||
const heroImage = resolveMediaUrl(post.previewImage)
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'rgba(30, 26, 23, 0.8)',
|
||||
zIndex: 1000,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: '20px',
|
||||
overflowY: 'auto'
|
||||
}} onClick={onClose}>
|
||||
<article style={{
|
||||
backgroundColor: '#F7F1E1',
|
||||
maxWidth: '900px',
|
||||
width: '100%',
|
||||
maxHeight: '90vh',
|
||||
<div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
inset: 0,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.6)',
|
||||
zIndex: 1000,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'flex-start',
|
||||
overflowY: 'auto',
|
||||
padding: '48px',
|
||||
position: 'relative',
|
||||
boxShadow: '0 10px 40px rgba(0,0,0,0.3)'
|
||||
}} onClick={(e) => e.stopPropagation()}>
|
||||
{/* Close Button */}
|
||||
padding: '48px 20px'
|
||||
}}
|
||||
onClick={onClose}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
maxWidth: '820px',
|
||||
width: '100%',
|
||||
backgroundColor: '#F7F1E1',
|
||||
border: '2px solid #8B7D6B',
|
||||
padding: '32px',
|
||||
boxShadow: '0 20px 60px rgba(0,0,0,0.35)'
|
||||
}}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '20px',
|
||||
right: '20px',
|
||||
top: '16px',
|
||||
right: '16px',
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
fontSize: '32px',
|
||||
cursor: 'pointer',
|
||||
color: '#8B7D6B',
|
||||
zIndex: 10
|
||||
fontSize: '24px',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
X
|
||||
</button>
|
||||
|
||||
{/* Header */}
|
||||
<div style={{ marginBottom: '32px' }}>
|
||||
{heroImage && (
|
||||
<div
|
||||
style={{
|
||||
marginLeft: '-32px',
|
||||
marginRight: '-32px',
|
||||
marginTop: '-32px',
|
||||
borderBottom: '2px solid #8B7D6B'
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={heroImage}
|
||||
alt={post.title}
|
||||
style={{ display: 'block', width: '100%', height: 'auto' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<header style={{ marginTop: '24px', marginBottom: '32px' }}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
gap: '16px',
|
||||
alignItems: 'center',
|
||||
marginBottom: '16px'
|
||||
marginBottom: '12px'
|
||||
}}>
|
||||
{post.isEditorsPick && (
|
||||
<span style={{
|
||||
backgroundColor: '#C89C2B',
|
||||
color: '#F7F1E1',
|
||||
padding: '6px 12px',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
letterSpacing: '0.15em',
|
||||
textTransform: 'uppercase'
|
||||
}}>
|
||||
Editor's Pick
|
||||
</span>
|
||||
)}
|
||||
<span style={{
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.15em',
|
||||
color: '#C89C2B',
|
||||
fontWeight: 'bold'
|
||||
color: '#8B7D6B',
|
||||
textTransform: 'uppercase'
|
||||
}}>
|
||||
{post.category}
|
||||
</span>
|
||||
<span style={{
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
color: '#8B7D6B'
|
||||
}}>
|
||||
{formatDate(post.datePublished)}
|
||||
{formatDate(post.createdAt)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h1 style={{
|
||||
|
||||
<h2 style={{
|
||||
fontFamily: 'Abril Fatface, serif',
|
||||
fontSize: '42px',
|
||||
fontWeight: '900',
|
||||
color: '#1E1A17',
|
||||
lineHeight: '1.2',
|
||||
marginBottom: '24px'
|
||||
marginBottom: '16px'
|
||||
}}>
|
||||
{post.title}
|
||||
</h1>
|
||||
</h2>
|
||||
|
||||
<div className="newspaper-rule" style={{
|
||||
width: '100px',
|
||||
height: '2px',
|
||||
backgroundColor: '#C89C2B',
|
||||
margin: '24px 0'
|
||||
}} />
|
||||
{post.linkUrl && (
|
||||
<a
|
||||
href={post.linkUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
backgroundColor: '#1E1A17',
|
||||
color: '#F7F1E1',
|
||||
padding: '12px 22px',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
letterSpacing: '0.15em',
|
||||
textTransform: 'uppercase',
|
||||
border: '2px solid #8B7D6B'
|
||||
}}
|
||||
>
|
||||
To Produkt
|
||||
</a>
|
||||
)}
|
||||
</header>
|
||||
|
||||
<div>
|
||||
{post.sections.map(section => renderSection(section))}
|
||||
</div>
|
||||
|
||||
|
||||
{/* Content with interleaved images */}
|
||||
<div style={{ marginBottom: '32px' }}>
|
||||
{(() => {
|
||||
const blocks = post.content.split('\n\n')
|
||||
const nodes: React.ReactNode[] = []
|
||||
const totalBlocks = blocks.length
|
||||
const totalImages = post.images.length
|
||||
const step = totalImages > 0 ? Math.ceil(totalBlocks / (totalImages + 1)) : Infinity
|
||||
let imageIndex = 0
|
||||
|
||||
blocks.forEach((paragraph, index) => {
|
||||
// Headers
|
||||
if (paragraph.startsWith('## ')) {
|
||||
nodes.push(
|
||||
<h3 key={`h3-${index}`} style={{
|
||||
fontFamily: 'Abril Fatface, serif',
|
||||
fontSize: '24px',
|
||||
fontWeight: '900',
|
||||
color: '#1E1A17',
|
||||
marginTop: '32px',
|
||||
marginBottom: '16px'
|
||||
}}>
|
||||
{paragraph.replace('## ', '')}
|
||||
</h3>
|
||||
)
|
||||
} else if (paragraph.startsWith('### ')) {
|
||||
nodes.push(
|
||||
<h4 key={`h4-${index}`} style={{
|
||||
fontFamily: 'Staatliches, sans-serif',
|
||||
fontSize: '20px',
|
||||
color: '#C89C2B',
|
||||
marginTop: '24px',
|
||||
marginBottom: '12px'
|
||||
}}>
|
||||
{paragraph.replace('### ', '')}
|
||||
</h4>
|
||||
)
|
||||
} else if (paragraph.startsWith('- ')) {
|
||||
const items = paragraph.split('\n').filter(line => line.startsWith('- '))
|
||||
nodes.push(
|
||||
<ul key={`ul-${index}`} style={{
|
||||
marginBottom: '16px',
|
||||
paddingLeft: '24px'
|
||||
}}>
|
||||
{items.map((item, i) => (
|
||||
<li
|
||||
key={`li-${index}-${i}`}
|
||||
style={{
|
||||
fontFamily: 'Spectral, serif',
|
||||
fontSize: '16px',
|
||||
color: '#4A4A4A',
|
||||
lineHeight: '1.8',
|
||||
marginBottom: '8px'
|
||||
}}
|
||||
dangerouslySetInnerHTML={{ __html: item.replace('- ', '').replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') }}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
} else {
|
||||
// Paragraphs
|
||||
const formattedText = paragraph.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||
nodes.push(
|
||||
<p key={`p-${index}`} style={{
|
||||
fontFamily: 'Spectral, serif',
|
||||
fontSize: '16px',
|
||||
color: '#4A4A4A',
|
||||
lineHeight: '1.8',
|
||||
marginBottom: '16px'
|
||||
}} dangerouslySetInnerHTML={{ __html: formattedText }} />
|
||||
)
|
||||
}
|
||||
|
||||
// Interleave images evenly through the content
|
||||
if (totalImages > 0 && imageIndex < totalImages && (index + 1) % step === 0) {
|
||||
nodes.push(
|
||||
<div
|
||||
key={`img-${imageIndex}`}
|
||||
style={{
|
||||
margin: '16px 0 32px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
border: '2px solid #8B7D6B',
|
||||
backgroundColor: 'white',
|
||||
padding: '6px',
|
||||
maxWidth: '360px',
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={post.images[imageIndex]}
|
||||
alt={`Image ${imageIndex + 1}`}
|
||||
style={{
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
height: 'auto',
|
||||
backgroundColor: '#F7F1E1'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
imageIndex++
|
||||
}
|
||||
})
|
||||
|
||||
// If any images remain, append them at the end
|
||||
while (imageIndex < totalImages) {
|
||||
nodes.push(
|
||||
<div
|
||||
key={`img-tail-${imageIndex}`}
|
||||
style={{
|
||||
margin: '16px 0 32px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
border: '2px solid #8B7D6B',
|
||||
backgroundColor: 'white',
|
||||
padding: '6px',
|
||||
maxWidth: '360px',
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={post.images[imageIndex]}
|
||||
alt={`Image ${imageIndex + 1}`}
|
||||
style={{
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
height: 'auto',
|
||||
backgroundColor: '#F7F1E1'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
imageIndex++
|
||||
}
|
||||
|
||||
return nodes
|
||||
})()}
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
<div style={{
|
||||
borderTop: '2px solid #8B7D6B',
|
||||
paddingTop: '24px',
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
gap: '8px'
|
||||
}}>
|
||||
{post.tags.map(tag => (
|
||||
<span key={tag} style={{
|
||||
backgroundColor: 'white',
|
||||
border: '1px solid #8B7D6B',
|
||||
padding: '6px 12px',
|
||||
fontFamily: 'Space Mono, monospace',
|
||||
fontSize: '12px',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.05em',
|
||||
color: '#8B7D6B'
|
||||
{post.footer && (
|
||||
<footer style={{
|
||||
borderTop: '2px solid #8B7D6B',
|
||||
marginTop: '32px',
|
||||
paddingTop: '24px'
|
||||
}}>
|
||||
<p style={{
|
||||
fontFamily: 'Spectral, serif',
|
||||
fontSize: '15px',
|
||||
color: '#4A4A4A',
|
||||
lineHeight: 1.6
|
||||
}}>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</article>
|
||||
{post.footer}
|
||||
</p>
|
||||
</footer>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user