fix(content): book extraction now works when film tags are present
When the user explicitly asks about books, don't bail on pattern extraction just because the AI also referenced films from the library. Also fix book pattern regex to match **Title** — *Author* format, strip sources section before extraction, and remove duplicate title below BookGrid cards. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
ad63a7b1af
commit
1973b24eaa
@@ -88,10 +88,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs font-semibold mt-2 truncate px-0.5"
|
||||
:class="isDark ? 'text-white/90' : 'text-gray-900'">
|
||||
{{ book.title }}
|
||||
</p>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -711,23 +711,26 @@ export function useContentPanel() {
|
||||
const patterns: { re: RegExp; titleIdx: number; authorIdx: number }[] = [
|
||||
// "Title" by Author
|
||||
{ re: /["""]([^"""]{2,80})["""]\s+by\s+([A-Z][^,\n\.]{1,50}?)(?:\s*[,()\n\.]|$)/gi, titleIdx: 1, authorIdx: 2 },
|
||||
// **Title** by Author
|
||||
{ re: /\*\*([^*]{2,80})\*\*\s+by\s+([A-Z][^,\n\.]{1,50}?)(?:\s*[,()\n\.]|$)/g, titleIdx: 1, authorIdx: 2 },
|
||||
// **Title** by/—/– Author (with optional italic on author)
|
||||
{ re: /\*\*([^*]{2,80})\*\*\s+(?:by|—|–)\s+\*?([A-Z][^*\n]{1,50}?)\*?(?:\s*[,()*\n]|$)/g, titleIdx: 1, authorIdx: 2 },
|
||||
// - Title — Author or Title by Author (in list)
|
||||
{ re: /(?:^|\n)\s*(?:\d+\.\s*|[-•]\s*)\*{0,2}([^*\n\-–—]{2,80}?)\*{0,2}\s+(?:by|—|–)\s+([A-Z][^,\n]{1,50}?)(?:\s*[\n(,.]|$)/gm, titleIdx: 1, authorIdx: 2 },
|
||||
{ re: /(?:^|\n)\s*(?:\d+\.\s*|[-•]\s*)\*{0,2}([^*\n\-–—]{2,80}?)\*{0,2}\s+(?:by|—|–)\s+\*?([A-Z][^*\n]{1,50}?)\*?(?:\s*[,()*\n]|$)/gm, titleIdx: 1, authorIdx: 2 },
|
||||
]
|
||||
|
||||
for (const { re, titleIdx, authorIdx } of patterns) {
|
||||
let m: RegExpExecArray | null
|
||||
const rx = new RegExp(re.source, re.flags)
|
||||
while ((m = rx.exec(text)) !== null) {
|
||||
const title = m[titleIdx].trim().replace(/^\*\*|\*\*$/g, '')
|
||||
const title = m[titleIdx].trim().replace(/^\*\*|\*\*$/g, '').replace(/^\[|\]$/g, '')
|
||||
const author = m[authorIdx].trim().replace(/^\*\*|\*\*$/g, '')
|
||||
if (title.length < 2 || author.length < 2) continue
|
||||
// Skip if it looks like a film/song/podcast tag
|
||||
if (/\[\[(film|song|podcast|book)(_ext)?:/.test(title)) continue
|
||||
// Skip numbers-only
|
||||
if (/^\d{4}$/.test(title) || /^\d{4}$/.test(author)) continue
|
||||
// Skip markdown links [text](url) — these are source references, not books
|
||||
const afterMatch = text.substring(m.index + m[0].length, m.index + m[0].length + 200)
|
||||
if (/^\s*\]\s*\(https?:/.test(afterMatch) || /\]\(https?:\/\//.test(m[0])) continue
|
||||
const key = `${title.toLowerCase()}|${author.toLowerCase()}`
|
||||
if (seen.has(key)) continue
|
||||
seen.add(key)
|
||||
@@ -763,11 +766,16 @@ export function useContentPanel() {
|
||||
if (externalBooks.length > 0) return externalBooks
|
||||
// Only do fallback pattern matching if the query or response looks book-related
|
||||
if (!isBookQuery(userQuery) && !isBookLikeResponse(text)) return []
|
||||
// Skip if other content types are already tagged
|
||||
if (extractFilmIds(text).length > 0 || /\[\[film_ext:/.test(text)) return []
|
||||
if (extractSongIds(text).length > 0 || /\[\[song_ext:/.test(text)) return []
|
||||
// Skip if other content types are the primary content (not just supplementary refs)
|
||||
// When user explicitly asked about books, film/song tags are just cross-references
|
||||
if (!isBookQuery(userQuery)) {
|
||||
if (extractFilmIds(text).length > 0 || /\[\[film_ext:/.test(text)) return []
|
||||
if (extractSongIds(text).length > 0 || /\[\[song_ext:/.test(text)) return []
|
||||
}
|
||||
if (isNewsLikeResponse(text)) return []
|
||||
return extractBooksFromPatterns(text)
|
||||
// Strip sources/references section at the end to avoid matching markdown links as books
|
||||
const cleanText = text.replace(/\n---\n\s*(?:Sources|References|Links):?\s*\n[\s\S]*$/i, '')
|
||||
return extractBooksFromPatterns(cleanText)
|
||||
}
|
||||
|
||||
function extractExternalTVSeries(text: string): TVSeries[] {
|
||||
|
||||
Reference in New Issue
Block a user