Fix blog excerpt rendering: remove shortcodes and decode HTML entities
- Add decodeExcerptEntities() to handle —, …, smart quotes, etc. - Add removeShortcodes() to strip [caption] and other WordPress shortcodes - Regenerate blog-posts.json and pages.json with cleaned excerpts Fixes issue where [caption] tags and raw HTML entities appeared in blog listings. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9cc37beadb
commit
204679b740
|
|
@ -119,10 +119,52 @@ function cleanContent(html) {
|
||||||
return clean;
|
return clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode HTML entities for excerpts
|
||||||
|
function decodeExcerptEntities(text) {
|
||||||
|
return text
|
||||||
|
// Common HTML entities
|
||||||
|
.replace(/—/g, '—')
|
||||||
|
.replace(/–/g, '–')
|
||||||
|
.replace(/…/g, '...')
|
||||||
|
.replace(/’/g, "'")
|
||||||
|
.replace(/‘/g, "'")
|
||||||
|
.replace(/”/g, '"')
|
||||||
|
.replace(/“/g, '"')
|
||||||
|
.replace(/ /g, ' ')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, "'")
|
||||||
|
.replace(/’/g, "'")
|
||||||
|
.replace(/‘/g, "'")
|
||||||
|
.replace(/“/g, '"')
|
||||||
|
.replace(/”/g, '"')
|
||||||
|
.replace(/—/g, '—')
|
||||||
|
.replace(/–/g, '–')
|
||||||
|
.replace(/…/g, '...');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove WordPress-style shortcodes
|
||||||
|
function removeShortcodes(text) {
|
||||||
|
// Remove [caption]...[/caption] shortcodes
|
||||||
|
let clean = text.replace(/\[caption[^\]]*\](.*?)\[\/caption\]/gi, '$1');
|
||||||
|
// Remove other common shortcodes
|
||||||
|
clean = clean.replace(/\[\/?[a-z_]+[^\]]*\]/gi, '');
|
||||||
|
return clean;
|
||||||
|
}
|
||||||
|
|
||||||
// Extract first paragraph as excerpt
|
// Extract first paragraph as excerpt
|
||||||
function extractExcerpt(content, maxLength = 200) {
|
function extractExcerpt(content, maxLength = 200) {
|
||||||
|
// First decode HTML entities in the raw content
|
||||||
|
let text = decodeExcerptEntities(content);
|
||||||
|
// Remove WordPress shortcodes
|
||||||
|
text = removeShortcodes(text);
|
||||||
// Remove HTML tags
|
// Remove HTML tags
|
||||||
const text = content.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
|
text = text.replace(/<[^>]+>/g, ' ');
|
||||||
|
// Clean up whitespace
|
||||||
|
text = text.replace(/\s+/g, ' ').trim();
|
||||||
|
|
||||||
if (text.length <= maxLength) return text;
|
if (text.length <= maxLength) return text;
|
||||||
return text.substring(0, maxLength).replace(/\s+\S*$/, '') + '...';
|
return text.substring(0, maxLength).replace(/\s+\S*$/, '') + '...';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue