|
|
@@ -67,14 +67,27 @@ export class ContentExtractor {
|
|
|
'body'
|
|
|
];
|
|
|
|
|
|
+ // Pick the element with the most text content across all candidate selectors.
|
|
|
+ // Two reasons this is needed instead of .first() with an early break:
|
|
|
+ // 1. WordPress/Yoast pages often have several <article> tags (real post +
|
|
|
+ // sidebar widget cards) — .first() grabbed the widget.
|
|
|
+ // 2. On Divi/Elementor sites the real article body isn't wrapped in <article>
|
|
|
+ // at all (it lives in #main-content), and the only <article> tags are the
|
|
|
+ // 300-char widget cards. Breaking on the first selector that crosses a low
|
|
|
+ // threshold meant we never reached #main-content.
|
|
|
+ // <body> is excluded from this search because it's the fallback below — letting it
|
|
|
+ // win would pull in any boilerplate not stripped above.
|
|
|
+ let bestTextLen = 0;
|
|
|
for (const selector of contentSelectors) {
|
|
|
- const element = $(selector).first();
|
|
|
- if (element.length > 0) {
|
|
|
- mainContent = element.html() || '';
|
|
|
- if (mainContent.trim().length > 100) {
|
|
|
- break;
|
|
|
+ if (selector === 'body') continue;
|
|
|
+ $(selector).each((_, el) => {
|
|
|
+ const $el = $(el);
|
|
|
+ const textLen = $el.text().trim().length;
|
|
|
+ if (textLen > bestTextLen) {
|
|
|
+ bestTextLen = textLen;
|
|
|
+ mainContent = $el.html() || '';
|
|
|
}
|
|
|
- }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
if (!mainContent) {
|