diff --git a/vue/src/composables/__tests__/useFeeds.spec.js b/vue/src/composables/__tests__/useFeeds.spec.js index 4557d03..f10bafa 100644 --- a/vue/src/composables/__tests__/useFeeds.spec.js +++ b/vue/src/composables/__tests__/useFeeds.spec.js @@ -934,4 +934,55 @@ describe('useFeeds', () => { expect(feeds.value[0].content).not.toContain('%7Bsize%7D') expect(feeds.value[0].content).not.toContain(' { + feeds.value = [{ + id: 1, + title: 'Article one', + url: 'https://www.aljazeera.com/news/2026/9/14/article-one', + content: '', + }] + axios.post.mockResolvedValueOnce({ + data: { + content: `
+

some article text long enough for readability to keep the paragraph as the main content body, padded with extra words to pass the content-length heuristics used by Mozilla Readability when scoring candidate nodes.

+

Recommended Stories

list of 3 itemsend of list
+

more article text long enough to survive readability's content-length heuristics as well, since it needs to look like part of the main body too.

+
`, + }, + }) + + await getReadable(feeds.value[0], 0) + + expect(feeds.value[0].readable).toBe(true) + expect(feeds.value[0].content).toContain('main content body') + expect(feeds.value[0].content).not.toContain('Recommended Stories') + expect(feeds.value[0].content).not.toContain('Unrelated story') + }) + + it('keeps other sections that are not the "Recommended Stories" block', async () => { + feeds.value = [{ + id: 1, + title: 'Article one', + url: 'https://www.aljazeera.com/news/2026/9/14/article-one', + content: '', + }] + axios.post.mockResolvedValueOnce({ + data: { + content: `
+

some article text long enough for readability to keep the paragraph as the main content body, padded with extra words to pass the content-length heuristics used by Mozilla Readability when scoring candidate nodes.

+

more article text long enough to survive readability's content-length heuristics as well, since it needs to look like part of the main body too.

+
`, + }, + }) + + await getReadable(feeds.value[0], 0) + + expect(feeds.value[0].readable).toBe(true) + expect(feeds.value[0].content).toContain('main content body') + }) }) diff --git a/vue/src/composables/useFeeds.js b/vue/src/composables/useFeeds.js index 43526c5..772c22e 100644 --- a/vue/src/composables/useFeeds.js +++ b/vue/src/composables/useFeeds.js @@ -271,6 +271,11 @@ async function getReadable(feed, index) { const container = el.closest('section') ?? el.closest('article') if (container) container.remove() }) + // Al Jazeera embeds a "Recommended Stories" section (a heading followed by + // a list of unrelated article teasers), marked up as
. + // It's not part of the article, so strip it before Readability pulls it + // into the parsed content. + doc.querySelectorAll('section.more-on').forEach(el => el.remove()) const article = new Readability(doc).parse(); if (!article) { showMessageForXSeconds('Could not extract readable content.', 5)