RoyalRoad: escape < and > when htmlparser2 (#1637)
* fix build error * add escape to lnmtl as well
This commit is contained in:
@@ -260,6 +260,22 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
|||||||
|
|
||||||
let state: ParsingState = ParsingState.Idle;
|
let state: ParsingState = ParsingState.Idle;
|
||||||
const chapterTextParts: string[] = [];
|
const chapterTextParts: string[] = [];
|
||||||
|
|
||||||
|
type EscapeChar = '&' | '<' | '>' | '"' | "'";
|
||||||
|
const escapeRegex = /[&<>"']/g;
|
||||||
|
const escapeMap: Record<EscapeChar, string> = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
"'": ''',
|
||||||
|
};
|
||||||
|
const escapeHtml = (text: string): string =>
|
||||||
|
escapeRegex.test(text)
|
||||||
|
? ((escapeRegex.lastIndex = 0),
|
||||||
|
text.replace(escapeRegex, char => escapeMap[char as EscapeChar]))
|
||||||
|
: text;
|
||||||
|
|
||||||
const parser = new Parser({
|
const parser = new Parser({
|
||||||
onopentag(name, attribs) {
|
onopentag(name, attribs) {
|
||||||
if (name === 'sentence' && attribs['class']?.includes('translated')) {
|
if (name === 'sentence' && attribs['class']?.includes('translated')) {
|
||||||
@@ -274,11 +290,11 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
|||||||
},
|
},
|
||||||
ontext(data) {
|
ontext(data) {
|
||||||
if (state === ParsingState.Chapter) {
|
if (state === ParsingState.Chapter) {
|
||||||
chapterTextParts.push(data);
|
chapterTextParts.push(escapeHtml(data));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onclosetag(name) {
|
onclosetag(name) {
|
||||||
if (name === 'sentence') {
|
if (name === 'sentence' && state === ParsingState.Chapter) {
|
||||||
chapterTextParts.push('</p>');
|
chapterTextParts.push('</p>');
|
||||||
state = ParsingState.Idle;
|
state = ParsingState.Idle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,7 +312,22 @@ class RoyalRoad implements Plugin.PluginBase {
|
|||||||
depth: number;
|
depth: number;
|
||||||
} | null = null;
|
} | null = null;
|
||||||
|
|
||||||
const parser = new AlternateParser({
|
type EscapeChar = '&' | '<' | '>' | '"' | "'";
|
||||||
|
const escapeRegex = /[&<>"']/g;
|
||||||
|
const escapeMap: Record<EscapeChar, string> = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"',
|
||||||
|
"'": ''',
|
||||||
|
};
|
||||||
|
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) {
|
onopentag(name, attribs) {
|
||||||
depth++;
|
depth++;
|
||||||
const classes = attribs['class'] || '';
|
const classes = attribs['class'] || '';
|
||||||
@@ -361,10 +376,10 @@ class RoyalRoad implements Plugin.PluginBase {
|
|||||||
ontext(text) {
|
ontext(text) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case ParsingState.InChapter:
|
case ParsingState.InChapter:
|
||||||
chapterHtmlParts.push(text);
|
chapterHtmlParts.push(escapeHtml(text));
|
||||||
break;
|
break;
|
||||||
case ParsingState.InNote:
|
case ParsingState.InNote:
|
||||||
notesHtmlParts.push(text);
|
notesHtmlParts.push(escapeHtml(text));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -383,6 +398,7 @@ class RoyalRoad implements Plugin.PluginBase {
|
|||||||
depth--;
|
depth--;
|
||||||
return;
|
return;
|
||||||
case ParsingState.InChapter:
|
case ParsingState.InChapter:
|
||||||
|
chapterHtmlParts.push(`</div>`);
|
||||||
state = ParsingState.Idle;
|
state = ParsingState.Idle;
|
||||||
stateDepth = 0;
|
stateDepth = 0;
|
||||||
depth--;
|
depth--;
|
||||||
@@ -406,7 +422,7 @@ class RoyalRoad implements Plugin.PluginBase {
|
|||||||
state === ParsingState.InChapter ||
|
state === ParsingState.InChapter ||
|
||||||
state === ParsingState.InNote
|
state === ParsingState.InNote
|
||||||
) {
|
) {
|
||||||
if (!parser.checkVoidElement(name)) {
|
if (!parser['isVoidElement'](name)) {
|
||||||
const closingTag = `</${name}>`;
|
const closingTag = `</${name}>`;
|
||||||
if (state === ParsingState.InChapter) {
|
if (state === ParsingState.InChapter) {
|
||||||
chapterHtmlParts.push(closingTag);
|
chapterHtmlParts.push(closingTag);
|
||||||
@@ -904,12 +920,6 @@ class RoyalRoad implements Plugin.PluginBase {
|
|||||||
|
|
||||||
export default new RoyalRoad();
|
export default new RoyalRoad();
|
||||||
|
|
||||||
class AlternateParser extends Parser {
|
|
||||||
public checkVoidElement(name: string): boolean {
|
|
||||||
return this.isVoidElement(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChapterEntry = {
|
type ChapterEntry = {
|
||||||
id: number;
|
id: number;
|
||||||
volumeId: number;
|
volumeId: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user