fix summary blob (#1633)
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user