feat(chat): add support for inline magazine sections and enhance content extraction

- Updated ChatMessage component to display a button for viewing brief magazine sections when available.
- Enhanced useContentPanel to extract and manage magazine sections, improving content organization.
- Refactored extractMagazineSections function to comprehensively handle various content formats, including headings and bullet points.
- Improved formatting of content to preserve bold text and newlines as paragraphs.

Made-with: Cursor
This commit is contained in:
Dorian
2026-03-02 21:38:01 +00:00
parent 2d056f9498
commit 5414060225
3 changed files with 117 additions and 19 deletions
@@ -95,6 +95,13 @@
>
View all {{ inlineWebsitesLinks.length }} websites
</button>
<button
v-else-if="inlineMagazineSections.length > 0"
class="text-[10px] text-accent/70 hover:text-accent transition-colors"
@click.stop="openPanel"
>
View brief
</button>
</div>
</div>
</div>
@@ -143,13 +150,15 @@ const inlineSongs = computed(() => inlineContent.value.songs)
const inlinePodcasts = computed(() => inlineContent.value.podcasts)
const inlineNewsLinks = computed(() => inlineContent.value.newsLinks ?? [])
const inlineWebsitesLinks = computed(() => inlineContent.value.websitesLinks ?? [])
const inlineMagazineSections = computed(() => inlineContent.value.magazineSections ?? [])
const hasContext = computed(() => !isUser.value && (
inlineFilms.value.length > 0 ||
inlineSongs.value.length > 0 ||
inlinePodcasts.value.length > 0 ||
inlineNewsLinks.value.length > 0 ||
inlineWebsitesLinks.value.length > 0
inlineWebsitesLinks.value.length > 0 ||
inlineMagazineSections.value.length > 0
))
const displayText = computed(() => {
@@ -128,8 +128,11 @@
</div>
</article>
<!-- Secondary stories grid -->
<div class="grid sm:grid-cols-2 gap-4">
<!-- Secondary stories grid (single col when many sections for readability) -->
<div
class="gap-4"
:class="sections.length > 4 ? 'flex flex-col' : 'grid sm:grid-cols-2'"
>
<article
v-for="(section, i) in sections.slice(1)"
:key="i"
@@ -278,12 +281,14 @@ const headlineText = computed(() => {
return q.length > 100 ? q.slice(0, 97) + '…' : q
})
/** Render content with **bold** preserved (sanitized). */
/** Render content with **bold** preserved and newlines as paragraphs (sanitized). */
function formatContent(text: string): string {
return text
const safe = text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
const withParas = safe.replace(/\n\n+/g, '</p><p class="mt-2">').replace(/\n/g, '<br/>')
return `<p>${withParas}</p>`
}
</script>