feat: add context to highlights (previous and next sentences)

This commit is contained in:
Gigi
2025-10-06 07:41:19 +01:00
parent beeb296d3b
commit 89bd9f631a

View File

@@ -26,12 +26,15 @@ export async function createHighlight(
// Parse article coordinate to get address pointer
const addressPointer = parseArticleCoordinate(article)
// Extract context (previous and next sentences from the same paragraph)
const context = extractContext(selectedText, article.content)
// Create highlight event using the blueprint
const highlightEvent = await factory.create(
HighlightBlueprint,
selectedText,
addressPointer,
comment ? { comment } : undefined
context ? { comment, context } : comment ? { comment } : undefined
)
// Update the alt tag to identify Boris as the creator
@@ -66,3 +69,80 @@ function parseArticleCoordinate(article: NostrEvent): AddressPointer {
}
}
/**
* Extracts context for a highlight by finding the previous and next sentences
* in the same paragraph as the selected text
*/
function extractContext(selectedText: string, articleContent: string): string | undefined {
if (!selectedText || !articleContent) return undefined
// Find the position of the selected text in the article
const selectedIndex = articleContent.indexOf(selectedText)
if (selectedIndex === -1) return undefined
// Split content into paragraphs (by double newlines or single newlines)
const paragraphs = articleContent.split(/\n\n+/)
// Find which paragraph contains the selected text
let currentPos = 0
let containingParagraph: string | undefined
for (const paragraph of paragraphs) {
const paragraphEnd = currentPos + paragraph.length
if (selectedIndex >= currentPos && selectedIndex < paragraphEnd) {
containingParagraph = paragraph
break
}
currentPos = paragraphEnd + 2 // Account for the double newline
}
if (!containingParagraph) return undefined
// Split paragraph into sentences (basic sentence splitting)
// This regex splits on periods, exclamation marks, or question marks followed by space or end of string
const sentences = containingParagraph.split(/([.!?]+\s+)/).filter(s => s.trim().length > 0)
// Reconstruct sentences properly by joining sentence text with punctuation
const reconstructedSentences: string[] = []
for (let i = 0; i < sentences.length; i++) {
if (sentences[i].match(/^[.!?]+\s*$/)) {
// This is punctuation, attach it to previous sentence
if (reconstructedSentences.length > 0) {
reconstructedSentences[reconstructedSentences.length - 1] += sentences[i]
}
} else {
reconstructedSentences.push(sentences[i])
}
}
// Find which sentence contains the selected text
let selectedSentenceIndex = -1
for (let i = 0; i < reconstructedSentences.length; i++) {
if (reconstructedSentences[i].includes(selectedText)) {
selectedSentenceIndex = i
break
}
}
if (selectedSentenceIndex === -1) return undefined
// Build context from previous and next sentences
const contextParts: string[] = []
// Add previous sentence if it exists
if (selectedSentenceIndex > 0) {
contextParts.push(reconstructedSentences[selectedSentenceIndex - 1].trim())
}
// Add the selected sentence itself
contextParts.push(reconstructedSentences[selectedSentenceIndex].trim())
// Add next sentence if it exists
if (selectedSentenceIndex < reconstructedSentences.length - 1) {
contextParts.push(reconstructedSentences[selectedSentenceIndex + 1].trim())
}
// Only return context if we have more than just the selected sentence
return contextParts.length > 1 ? contextParts.join(' ') : undefined
}