Repository: zestedesavoir/zmarkdown
Pull request #269 (2018-08-31 13:43:51)

remark-grid-tables: table can be followed by spaces


Patch:
diff --git a/packages/remark-grid-tables/dist/index.js b/packages/remark-grid-tables/dist/index.js
index 2c14878c..3ca2ffe0 100644
--- a/packages/remark-grid-tables/dist/index.js
+++ b/packages/remark-grid-tables/dist/index.js
@@ -74,7 +74,7 @@ var TablePart = function () {
       // Update last row according to a line.
       var mergeChars = isEndLine ? '+|' : '|';
       var newCells = [this.lastRow()._cells[0]];
-      for (var c = 1; c < this.lastRow()._cells.length; ++c) {
+      for (var c = 1; c < this.lastRow()._cells.length; c++) {
         var cell = this.lastRow()._cells[c];
 
         // Only cells with rowspan equals can be merged
@@ -92,7 +92,7 @@ var TablePart = function () {
     value: function updateWithPartLine(line) {
       // Get cells not finished
       var remainingCells = [];
-      for (var c = 0; c < this.lastRow()._cells.length; ++c) {
+      for (var c = 0; c < this.lastRow()._cells.length; c++) {
         var cell = this.lastRow()._cells[c];
         var partLine = line.substring(cell._startPosition - 1, cell._endPosition + 1);
         if (!isSeparationLine(partLine)) {
@@ -104,16 +104,16 @@ var TablePart = function () {
       // Generate new row
       this.addRow();
       var newCells = [];
-      for (var _c = 0; _c < remainingCells.length; ++_c) {
+      for (var _c = 0; _c < remainingCells.length; _c++) {
         var remainingCell = remainingCells[_c];
-        for (var cc = 0; cc < this.lastRow()._cells.length; ++cc) {
+        for (var cc = 0; cc < this.lastRow()._cells.length; cc++) {
           var _cell = this.lastRow()._cells[cc];
           if (_cell._endPosition < remainingCell._startPosition && !newCells.includes(_cell)) {
             newCells.push(_cell);
           }
         }
         newCells.push(remainingCell);
-        for (var _cc = 0; _cc < this.lastRow()._cells.length; ++_cc) {
+        for (var _cc = 0; _cc < this.lastRow()._cells.length; _cc++) {
           var _cell2 = this.lastRow()._cells[_cc];
           if (_cell2._startPosition > remainingCell._endPosition && !newCells.includes(_cell2)) {
             newCells.push(_cell2);
@@ -122,9 +122,9 @@ var TablePart = function () {
       }
 
       // Remove duplicates
-      for (var nc = 0; nc < newCells.length; ++nc) {
+      for (var nc = 0; nc < newCells.length; nc++) {
         var newCell = newCells[nc];
-        for (var ncc = 0; ncc < newCells.length; ++ncc) {
+        for (var ncc = 0; ncc < newCells.length; ncc++) {
           if (nc !== ncc) {
             var other = newCells[ncc];
             if (other._startPosition >= newCell._startPosition && other._endPosition <= newCell._endPosition) {
@@ -153,7 +153,7 @@ var TableRow = function () {
 
     this._linesInfos = linesInfos;
     this._cells = [];
-    for (var i = 0; i < linesInfos.length - 1; ++i) {
+    for (var i = 0; i < linesInfos.length - 1; i++) {
       this._cells.push(new TableCell(linesInfos[i] + 1, linesInfos[i + 1]));
     }
   }
@@ -161,7 +161,7 @@ var TableRow = function () {
   _createClass(TableRow, [{
     key: 'updateContent',
     value: function updateContent(line) {
-      for (var c = 0; c < this._cells.length; ++c) {
+      for (var c = 0; c < this._cells.length; c++) {
         var cell = this._cells[c];
         cell._lines.push(line.substring(cell._startPosition, cell._endPosition));
       }
@@ -188,7 +188,7 @@ var TableCell = function () {
       this._endPosition = other._endPosition;
       this._colspan += other._colspan;
       var newLines = [];
-      for (var l = 0; l < this._lines.length; ++l) {
+      for (var l = 0; l < this._lines.length; l++) {
         newLines.push(this._lines[l] + '|' + other._lines[l]);
       }
       this._lines = newLines;
@@ -226,7 +226,7 @@ function isPartLine(line) {
 
 function findAll(content, characters) {
   var pos = [];
-  for (var i = 0; i < content.length; ++i) {
+  for (var i = 0; i < content.length; i++) {
     var char = content[i];
     if (characters.includes(char)) {
       pos.push(i);
@@ -273,7 +273,7 @@ function extractTable(value, eat, tokenizer) {
   var possibleGridTable = value.split('\n');
   var i = 0;
   var before = [];
-  for (; i < possibleGridTable.length; ++i) {
+  for (; i < possibleGridTable.length; i++) {
     var line = possibleGridTable[i];
     if (isSeparationLine(line)) break;
     if (line.length === 0) break;
@@ -285,7 +285,7 @@ function extractTable(value, eat, tokenizer) {
   var lineLength = possibleGridTable[i + 1].length;
   var gridTable = [];
   var hasHeader = false;
-  for (; i < possibleGridTable.length; ++i) {
+  for (; i < possibleGridTable.length; i++) {
     var _line = possibleGridTable[i];
     var isMainLine = totalMainLineRegex.exec(_line);
     // line is in table
@@ -306,7 +306,7 @@ function extractTable(value, eat, tokenizer) {
   // if the last line is not a plain line
   if (!separationLineRegex.exec(gridTable[gridTable.length - 1])) {
     // Remove lines not in the table
-    for (var j = gridTable.length - 1; j >= 0; --j) {
+    for (var j = gridTable.length - 1; j >= 0; j--) {
       var isSeparation = separationLineRegex.exec(gridTable[j]);
       if (isSeparation) break;
       gridTable.pop();
@@ -316,7 +316,7 @@ function extractTable(value, eat, tokenizer) {
 
   // Extract lines after table
   var after = [];
-  for (; i < possibleGridTable.length; ++i) {
+  for (; i < possibleGridTable.length; i++) {
     var _line2 = possibleGridTable[i];
     if (_line2.length === 0) break;
     after.push(_line2);
@@ -328,7 +328,7 @@ function extractTable(value, eat, tokenizer) {
 function extractTableContent(lines, linesInfos, hasHeader) {
   var table = new Table(linesInfos);
 
-  for (var l = 0; l < lines.length; ++l) {
+  for (var l = 0; l < lines.length; l++) {
     var line = lines[l];
     // Get if the line separate the head of the table from the body
     var matchHeader = hasHeader & isHeaderLine(line) !== null;
@@ -375,7 +375,7 @@ function generateTable(tableContent, now, tokenizer) {
 
   var hasHeader = tableContent._parts.length > 1;
 
-  for (var p = 0; p < tableContent._parts.length; ++p) {
+  for (var p = 0; p < tableContent._parts.length; p++) {
     var part = tableContent._parts[p];
     var partElt = {
       type: 'tableHeader',
@@ -384,7 +384,7 @@ function generateTable(tableContent, now, tokenizer) {
         hName: hasHeader && p === 0 ? 'thead' : 'tbody'
       }
     };
-    for (var r = 0; r < part._rows.length; ++r) {
+    for (var r = 0; r < part._rows.length; r++) {
       var row = part._rows[r];
       var rowElt = {
         type: 'tableRow',
@@ -393,13 +393,14 @@ function generateTable(tableContent, now, tokenizer) {
           hName: 'tr'
         }
       };
-      for (var c = 0; c < row._cells.length; ++c) {
+      for (var c = 0; c < row._cells.length; c++) {
         var cell = row._cells[c];
+        var tokenizedContent = tokenizer.tokenizeBlock(cell._lines.map(function (e) {
+          return e.trim();
+        }).join('\n'), now);
         var cellElt = {
           type: 'tableCell',
-          children: tokenizer.tokenizeBlock(cell._lines.map(function (e) {
-            return e.trim();
-          }).join('\n'), now),
+          children: tokenizedContent,
           data: {
             hName: hasHeader && p === 0 ? 'th' : 'td',
             hProperties: {
@@ -411,8 +412,8 @@ function generateTable(tableContent, now, tokenizer) {
 
         var endLine = r + cell._rowspan;
         if (cell._rowspan > 1 && endLine - 1 < part._rows.length) {
-          for (var rs = 1; rs < cell._rowspan; ++rs) {
-            for (var cc = 0; cc < part._rows[r + rs]._cells.length; ++cc) {
+          for (var rs = 1; rs < cell._rowspan; rs++) {
+            for (var cc = 0; cc < part._rows[r + rs]._cells.length; cc++) {
               var other = part._rows[r + rs]._cells[cc];
               if (cell._startPosition === other._startPosition && cell._endPosition === other._endPosition && cell._colspan === other._colspan && cell._rowspan === other._rowspan && cell._lines === other._lines) {
                 part._rows[r + rs]._cells.splice(cc, 1);
@@ -456,13 +457,21 @@ function gridTableTokenizer(eat, value, silent) {
     tagName: 'WrapperBlock',
     children: []
   };
+
   if (before.length) {
-    wrapperBlock.children.push(this.tokenizeBlock(before.join('\n'), now)[0]);
+    var tokensBefore = this.tokenizeBlock(before.join('\n'), now)[0];
+    wrapperBlock.children.push(tokensBefore);
   }
+
   wrapperBlock.children.push(tableElt);
+
   if (after.length) {
-    wrapperBlock.children.push(this.tokenizeBlock(after.join('\n'), now)[0]);
+    var tokensAfter = this.tokenizeBlock(after.join('\n'), now);
+    if (tokensAfter.length) {
+      wrapperBlock.children.push(tokensAfter[0]);
+    }
   }
+
   return eat(merged)(wrapperBlock);
 }
 
@@ -472,11 +481,11 @@ function deleteWrapperBlock() {
 
     var newChildren = [];
     var replace = false;
-    for (var c = 0; c < node.children.length; ++c) {
+    for (var c = 0; c < node.children.length; c++) {
       var child = node.children[c];
       if (child.tagName === 'WrapperBlock' && child.type === 'element') {
         replace = true;
-        for (var cc = 0; cc < child.children.length; ++cc) {
+        for (var cc = 0; cc < child.children.length; cc++) {
           newChildren.push(child.children[cc]);
         }
       } else {
diff --git a/packages/remark-grid-tables/src/index.js b/packages/remark-grid-tables/src/index.js
index 0899d7eb..556421fe 100644
--- a/packages/remark-grid-tables/src/index.js
+++ b/packages/remark-grid-tables/src/index.js
@@ -48,7 +48,7 @@ class TablePart {
     // Update last row according to a line.
     const mergeChars = isEndLine ? '+|' : '|'
     const newCells = [this.lastRow()._cells[0]]
-    for (let c = 1; c < this.lastRow()._cells.length; ++c) {
+    for (let c = 1; c < this.lastRow()._cells.length; c++) {
       const cell = this.lastRow()._cells[c]
 
       // Only cells with rowspan equals can be merged
@@ -66,7 +66,7 @@ class TablePart {
   updateWithPartLine (line) {
     // Get cells not finished
     const remainingCells = []
-    for (let c = 0; c < this.lastRow()._cells.length; ++c) {
+    for (let c = 0; c < this.lastRow()._cells.length; c++) {
       const cell = this.lastRow()._cells[c]
       const partLine = line.substring(cell._startPosition - 1, cell._endPosition + 1)
       if (!isSeparationLine(partLine)) {
@@ -78,16 +78,16 @@ class TablePart {
     // Generate new row
     this.addRow()
     const newCells = []
-    for (let c = 0; c < remainingCells.length; ++c) {
+    for (let c = 0; c < remainingCells.length; c++) {
       const remainingCell = remainingCells[c]
-      for (let cc = 0; cc < this.lastRow()._cells.length; ++cc) {
+      for (let cc = 0; cc < this.lastRow()._cells.length; cc++) {
         const cell = this.lastRow()._cells[cc]
         if (cell._endPosition < remainingCell._startPosition && !newCells.includes(cell)) {
           newCells.push(cell)
         }
       }
       newCells.push(remainingCell)
-      for (let cc = 0; cc < this.lastRow()._cells.length; ++cc) {
+      for (let cc = 0; cc < this.lastRow()._cells.length; cc++) {
         const cell = this.lastRow()._cells[cc]
         if (cell._startPosition > remainingCell._endPosition && !newCells.includes(cell)) {
           newCells.push(cell)
@@ -96,9 +96,9 @@ class TablePart {
     }
 
     // Remove duplicates
-    for (let nc = 0; nc < newCells.length; ++nc) {
+    for (let nc = 0; nc < newCells.length; nc++) {
       let newCell = newCells[nc]
-      for (let ncc = 0; ncc < newCells.length; ++ncc) {
+      for (let ncc = 0; ncc < newCells.length; ncc++) {
         if (nc !== ncc) {
           const other = newCells[ncc]
           if (other._startPosition >= newCell._startPosition &&
@@ -123,13 +123,13 @@ class TableRow {
   constructor (linesInfos) {
     this._linesInfos = linesInfos
     this._cells = []
-    for (let i = 0; i < linesInfos.length - 1; ++i) {
+    for (let i = 0; i < linesInfos.length - 1; i++) {
       this._cells.push(new TableCell(linesInfos[i] + 1, linesInfos[i + 1]))
     }
   }
 
   updateContent (line) {
-    for (let c = 0; c < this._cells.length; ++c) {
+    for (let c = 0; c < this._cells.length; c++) {
       const cell = this._cells[c]
       cell._lines.push(line.substring(cell._startPosition, cell._endPosition))
     }
@@ -149,7 +149,7 @@ class TableCell {
     this._endPosition = other._endPosition
     this._colspan += other._colspan
     const newLines = []
-    for (let l = 0; l < this._lines.length; ++l) {
+    for (let l = 0; l < this._lines.length; l++) {
       newLines.push(`${this._lines[l]}|${other._lines[l]}`)
     }
     this._lines = newLines
@@ -185,7 +185,7 @@ function isPartLine (line) {
 
 function findAll (content, characters) {
   const pos = []
-  for (let i = 0; i < content.length; ++i) {
+  for (let i = 0; i < content.length; i++) {
     const char = content[i]
     if (characters.includes(char)) {
       pos.push(i)
@@ -229,7 +229,7 @@ function extractTable (value, eat, tokenizer) {
   const possibleGridTable = value.split('\n')
   let i = 0
   const before = []
-  for (; i < possibleGridTable.length; ++i) {
+  for (; i < possibleGridTable.length; i++) {
     const line = possibleGridTable[i]
     if (isSeparationLine(line)) break
     if (line.length === 0) break
@@ -241,7 +241,7 @@ function extractTable (value, eat, tokenizer) {
   const lineLength = possibleGridTable[i + 1].length
   const gridTable = []
   let hasHeader = false
-  for (; i < possibleGridTable.length; ++i) {
+  for (; i < possibleGridTable.length; i++) {
     const line = possibleGridTable[i]
     const isMainLine = totalMainLineRegex.exec(line)
     // line is in table
@@ -262,7 +262,7 @@ function extractTable (value, eat, tokenizer) {
   // if the last line is not a plain line
   if (!separationLineRegex.exec(gridTable[gridTable.length - 1])) {
     // Remove lines not in the table
-    for (let j = gridTable.length - 1; j >= 0; --j) {
+    for (let j = gridTable.length - 1; j >= 0; j--) {
       const isSeparation = separationLineRegex.exec(gridTable[j])
       if (isSeparation) break
       gridTable.pop()
@@ -272,7 +272,7 @@ function extractTable (value, eat, tokenizer) {
 
   // Extract lines after table
   const after = []
-  for (; i < possibleGridTable.length; ++i) {
+  for (; i < possibleGridTable.length; i++) {
     const line = possibleGridTable[i]
     if (line.length === 0) break
     after.push(line)
@@ -284,7 +284,7 @@ function extractTable (value, eat, tokenizer) {
 function extractTableContent (lines, linesInfos, hasHeader) {
   const table = new Table(linesInfos)
 
-  for (let l = 0; l < lines.length; ++l) {
+  for (let l = 0; l < lines.length; l++) {
     const line = lines[l]
     // Get if the line separate the head of the table from the body
     const matchHeader = hasHeader & isHeaderLine(line) !== null
@@ -331,7 +331,7 @@ function generateTable (tableContent, now, tokenizer) {
 
   const hasHeader = tableContent._parts.length > 1
 
-  for (let p = 0; p < tableContent._parts.length; ++p) {
+  for (let p = 0; p < tableContent._parts.length; p++) {
     const part = tableContent._parts[p]
     const partElt = {
       type: 'tableHeader',
@@ -340,7 +340,7 @@ function generateTable (tableContent, now, tokenizer) {
         hName: (hasHeader && p === 0) ? 'thead' : 'tbody',
       },
     }
-    for (let r = 0; r < part._rows.length; ++r) {
+    for (let r = 0; r < part._rows.length; r++) {
       const row = part._rows[r]
       const rowElt = {
         type: 'tableRow',
@@ -349,11 +349,15 @@ function generateTable (tableContent, now, tokenizer) {
           hName: 'tr',
         },
       }
-      for (let c = 0; c < row._cells.length; ++c) {
+      for (let c = 0; c < row._cells.length; c++) {
         const cell = row._cells[c]
+        const tokenizedContent = tokenizer.tokenizeBlock(
+          cell._lines.map((e) => e.trim()).join('\n'),
+          now
+        )
         const cellElt = {
           type: 'tableCell',
-          children: tokenizer.tokenizeBlock(cell._lines.map((e) => e.trim()).join('\n'), now),
+          children: tokenizedContent,
           data: {
             hName: (hasHeader && p === 0) ? 'th' : 'td',
             hProperties: {
@@ -365,8 +369,8 @@ function generateTable (tableContent, now, tokenizer) {
 
         const endLine = r + cell._rowspan
         if (cell._rowspan > 1 && endLine - 1 < part._rows.length) {
-          for (let rs = 1; rs < cell._rowspan; ++rs) {
-            for (let cc = 0; cc < part._rows[r + rs]._cells.length; ++cc) {
+          for (let rs = 1; rs < cell._rowspan; rs++) {
+            for (let cc = 0; cc < part._rows[r + rs]._cells.length; cc++) {
               const other = part._rows[r + rs]._cells[cc]
               if (cell._startPosition === other._startPosition &&
               cell._endPosition === other._endPosition &&
@@ -409,13 +413,21 @@ function gridTableTokenizer (eat, value, silent) {
     tagName: 'WrapperBlock',
     children: [],
   }
+
   if (before.length) {
-    wrapperBlock.children.push(this.tokenizeBlock(before.join('\n'), now)[0])
+    const tokensBefore = this.tokenizeBlock(before.join('\n'), now)[0]
+    wrapperBlock.children.push(tokensBefore)
   }
+
   wrapperBlock.children.push(tableElt)
+
   if (after.length) {
-    wrapperBlock.children.push(this.tokenizeBlock(after.join('\n'), now)[0])
+    const tokensAfter = this.tokenizeBlock(after.join('\n'), now)
+    if (tokensAfter.length) {
+      wrapperBlock.children.push(tokensAfter[0])
+    }
   }
+
   return eat(merged)(wrapperBlock)
 }
 
@@ -425,11 +437,11 @@ function deleteWrapperBlock () {
 
     const newChildren = []
     let replace = false
-    for (let c = 0; c < node.children.length; ++c) {
+    for (let c = 0; c < node.children.length; c++) {
       const child = node.children[c]
       if (child.tagName === 'WrapperBlock' && child.type === 'element') {
         replace = true
-        for (let cc = 0; cc < child.children.length; ++cc) {
+        for (let cc = 0; cc < child.children.length; cc++) {
           newChildren.push(child.children[cc])
         }
       } else {


Test patch:
diff --git a/packages/remark-grid-tables/__tests__/__snapshots__/index.js.snap b/packages/remark-grid-tables/__tests__/__snapshots__/index.js.snap
index 13c3dc53..6fa64e05 100644
--- a/packages/remark-grid-tables/__tests__/__snapshots__/index.js.snap
+++ b/packages/remark-grid-tables/__tests__/__snapshots__/index.js.snap
@@ -70,3 +70,5 @@ exports[`regression: grid table in non-fenced code block 1`] = `
 +---+---+---+
 </code></pre>"
 `;
+
+exports[`regression: should not crash with two spaces on the next line 1`] = `"<table><tbody><tr><td colspan=\\"1\\" rowspan=\\"1\\"><p>:)</p></td><td colspan=\\"1\\" rowspan=\\"1\\"><p>:)</p></td></tr></tbody></table>"`;
diff --git a/packages/remark-grid-tables/__tests__/index.js b/packages/remark-grid-tables/__tests__/index.js
index d7c1e143..10e2f4e1 100644
--- a/packages/remark-grid-tables/__tests__/index.js
+++ b/packages/remark-grid-tables/__tests__/index.js
@@ -1,6 +1,7 @@
 import {readFileSync as file} from 'fs'
 import {join} from 'path'
 import unified from 'unified'
+import dedent from 'dedent'
 import reParse from 'remark-parse'
 import stringify from 'rehype-stringify'
 import remark2rehype from 'remark-rehype'
@@ -57,6 +58,17 @@ test('regression: grid table in non-fenced code block', () => {
   expect(contents).toMatchSnapshot()
 })
 
+test('regression: should not crash with two spaces on the next line', () => {
+  const {contents} = render(dedent`
+    +----+----+
+    + :) | :) +
+    +----+----+
+    ··
+    `.replace(/·/g, ' '))
+
+  expect(contents).toMatchSnapshot()
+})
+
 test('stringify', () => {
   const fileExample = file(join(__dirname, 'grid-tables.md'))
   const {contents} = render(fileExample)