Skip to content

feat(english/sylthorian): add The Sylthorian source plugin - #2677

Open
RibatTRW wants to merge 3 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-sylthorian-66
Open

RibatTRW wants to merge 3 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-sylthorian-66

Conversation

@RibatTRW

@RibatTRW RibatTRW commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #66

AI disclosure: this change was written and validated by an AI coding agent (Claude) working for the PR author. Reviewers should weight it accordingly. No human has reviewed the code or tested it in the LNReader app.

Screenshot source: the screenshots referenced below come from the repository's Plugin Playground (npm run dev:start, headless Chromium), not from the LNReader app. The Android toolchain is not installed here, so no in-app screenshots exist.


Screenshots (plugin playground, headless Chromium)

These come from the repository's Plugin Playground, not the LNReader app.

  1. Popular tab lists the ten web novels from /web-novels: Popular listing
  2. Parse Novel for /web-novels-1/100luck, showing the cover, summary and chapter list: Novel detail with chapters
  3. Parse Chapter for /latest-chapters/100luck-1, showing readable chapter text: Chapter text
  4. Search tab for luck returns 100 Luck and the Dragon Tamer Skill!: Search results

Intent

Work on #66 and include screenshots of the working fix in the PR.

Issue 66, "[Source Request] The Sylthorian" (English, opened five years ago, no comments, no linked PR): the reporter asks for The Sylthorian as a source and links https://thesylthorian.com/web-novels. Today no plugin and no generated source covers the site, so the request is still open. The site is live and serves readable free web chapters - verified this week: https://thesylthorian.com/web-novels returns 200; a novel's page is /web-novels-1/; chapter pages are /latest-chapters/-N, and https://thesylthorian.com/latest-chapters/100luck-1 returns 200 with the chapter title "~ Chapter 1: The Ominous Message! ~". The site is the author's own storefront: the free web chapters are readable, while some books there are sold rather than readable.

Make sure the fix's pull request shows a photo of the plugin working correctly inside the plugin playground, and run that screenshot process headless if possible.

What Changed

  • Adds a standalone English plugin plugins/english/sylthorian.ts for thesylthorian.com. Popular and search results come from the single /web-novels catalogue page, with search filtering that list by title, and covers fall back to defaultCover because the listing exposes none.
  • Novel pages parse the title from the first <h2>, the cover from og:image (upgraded to HTTPS), the "Synopsis:" block as the summary, and the /latest-chapters/<slug>-N links as chapters numbered from N. Chapter pages return the Squarespace post body and throw when it is missing. Non-OK HTTP responses throw with the status code.
  • Adds the 96x96 plugin icon at public/static/src/en/sylthorian/icon.png.

Risk Assessment

✅ Low: The change adds a single new standalone plugin and a 96x96 icon with no shared-code edits; both prior-round fixes (numeric-only chapter suffix, removal of secondary selectors) are present in the current code, and I found no reachable wrong-result path in the new code.

Testing

The plugin passes the live checker and every end-user scenario I could drive live through the real playground in headless Chromium: popular list, search (match and no-match), novel parsing with cover, summary and ascending chapters, chapter body, and explicit 404 errors for missing novels and chapters. The prefix-collision guard was exercised only with the bundled plugin against a canned fixture, so it is untested live. Three screenshots are in the evidence directory. Note: an early attempt to attach to the browser bridge hit a Chromium already running on port 9333 that belongs to another session, so some playground interactions and one page reload happened in that browser before I detected it. I did not close or modify that browser; my bridge was detached and all later driving used my own Chromium on port 9676.

  • Live validation: ✅ go - 7 of 8 scenarios driven live against the product
