Markdown Table Generator — Swift 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 Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.
// markdown-table — Swift port: split delimiter-separated rows and render a padded GFM table, ported from src/lib/markdown-table.ts.
import Foundation
enum Align: String { case none, left, center, right }
/// escapeCell: newlines collapse to spaces, a literal '|' renders as '\|'.
func escapeCell(_ cell: String) -> String {
var out = ""
for ch in cell {
switch ch {
case "\r", "\n": out.append(" ")
case "|": out.append("\\|")
default: out.append(ch)
}
}
return out
}
/// splitLine: literal-delimiter split (',', '\t', ';'), each cell trimmed.
func splitLine(_ line: String, _ delim: Character) -> [String] {
line.split(separator: delim, omittingEmptySubsequences: false)
.map { String($0).trimmingCharacters(in: .whitespacesAndNewlines) }
}
/// parseTable: non-empty lines, each split by the delimiter.
func parseTable(_ input: String, _ delim: Character) -> [[String]] {
input.split(separator: "\n", omittingEmptySubsequences: false)
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty }
.map { splitLine($0, delim) }
}
/// pad: fill to width honoring right/center/left alignment.
func pad(_ cell: String, _ width: Int, _ align: Align) -> String {
let diff = width - cell.count
guard diff > 0 else { return cell }
switch align {
case .right: return String(repeating: " ", count: diff) + cell
case .center:
return String(repeating: " ", count: diff / 2) + cell
+ String(repeating: " ", count: diff - diff / 2)
case .left, .none: return cell + String(repeating: " ", count: diff)
}
}
/// sepCell: ---, :--, --:, :-: — the alignment separator, min width 3.
func sepCell(_ align: Align, _ width: Int) -> String {
let w = max(3, width)
switch align {
case .center: return ":" + String(repeating: "-", count: w - 2) + ":"
case .right: return String(repeating: "-", count: w - 1) + ":"
case .left: return ":" + String(repeating: "-", count: w - 1)
case .none: return String(repeating: "-", count: 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.
func toMarkdown(_ rows: [[String]], header: Bool = true, aligns: [Align] = []) -> String {
guard !rows.isEmpty else { return "" }
let cols = rows.map { $0.count }.max()!
var grid = rows.map { row -> [String] in
var cells = row.map(escapeCell)
while cells.count < cols { cells.append("") }
return cells
}
let align = (0..<cols).map { aligns.indices.contains($0) ? aligns[$0] : .none }
let widths = (0..<cols).map { c in max(3, grid.map { $0[c].count }.max()!) }
func line(_ cells: [String]) -> String {
"| " + cells.enumerated()
.map { pad($0.element, widths[$0.offset], align[$0.offset]) }
.joined(separator: " | ") + " |"
}
let separator = "| " + align.enumerated()
.map { sepCell($0.element, widths[$0.offset]) }
.joined(separator: " | ") + " |"
let head = header ? grid.removeFirst() : Array(repeating: "", count: cols)
let data = grid
return ([line(head), separator] + data.map(line)).joined(separator: "\n")
}
// Demo: a CSV-ish grid with a literal pipe in one cell (escaped on output).
let rows = parseTable("Name,Price,Qty\nWire | cable,2 m,1\nLED,3 mm,25", ",")
print(toMarkdown(rows, aligns: [.none, .right, .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 →