Skip to content

Markdown Table Generator — Java 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 Java implementation — the same logic the interactive tool runs, in a shareable, citable form.

// markdown-table — Java (17+) port: split delimiter-separated rows and render a padded GFM table, ported from src/lib/markdown-table.ts.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

public class MarkdownTable {

    enum Align { NONE, LEFT, CENTER, RIGHT }

    // splitLine: literal-delimiter split (',', '\t', ';'), each cell trimmed.
    static List<String> splitLine(String line, char delim) {
        List<String> cells = new ArrayList<>();
        for (String c : line.split(String.valueOf(delim), -1)) cells.add(c.trim());
        return cells;
    }

    // parseTable: non-empty lines, each split by the delimiter.
    static List<List<String>> parseTable(String input, char delim) {
        List<List<String>> rows = new ArrayList<>();
        for (String l : input.split("\r?\n", -1)) {
            String t = l.trim();
            if (!t.isEmpty()) rows.add(splitLine(t, delim));
        }
        return rows;
    }

    // escapeCell: newlines collapse to spaces, a literal '|' renders as '\|'.
    static String escapeCell(String cell) {
        return cell.replaceAll("\r?\n", " ").replace("|", "\\|");
    }

    // 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 switch (align) {
            case RIGHT -> " ".repeat(diff) + cell;
            case CENTER -> " ".repeat(diff / 2) + cell + " ".repeat(diff - diff / 2);
            default -> cell + " ".repeat(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 switch (align) {
            case CENTER -> ":" + "-".repeat(w - 2) + ":";
            case RIGHT -> "-".repeat(w - 1) + ":";
            case LEFT -> ":" + "-".repeat(w - 1);
            case NONE -> "-".repeat(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.
    static String toMarkdown(List<List<String>> rows, boolean header, List<Align> aligns) {
        if (rows.isEmpty()) return "";
        int cols = rows.stream().mapToInt(List::size).max().orElse(0); // effectively final

        List<List<String>> grid = new ArrayList<>();
        for (List<String> r : rows) {
            List<String> cells = new ArrayList<>(r.stream().map(MarkdownTable::escapeCell).toList());
            while (cells.size() < cols) cells.add("");
            grid.add(cells);
        }
        List<Align> align = new ArrayList<>(Collections.nCopies(cols, Align.NONE));
        List<Integer> widths = new ArrayList<>(Collections.nCopies(cols, 3));
        for (int c = 0; c < cols; c++) {
            if (c < aligns.size()) align.set(c, aligns.get(c));
            for (List<String> r : grid) widths.set(c, Math.max(widths.get(c), r.get(c).length()));
        }

        Function<List<String>, String> line = cells -> {
            StringBuilder sb = new StringBuilder("| ");
            for (int i = 0; i < cols; i++) {
                if (i > 0) sb.append(" | ");
                sb.append(pad(cells.get(i), widths.get(i), align.get(i)));
            }
            return sb.append(" |").toString();
        };
        StringBuilder separator = new StringBuilder("| ");
        for (int c = 0; c < cols; c++) {
            if (c > 0) separator.append(" | ");
            separator.append(sepCell(align.get(c), widths.get(c)));
        }
        separator.append(" |");

        List<String> out = new ArrayList<>();
        out.add(line.apply(header ? grid.get(0) : Collections.nCopies(cols, "")));
        out.add(separator.toString());
        for (int i = header ? 1 : 0; i < grid.size(); i++) out.add(line.apply(grid.get(i)));
        return String.join("\n", out);
    }

    public static void main(String[] args) {
        // Demo: a CSV-ish grid with a literal pipe in one cell (escaped on output).
        List<List<String>> rows = parseTable("Name,Price,Qty\nWire | cable,2 m,1\nLED,3 mm,25", ',');
        System.out.println(toMarkdown(rows, true, List.of(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 →