Skip to content

Commit

Permalink
fix: escape html in renderer (#3495)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: escape html in renderers for all tokens.
  • Loading branch information
UziTech authored Nov 9, 2024
1 parent dc4ae3b commit 58d66e5
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 85 deletions.
7 changes: 1 addition & 6 deletions src/Lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,7 @@ export class _Lexer {
if (token = this.tokenizer.tag(src)) {
src = src.substring(token.raw.length);
lastToken = tokens[tokens.length - 1];
if (lastToken && token.type === 'text' && lastToken.type === 'text') {
lastToken.raw += token.raw;
lastToken.text += token.text;
} else {
tokens.push(token);
}
tokens.push(token);
continue;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,15 @@ export class _Parser {
let textToken = token;
let body = this.renderer.text(textToken);
while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
textToken = tokens[++i] as Tokens.Text | Tokens.Tag;
textToken = tokens[++i] as Tokens.Text;
body += '\n' + this.renderer.text(textToken);
}
if (top) {
out += this.renderer.paragraph({
type: 'paragraph',
raw: body,
text: body,
tokens: [{ type: 'text', raw: body, text: body }],
tokens: [{ type: 'text', raw: body, text: body, escaped: true }],
});
} else {
out += body;
Expand Down
18 changes: 11 additions & 7 deletions src/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,15 @@ export class _Renderer {
if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);
item.tokens[0].tokens[0].escaped = true;
}
} else {
item.tokens.unshift({
type: 'text',
raw: checkbox + ' ',
text: checkbox + ' ',
escaped: true,
});
}
} else {
Expand Down Expand Up @@ -164,7 +166,7 @@ export class _Renderer {
}

codespan({ text }: Tokens.Codespan): string {
return `<code>${text}</code>`;
return `<code>${escape(text, true)}</code>`;
}

br(token: Tokens.Br): string {
Expand All @@ -184,7 +186,7 @@ export class _Renderer {
href = cleanHref;
let out = '<a href="' + href + '"';
if (title) {
out += ' title="' + title + '"';
out += ' title="' + (escape(title)) + '"';
}
out += '>' + text + '</a>';
return out;
Expand All @@ -193,19 +195,21 @@ export class _Renderer {
image({ href, title, text }: Tokens.Image): string {
const cleanHref = cleanUrl(href);
if (cleanHref === null) {
return text;
return escape(text);
}
href = cleanHref;

let out = `<img src="${href}" alt="${text}"`;
if (title) {
out += ` title="${title}"`;
out += ` title="${escape(title)}"`;
}
out += '>';
return out;
}

text(token: Tokens.Text | Tokens.Escape | Tokens.Tag) : string {
return 'tokens' in token && token.tokens ? this.parser.parseInline(token.tokens) : token.text;
text(token: Tokens.Text | Tokens.Escape) : string {
return 'tokens' in token && token.tokens
? this.parser.parseInline(token.tokens)
: ('escaped' in token && token.escaped ? token.text : escape(token.text));
}
}
26 changes: 10 additions & 16 deletions src/Tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { _defaults } from './defaults.ts';
import {
rtrim,
splitCells,
escape,
findClosingBracket,
} from './helpers.ts';
import type { Rules } from './rules.ts';
Expand All @@ -12,7 +11,7 @@ import type { MarkedOptions } from './MarkedOptions.ts';

function outputLink(cap: string[], link: Pick<Tokens.Link, 'href' | 'title'>, raw: string, lexer: _Lexer): Tokens.Link | Tokens.Image {
const href = link.href;
const title = link.title ? escape(link.title) : null;
const title = link.title || null;
const text = cap[1].replace(/\\([\[\]])/g, '$1');

if (cap[0].charAt(0) !== '!') {
Expand All @@ -33,7 +32,7 @@ function outputLink(cap: string[], link: Pick<Tokens.Link, 'href' | 'title'>, ra
raw,
href,
title,
text: escape(text),
text,
};
}

Expand Down Expand Up @@ -583,7 +582,7 @@ export class _Tokenizer {
return {
type: 'escape',
raw: cap[0],
text: escape(cap[1]),
text: cap[1],
};
}
}
Expand Down Expand Up @@ -766,7 +765,6 @@ export class _Tokenizer {
if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
text = text.substring(1, text.length - 1);
}
text = escape(text, true);
return {
type: 'codespan',
raw: cap[0],
Expand Down Expand Up @@ -802,10 +800,10 @@ export class _Tokenizer {
if (cap) {
let text, href;
if (cap[2] === '@') {
text = escape(cap[1]);
text = cap[1];
href = 'mailto:' + text;
} else {
text = escape(cap[1]);
text = cap[1];
href = text;
}

Expand All @@ -830,7 +828,7 @@ export class _Tokenizer {
if (cap = this.rules.inline.url.exec(src)) {
let text, href;
if (cap[2] === '@') {
text = escape(cap[0]);
text = cap[0];
href = 'mailto:' + text;
} else {
// do extended autolink path validation
Expand All @@ -839,7 +837,7 @@ export class _Tokenizer {
prevCapZero = cap[0];
cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? '';
} while (prevCapZero !== cap[0]);
text = escape(cap[0]);
text = cap[0];
if (cap[1] === 'www.') {
href = 'http://' + cap[0];
} else {
Expand All @@ -865,16 +863,12 @@ export class _Tokenizer {
inlineText(src: string): Tokens.Text | undefined {
const cap = this.rules.inline.text.exec(src);
if (cap) {
let text;
if (this.lexer.state.inRawBlock) {
text = cap[0];
} else {
text = escape(cap[0]);
}
const escaped = this.lexer.state.inRawBlock;
return {
type: 'text',
raw: cap[0],
text,
text: cap[0],
escaped,
};
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export namespace Tokens {
raw: string;
text: string;
tokens?: Token[];
escaped?: boolean;
}

export interface Def {
Expand All @@ -142,7 +143,7 @@ export namespace Tokens {
}

export interface Tag {
type: 'text' | 'html';
type: 'html';
raw: string;
inLink: boolean;
inRawBlock: boolean;
Expand Down
Loading

0 comments on commit 58d66e5

Please sign in to comment.