Skip to content

Commit

Permalink
Support multiple lines in table cells
Browse files Browse the repository at this point in the history
Plain Markdown syntax doesn't support more than one line in a table cell, but Google Docs lets you have many paragraphs or lines in each cell. This update supports multiple lines by adding a custom handler for table cell nodes which outputs MDast `html` nodes representing `<br>` tags to use in the table.

Fixes #10.
  • Loading branch information
Mr0grog committed Mar 6, 2020
1 parent 47a3fd3 commit 3d1999c
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fixGoogleHtml from './lib/fix-google-html';
import handlers from './lib/custom-converters';
// rehype-dom-parse is a lightweight version of rehype-parse that leverages
// browser APIs -- reduces bundle size by ~200 kB!
// const parse = require('rehype-dom-parse').default;
Expand All @@ -12,7 +13,7 @@ const processor = unified()
.use(parse)
.use(fixGoogleHtml)
// .use(require('./lib/log-tree').default)
.use(rehype2remarkWithSpaces)
.use(rehype2remarkWithSpaces, null, {handlers})
.use(stringify, {listItemIndent: '1'});

function convertToMarkdown (html) {
Expand Down
57 changes: 57 additions & 0 deletions lib/custom-converters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const all = require('hast-util-to-mdast/lib/all');

/**
* @typedef {{type: string, children: Array<UnistNode>}} UnistNode
*/

/**
* @typedef {(node: UnistNode, type: string, props: any, children: Array<UnistNode>) => UnistNode} NodeBuilder
*/

/**
* Convert a Rehype table cell node to an MDast table cell node, using HTML
* nodes to represent multiline/block content inside the cell (since plain
* Markdown can only support inline/phrasing content in cells).
*
* This is basically a customization of:
* https://github.com/syntax-tree/hast-util-to-mdast/blob/master/lib/handlers/table-cell.js
*
* @param {NodeBuilder} h Creates a new mdast node
* @param {UnistNode} node The original rehype node to convert
*/
export function convertTableCell (h, node) {
let children = all(h, node);

// If there is more than one child and any of them are multiline/block
// objects, find a way to represent them (Markdown only support inline
// content in table cells).
// TODO: handle more than just paragraphs and line breaks? (lists, etc.)
// TODO: technically block elements could be deeply nested, but this
// implementation doesn't handle that. It's unlikely to occur in Google Docs.
if (children.length > 1) {
let newChildren = [];
for (let i = 0, len = children.length; i < len; i++) {
const child = children[i];
if (child.type === 'break') {
newChildren.push({type: 'html', value: '<br>'});
}
else if (child.type === 'paragraph') {
// Instead of using `<p>` elements, keep the resulting markup as simple
// as possible by just inserting `<br>` elements between paragraphs.
if (i > 0) newChildren.push({type: 'html', value: '<br>'});
newChildren.push(...child.children);
}
else {
newChildren.push(child);
}
}
children = newChildren;
}

return h(node, 'tableCell', children)
}

export default {
td: convertTableCell,
th: convertTableCell
};

0 comments on commit 3d1999c

Please sign in to comment.