release: v0.15.0 (#585)
Eighteen changes since v0.14.0. See CHANGELOG.md for the full list and the upgrade notes (bump IMAGE_CACHE_VERSION).
This commit is contained in:
@@ -7,6 +7,7 @@ import { ProofingProvider, useProofing } from '@/components/ProofingContext';
|
||||
import { ProofingModal } from '@/components/ProofingModal';
|
||||
import { FadeIn } from '@/components/FadeIn';
|
||||
import type { ParsedEssay, EssayBlock } from '@/lib/essay';
|
||||
import { renderInlineMarkdown } from '@/lib/essay';
|
||||
import type { PhotoItem } from './PhotoGrid';
|
||||
import './essay.css';
|
||||
import { useDictionary } from '@/components/I18nProvider';
|
||||
@@ -78,7 +79,15 @@ function EssayViewContent({
|
||||
return (
|
||||
<blockquote key={idx} className="essay-quote">
|
||||
<div dangerouslySetInnerHTML={{ __html: block.text }} />
|
||||
{block.author && <span className="essay-quote__author">— {block.author}</span>}
|
||||
{block.author && (
|
||||
<span
|
||||
className="essay-quote__author"
|
||||
// The attribution keeps its Markdown and is rendered here, like
|
||||
// the quote body, so `[link](…)` becomes an anchor (#559).
|
||||
// renderInlineMarkdown escapes everything it does not emit.
|
||||
dangerouslySetInnerHTML={{ __html: `— ${renderInlineMarkdown(block.author)}` }}
|
||||
/>
|
||||
)}
|
||||
</blockquote>
|
||||
);
|
||||
|
||||
@@ -312,9 +321,9 @@ function EssayViewContent({
|
||||
gap: '12px',
|
||||
padding: '8px 16px',
|
||||
borderRadius: '30px',
|
||||
background: 'var(--bg-surface, #1e1e1e)',
|
||||
background: 'var(--bg-card, #1e1e1e)',
|
||||
color: 'var(--text-primary, #ffffff)',
|
||||
border: '1px solid var(--border-color, rgba(255,255,255,0.15))',
|
||||
border: '1px solid var(--border-subtle, rgba(255,255,255,0.15))',
|
||||
boxShadow: '0 8px 24px rgba(0,0,0,0.4)',
|
||||
backdropFilter: 'blur(8px)',
|
||||
}}
|
||||
@@ -325,8 +334,8 @@ function EssayViewContent({
|
||||
style={{
|
||||
background: proofing.isFilterActive
|
||||
? 'var(--accent, #e60012)'
|
||||
: 'rgba(255,255,255,0.15)',
|
||||
color: '#fff',
|
||||
: 'var(--bg-card-hover)',
|
||||
color: proofing.isFilterActive ? '#fff' : 'var(--text-primary)',
|
||||
border: 'none',
|
||||
padding: '6px 14px',
|
||||
borderRadius: '20px',
|
||||
|
||||
@@ -266,9 +266,9 @@ function PhotoGridInner({
|
||||
gap: '12px',
|
||||
padding: '8px 16px',
|
||||
borderRadius: '30px',
|
||||
background: 'var(--bg-surface, #1e1e1e)',
|
||||
background: 'var(--bg-card, #1e1e1e)',
|
||||
color: 'var(--text-primary, #ffffff)',
|
||||
border: '1px solid var(--border-color, rgba(255,255,255,0.15))',
|
||||
border: '1px solid var(--border-subtle, rgba(255,255,255,0.15))',
|
||||
boxShadow: '0 8px 24px rgba(0,0,0,0.4)',
|
||||
backdropFilter: 'blur(8px)',
|
||||
}}
|
||||
@@ -279,8 +279,8 @@ function PhotoGridInner({
|
||||
style={{
|
||||
background: proofing.isFilterActive
|
||||
? 'var(--accent, #e60012)'
|
||||
: 'rgba(255,255,255,0.15)',
|
||||
color: '#fff',
|
||||
: 'var(--bg-card-hover)',
|
||||
color: proofing.isFilterActive ? '#fff' : 'var(--text-primary)',
|
||||
border: 'none',
|
||||
padding: '6px 14px',
|
||||
borderRadius: '20px',
|
||||
|
||||
@@ -55,13 +55,19 @@ function AlbumGrid({
|
||||
key={album.id}
|
||||
href={`/${slug}/${album.slug}`}
|
||||
className="subpage-grid__item"
|
||||
style={ph?.dominantColor ? { backgroundColor: ph.dominantColor } : undefined}
|
||||
aria-label={getServerDictionary().subpage.coverAria(
|
||||
album.albumName,
|
||||
photoCount(album.assetCount),
|
||||
)}
|
||||
>
|
||||
<span className="subpage-grid__item-media">
|
||||
{/* The loading colour belongs to the image, not the card: presets
|
||||
with a caption bar below the cover (studio-modern) would
|
||||
otherwise paint the bar in the photo's dominant colour, and
|
||||
their --text-primary caption becomes dark-on-dark in light mode. */}
|
||||
<span
|
||||
className="subpage-grid__item-media"
|
||||
style={ph?.dominantColor ? { backgroundColor: ph.dominantColor } : undefined}
|
||||
>
|
||||
{album.albumThumbnailAssetId ? (
|
||||
<Image
|
||||
src={imageUrl(album.albumThumbnailAssetId, 'preview')}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
}
|
||||
|
||||
.essay-header__title {
|
||||
font-family: var(--font-heading, serif);
|
||||
font-family: var(--font-serif, serif);
|
||||
font-size: clamp(2.2rem, 5vw, 3.8rem);
|
||||
font-weight: 700;
|
||||
line-height: 1.15;
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
|
||||
.essay-header__subtitle {
|
||||
font-family: var(--font-body, sans-serif);
|
||||
font-family: var(--font-sans, sans-serif);
|
||||
font-size: clamp(1.1rem, 2.5vw, 1.4rem);
|
||||
opacity: 0.8;
|
||||
line-height: 1.5;
|
||||
@@ -60,7 +60,7 @@
|
||||
.essay-prose {
|
||||
max-width: var(--essay-measure);
|
||||
margin: 0 auto 2.5rem auto;
|
||||
font-family: var(--font-body, sans-serif);
|
||||
font-family: var(--font-sans, sans-serif);
|
||||
font-size: clamp(1.05rem, 2vw, 1.2rem);
|
||||
line-height: 1.75;
|
||||
color: var(--text-primary, rgba(255, 255, 255, 0.92));
|
||||
@@ -71,7 +71,7 @@
|
||||
}
|
||||
|
||||
.essay-heading {
|
||||
font-family: var(--font-heading, serif);
|
||||
font-family: var(--font-serif, serif);
|
||||
max-width: var(--essay-measure);
|
||||
margin: 3.5rem auto 1.5rem auto;
|
||||
font-weight: 600;
|
||||
@@ -94,9 +94,9 @@
|
||||
margin: 3.5rem auto;
|
||||
padding: 1.5rem 2rem;
|
||||
border-left: 3px solid var(--accent, #e60012);
|
||||
background: var(--bg-surface, rgba(255, 255, 255, 0.03));
|
||||
background: var(--bg-card, rgba(255, 255, 255, 0.03));
|
||||
border-radius: 0 8px 8px 0;
|
||||
font-family: var(--font-heading, serif);
|
||||
font-family: var(--font-serif, serif);
|
||||
font-style: italic;
|
||||
font-size: clamp(1.15rem, 2.2vw, 1.35rem);
|
||||
line-height: 1.6;
|
||||
@@ -142,7 +142,7 @@
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: var(--radius, 0px);
|
||||
border-radius: var(--radius-md, 0px);
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user