docs: function drawTable(table) {
  	// | First Header  | Second Header |
  	// | ------------- | ------------- |
  	// | Content Cell  | Content Cell  |
  	// | Content Cell  | Content Cell  |
  
  	// There must be at least 3 dashes separating each header cell.
  	// https://gist.github.com/IanWang/28965e13cdafdef4e11dc91f578d160d#tables
  
  	const flatRender = tableHasSubTables(table); // Render the table has regular text
  	let lines = [];
  	lines.push(BLOCK_OPEN);
  	let headerDone = false;
  	for (let trIndex = 0; trIndex < table.lines.length; trIndex++) {
  		const tr = table.lines[trIndex];
  		const isHeader = tr.isHeader;
  		let line = [];
  		let headerLine = [];
  		let emptyHeader = null;
  		for (let tdIndex = 0; tdIndex < tr.lines.length; tdIndex++) {
  			const td = tr.lines[tdIndex];
  
  			if (flatRender) {
  				line.push(BLOCK_OPEN);
  
  				let currentCells = [];
  
  				const renderCurrentCells = () => {
  					if (!currentCells.length) return;
  					const cellText = processMdArrayNewLines(currentCells);
  					line.push(cellText);
  					currentCells = [];
  				}
  
  				// In here, recursively render the tables
  				for (let i = 0; i < td.lines.length; i++) {
  					const c = td.lines[i];
  					if (typeof c === 'object' && ['table', 'td', 'tr', 'th'].indexOf(c.type) >= 0) { // This is a table
  						renderCurrentCells();
  						currentCells = currentCells.concat(drawTable(c));
  					} else { // This is plain text
  						currentCells.push(c);
  					}
  				}
  
  				renderCurrentCells();
  
  				line.push(BLOCK_CLOSE);
  			} else { // Regular table rendering
  
  				// A cell in a Markdown table cannot have actual new lines so replace
  				// them with <br>, which are supported by the markdown renderers.
  				let cellText = processMdArrayNewLines(td.lines, true)
  				let lines = cellText.split('\n');
  				lines = postProcessMarkdown(lines);
  				cellText = lines.join('\n').replace(/\n+/g, "<br>");
  
  				// Inside tables cells, "|" needs to be escaped
  				cellText = cellText.replace(/\|/g, "\\|");
  
  				// Previously the width of the cell was as big as the content since it looks nicer, however that often doesn't work
  				// since the content can be very long, resulting in unreadable markdown. So no solution is perfect but making it a
  				// width of 3 is a bit better. Note that 3 is the minimum width of a cell - below this, it won't be rendered by
  				// markdown parsers.
  				const width = 3;
  				line.push(stringPadding(cellText, width, ' ', stringPadding.RIGHT));
  
  				if (!headerDone) {
  					if (!isHeader) {
  						if (!emptyHeader) emptyHeader = [];
  						let h = stringPadding(' ', width, ' ', stringPadding.RIGHT);
  						emptyHeader.push(h);
  					}
  					headerLine.push('-'.repeat(width));
  				}
  
  			}
  		}
  
  		if (flatRender) {
  			headerDone = true;
  			lines.push(BLOCK_OPEN);
  			lines = lines.concat(line);
  			lines.push(BLOCK_CLOSE);
  		} else {
  			if (emptyHeader) {
  				lines.push('| ' + emptyHeader.join(' | ') + ' |');
  				lines.push('| ' + headerLine.join(' | ') + ' |');
  				headerDone = true;
  			}
  
  			lines.push('| ' + line.join(' | ') + ' |');
  
  			if (!headerDone) {
  				lines.push('| ' + headerLine.join(' | ') + ' |');
  				headerDone = true;
  			}
  		}
  	}
  
  	lines.push(BLOCK_CLOSE);
  
  	return flatRender ? lines : lines.join('<<<<:D>>>>' + NEWLINE + '<<<<:D>>>>').split('<<<<:D>>>>');
  }