/**
* HansardContentRenderer Component
*
* Renders Hansard statement content with:
* - Automatic entity linking (bills, committees, petitions)
* - Paragraph splitting for proper formatting
* - Legacy link processing (written questions links)
*/
'use client';
import React, { useMemo } from 'react';
import { MentionRenderer } from '@/components/mentions/MentionRenderer';
import { processHansardLinks } from '@/lib/utils/hansardLinkProcessor';
interface HansardContentRendererProps {
/** The raw content text from Hansard */
content: string;
/** Current locale (en/fr) */
locale: string;
/** Parliamentary session for bill URLs (e.g., "45-1") */
session?: string;
/** Additional className for styling */
className?: string;
}
/**
* Check if text contains legacy Hansard links that need HTML processing
*/
function hasLegacyHansardLinks(text: string): boolean {
// Check for written questions references
const patterns = [
/\[For text of questions and responses, see Written Questions website\]/i,
/\[Pour le texte des questions et des réponses, voir le site Web des questions écrites\]/i,
];
return patterns.some((p) => p.test(text));
}
/**
* Renders a single paragraph with entity links
*/
const ParagraphRenderer: React.FC<{
text: string;
locale: string;
session: string;
hasLegacyLinks: boolean;
}> = ({ text, locale, session, hasLegacyLinks }) => {
// If paragraph has legacy links, use dangerouslySetInnerHTML for that part
if (hasLegacyLinks && hasLegacyHansardLinks(text)) {
return (
<p
className="mt-3 first:mt-0"
dangerouslySetInnerHTML={{ __html: processHansardLinks(text) }}
/>
);
}
// Otherwise use MentionRenderer for entity linking
return (
<p className="mt-3 first:mt-0">
<MentionRenderer
text={text}
naturalLanguage
subtleLinks
session={session}
/>
</p>
);
};
/**
* HansardContentRenderer - Renders Hansard content with automatic entity linking
*
* Splits content into paragraphs and processes each one with MentionRenderer
* for natural language entity detection (bills, committees, petitions).
*
* @example
* ```tsx
* <HansardContentRenderer
* content="Bill C-234 was discussed in the Standing Committee on Finance..."
* locale="en"
* session="45-1"
* />
* ```
*/
export function HansardContentRenderer({
content,
locale,
session = '45-1',
className = '',
}: HansardContentRendererProps) {
// Split content into paragraphs and check for legacy links
const { paragraphs, hasLegacyLinks } = useMemo(() => {
if (!content) {
return { paragraphs: [], hasLegacyLinks: false };
}
// Split on double newlines (paragraph breaks)
const paras = content
.split(/\n\n+/)
.map((p) => p.trim())
.filter((p) => p.length > 0);
// Check if any paragraph has legacy links
const legacy = paras.some(hasLegacyHansardLinks);
return { paragraphs: paras, hasLegacyLinks: legacy };
}, [content]);
if (paragraphs.length === 0) {
return null;
}
return (
<div
className={`text-gray-900 dark:text-gray-100 whitespace-pre-wrap leading-relaxed ${className}`}
>
{paragraphs.map((paragraph, index) => (
<ParagraphRenderer
key={index}
text={paragraph}
locale={locale}
session={session}
hasLegacyLinks={hasLegacyLinks}
/>
))}
</div>
);
}
export default HansardContentRenderer;