Merge pull request #3552 from maunium/fix-html-parsing-for-edit

Fix some things in the edit HTML parser
This commit is contained in:
Bruno Windels 2019-10-21 09:25:53 +00:00 committed by GitHub
commit b237ecab29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 14 deletions

View file

@ -58,7 +58,16 @@ function parseLink(a, partCreator) {
function parseCodeBlock(n, partCreator) { function parseCodeBlock(n, partCreator) {
const parts = []; const parts = [];
const preLines = ("```\n" + n.textContent + "```").split("\n"); let language = "";
if (n.firstChild && n.firstChild.nodeName === "CODE") {
for (const className of n.firstChild.classList) {
if (className.startsWith("language-")) {
language = className.substr("language-".length);
break;
}
}
}
const preLines = ("```" + language + "\n" + n.textContent + "```").split("\n");
preLines.forEach((l, i) => { preLines.forEach((l, i) => {
parts.push(partCreator.plain(l)); parts.push(partCreator.plain(l));
if (i < preLines.length - 1) { if (i < preLines.length - 1) {
@ -99,7 +108,10 @@ function parseElement(n, partCreator, lastNode, state) {
case "LI": { case "LI": {
const indent = " ".repeat(state.listDepth - 1); const indent = " ".repeat(state.listDepth - 1);
if (n.parentElement.nodeName === "OL") { if (n.parentElement.nodeName === "OL") {
return partCreator.plain(`${indent}1. `); // The markdown parser doesn't do nested indexed lists at all, but this supports it anyway.
let index = state.listIndex[state.listIndex.length - 1];
state.listIndex[state.listIndex.length - 1] += 1;
return partCreator.plain(`${indent}${index}. `);
} else { } else {
return partCreator.plain(`${indent}- `); return partCreator.plain(`${indent}- `);
} }
@ -111,23 +123,25 @@ function parseElement(n, partCreator, lastNode, state) {
break; break;
} }
case "OL": case "OL":
state.listIndex.push(n.start || 1);
// fallthrough
case "UL": case "UL":
state.listDepth = (state.listDepth || 0) + 1; state.listDepth = (state.listDepth || 0) + 1;
// es-lint-disable-next-line no-fallthrough // fallthrough
default: default:
// don't textify block nodes we'll decend into // don't textify block nodes we'll descend into
if (!checkDecendInto(n)) { if (!checkDescendInto(n)) {
return partCreator.plain(n.textContent); return partCreator.plain(n.textContent);
} }
} }
} }
function checkDecendInto(node) { function checkDescendInto(node) {
switch (node.nodeName) { switch (node.nodeName) {
case "PRE": case "PRE":
// a code block is textified in parseCodeBlock // a code block is textified in parseCodeBlock
// as we don't want to preserve markup in it, // as we don't want to preserve markup in it,
// so no need to decend into it // so no need to descend into it
return false; return false;
default: default:
return checkBlockNode(node); return checkBlockNode(node);
@ -168,7 +182,9 @@ function parseHtmlMessage(html, partCreator, isQuotedMessage) {
const parts = []; const parts = [];
let lastNode; let lastNode;
let inQuote = isQuotedMessage; let inQuote = isQuotedMessage;
const state = {}; const state = {
listIndex: [],
};
function onNodeEnter(n) { function onNodeEnter(n) {
if (checkIgnored(n)) { if (checkIgnored(n)) {
@ -203,11 +219,11 @@ function parseHtmlMessage(html, partCreator, isQuotedMessage) {
parts.push(...newParts); parts.push(...newParts);
const decend = checkDecendInto(n); const descend = checkDescendInto(n);
// when not decending (like for PRE), onNodeLeave won't be called to set lastNode // when not descending (like for PRE), onNodeLeave won't be called to set lastNode
// so do that here. // so do that here.
lastNode = decend ? null : n; lastNode = descend ? null : n;
return decend; return descend;
} }
function onNodeLeave(n) { function onNodeLeave(n) {
@ -219,6 +235,8 @@ function parseHtmlMessage(html, partCreator, isQuotedMessage) {
inQuote = false; inQuote = false;
break; break;
case "OL": case "OL":
state.listIndex.pop();
// fallthrough
case "UL": case "UL":
state.listDepth -= 1; state.listDepth -= 1;
break; break;

View file

@ -21,8 +21,8 @@ import DocumentOffset from "./offset";
export function walkDOMDepthFirst(rootNode, enterNodeCallback, leaveNodeCallback) { export function walkDOMDepthFirst(rootNode, enterNodeCallback, leaveNodeCallback) {
let node = rootNode.firstChild; let node = rootNode.firstChild;
while (node && node !== rootNode) { while (node && node !== rootNode) {
const shouldDecend = enterNodeCallback(node); const shouldDescend = enterNodeCallback(node);
if (shouldDecend && node.firstChild) { if (shouldDescend && node.firstChild) {
node = node.firstChild; node = node.firstChild;
} else if (node.nextSibling) { } else if (node.nextSibling) {
node = node.nextSibling; node = node.nextSibling;