feat: add markdown rendering support for Content component
Detect markdown-formatted posts (from bots etc.) and render them with react-markdown instead of plain text, with feed-friendly styles (flattened headings, compact lists, scrollable tables). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fc8a160d9a
commit
cc1aa7f989
3 changed files with 196 additions and 7 deletions
43
src/lib/markdown.ts
Normal file
43
src/lib/markdown.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Detects whether a string contains meaningful Markdown formatting.
|
||||
* Strips URLs and nostr: references first to avoid false positives.
|
||||
*/
|
||||
export function containsMarkdown(content: string): boolean {
|
||||
// Remove URLs and nostr: references to avoid false positives
|
||||
const cleaned = content
|
||||
.replace(/https?:\/\/[^\s)>\]]+/g, '')
|
||||
.replace(/nostr:[a-z0-9]+/g, '')
|
||||
|
||||
// Strong signals — any single one triggers markdown
|
||||
const strongPatterns = [
|
||||
/^```/m, // code fence
|
||||
/\|[\s]*:?-+:?[\s]*\|/ // table separator |---|
|
||||
]
|
||||
|
||||
for (const pattern of strongPatterns) {
|
||||
if (pattern.test(cleaned)) return true
|
||||
}
|
||||
|
||||
// Medium signals — need 2+ different types
|
||||
const mediumPatterns = [
|
||||
/^#{1,6}\s+\S/m, // ATX heading (# text), not #hashtag
|
||||
/\*\*[^*\n]+\*\*/, // bold **text**
|
||||
/__[^_\n]+__/, // bold __text__
|
||||
/\[[^\]]+\]\([^)]+\)/, // link [text](url)
|
||||
/^>\s+\S/m, // blockquote > text
|
||||
/^[-*]\s+\S/m, // unordered list - item or * item
|
||||
/^\d+\.\s+\S/m, // ordered list 1. item
|
||||
/^---$/m, // horizontal rule
|
||||
/~~[^~\n]+~~/ // strikethrough ~~text~~
|
||||
]
|
||||
|
||||
let matchCount = 0
|
||||
for (const pattern of mediumPatterns) {
|
||||
if (pattern.test(cleaned)) {
|
||||
matchCount++
|
||||
if (matchCount >= 2) return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue