         }
     }
 
+    /**
+     Render the table to a `String`.
+
+     - returns: The `String` representation of the table.
+    */
     public func render() -> String {
         let separator = fence(strings: columns.map({ column in
             return repeatElement(rowFence, count: column.width + 2).joined()

    }
}

public struct TextTable {
    private var columns: [TextTableColumn]
    public var columnFence = "|"
    public var rowFence = "-"
    public var cornerFence = "+"
    public var header: String? = nil

    public init(columns: [TextTableColumn], header: String? = nil) {
        self.columns = columns
        self.header = header
    }

    public init<T: TextTableObject>(objects: [T], header: String? = nil) {
        self.header = header ?? T.tableHeader
        columns = T.columnHeaders.map { TextTableColumn(header: $0) }
        objects.forEach { addRow(values: $0.tableValues) }
    }

    public mutating func addRow(values: [CustomStringConvertible]) {
        let values = values.count >= columns.count ? values :
            values + [CustomStringConvertible](repeating: "", count: columns.count - values.count)

        return [top, columnHeaders, separator, values, separator].paragraph()
    }

    /**
     Render the table's header to a `String`.

     - returns: The `String` representation of the table header. `nil` if `header` is `nil`.
    */
    private func renderTableHeader() -> String? {
        guard let header = header else {
            return nil
