From 5634303363cbe8217cb749f814d12e43d820c67f Mon Sep 17 00:00:00 2001 From: Enoch Ma Date: Thu, 5 Feb 2026 09:25:53 +0100 Subject: [PATCH] feat(route/bbc): improve bbc (cn) (#21066) --- lib/routes/bbc/utils.ts | 35 ----------- lib/routes/bbc/utils.tsx | 129 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 35 deletions(-) delete mode 100644 lib/routes/bbc/utils.ts create mode 100644 lib/routes/bbc/utils.tsx diff --git a/lib/routes/bbc/utils.ts b/lib/routes/bbc/utils.ts deleted file mode 100644 index e6ad2cbb8..000000000 --- a/lib/routes/bbc/utils.ts +++ /dev/null @@ -1,35 +0,0 @@ -const ProcessFeed = ($) => { - // by default treat it as a hybrid news with video and story-body__inner - let content = $('#main-content article'); - - if (content.length === 0) { - // it's a video news with video and story-body - content = $('div.story-body'); - } - - if (content.length === 0) { - // chinese version has different structure - content = $('main[role="main"]'); - } - - // remove useless DOMs - content.find('header, section, [data-testid="bbc-logo-wrapper"]').remove(); - - content.find('noscript').each((i, e) => { - $(e).parent().html($(e).html()); - }); - - content.find('img').each((i, e) => { - if (!$(e).attr('src') && $(e).attr('srcSet')) { - const srcs = $(e).attr('srcSet').split(', '); - const lastSrc = srcs.at(-1); - $(e).attr('src', lastSrc.split(' ')[0]); - } - }); - - content.find('[data-component="media-block"] figcaption').prepend('View video in browser: '); - - return content.html(); -}; - -export default { ProcessFeed }; diff --git a/lib/routes/bbc/utils.tsx b/lib/routes/bbc/utils.tsx new file mode 100644 index 000000000..164ba2aeb --- /dev/null +++ b/lib/routes/bbc/utils.tsx @@ -0,0 +1,129 @@ +import { renderToString } from 'hono/jsx/dom/server'; + +const processImageAttributes = ($img) => { + if (!$img.attr('src') && $img.attr('srcSet')) { + const srcs = $img.attr('srcSet').split(', '); + const lastSrc = srcs.at(-1); + if (lastSrc) { + $img.attr('src', lastSrc.split(' ')[0]); + } + } + $img.removeAttr('srcset').removeAttr('sizes'); +}; + +const buildCleanFigure = (src, alt, figcaptionContent) => + renderToString( +
+ {alt} + {figcaptionContent &&
{figcaptionContent}
} +
+ ); + +const cleanFigureElement = ($, figure) => { + const $figure = $(figure); + const $img = $figure.find('img'); + + if ($img.length === 0) { + return; + } + + processImageAttributes($img); + + let sourceText = ''; + let captionText = ''; + + // extract image source: (simp chinese/trad chinese) + const $sourceP = $figure.find('p[class*="css-"]').first(); + if ($sourceP.length > 0) { + const sourceSpans = $sourceP.find('span'); + if (sourceSpans.length >= 2) { + sourceText = sourceSpans.eq(1).text().trim(); + } + } + + let $figcaption = $figure.find('figcaption'); + + // english version + if ($figcaption.length === 0) { + const $next = $figure.next(); + if ($next.length > 0) { + $figcaption = $next.find('figcaption'); + // if found, remove the sibling div after extracting caption + if ($figcaption.length > 0) { + $next.remove(); + } + } + } + + if ($figcaption.length > 0) { + // try to find caption in specific elements, excluding visually-hidden labels + const $captionParagraph = $figcaption.find('[data-testid="caption-paragraph"]'); + + if ($captionParagraph.length > 0) { + captionText = $captionParagraph.text().trim(); + } else { + // remove visually-hidden elements (like "Image caption, " labels) + const $figcaptionClone = $figcaption.clone(); + $figcaptionClone.find('.visually-hidden, [class*="VisuallyHidden"]').remove(); + captionText = $figcaptionClone.text().trim(); + } + } + + const parts = [sourceText, captionText].filter(Boolean); + const figcaptionContent = parts.join(' / '); + + $figure.replaceWith(buildCleanFigure($img.attr('src'), $img.attr('alt') || '', figcaptionContent)); +}; + +const ProcessFeed = ($) => { + // by default treat it as a hybrid news with video and story-body__inner + let content = $('#main-content article'); + + if (content.length === 0) { + // it's a video news with video and story-body + content = $('div.story-body'); + } + + if (content.length === 0) { + // chinese version has different structure + content = $('main[role="main"]'); + } + + // remove useless DOMs + content.find('header, section, [data-testid="bbc-logo-wrapper"]').remove(); + + // remove article title as it's already in RSS item title + content.find('h1').remove(); + + content.find('noscript').each((i, e) => { + $(e).parent().html($(e).html()); + }); + + // clean up figure elements with images + content.find('figure').each((i, figure) => cleanFigureElement($, figure)); + + // handle standalone images with figcaption siblings (English version) + content + .find('img') + .not('figure img') + .each((i, img) => { + const $img = $(img); + processImageAttributes($img); + + // check for figcaption sibling + const $next = $img.next(); + if ($next.length > 0 && $next.find('figcaption').length > 0) { + const captionText = $next.find('figcaption').first().text().trim(); + if (captionText) { + $img.replaceWith(buildCleanFigure($img.attr('src'), $img.attr('alt') || '', captionText)); + $next.remove(); + } + } + }); + + content.find('[data-component="media-block"] figcaption').prepend('View video in browser: '); + + return content.html(); +}; + +export default { ProcessFeed };