RoyalRoad: escape < and > when htmlparser2 (#1637)

* fix build error

* add escape to lnmtl as well
This commit is contained in:
K1ngfish3r
2025-04-17 07:27:33 +05:00
committed by GitHub
parent 32fccc7738
commit 0d4d850935
2 changed files with 38 additions and 12 deletions
+18 -2
View File
@@ -260,6 +260,22 @@ class LnMTLPlugin implements Plugin.PagePlugin {
let state: ParsingState = ParsingState.Idle;
const chapterTextParts: string[] = [];
type EscapeChar = '&' | '<' | '>' | '"' | "'";
const escapeRegex = /[&<>"']/g;
const escapeMap: Record<EscapeChar, string> = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
};
const escapeHtml = (text: string): string =>
escapeRegex.test(text)
? ((escapeRegex.lastIndex = 0),
text.replace(escapeRegex, char => escapeMap[char as EscapeChar]))
: text;
const parser = new Parser({
onopentag(name, attribs) {
if (name === 'sentence' && attribs['class']?.includes('translated')) {
@@ -274,11 +290,11 @@ class LnMTLPlugin implements Plugin.PagePlugin {
},
ontext(data) {
if (state === ParsingState.Chapter) {
chapterTextParts.push(data);
chapterTextParts.push(escapeHtml(data));
}
},
onclosetag(name) {
if (name === 'sentence') {
if (name === 'sentence' && state === ParsingState.Chapter) {
chapterTextParts.push('</p>');
state = ParsingState.Idle;
}
+20 -10
View File
@@ -312,7 +312,22 @@ class RoyalRoad implements Plugin.PluginBase {
depth: number;
} | null = null;
const parser = new AlternateParser({
type EscapeChar = '&' | '<' | '>' | '"' | "'";
const escapeRegex = /[&<>"']/g;
const escapeMap: Record<EscapeChar, string> = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
};
const escapeHtml = (text: string): string =>
escapeRegex.test(text)
? ((escapeRegex.lastIndex = 0),
text.replace(escapeRegex, char => escapeMap[char as EscapeChar]))
: text;
const parser = new Parser({
onopentag(name, attribs) {
depth++;
const classes = attribs['class'] || '';
@@ -361,10 +376,10 @@ class RoyalRoad implements Plugin.PluginBase {
ontext(text) {
switch (state) {
case ParsingState.InChapter:
chapterHtmlParts.push(text);
chapterHtmlParts.push(escapeHtml(text));
break;
case ParsingState.InNote:
notesHtmlParts.push(text);
notesHtmlParts.push(escapeHtml(text));
break;
}
},
@@ -383,6 +398,7 @@ class RoyalRoad implements Plugin.PluginBase {
depth--;
return;
case ParsingState.InChapter:
chapterHtmlParts.push(`</div>`);
state = ParsingState.Idle;
stateDepth = 0;
depth--;
@@ -406,7 +422,7 @@ class RoyalRoad implements Plugin.PluginBase {
state === ParsingState.InChapter ||
state === ParsingState.InNote
) {
if (!parser.checkVoidElement(name)) {
if (!parser['isVoidElement'](name)) {
const closingTag = `</${name}>`;
if (state === ParsingState.InChapter) {
chapterHtmlParts.push(closingTag);
@@ -904,12 +920,6 @@ class RoyalRoad implements Plugin.PluginBase {
export default new RoyalRoad();
class AlternateParser extends Parser {
public checkVoidElement(name: string): boolean {
return this.isVoidElement(name);
}
}
type ChapterEntry = {
id: number;
volumeId: number;