From a52faf49c7869765d8b0f4dd87008218f94e4834 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Mon, 1 Dec 2025 22:52:08 +0100 Subject: [PATCH] parse book:: on kind 1111 --- src/lib/nostr-parser.tsx | 57 +++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/src/lib/nostr-parser.tsx b/src/lib/nostr-parser.tsx index 50d411e..7ebf566 100644 --- a/src/lib/nostr-parser.tsx +++ b/src/lib/nostr-parser.tsx @@ -6,6 +6,7 @@ import { nip19 } from 'nostr-tools' import { EmbeddedMention, EmbeddedNote } from '@/components/Embedded' import ImageGallery from '@/components/ImageGallery' import WebPreview from '@/components/WebPreview' +import { BookstrContent } from '@/components/Bookstr/BookstrContent' import { cleanUrl, isImage, isMedia } from '@/lib/url' import { getImetaInfosFromEvent } from '@/lib/event' import { TImetaInfo } from '@/types' @@ -14,7 +15,7 @@ import logger from '@/lib/logger' export interface ParsedNostrContent { elements: Array<{ - type: 'text' | 'nostr' | 'image' | 'video' | 'audio' | 'hashtag' | 'wikilink' | 'gallery' | 'url' | 'jumble-note' + type: 'text' | 'nostr' | 'image' | 'video' | 'audio' | 'hashtag' | 'wikilink' | 'bookstr-wikilink' | 'gallery' | 'url' | 'jumble-note' content: string bech32Id?: string nostrType?: 'npub' | 'nprofile' | 'nevent' | 'naddr' | 'note' @@ -22,6 +23,7 @@ export interface ParsedNostrContent { hashtag?: string wikilink?: string displayText?: string + bookstrWikilink?: string images?: TImetaInfo[] url?: string noteId?: string @@ -52,7 +54,7 @@ export function parseNostrContent(content: string, event?: Event): ParsedNostrCo // Collect all matches (nostr, URLs, hashtags, wikilinks, and jumble notes) and sort by position const allMatches: Array<{ - type: 'nostr' | 'image' | 'video' | 'audio' | 'hashtag' | 'wikilink' | 'url' | 'jumble-note' + type: 'nostr' | 'image' | 'video' | 'audio' | 'hashtag' | 'wikilink' | 'bookstr-wikilink' | 'url' | 'jumble-note' match: RegExpExecArray start: number end: number @@ -60,6 +62,7 @@ export function parseNostrContent(content: string, event?: Event): ParsedNostrCo hashtag?: string wikilink?: string displayText?: string + bookstrWikilink?: string noteId?: string }> = [] @@ -128,17 +131,31 @@ export function parseNostrContent(content: string, event?: Event): ParsedNostrCo }) } - // Find wikilink matches + // Find wikilink matches (including bookstr wikilinks) let wikilinkMatch while ((wikilinkMatch = wikilinkRegex.exec(content)) !== null) { - allMatches.push({ - type: 'wikilink', - match: wikilinkMatch, - start: wikilinkMatch.index, - end: wikilinkMatch.index + wikilinkMatch[0].length, - wikilink: wikilinkMatch[1], - displayText: wikilinkMatch[2] || wikilinkMatch[1] - }) + const linkContent = wikilinkMatch[1] + const displayText = wikilinkMatch[2] || linkContent + + // Check if this is a bookstr wikilink (NKBIP-08 format: book::...) + if (linkContent.startsWith('book::')) { + allMatches.push({ + type: 'bookstr-wikilink', + match: wikilinkMatch, + start: wikilinkMatch.index, + end: wikilinkMatch.index + wikilinkMatch[0].length, + bookstrWikilink: linkContent.trim() + }) + } else { + allMatches.push({ + type: 'wikilink', + match: wikilinkMatch, + start: wikilinkMatch.index, + end: wikilinkMatch.index + wikilinkMatch[0].length, + wikilink: linkContent, + displayText: displayText + }) + } } // Find Jumble note URL matches @@ -159,7 +176,7 @@ export function parseNostrContent(content: string, event?: Event): ParsedNostrCo let lastIndex = 0 - for (const { type, match, start, end, url, hashtag, wikilink, displayText, noteId } of allMatches) { + for (const { type, match, start, end, url, hashtag, wikilink, displayText, bookstrWikilink, noteId } of allMatches) { // Add text before the match if (start > lastIndex) { const textContent = content.slice(lastIndex, start) @@ -214,6 +231,12 @@ export function parseNostrContent(content: string, event?: Event): ParsedNostrCo content: match[0], hashtag: hashtag }) + } else if (type === 'bookstr-wikilink' && bookstrWikilink) { + elements.push({ + type: 'bookstr-wikilink', + content: match[0], + bookstrWikilink: bookstrWikilink + }) } else if (type === 'wikilink' && wikilink) { elements.push({ type: 'wikilink', @@ -472,6 +495,16 @@ export function renderNostrContent(parsedContent: ParsedNostrContent, className? ) } + if (element.type === 'bookstr-wikilink' && element.bookstrWikilink) { + return ( + + ) + } + if (element.type === 'wikilink' && element.wikilink && element.displayText) { const normalizedWikilink = element.wikilink.toLowerCase() return (