fix summary blob (#1633)

This commit is contained in:
K1ngfish3r
2025-04-13 19:07:29 +05:00
committed by GitHub
parent 63e7f42879
commit 485c98343b
+66 -38
View File
@@ -8,7 +8,7 @@ import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
class RoyalRoad implements Plugin.PluginBase { class RoyalRoad implements Plugin.PluginBase {
id = 'royalroad'; id = 'royalroad';
name = 'Royal Road'; name = 'Royal Road';
version = '2.2.1'; version = '2.2.2';
icon = 'src/en/royalroad/icon.png'; icon = 'src/en/royalroad/icon.png';
site = 'https://www.royalroad.com/'; site = 'https://www.royalroad.com/';
@@ -45,8 +45,10 @@ class RoyalRoad implements Plugin.PluginBase {
} }
}, },
}); });
parser.write(html); parser.write(html);
parser.end(); parser.end();
return novels; return novels;
} }
@@ -111,10 +113,14 @@ class RoyalRoad implements Plugin.PluginBase {
} }
let state: ParsingState = ParsingState.Idle; let state: ParsingState = ParsingState.Idle;
let scriptContent = '';
let statusText = ''; let statusText = '';
let statusSpanCounter = 0; let statusSpanCounter = 0;
const nameParts: string[] = [];
const summaryParts: string[] = [];
const scriptContentParts: string[] = [];
const genreArray: string[] = []; const genreArray: string[] = [];
let chapterJson: ChapterEntry[] = []; let chapterJson: ChapterEntry[] = [];
let volumeJson: VolumeEntry[] = []; let volumeJson: VolumeEntry[] = [];
@@ -137,7 +143,16 @@ class RoyalRoad implements Plugin.PluginBase {
case 'div': case 'div':
if (attribs['class'] === 'description') { if (attribs['class'] === 'description') {
state = ParsingState.InDescription; state = ParsingState.InDescription;
novel.summary = ''; }
break;
case 'hr':
if (state === ParsingState.InDescription) {
summaryParts.push('\n---\n');
}
break;
case 'br':
if (state === ParsingState.InDescription) {
summaryParts.push('\n\n');
} }
break; break;
case 'span': case 'span':
@@ -161,7 +176,6 @@ class RoyalRoad implements Plugin.PluginBase {
break; break;
case 'script': case 'script':
state = ParsingState.InScript; state = ParsingState.InScript;
scriptContent = '';
break; break;
} }
}, },
@@ -171,13 +185,13 @@ class RoyalRoad implements Plugin.PluginBase {
switch (state) { switch (state) {
case ParsingState.InTitle: case ParsingState.InTitle:
novel.name += text; nameParts.push(text);
break; break;
case ParsingState.InAuthor: case ParsingState.InAuthor:
novel.author = trimmedText; novel.author = trimmedText;
break; break;
case ParsingState.InDescription: case ParsingState.InDescription:
novel.summary += text; summaryParts.push(text);
break; break;
case ParsingState.InStatusSpan: case ParsingState.InStatusSpan:
statusText = trimmedText; statusText = trimmedText;
@@ -186,7 +200,7 @@ class RoyalRoad implements Plugin.PluginBase {
genreArray.push(trimmedText); genreArray.push(trimmedText);
break; break;
case ParsingState.InScript: case ParsingState.InScript:
scriptContent += text; scriptContentParts.push(text);
break; break;
} }
}, },
@@ -194,7 +208,7 @@ class RoyalRoad implements Plugin.PluginBase {
switch (name) { switch (name) {
case 'h1': case 'h1':
if (state === ParsingState.InTitle) { if (state === ParsingState.InTitle) {
novel.name = novel.name.trim(); novel.name = nameParts.join('').trim();
state = ParsingState.Idle; state = ParsingState.Idle;
} }
break; break;
@@ -205,11 +219,20 @@ class RoyalRoad implements Plugin.PluginBase {
state = ParsingState.Idle; state = ParsingState.Idle;
} }
break; break;
case 'p':
if (state === ParsingState.InDescription) {
summaryParts.push('\n\n');
}
break;
case 'div': case 'div':
if (state === ParsingState.InDescription) { if (state === ParsingState.InDescription) {
if (novel.summary) { novel.summary = summaryParts
novel.summary = novel.summary.trim(); .join('')
} .replace(/ /g, ' ')
.replace(/\s*\n\s*/g, '\n')
.replace(/\n{3,}/g, '\n\n')
.trim();
summaryParts.length = 0;
state = ParsingState.Idle; state = ParsingState.Idle;
} }
break; break;
@@ -224,6 +247,7 @@ class RoyalRoad implements Plugin.PluginBase {
case 'script': case 'script':
if (state === ParsingState.InScript) { if (state === ParsingState.InScript) {
state = ParsingState.Idle; state = ParsingState.Idle;
const scriptContent = scriptContentParts.join('');
const chapterMatch = scriptContent.match( const chapterMatch = scriptContent.match(
/window\.chapters\s*=\s*(\[.*?\]);/, /window\.chapters\s*=\s*(\[.*?\]);/,
); );
@@ -272,9 +296,6 @@ class RoyalRoad implements Plugin.PluginBase {
}; };
}); });
}, },
onerror(error) {
console.error('HTML Parser Error:', error);
},
}); });
parser.write(html); parser.write(html);
@@ -298,13 +319,13 @@ class RoyalRoad implements Plugin.PluginBase {
let stateDepth = 0; let stateDepth = 0;
let depth = 0; let depth = 0;
let chapterHtml = ''; const chapterHtmlParts: string[] = [];
let notesHtml = ''; const notesHtmlParts: string[] = [];
let beforeNotes = ''; const beforeNotesParts: string[] = [];
let afterNotes = ''; const afterNotesParts: string[] = [];
let isBeforeChapter = true; let isBeforeChapter = true;
const match = html.match(/<style>\n\s+.(.+?){[^.]+?display: none;/); const match = html.match(/<style>\n\s+.(.+?){[^{]+?display: none;/);
const hiddenClass = match?.[1]?.trim(); const hiddenClass = match?.[1]?.trim();
let stateBeforeHidden: { let stateBeforeHidden: {
state: ChapterParsingState; state: ChapterParsingState;
@@ -336,7 +357,6 @@ class RoyalRoad implements Plugin.PluginBase {
} else if (classes.includes('author-note-portlet')) { } else if (classes.includes('author-note-portlet')) {
state = ChapterParsingState.InNote; state = ChapterParsingState.InNote;
stateDepth = depth; stateDepth = depth;
notesHtml = '';
} }
break; break;
case ChapterParsingState.InHidden: case ChapterParsingState.InHidden:
@@ -355,19 +375,19 @@ class RoyalRoad implements Plugin.PluginBase {
tag += '>'; tag += '>';
if (state === ChapterParsingState.InChapter) { if (state === ChapterParsingState.InChapter) {
chapterHtml += tag; chapterHtmlParts.push(tag);
} else { } else {
notesHtml += tag; notesHtmlParts.push(tag);
} }
} }
}, },
ontext(text) { ontext(text) {
switch (state) { switch (state) {
case ChapterParsingState.InChapter: case ChapterParsingState.InChapter:
chapterHtml += text; chapterHtmlParts.push(text);
break; break;
case ChapterParsingState.InNote: case ChapterParsingState.InNote:
notesHtml += text; notesHtmlParts.push(text);
break; break;
} }
}, },
@@ -392,38 +412,46 @@ class RoyalRoad implements Plugin.PluginBase {
return; return;
case ChapterParsingState.InNote: case ChapterParsingState.InNote:
const noteClass = `author-note-${isBeforeChapter ? 'before' : 'after'}`; const noteClass = `author-note-${isBeforeChapter ? 'before' : 'after'}`;
const fullNote = `<div class="${noteClass}">${notesHtml.trim()}</div>`; const notesHtml = notesHtmlParts.join('').trim();
const fullNote = `<div class="${noteClass}">${notesHtml}</div>`;
if (isBeforeChapter) { if (isBeforeChapter) {
beforeNotes += fullNote; beforeNotesParts.push(fullNote);
} else { } else {
afterNotes += fullNote; afterNotesParts.push(fullNote);
} }
notesHtml = ''; notesHtmlParts.length = 0;
state = ChapterParsingState.Idle; state = ChapterParsingState.Idle;
stateDepth = 0; stateDepth = 0;
depth--; depth--;
return; return;
} }
} } else if (
if (
state === ChapterParsingState.InChapter || state === ChapterParsingState.InChapter ||
state === ChapterParsingState.InNote state === ChapterParsingState.InNote
) { ) {
const closingTag = `</${name}>`; // Avoid adding closing tags for self-closing elements
if (state === ChapterParsingState.InChapter) { const selfClosingTags = ['img', 'br', 'hr'];
chapterHtml += closingTag; if (!selfClosingTags.includes(name)) {
} else { const closingTag = `</${name}>`;
notesHtml += closingTag; if (state === ChapterParsingState.InChapter) {
chapterHtmlParts.push(closingTag);
} else {
notesHtmlParts.push(closingTag);
}
} }
} }
depth--; depth--;
}, },
}); });
parser.write(html); parser.write(html);
parser.end(); parser.end();
return [beforeNotes, chapterHtml.trim(), afterNotes] return [
beforeNotesParts.length > 0 ? beforeNotesParts.join('') : null,
chapterHtmlParts.length > 0 ? chapterHtmlParts.join('').trim() : null,
afterNotesParts.length > 0 ? afterNotesParts.join('') : null,
]
.filter(Boolean) .filter(Boolean)
.join('\n<hr class="notes-separator">\n'); .join('\n<hr class="notes-separator">\n');
} }
@@ -438,8 +466,8 @@ class RoyalRoad implements Plugin.PluginBase {
globalFilters: 'true', globalFilters: 'true',
}); });
const searchUrl = `${this.site}fictions/search?${params.toString()}`; const searchUrl = `${this.site}fictions/search?${params.toString()}`;
const body = await fetchApi(searchUrl).then(r => r.text()); const body = await fetchApi(searchUrl).then(r => r.text());
return this.parseNovels(body); return this.parseNovels(body);
} }