From 95a230b1ef92cd41f0afa8b8e36306bbab2abfb1 Mon Sep 17 00:00:00 2001 From: Ryan Salazar Date: Wed, 27 May 2026 13:20:42 +0000 Subject: [PATCH] articles: strip dead WP image tags from imported post bodies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rewriteLegacyImageUrlsInHtml only swapped URLs that had a mapping in legacy-image-map.json — anything missing the map was left pointing at the dead https://www.broadcastbeat.com/wp-content/uploads/ host (404 in browsers, bad for SEO, broken-image icons everywhere). New stripDeadLegacyImages() pass runs after the rewrite and removes: -
blocks whose only inner image is a dead WP image - wrappers around dead images - Bare tags - Empty
leftovers …leaving body copy intact and figcaption-less. cleanLegacyImages() is the one-call helper that pipes both steps. Applied via rowToArticle so every /news/ render gets it. --- src/lib/articles/legacy-source.ts | 4 ++-- src/lib/legacy-image.ts | 37 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/lib/articles/legacy-source.ts b/src/lib/articles/legacy-source.ts index 3fa45e8..ca6f878 100644 --- a/src/lib/articles/legacy-source.ts +++ b/src/lib/articles/legacy-source.ts @@ -1,6 +1,6 @@ import { createClient } from "@supabase/supabase-js"; import type { Article } from "./types"; -import { rewriteLegacyImageUrl, rewriteLegacyImageUrlsInHtml } from "@/lib/legacy-image"; +import { rewriteLegacyImageUrl, cleanLegacyImages } from "@/lib/legacy-image"; const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL!; const SUPABASE_ANON = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!; @@ -128,7 +128,7 @@ function rowToArticle(row: ImportedPostRow, section: Section = "news"): Article const image = row.featured_image ? rewriteLegacyImageUrl(row.featured_image) : FALLBACK_IMAGE; - const content = rewriteLegacyImageUrlsInHtml(row.content || ""); + const content = cleanLegacyImages(row.content || ""); const author = row.author_name || "Broadcast Beat"; return { slug: row.wp_slug, diff --git a/src/lib/legacy-image.ts b/src/lib/legacy-image.ts index 1479306..7fb59db 100644 --- a/src/lib/legacy-image.ts +++ b/src/lib/legacy-image.ts @@ -32,3 +32,40 @@ export function rewriteLegacyImageUrlsInHtml(html: string): string { (m) => rewriteLegacyImageUrl(m), ); } + +/** + * Strip , , and their wrapping
/ tags whose src + * still points at the dead WP host AFTER rewriteLegacyImageUrl ran. These + * load 404s in the browser and hurt SEO; better to remove than to leave + * broken image icons. Tags whose src is anything else are left alone. + */ +export function stripDeadLegacyImages(html: string): string { + if (!html) return html; + + // Match tags whose src still hits the dead WP host. + const DEAD_HOST_RE = /https?:\/\/(?:www\.)?broadcastbeat\.com\/wp-content\/uploads\//i; + + // Drop entire
...
blocks whose only inner content is a + // dead-image . Preserves figures that wrap working images. + let out = html.replace(/]*>([\s\S]*?)<\/figure>/gi, (full, inner) => { + if (!/]*\bsrc\s*=\s*["'][^"']*broadcastbeat\.com\/wp-content\/uploads\/[^"']*["']/i.test(inner)) return full; + // figure contains a dead image — drop entirely + return ""; + }); + + // Drop
wrappers + out = out.replace(/]*>\s*]*\bsrc\s*=\s*["'][^"']*broadcastbeat\.com\/wp-content\/uploads\/[^"']*["'][^>]*\/?>\s*<\/a>/gi, ""); + + // Drop bare + out = out.replace(/]*\bsrc\s*=\s*["'][^"']*broadcastbeat\.com\/wp-content\/uploads\/[^"']*["'][^>]*\/?>/gi, ""); + + // Drop empty
left over after image removal. + out = out.replace(/]*>\s*(?:]*>\s*<\/figcaption>\s*)?<\/figure>/gi, ""); + + return out; +} + +/** One-call helper: rewrite mapped URLs, then strip anything still dead. */ +export function cleanLegacyImages(html: string): string { + return stripDeadLegacyImages(rewriteLegacyImageUrlsInHtml(html)); +}