Skip to content

fix(english): load every part of multi-part Toasteful chapters - #2706

Open
RibatTRW wants to merge 3 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-toasteful-parts-2705
Open

RibatTRW wants to merge 3 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-toasteful-parts-2705

Conversation

@RibatTRW

@RibatTRW RibatTRW commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #2705. On some Toasteful novels, LNReader shows only the first part of a chapter that the site splits into parts.

The reporter's novel, I Was Reincarnated as a Nameless Combatant in a Japanese-style Fantasy Depressive Erotic Game, but the Women Around Me Are All Dangerous, and I Have a Bad Feeling about It (/2022/11/mob-yandere.html), links only part 1 of each chapter from its novel page. For example, "Chapter 4" links to mob-yandere-4-1.html. Parts 2–5 are separate posts that a reader reaches through the chapter's "Next CH." link. The site's sitemap has 805 posts for this novel, but its novel page links only 263, so the plugin never saw the other parts. A few chapters in other novels have the same layout, for example kokuyaku-v1c23-2, hajimari-trainer-v3c12-2, hero-mother-66-2 and enchanting-mage-v17c18-2.

I also checked two other possible causes, and neither applies. No novel page drops number-only part links: I checked all 72 novels. No chapter post hides parts behind tabs or in-post pagination: I checked 30 sampled "Part" chapters.

parseChapter now follows "Next CH." from a chapter and joins the parts. It does this only while the next post continues the same chapter and is not linked from the novel page. The PR's own changes are listed under "What Changed" below.

