Markdown Table Generator — C# source
Turn pipe, CSV, tab, semicolon, or space-separated data into a clean GitHub-Flavored Markdown table. Auto-detects the delimiter, pads columns, escapes pipes, and supports per-column alignment - all in your browser.
This is the C# implementation — the same logic the interactive tool runs, in a shareable, citable form.
// markdown-table — C# (.NET 8) port: split delimiter-separated rows and render a padded GFM table, ported from src/lib/markdown-table.ts.
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
enum Align { None, Left, Center, Right }
static class MarkdownTable
{
// escapeCell: newlines collapse to spaces, a literal '|' renders as '\|'.
static string EscapeCell(string cell) =>
cell.Replace("\r\n", "\n").Replace("\n", " ").Replace("|", "\\|");
// splitLine: literal-delimiter split (',', '\t', ';'), each cell trimmed.
static string[] SplitLine(string line, char delim) =>
line.Split(delim).Select(c => c.Trim()).ToArray();
// parseTable: non-empty lines, each split by the delimiter.
public static string[][] ParseTable(string input, char delim) =>
input.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None)
.Select(l => l.Trim())
.Where(l => l.Length > 0)
.Select(l => SplitLine(l, delim))
.ToArray();
// pad: fill to width honoring right/center/left alignment.
static string Pad(string cell, int width, Align align)
{
int diff = width - cell.Length;
if (diff <= 0) return cell;
return align switch
{
Align.Right => new string(' ', diff) + cell,
Align.Center => new string(' ', diff / 2) + cell + new string(' ', diff - diff / 2),
_ => cell + new string(' ', diff), // Left, None -> left-aligned
};
}
// sepCell: ---, :--, --:, :-: — the alignment separator, min width 3.
static string SepCell(Align align, int width)
{
int w = Math.Max(3, width);
return align switch
{
Align.Center => ":" + new string('-', w - 2) + ":",
Align.Right => new string('-', w - 1) + ":",
Align.Left => ":" + new string('-', w - 1),
_ => new string('-', w),
};
}
// toMarkdown: pad every column to its widest (escaped) cell and lay rows
// out as '| a | b |', with the separator row under the header row.
public static string ToMarkdown(string[][] rows, bool header = true, Align[]? aligns = null)
{
if (rows.Length == 0) return "";
int cols = rows.Max(r => r.Length);
string[][] grid = rows.Select(r =>
{
var cells = r.Select(EscapeCell).ToList();
while (cells.Count < cols) cells.Add("");
return cells.ToArray();
}).ToArray();
Align[] align = Enumerable.Range(0, cols)
.Select(i => aligns != null && i < aligns.Length ? aligns[i] : Align.None).ToArray();
int[] widths = Enumerable.Range(0, cols)
.Select(c => Math.Max(3, grid.Max(r => r[c].Length))).ToArray();
string Line(string[] cells) =>
"| " + string.Join(" | ", cells.Select((c, i) => Pad(c, widths[i], align[i]))) + " |";
string separator = "| " + string.Join(" | ", align.Select((a, i) => SepCell(a, widths[i]))) + " |";
string[] head = header ? grid[0] : Enumerable.Repeat("", cols).ToArray();
IEnumerable<string[]> data = header ? grid.Skip(1) : grid;
return string.Join("\n", new[] { Line(head), separator }.Concat(data.Select(Line)));
}
}
class Program
{
static void Main()
{
// Demo: a CSV-ish grid with a literal pipe in one cell (escaped on output).
string[][] rows = MarkdownTable.ParseTable("Name,Price,Qty\nWire | cable,2 m,1\nLED,3 mm,25", ',');
Console.WriteLine(MarkdownTable.ToMarkdown(rows,
aligns: new[] { Align.None, Align.Right, Align.Center }));
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →