1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-02 12:47:41 +02:00

All: Fixes #2640: HTML code within Markdown was rendered incorrectly in some cases

This commit is contained in:
Laurent Cozic 2020-03-04 00:54:27 +00:00
parent 80fff62b34
commit cb2df32d91
4 changed files with 61 additions and 1 deletions

View File

@ -0,0 +1 @@
<p><a href="#" onclick="">Testing <strong>inline</strong> text</a></p>

View File

@ -0,0 +1 @@
<a href="#" onclick="alert('ohno')">Testing **inline** text</a>

View File

@ -1,6 +1,20 @@
const md5 = require('md5');
const htmlUtils = require('../../htmlUtils');
function getOpenTagName(html:string):string {
const m = html.toLowerCase().match(/<([a-z]+)(\s|>)/);
if (!m || m.length < 2) return null;
return m[1];
}
function isSelfClosedTag(html:string):boolean {
return html.substr(-2) === '/>';
}
function stripOffClosingTag(html:string, tagName:string):string {
return html.substr(0, html.length - tagName.length - 3);
}
// @ts-ignore: Keep the function signature as-is despite unusued arguments
function installRule(markdownIt:any, mdOptions:any, ruleOptions:any, context:any) {
markdownIt.core.ruler.push('sanitize_html', (state:any) => {
@ -18,8 +32,51 @@ function installRule(markdownIt:any, mdOptions:any, ruleOptions:any, context:any
const cacheKey = md5(escape(token.content));
let sanitizedContent = context.cache.get(cacheKey);
// For html_inline, the content is only a fragment of HTML, as it will be rendered, but
// it's not necessarily valid HTML. For example this HTML:
//
// <a href="#">Testing</a>
//
// will be rendered as three tokens:
//
// html_inline: <a href="#">
// text: Testing
// html_inline: </a>
//
// The problem for us is that when we pass this HTML fragment to the sanitize function
// it is going to turn it into valid HTML. Thus:
//
// "<a href="#">" becomes "<a href="#"></a>"
// "</a>" becomes ""
//
// So the result would be "<a href="#"></a>Testing"
//
// Because of this, we need to be careful with html_inline:
//
// 0. Check if it's an opening or closing tag - only opening ones need to be processed
// 1. Sanitize the fragment
// 2. Strip off the closing tag that was added
//
// Also self-closing tags need to be handled.
//
// html_block is not a problem as the whole content is valid HTML.
if (!sanitizedContent) {
if (token.type === 'html_inline') {
const openTagName = getOpenTagName(token.content);
const isSelfClosed = isSelfClosedTag(token.content);
if (!openTagName) {
sanitizedContent = token.content;
} else {
sanitizedContent = htmlUtils.sanitizeHtml(token.content);
if (!isSelfClosed) {
sanitizedContent = stripOffClosingTag(sanitizedContent, openTagName);
}
}
} else { // html_block
sanitizedContent = htmlUtils.sanitizeHtml(token.content);
}
}
token.content = sanitizedContent;

View File

@ -32,6 +32,7 @@ const updateIgnoredTypeScriptBuildTask = async function() {
'**/.git/**',
'**/ElectronClient/lib/**',
'**/CliClient/build/lib/**',
'**/CliClient/tests-build/lib/**',
'**/ElectronClient/dist/**',
],
}).map(f => f.substr(__dirname.length + 1));