/**
* Utilities for converting WordPress HTML content to React components
*/
import Image from "next/image"
import { ReactNode } from "react"
export interface WordPressImage {
originalUrl: string
localPath: string
alt: string
needsAltText: boolean
}
export interface ImageMapping {
[originalUrl: string]: WordPressImage
}
/**
* Load image mapping
*/
export function loadImageMapping(): ImageMapping {
try {
// Use dynamic import for fs in Next.js server components
const fs = require("fs")
const path = require("path")
// In Next.js, process.cwd() returns the code directory (where Next.js runs from)
const mappingPath = path.join(
process.cwd(),
"lib",
"wordpress-data",
"image-mapping.json"
)
if (!fs.existsSync(mappingPath)) {
console.warn("Image mapping file not found at:", mappingPath)
return {}
}
const mappingData = JSON.parse(fs.readFileSync(mappingPath, "utf8"))
const mapping: ImageMapping = {}
// Handle both array and object formats
if (Array.isArray(mappingData)) {
mappingData.forEach((img: any) => {
if (img && img.originalUrl) {
// Map the structure to match WordPressImage interface
mapping[img.originalUrl] = {
originalUrl: img.originalUrl,
localPath: img.localPath || img.path || "",
alt: img.alt || img.altText || "",
needsAltText: img.needsAltText || false,
}
}
})
} else if (typeof mappingData === "object" && mappingData !== null) {
Object.assign(mapping, mappingData)
}
return mapping
} catch (e) {
console.warn("Could not load image mapping:", e)
// Return empty object instead of throwing
return {}
}
}
/**
* Clean HTML entities
*/
export function cleanHtmlEntities(text: string): string {
if (!text || typeof text !== "string") {
return ""
}
return (
text
// First, handle 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, "...")
// Remove any remaining HTML tags (except those we want to preserve in dangerouslySetInnerHTML contexts)
// This strips out any stray tags that shouldn't be in plain text content
.replace(/<(?!\/?(strong|b|em|i|a)\b)[^>]+>/gi, "")
.trim()
)
}
/**
* Clean HTML from headings - strips ALL HTML tags and entities
* Use this for headings where we never want any HTML markup
*/
export function cleanHeadingText(text: string): string {
if (!text || typeof text !== "string") {
return ""
}
return (
text
// First, handle 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, "...")
// Remove ALL HTML tags - no exceptions for headings
.replace(/<[^>]+>/g, "")
// Clean up any leftover whitespace
.replace(/\s+/g, " ")
.trim()
)
}
/**
* Strip HTML tags and get clean text
*/
export function stripHtml(html: string): string {
if (!html || typeof html !== "string") {
return ""
}
return html
.replace(/