0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-06 14:22:52 +00:00

Fix catastrophic backtracking and trim starting pipes

This commit is contained in:
Trevor Buckner
2021-08-07 00:48:59 -04:00
parent 8103d7d31f
commit 9ea068bf64

View File

@@ -240,7 +240,7 @@ const spanTable = {
start(src) { return src.match(/^\n *([^\n ].*\|.*)\n/)?.index; }, // Hint to Marked.js to stop and check for a match start(src) { return src.match(/^\n *([^\n ].*\|.*)\n/)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) { tokenizer(src, tokens) {
//const regex = this.tokenizer.rules.block.table; //const regex = this.tokenizer.rules.block.table;
const regex = new RegExp('^ *([^\\n ].*\\|.*\\n(?:.*?[^\\s].*\\n)*?)' // Header const regex = new RegExp('^ *([^\\n ].*\\|.*\\n(?: *[^\\s].*\\n)*?)' // Header
+ ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)\\|?' // Align + ' {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)\\|?' // Align
+ '(?:\\n *((?:(?!\\n| {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})' // Cells + '(?:\\n *((?:(?!\\n| {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})' // Cells
+ '(?:\\n+|$)| {0,3}#{1,6} | {0,3}>| {4}[^\\n]| {0,3}(?:`{3,}' + '(?:\\n+|$)| {0,3}#{1,6} | {0,3}>| {4}[^\\n]| {0,3}(?:`{3,}'
@@ -369,9 +369,9 @@ const getTableCell = (text, cell, type, align)=>{
}; };
const splitCells = (tableRow, count, prevRow = [])=>{ const splitCells = (tableRow, count, prevRow = [])=>{
// ensure that every cell-delimiting pipe has a space // trim any excessive pipes at start of row
// before it to distinguish it from an escaped pipe tableRow = tableRow.replace(/^\|+(?=\|)/, '')
const row = tableRow.replace(/(\|+)/g, (match, p1, offset, str)=>{ .replace(/(\|+)/g, (match, p1, offset, str)=>{
let escaped = false, let escaped = false,
curr = offset; curr = offset;
while (--curr >= 0 && str[curr] === '\\') escaped = !escaped; while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
@@ -380,12 +380,12 @@ const splitCells = (tableRow, count, prevRow = [])=>{
// so we leave it and the slashes alone // so we leave it and the slashes alone
return p1; return p1;
} else { } else {
// add space before unescaped | // add space before unescaped | to distinguish it from an escaped pipe
return ` ${p1}`; return ` ${p1}`;
} }
}); });
const cells = row.split(/(?: \||(?<=\|)\|)(?=[^\|]|$)/g); const cells = tableRow.split(/(?: \||(?<=\|)\|)(?=[^\|]|$)/g);
let i = 0; let i = 0;
// First/last cell in a row cannot be empty if it has no leading/trailing pipe // First/last cell in a row cannot be empty if it has no leading/trailing pipe
@@ -400,7 +400,7 @@ const splitCells = (tableRow, count, prevRow = [])=>{
rowspan : 1, rowspan : 1,
colspan : Math.max(cells[i].length - trimmedCell.length, 1), colspan : Math.max(cells[i].length - trimmedCell.length, 1),
text : trimmedCell.trim().replace(/\\\|/g, '|') text : trimmedCell.trim().replace(/\\\|/g, '|')
// leading or trailing whitespace is ignored per the gfm spec // trim whitespace and display escaped pipes as normal character
}; };
// Handle Rowspan // Handle Rowspan
@@ -411,6 +411,7 @@ const splitCells = (tableRow, count, prevRow = [])=>{
for (j = 0; j < prevRow.length; j++) { for (j = 0; j < prevRow.length; j++) {
prevCell = prevRow[j]; prevCell = prevRow[j];
if((prevCols == numCols) && (prevCell.colspan == cells[i].colspan)) { if((prevCols == numCols) && (prevCell.colspan == cells[i].colspan)) {
// merge into matching cell in previous row (the "target")
cells[i].rowSpanTarget = prevCell.rowSpanTarget ?? prevCell; cells[i].rowSpanTarget = prevCell.rowSpanTarget ?? prevCell;
cells[i].rowSpanTarget.text += ` ${cells[i].text.slice(0, -1)}`; cells[i].rowSpanTarget.text += ` ${cells[i].text.slice(0, -1)}`;
cells[i].rowSpanTarget.rowspan += 1; cells[i].rowSpanTarget.rowspan += 1;