Enhance content parsing and metadata extraction in HTMLContentRenderer and ToggleTableRow
- Improved HTMLContentRenderer to better handle JSON content and extract HTML safely. - Updated ToggleTableRow to robustly extract meta descriptions, including parsing potential JSON strings. - Refactored Content page to conditionally display meta descriptions based on JSON parsing results, enhancing user experience.
This commit is contained in:
@@ -195,7 +195,47 @@ const HTMLContentRenderer: React.FC<HTMLContentRendererProps> = ({
|
||||
|
||||
// If content is a string, try to parse as JSON first
|
||||
if (typeof content === 'string') {
|
||||
// Try to parse as JSON (content outline from GPT-4o mini)
|
||||
// Check if it's a JSON string that contains the actual content
|
||||
if (content.trim().startsWith('{') || content.trim().startsWith('[')) {
|
||||
try {
|
||||
const parsed = JSON.parse(content);
|
||||
if (typeof parsed === 'object' && parsed !== null) {
|
||||
// If it's a full AI response JSON with a 'content' field, use that
|
||||
if (parsed.content && typeof parsed.content === 'string') {
|
||||
// Recursively process the extracted content
|
||||
const extractedContent = parsed.content;
|
||||
// Check if extracted content is HTML
|
||||
if (isHTML(extractedContent)) {
|
||||
const sanitized = sanitizeHTML(extractedContent);
|
||||
if (sanitized.trim().startsWith('<article') || sanitized.trim().startsWith('<div')) {
|
||||
return `<div class="normalized-html-content">${sanitized}</div>`;
|
||||
}
|
||||
return `<div class="normalized-html-content"><article>${sanitized}</article></div>`;
|
||||
}
|
||||
// If extracted content is still JSON, try parsing again
|
||||
if (extractedContent.trim().startsWith('{')) {
|
||||
try {
|
||||
const nestedParsed = JSON.parse(extractedContent);
|
||||
if (nestedParsed.H2 || nestedParsed.H3 || nestedParsed.introduction || nestedParsed.sections) {
|
||||
return formatContentOutline(nestedParsed);
|
||||
}
|
||||
} catch {
|
||||
// Not nested JSON, continue
|
||||
}
|
||||
}
|
||||
// Use extracted content as-is (will be processed below)
|
||||
content = extractedContent;
|
||||
} else if (parsed.H2 || parsed.H3 || parsed.introduction || parsed.sections) {
|
||||
// It's a content outline structure
|
||||
return formatContentOutline(parsed);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Not valid JSON, continue with HTML/text processing
|
||||
}
|
||||
}
|
||||
|
||||
// Try to parse as JSON (content outline from GPT-4o mini) - for non-brace-starting JSON
|
||||
try {
|
||||
const parsed = JSON.parse(content);
|
||||
if (typeof parsed === 'object' && (parsed.H2 || parsed.H3 || parsed.introduction || parsed.sections)) {
|
||||
|
||||
@@ -169,12 +169,35 @@ const ToggleMetadata: React.FC<ToggleMetadataProps> = ({ row, contentMetadata })
|
||||
contentMetadata?.metadata?.categories ||
|
||||
[];
|
||||
|
||||
const metaDescription =
|
||||
row.meta_description ||
|
||||
row.content_meta_description ||
|
||||
contentMetadata?.meta_description ||
|
||||
contentMetadata?.metadata?.meta_description ||
|
||||
null;
|
||||
// Extract meta_description, avoiding JSON strings
|
||||
let metaDescription: string | null = null;
|
||||
|
||||
// Try direct fields first
|
||||
if (row.meta_description && typeof row.meta_description === 'string') {
|
||||
metaDescription = row.meta_description;
|
||||
} else if (row.content_meta_description && typeof row.content_meta_description === 'string') {
|
||||
metaDescription = row.content_meta_description;
|
||||
} else if (contentMetadata?.meta_description && typeof contentMetadata.meta_description === 'string') {
|
||||
metaDescription = contentMetadata.meta_description;
|
||||
} else if (contentMetadata?.metadata?.meta_description && typeof contentMetadata.metadata.meta_description === 'string') {
|
||||
metaDescription = contentMetadata.metadata.meta_description;
|
||||
}
|
||||
|
||||
// If metaDescription looks like JSON, try to parse it
|
||||
if (metaDescription && metaDescription.trim().startsWith('{')) {
|
||||
try {
|
||||
const parsed = JSON.parse(metaDescription);
|
||||
// If parsed object has meta_description, use that
|
||||
if (parsed.meta_description && typeof parsed.meta_description === 'string') {
|
||||
metaDescription = parsed.meta_description;
|
||||
} else {
|
||||
// If it's a full JSON response, extract meta_description from it
|
||||
metaDescription = parsed.meta_description || null;
|
||||
}
|
||||
} catch {
|
||||
// Not valid JSON, keep as is
|
||||
}
|
||||
}
|
||||
|
||||
const hasMetadata =
|
||||
primaryKeyword ||
|
||||
@@ -263,18 +286,6 @@ const ToggleMetadata: React.FC<ToggleMetadataProps> = ({ row, contentMetadata })
|
||||
</div>
|
||||
);
|
||||
};
|
||||
<div className="html-content-wrapper">
|
||||
<HTMLContentRenderer
|
||||
content={content}
|
||||
className="text-sm text-gray-700 dark:text-gray-300 leading-relaxed"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle Button Component - To be used in table cells
|
||||
|
||||
Reference in New Issue
Block a user