Before / after (reporter's novel, plugin parseChapter)

Chapter Parts on site 1.0.1 (words) 1.0.2 (words)
Chapter 4 (mob-yandere-4-1) 2 2613 (part 1 only) 4740
Chapter 10 (mob-yandere-10-1) 2 2763 (part 1 only) 4137
Chapter 89 (mob-yandere-89-1) 4 2054 (part 1 only) 8546
  • Whole novel: loading every chapter in the list reads 791 of the 805 posts on the site, up from 263. Of the 14 still unread, 12 sit behind three novel-page links that use the wrong month folder (chapter 176 and the volume 12 and 13 epilogues). Those links return 404 on the site as well, before and after this change. The other 2 posts are not linked from anywhere on the site.
  • Regression sweep: I took the first, middle and last chapter of all 72 novels (216 chapters) and compared the output of 1.0.1 and 1.0.2:
    • 201 are byte-identical.
    • 14 are novel-page links that return 404 on the site, unchanged by this PR.
    • 1 is a multi-part Mob Yandere chapter, which now loads all of its parts as intended.
  • Edge cases: I checked 18 chapters against the site's own "Next CH." chains, and all pass. These cases are covered:
    • Parts the novel page lists separately stay separate (kokuyaku-v1c28 and kokuyaku-v1c28-2).
    • An unlisted next chapter is not merged (hero-mother-379 → hero-mother-380).
    • Irregular part slugs load (mob-yandere-155-3-revise, mob-yandere-183-2-rev).
    • Volume epilogues split into Top and Bottom load correctly.
    • Posts whose "Next CH." is empty, which the site fills in client-side, load (mob-yandere-149, mob-yandere-195).
    • The Add Toasteful source plugin (English) #2671 test novels and the novel's last chapter are unchanged.
  • Empty later part (review follow-up): I forced part 2 of Chapter 4 to return HTTP 200 with no text. The previous head (7425d56) returned the chapter as a success with only part 1. It now throws Toasteful: no readable chapter text was found in /2022/11/mob-yandere-4-2.html. A short but non-empty part is still accepted. On the live novel, all chapters still load (791 of 805 posts read, same as before), so no real part is empty.
  • Part counts in the pipeline's Testing section below come from counting <hr> tags, and chapters contain <hr> tags of their own. For example, Chapter 10 (mob-yandere-10-1) has 2 parts on the site, not 5.
  • npm run check:plugin -- plugins/english/toasteful.ts passes, and ESLint and Prettier are clean.

Screenshots (plugin playground, live site)

The reporter's novel in Parse Novel:

Plugin playground: the reporter's novel parsed by Toasteful 1.0.2

Chapter 4 in Parse Chapter. The end of part 1 runs straight into the start of part 2 ("For the note, it is surprisingly difficult…"):

Plugin playground: Chapter 4 now contains part 1 and part 2

The popular list still loads:

Plugin playground: Toasteful popular list

This PR was written with an AI coding agent (Claude Code) and checked by the no-mistakes pipeline. I reproduced and verified everything above against the live site, so please weight your review with that in mind.

What Changed

  • parseChapter in plugins/english/toasteful.ts now follows the chapter's "Next CH." link and appends each later part, joined with <hr>. This covers novels whose novel page links only part 1 (e.g. mob-yandere), so the rest of the chapter is no longer cut off.
  • Part detection:
    • It guesses the next part number when "Next CH." is empty.
    • It stops at the first of these: a path already seen, a part from a different chapter or novel (checked by slug stem), a post the novel page lists as its own chapter, a 404, or 20 parts.
    • It throws on other HTTP failures and on a later part with no readable text.
  • Chapter cleanup moved into a chapterContent helper. Plugin version bumped from 1.0.1 to 1.0.2.

Risk Assessment

✅ Low: The change is confined to one plugin's parseChapter. It follows the recorded decision (throw on non-404 failures, break on 404), and the slug and listing guards stop it from running into the next real chapter.

Testing

I bundled the plugin and ran it against the live toasteful.com site. Search found the reported novel, and parseNovel returned 266 chapters. Loading chapter mob-yandere-10-1 returned 38,707 characters in 5 parts joined by &lt;hr&gt;. With part 2 forced to HTTP 429, the chapter threw "Toasteful: HTTP 429." instead of returning only part 1. With part 2 forced to 404, the chapter ended there and returned 2 parts. The repo's check:plugin passed on all four checks. I did not run the base commit for comparison. I did not post the PR JSON reply on the issue comment, because that is a later delivery step.

  • Live validation: ✅ go - 4 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Reported novel lists many chapters and a multi-part chapter loads every part ✅ pass live live.txt: 266 chapters, mob-yandere-10-1 returned 5 parts (4 &lt;hr&gt; separators), 38707 characters
A later part fetch returning 429 throws instead of returning a truncated chapter ✅ pass live live.txt: THROW Toasteful: HTTP 429.
A 404 on a later part ends the chapter without throwing ✅ pass live live.txt: OK len 25343, 2 parts
Repo live check of the plugin passes ✅ pass live npm run check:plugin output: popularNovels, searchNovels, parseNovel and parseChapter all PASS
Evidence: live driver output
search 1 [
]
chapters 266 [
]
target /2022/11/mob-yandere-10-1.html
OK len 38707 hrs 4
== 429
target /2022/11/mob-yandere-10-1.html
THROW Toasteful: HTTP 429.
== 404
target /2022/11/mob-yandere-10-1.html
OK len 25343 hrs 2

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 4 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Reported novel lists many chapters and a multi-part chapter loads every part ✅ pass live live.txt: 266 chapters, mob-yandere-10-1 returned 5 parts (4 &lt;hr&gt; separators), 38707 characters
A later part fetch returning 429 throws instead of returning a truncated chapter ✅ pass live live.txt: THROW Toasteful: HTTP 429.
A 404 on a later part ends the chapter without throwing ✅ pass live live.txt: OK len 25343, 2 parts
Repo live check of the plugin passes ✅ pass live npm run check:plugin output: popularNovels, searchNovels, parseNovel and parseChapter all PASS
  • npm run check:plugin -- plugins/english/toasteful.ts (passed)
  • Bundled the real plugin and ran searchNovels, parseNovel and parseChapter on the reported novel against the live site
  • Same run with part 2 of mob-yandere-10-1 forced to return 429, then 404
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Some Toasteful novels (e.g. "I Was Reincarnated as a Nameless Combatant
in a Japanese-style Fantasy Depressive Erotic Game...", mob-yandere) link
only part 1 of each chapter from the novel page; parts 2+ are separate
posts reached only through the chapter's "Next CH." link, so the app
showed just the first part.

parseChapter now follows "Next CH." while it leads to a post that shares
the chapter's slug stem and is not linked from the novel page, and joins
the parts. When a post ships an empty "Next CH." (the site fills it in
client-side), the next part number is tried instead. Parts the novel page
lists as their own chapters, and the next chapter of a novel, are left
alone.

Closes lnreader#2705
@greptile-apps

greptile-apps Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] Loads multi-part chapters from a web novel source.

Fix the empty later-page check before merging so incomplete chapters do not look successfully loaded.

Findings

  1. P1 Empty parts pass unnoticed ▶

Summary

Updates Toasteful to load later chapter parts and join them with <hr>.

  • Toasteful chapters include all their linked parts.

Acknowledged behavior: RibatTRW explicitly describes stopping at HTTP 404 and limiting chapters to 20 parts. These limits were not reported as defects.

Reviews (1) · Last reviewed commit: "no-mistakes(review): throw on non-404 fa..." · Reviewed by Greptile

Comment thread plugins/english/toasteful.ts Outdated
Comment on lines +327 to +329
const $part = loadCheerio(await response.text());
next = $part('.ChapterNav a.next').attr('href');
parts.push(this.chapterContent($part));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Empty parts pass unnoticed

If a later part returns HTTP 200 without chapter text, chapterContent returns an empty string and this loop appends it without checking. Part 1 alone can satisfy the combined 200-character check, so parseChapter returns an incomplete chapter as a success.

Reject later pages with no readable text before appending them. Short but valid parts can still use the combined length check.

Knowledge Base Used: English source plugins

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, fixed in 752534a. A later part whose cleaned content has no readable text now throws Toasteful: no readable chapter text was found in <part path>. instead of being appended. Short but non-empty parts still go through the combined length check. I checked this by forcing part 2 of mob-yandere-4-1 to return HTTP 200 with an empty body. The previous head returned part 1 as a success, and now it throws. A full pass over the reporter's novel still reads the same 791 of 805 posts, so no real part is empty. (Reply written with an AI coding agent.)

A later part that returns HTTP 200 with no readable text was appended as
an empty string, and part 1 alone could satisfy the combined length
check, so an incomplete chapter was returned as a success. Throw when a
later part has no readable text; short but non-empty parts still pass.
RibatTRW added a commit to RibatTRW/lnreader-plugins that referenced this pull request Oct 18, 2026
@RibatTRW RibatTRW mentioned this pull request Oct 18, 2026
5 tasks done

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Toasteful

1 participant