feat: improve support for long-form articles
This commit is contained in:
@@ -34,10 +34,10 @@ export default function ImageWithLightbox({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-fit max-w-full">
|
||||
<div className="w-full">
|
||||
<Image
|
||||
key={0}
|
||||
className={cn('rounded-lg max-h-[80vh] sm:max-h-[50vh] border cursor-zoom-in', className)}
|
||||
className={cn('rounded-lg border cursor-zoom-in', className)}
|
||||
classNames={{
|
||||
errorPlaceholder: 'aspect-square h-[30vh]'
|
||||
}}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { SecondaryPageLink, useSecondaryPage } from '@/PageManager'
|
||||
import ImageWithLightbox from '@/components/ImageWithLightbox'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { getLongFormArticleMetadataFromEvent } from '@/lib/event-metadata'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { toNote, toNoteList, toProfile } from '@/lib/link'
|
||||
import { ExternalLink } from 'lucide-react'
|
||||
import { Event, kinds } from 'nostr-tools'
|
||||
import { useMemo } from 'react'
|
||||
import Markdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
@@ -16,6 +18,7 @@ export default function LongFormArticle({
|
||||
event: Event
|
||||
className?: string
|
||||
}) {
|
||||
const { push } = useSecondaryPage()
|
||||
const metadata = useMemo(() => getLongFormArticleMetadataFromEvent(event), [event])
|
||||
|
||||
return (
|
||||
@@ -28,15 +31,6 @@ export default function LongFormArticle({
|
||||
<p className="break-words">{metadata.summary}</p>
|
||||
</blockquote>
|
||||
)}
|
||||
{metadata.tags.length > 0 && (
|
||||
<div className="flex gap-1 flex-wrap">
|
||||
{metadata.tags.map((tag) => (
|
||||
<Badge key={tag} variant="secondary" className="break-words">
|
||||
{tag}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{metadata.image && (
|
||||
<ImageWithLightbox
|
||||
image={{ url: metadata.image, pubkey: event.pubkey }}
|
||||
@@ -45,12 +39,55 @@ export default function LongFormArticle({
|
||||
)}
|
||||
<Markdown
|
||||
remarkPlugins={[remarkGfm, remarkNostr]}
|
||||
urlTransform={(url) => {
|
||||
if (url.startsWith('nostr:')) {
|
||||
return url.slice(6) // Remove 'nostr:' prefix for rendering
|
||||
}
|
||||
return url
|
||||
}}
|
||||
components={
|
||||
{
|
||||
nostr: (props) => <NostrNode {...props} />,
|
||||
a: (props) => (
|
||||
<a {...props} target="_blank" rel="noreferrer noopener" className="break-words" />
|
||||
),
|
||||
a: ({ href, children, ...props }) => {
|
||||
if (!href) {
|
||||
return <span {...props} className="break-words" />
|
||||
}
|
||||
if (
|
||||
href.startsWith('note1') ||
|
||||
href.startsWith('nevent1') ||
|
||||
href.startsWith('naddr1')
|
||||
) {
|
||||
return (
|
||||
<SecondaryPageLink
|
||||
to={toNote(href)}
|
||||
className="break-words underline text-foreground"
|
||||
>
|
||||
{children}
|
||||
</SecondaryPageLink>
|
||||
)
|
||||
}
|
||||
if (href.startsWith('npub1') || href.startsWith('nprofile1')) {
|
||||
return (
|
||||
<SecondaryPageLink
|
||||
to={toProfile(href)}
|
||||
className="break-words underline text-foreground"
|
||||
>
|
||||
{children}
|
||||
</SecondaryPageLink>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<a
|
||||
{...props}
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
className="break-words inline-flex items-baseline gap-1"
|
||||
>
|
||||
{children} <ExternalLink className="size-3" />
|
||||
</a>
|
||||
)
|
||||
},
|
||||
p: (props) => <p {...props} className="break-words" />,
|
||||
div: (props) => <div {...props} className="break-words" />,
|
||||
code: (props) => <code {...props} className="break-words whitespace-pre-wrap" />
|
||||
@@ -59,6 +96,23 @@ export default function LongFormArticle({
|
||||
>
|
||||
{event.content}
|
||||
</Markdown>
|
||||
{metadata.tags.length > 0 && (
|
||||
<div className="flex gap-2 flex-wrap pb-2">
|
||||
{metadata.tags.map((tag) => (
|
||||
<div
|
||||
key={tag}
|
||||
title={tag}
|
||||
className="flex items-center rounded-full px-3 bg-muted text-muted-foreground max-w-44 cursor-pointer hover:bg-accent hover:text-accent-foreground"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] }))
|
||||
}}
|
||||
>
|
||||
#<span className="truncate">{tag}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { getLongFormArticleMetadataFromEvent } from '@/lib/event-metadata'
|
||||
import { toNoteList } from '@/lib/link'
|
||||
import { useSecondaryPage } from '@/PageManager'
|
||||
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { Event, kinds } from 'nostr-tools'
|
||||
import { useMemo } from 'react'
|
||||
import Image from '../Image'
|
||||
|
||||
@@ -13,6 +14,7 @@ export default function LongFormArticlePreview({
|
||||
className?: string
|
||||
}) {
|
||||
const { isSmallScreen } = useScreenSize()
|
||||
const { push } = useSecondaryPage()
|
||||
const metadata = useMemo(() => getLongFormArticleMetadataFromEvent(event), [event])
|
||||
|
||||
const titleComponent = <div className="text-xl font-semibold line-clamp-2">{metadata.title}</div>
|
||||
@@ -20,9 +22,16 @@ export default function LongFormArticlePreview({
|
||||
const tagsComponent = metadata.tags.length > 0 && (
|
||||
<div className="flex gap-1 flex-wrap">
|
||||
{metadata.tags.map((tag) => (
|
||||
<Badge key={tag} variant="secondary">
|
||||
{tag}
|
||||
</Badge>
|
||||
<div
|
||||
key={tag}
|
||||
className="flex items-center rounded-full text-xs px-2.5 py-0.5 bg-muted text-muted-foreground max-w-32 cursor-pointer hover:bg-accent hover:text-accent-foreground"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] }))
|
||||
}}
|
||||
>
|
||||
#<span className="truncate">{tag}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -119,8 +119,8 @@ const NoteList = forwardRef(
|
||||
subRequests.map(({ urls, filter }) => ({
|
||||
urls,
|
||||
filter: {
|
||||
...filter,
|
||||
kinds: KINDS,
|
||||
...filter,
|
||||
limit: areAlgoRelays ? ALGO_LIMIT : LIMIT
|
||||
}
|
||||
})),
|
||||
|
||||
Reference in New Issue
Block a user