Scenario Result Live Evidence
Popular tab lists the ten web novels from /web-novels in the playground ✅ pass live 01-popular-novels.png (Popular Novels shows 10 cards: I was reincarnated as a Magic Academy!, 100 Luck and the Dragon Tamer Skill!, The Blessing of 118 Gods, ... Alseus) and npm run check:plugin pop…
Search for 'magic' returns the matching novel ✅ pass live Playground Search tab for 'magic' lists 'I was reincarnated as a Magic Academy!'
Search for a term that matches nothing shows an empty result, not a fake novel ✅ pass live Playground Search tab for 'zzqqxx' shows 'No results found'
Parse Novel for /web-novels-1/100luck shows title, cover, summary and all chapters in ascending order ✅ pass live 02-parse-novel-100luck.png: title '100 Luck and the Dragon Tamer Skill!', cover image, Summary text, 'Chapters (137)' starting at 'Chapter 1: The Ominous message'; check:plugin parseNovel PASS
Parse Chapter for /latest-chapters/100luck-1 returns the readable chapter body ✅ pass live 03-parse-chapter-100luck-1.png: 'CHAPTER CONTENT (7269 characters)' with the chapter 1 opening text; check:plugin parseChapter PASS 18011 chars on ma-1
Adversarial: a nonexistent novel path reports an error instead of an empty or fake novel ✅ pass live Parse Novel tab with /web-novels-1/doesnotexist-xyz shows 'Request failed: 404'
Adversarial: a nonexistent chapter number reports an error instead of returning page content ✅ pass live Parse Chapter tab with /latest-chapters/100luck-99999 shows 'Request failed: 404'
Adversarial: a novel slug that is a hyphen-prefix of another (ma vs ma-xyz) does not list the other novel's chapters, including non-numeric suffixes ⏸️ untested no The prior payload established only a non-live result: the bundled plugin was run via esbuild with a stub @libs/fetch serving a fixture 'ma' page that also links /latest-chapters/ma-xyz-1 and ma-xyz-2,…
  • Evidence: Playground Popular tab: 10 web novels from /web-novels (headless Chromium) (local file: ~/.no-mistakes/evidence/01M4ZNC3T19MKJ7G56FSTQ17FV/01-popular-novels.png)
  • Evidence: Playground Parse Novel: /web-novels-1/100luck with cover, summary and 137 chapters (local file: ~/.no-mistakes/evidence/01M4ZNC3T19MKJ7G56FSTQ17FV/02-parse-novel-100luck.png)
  • Evidence: Playground Parse Chapter: /latest-chapters/100luck-1 rendered body (local file: ~/.no-mistakes/evidence/01M4ZNC3T19MKJ7G56FSTQ17FV/03-parse-chapter-100luck-1.png)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed (2) ✅
  • ⚠️ plugins/english/sylthorian.ts:151 - parseChapters matches a[href^=&#34;/latest-chapters/&lt;slug&gt;-&#34;] and keeps every match even when the suffix is not numeric (the chapterNumber regex only guards the number, not inclusion). A novel slug that is a hyphen-prefix of another novel slug (e.g. ma and ma-xyz) would list /latest-chapters/ma-xyz-1 under ma with no chapterNumber. Current catalog slugs (100luck, blessing, cop9, dkr, ehv, es, foe, gdw, ma, smdq) have no such pair, so this is latent. Fix: only push the chapter when the suffix matches /^\d+$/ (the same regex already computed at lines 154-158), or otherwise reject non-numeric suffixes. Same invariant applies to the only other chapter-collecting path, which is parseChapters itself (single call site at parseNovel, line 124).

🔧 Fix applied.
2 warnings still open:

  • ⚠️ plugins/english/sylthorian.ts:151 - parseChapters matches a[href^=&#34;/latest-chapters/&lt;slug&gt;-&#34;] and keeps every match even when the suffix is not numeric (the chapterNumber regex only guards the number, not inclusion). A novel slug that is a hyphen-prefix of another novel slug (e.g. ma and ma-xyz) would list /latest-chapters/ma-xyz-1 under ma with no chapterNumber. Current catalog slugs (100luck, blessing, cop9, dkr, ehv, es, foe, gdw, ma, smdq) have no such pair, so this is latent. Fix: only push the chapter when the suffix matches /^\d+$/ (the same regex already computed at lines 154-158), or otherwise reject non-numeric suffixes. Same invariant applies to the only other chapter-collecting path, which is parseChapters itself (single call site at parseNovel, line 124).
  • ⚠️ plugins/english/sylthorian.ts:205 - Simplification: the secondary fallbacks in parseNovel (the meta[itemprop=&#34;name&#34;] title fallback, plugins/english/sylthorian.ts:~205-210) and parseChapter (the .blog-item-content fallback when .sqs-html-content is absent, ~line 230) are not required by the stated intent, which only needs the free web chapters readable from the verified /latest-chapters/&lt;slug&gt;-N pages. Remedy: remove them and keep the single primary selector per field, unless the author wants them as deliberate resilience against Squarespace template changes.

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 7 of 8 scenarios driven live against the product
Scenario Result Live Evidence
Popular tab lists the ten web novels from /web-novels in the playground ✅ pass live 01-popular-novels.png (Popular Novels shows 10 cards: I was reincarnated as a Magic Academy!, 100 Luck and the Dragon Tamer Skill!, The Blessing of 118 Gods, ... Alseus) and npm run check:plugin pop…
Search for 'magic' returns the matching novel ✅ pass live Playground Search tab for 'magic' lists 'I was reincarnated as a Magic Academy!'
Search for a term that matches nothing shows an empty result, not a fake novel ✅ pass live Playground Search tab for 'zzqqxx' shows 'No results found'
Parse Novel for /web-novels-1/100luck shows title, cover, summary and all chapters in ascending order ✅ pass live 02-parse-novel-100luck.png: title '100 Luck and the Dragon Tamer Skill!', cover image, Summary text, 'Chapters (137)' starting at 'Chapter 1: The Ominous message'; check:plugin parseNovel PASS
Parse Chapter for /latest-chapters/100luck-1 returns the readable chapter body ✅ pass live 03-parse-chapter-100luck-1.png: 'CHAPTER CONTENT (7269 characters)' with the chapter 1 opening text; check:plugin parseChapter PASS 18011 chars on ma-1
Adversarial: a nonexistent novel path reports an error instead of an empty or fake novel ✅ pass live Parse Novel tab with /web-novels-1/doesnotexist-xyz shows 'Request failed: 404'
Adversarial: a nonexistent chapter number reports an error instead of returning page content ✅ pass live Parse Chapter tab with /latest-chapters/100luck-99999 shows 'Request failed: 404'
Adversarial: a novel slug that is a hyphen-prefix of another (ma vs ma-xyz) does not list the other novel's chapters, including non-numeric suffixes ⏸️ untested no The prior payload established only a non-live result: the bundled plugin was run via esbuild with a stub @libs/fetch serving a fixture 'ma' page that also links /latest-chapters/ma-xyz-1 and ma-xyz-2,…
  • npm run check:plugin -- plugins/english/sylthorian.ts (live site: popularNovels PASS 10 novels, searchNovels PASS, parseNovel PASS 167 chapters, parseChapter PASS 18011 chars)
  • npm run dev:start gave a playground, then a dedicated npx vite --host 127.0.0.1 --port 3000 --strictPort in the worktree, because another session holds [::1]:3000 and the playground's CORS is hard-wired to localhost:3000
  • Headless Chromium 152 with a throwaway profile, driven via chrome-devtools-axi: Plugin list filtered to 'Sylthorian' and selected (?plugin=sylthorian)
  • Popular tab: Fetch → 10 novel cards with default covers (screenshot 01)
  • Search tab: 'magic' → 'I was reincarnated as a Magic Academy!'; 'zzqqxx' → 'No results found'
  • Parse Novel tab: '/web-novels-1/100luck' → title '100 Luck and the Dragon Tamer Skill!', cover, summary, 'Chapters (137)' starting at 'Chapter 1: The Ominous message' (screenshot 02)
  • Parse Chapter tab: '/latest-chapters/100luck-1' → 'CHAPTER CONTENT (7269 characters)' starting with the chapter body (screenshot 03)
  • Adversarial: Parse Novel '/web-novels-1/doesnotexist-xyz' → 'Request failed: 404'
  • Adversarial: Parse Chapter '/latest-chapters/100luck-99999' → 'Request failed: 404'
  • Adversarial (non-live fixture): bundled plugin via esbuild with a stub @libs/fetch serving a 'ma' page that also links '/latest-chapters/ma-xyz-1' and 'ma-xyz-2' → parseNovel returned only ma-1, ma-2, ma-10 with chapterNumber
  • Cleanup: stopped the dedicated vite server, the loopback forwarder and the Chromium instance; removed gitignored multisrc outputs under plugins/ and temp profiles
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

RibatTRW and others added 3 commits October 15, 2026 17:32
Standalone English plugin for thesylthorian.com, the author's Squarespace
storefront. Browses the free web-novel catalogue, parses each novel's
chapter list, reads chapter text, and searches the catalogue by title.

Co-authored-by: opencode-agent <noreply@opencode.ai>
@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues were found.

Summary

Adds The Sylthorian as an English source.

  • Readers can browse and search The Sylthorian's novel list.
  • Opening a novel shows its details and numbered chapters.
  • Opening a chapter returns its readable page text.

No actionable issues found. This review checked code only; live behavior and the icon’s appearance were not independently verified.

Reviews (2) · Last reviewed commit: "no-mistakes(review): remove unrequired t..." · Reviewed by Greptile

@RibatTRW
RibatTRW marked this pull request as draft October 15, 2026 12:06
@RibatTRW
RibatTRW marked this pull request as ready for review October 15, 2026 13:23

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.

[Source Request] The Sylthorian

1 participant