Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions plugin/js/parsers/LightNovelWorldOrgParser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"use strict";

// Use one or more of these to specify when the parser is to be used
Copy link
Owner

Choose a reason for hiding this comment

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

FYI. This comment is no longer relevant, you've specified one.


parserFactory.register("lightnovelworld.org", () => new LightNovelWorldOrgParser());

class LightNovelWorldOrgParser extends Parser {
constructor() {
super();
}

// eslint-disable-next-line no-unused-vars
async getChapterUrls(dom, chapterUrlsUI) {
const url = dom.baseURI;
const match = url.match(new RegExp("/novel/([^/]+)"));
if (!match) {
throw new Error("Could not extract novel name from URL");
}
const novelName = match[1];
return await this.getChapterUrlsFromApi(novelName);
}

async getChapterUrlsFromApi(novelName) {
const baseUrl = `https://lightnovelworld.org/api/novel/${novelName}/chapters/`;
const limit = 500; // max limit (more than 500 just defaults to 500)
let offset = 0;
let allChapters = [];
let hasMore = true;

while (hasMore) {
const apiUrl = `${baseUrl}?offset=${offset}&limit=${limit}`;
const response = await HttpClient.fetchJson(apiUrl);
const data = response.json;

if (data.chapters) {
const chapters = data.chapters.map(chapter => ({
sourceUrl: `https://lightnovelworld.org/novel/${novelName}/chapter/${chapter.number}/`,
title: chapter.title
}));
allChapters.push(...chapters);
}

hasMore = data.has_more;
offset += limit;
}

return allChapters;
}

findContent(dom) {
return dom.querySelector(".chapter-content");
}

extractTitleImpl(dom) {
return dom.querySelector(".novel-title");
}


extractAuthor(dom) {
let authorLabel = dom.querySelector(".novel-author");
let authorText = authorLabel?.textContent?.trim() ?? super.extractAuthor(dom);
// Remove "Author: " prefix if present
return authorText.replace(/^Author:\s*/i, "");
}

extractLanguage(dom) {
return dom.querySelector("html").getAttribute("lang");
Copy link
Owner

Choose a reason for hiding this comment

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

FYI. Base class already looks for the language there. So, this function is not needed in this case.

}

extractSubject(dom) {
let tags = [...dom.querySelectorAll(".genre-tags")];
return tags.map(e => e.textContent.trim()).join(", ");
}

extractDescription(dom) {
return dom.querySelector(".summary-content").textContent.trim();
}

findChapterTitle(dom) {
return dom.querySelector(".chapter-title");
}

findCoverImageUrl(dom) {
return util.getFirstImgSrc(dom, ".novel-cover-container");
}
}
1 change: 1 addition & 0 deletions plugin/popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ <h3>Instructions</h3>
<script src="js/parsers/LightnovelreaderParser.js"></script>
<script src="js/parsers/LightnovelreadParser.js"></script>
<script src="js/parsers/LightnovelsmeParser.js"></script>
<script src="js/parsers/LightNovelWorldOrgParser.js"></script>
<script src="js/parsers/LightNovelWorldParser.js"></script>
<script src="js/parsers/LiteroticaParser.js"></script>
<script src="js/parsers/LnmtlParser.js"></script>
Expand Down
Loading