JSFiddle - React, Tailwind, and code Playground

by Eugene Trounev

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.2/underscore-min.js"></script>
<pre id="content">

</pre>

JavaScript

const Marks = {
	"strong": ["**", "**"],
	"em": ["*","*"],
	"code": ["`", "`"]
}
const NewLine = "\n";
const markupRenderer = (textBlock) => {
	let text = textBlock.text || "";
	return textBlock.marks ? textBlock.marks.reduce((acc, mark) => {
		console.log(mark);
		return Marks[mark.type][0] + acc + Marks[mark.type][1];
	}, text) : text;
}
const mdRenderer = (content, index) => {
	if(Array.isArray(content)) return content.map(mdRenderer).join("");
	let md = "";
	let closingMark = "";
	switch (content.type) {
		case "table_row":
			closingMark = NewLine;
			break;
		case "table_header":
		case "table_cell":
			closingMark = new Array(content.attrs.colspan).fill("|").join("");
			if(index === 0 && !content.content) md += "| ";
			break;
		case "text":
			md += markupRenderer(content);
			break;
	}
	if (content.content) {
		md += mdRenderer(content.content);
		md += closingMark;
	};
	return md;
};
	
function toMarkdown(spec) {
	const filterHeaderCols = col => col.type === "table_header";
	let md = "";
	let content = spec.doc.content.find(i => i.type === "table");
	if (content) {
		content = content.content.filter(i => i.type === "table_row");
		const cols =  content[0].content.reduce((acc, col) => acc + col.attrs.colspan, 0);
		const headerRows = content.filter(({content}) => 
			content.filter(filterHeaderCols).length === content.length
		);
		const bodyRows = content.slice(headerRows.length);
		if (headerRows.length > 0) {
			md += mdRenderer(headerRows);
			md += new Array(cols).fill("---").join(" | ");
			md += NewLine;
		}
		md += mdRenderer(bodyRows);
	}
	return md;
}

const Spec =...