Skip to content

Commit 65c2df3

Browse files
committed
Markdown tables
1 parent 9640ab9 commit 65c2df3

File tree

8 files changed

+193
-8
lines changed

8 files changed

+193
-8
lines changed

Docs/Reference/MarkdownGenerator/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Run `sourcedocs` in the repository root to update this documentation.
1010
- [MarkdownImage](/Docs/Reference/MarkdownGenerator/structs/MarkdownImage.md)
1111
- [MarkdownLink](/Docs/Reference/MarkdownGenerator/structs/MarkdownLink.md)
1212
- [MarkdownList](/Docs/Reference/MarkdownGenerator/structs/MarkdownList.md)
13+
- [MarkdownTable](/Docs/Reference/MarkdownGenerator/structs/MarkdownTable.md)
1314

1415

1516

Docs/Reference/MarkdownGenerator/structs/MarkdownImage.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ MarkdownImage.Type
2121

2222
Render an HTML image in Markdown format
2323

24-
MarkdownImage(url: "http://www.enekoalonso.com/media/sourcedocs-header.jpg", altText: "SourceDocs Header").markdown
24+
MarkdownImage(url: "http://example.com/image.jpg", altText: "SourceDocs Header").markdown
2525

2626
Would render as:
2727

28-
![SourceDocs Header](http://www.enekoalonso.com/media/sourcedocs-header.jpg)
28+
![SourceDocs Header](http://example.com/image.jpg)
2929

3030
--------------------
3131

Docs/Reference/MarkdownGenerator/structs/MarkdownLink.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ MarkdownLink.Type
2121

2222
Render an HTML link in Markdown format
2323

24-
MarkdownLink(text: "Google", url: "https://www.google.com").markdown
24+
MarkdownLink(text: "Google", url: "https://example.com").markdown
2525

2626
Would render as:
2727

28-
[Google](https://www.google.com)
28+
[Google](https://example.com)
2929

3030
--------------------
3131

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
**STRUCT**
2+
# `MarkdownTable`
3+
4+
**Contents**
5+
- [Properties](#properties)
6+
- `markdown`
7+
- [Methods](#methods)
8+
- `init(headers:data:)`
9+
10+
**Declaration**
11+
```swift
12+
public struct MarkdownTable: MarkdownConvertible
13+
```
14+
15+
**Infered Type**
16+
```swift
17+
MarkdownTable.Type
18+
```
19+
20+
Render a two dimmensional Markdown table.
21+
22+
| | Name | Department |
23+
| - | ---- | ---------- |
24+
| 🍏 | Apple | Fruits |
25+
| 🍊 | Orange | Fruits |
26+
| 🥖 | Bread | Bakery |
27+
28+
*Notes*:
29+
- Markdown tables are not supported by all Markdown readers.
30+
- Table headers are required.
31+
- Table cells cannot contain multiple lines. New line characters are replaced by a space.
32+
33+
--------------------
34+
35+
## Properties
36+
### `markdown`
37+
38+
**Declaration**
39+
```swift
40+
public var markdown: String
41+
```
42+
43+
**Infered Type**
44+
```swift
45+
String
46+
```
47+
48+
Generated Markdown output
49+
50+
--------------------
51+
52+
## Methods
53+
### `init(headers:data:)`
54+
55+
**Declaration**
56+
```swift
57+
public init(headers: [String], data: [[String]])
58+
```
59+
60+
**Infered Type**
61+
```swift
62+
(MarkdownTable.Type) -> ([String], [[String]]) -> MarkdownTable
63+
```
64+
65+
MarkdownTable initializer
66+
67+
- Parameters:
68+
- headers: List of table header titles.
69+
- data: Two-dimensional `String` array with the table content. Rows are defined by
70+
the outer array, columns are defined by the inner arrays.
71+
72+
An array of rows, each row containing an array of columns. All rows should contain the same
73+
number of colums as the headers array, to avoid formatting issues.
74+
75+
#### Parameters
76+
| Name | Description |
77+
| ---- | ----------- |
78+
| `headers` | List of table header titles. |
79+
| `data` | Two-dimensional `String` array with the table content. Rows are defined by the outer array, columns are defined by the inner arrays.
80+
An array of rows, each row containing an array of columns. All rows should contain the same number of colums as the headers array, to avoid formatting issues. |

Sources/MarkdownGenerator/MarkdownImage.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import Foundation
99

1010
/// Render an HTML image in Markdown format
1111
///
12-
/// MarkdownImage(url: "http://www.enekoalonso.com/media/sourcedocs-header.jpg", altText: "SourceDocs Header").markdown
12+
/// MarkdownImage(url: "http://example.com/image.jpg", altText: "SourceDocs Header").markdown
1313
///
1414
/// Would render as:
1515
///
16-
/// ![SourceDocs Header](http://www.enekoalonso.com/media/sourcedocs-header.jpg)
16+
/// ![SourceDocs Header](http://example.com/image.jpg)
1717
///
1818
public struct MarkdownImage: MarkdownConvertible {
1919

Sources/MarkdownGenerator/MarkdownLink.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import Foundation
99

1010
/// Render an HTML link in Markdown format
1111
///
12-
/// MarkdownLink(text: "Google", url: "https://www.google.com").markdown
12+
/// MarkdownLink(text: "Google", url: "https://example.com").markdown
1313
///
1414
/// Would render as:
1515
///
16-
/// [Google](https://www.google.com)
16+
/// [Google](https://example.com)
1717
///
1818
public struct MarkdownLink: MarkdownConvertible {
1919

Sources/MarkdownGenerator/MarkdownTable.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,56 @@
66
//
77

88
import Foundation
9+
10+
/// Render a two dimmensional Markdown table.
11+
///
12+
/// | | Name | Department |
13+
/// | - | ---- | ---------- |
14+
/// | 🍏 | Apple | Fruits |
15+
/// | 🍊 | Orange | Fruits |
16+
/// | 🥖 | Bread | Bakery |
17+
///
18+
/// *Notes*:
19+
/// - Markdown tables are not supported by all Markdown readers.
20+
/// - Table headers are required.
21+
/// - Table cells cannot contain multiple lines. New line characters are replaced by a space.
22+
public struct MarkdownTable: MarkdownConvertible {
23+
24+
let headers: [String]
25+
let data: [[String]]
26+
27+
/// MarkdownTable initializer
28+
///
29+
/// - Parameters:
30+
/// - headers: List of table header titles.
31+
/// - data: Two-dimensional `String` array with the table content. Rows are defined by
32+
/// the outer array, columns are defined by the inner arrays.
33+
///
34+
/// An array of rows, each row containing an array of columns. All rows should contain the same
35+
/// number of colums as the headers array, to avoid formatting issues.
36+
public init(headers: [String], data: [[String]]) {
37+
self.headers = headers.map { $0.isEmpty ? " " : $0 }
38+
self.data = data
39+
}
40+
41+
/// Generated Markdown output
42+
public var markdown: String {
43+
let headerRow = makeRow(values: headers)
44+
let separatorRow = makeRow(values: headers.map { Array(repeating: "-", count: $0.count).joined() })
45+
let dataRows = data.map { columns in
46+
return makeRow(values: columns)
47+
}
48+
return """
49+
\(headerRow)
50+
\(separatorRow)
51+
\(dataRows.joined(separator: String.newLine))
52+
"""
53+
}
54+
55+
// Convert a String array into a markdown formatter table row.
56+
// Table cells cannot contain multiple lines. New line characters are replaced by a space.
57+
private func makeRow(values: [String]) -> String {
58+
let values = values.map { $0.replacingOccurrences(of: String.newLine, with: " ") }
59+
return "| " + values.joined(separator: " | ") + " |"
60+
}
61+
}

Tests/MarkdownGeneratorTests/MarkdownTableTests.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,59 @@
66
//
77

88
import XCTest
9+
import MarkdownGenerator
910

1011
class MarkdownTableTests: XCTestCase {
1112

13+
func test1x1Table() {
14+
let data: [[String]] = [[]]
15+
let table = MarkdownTable(headers: ["Header"], data: data)
16+
17+
let output = """
18+
| Header |
19+
| ------ |
20+
| |
21+
"""
22+
23+
XCTAssertEqual(table.markdown, output)
24+
}
25+
26+
func test3x3Table() {
27+
let data: [[String]] = [
28+
["🍏", "Apple", "Fruits"],
29+
["🍊", "Orange", "Fruits"],
30+
["🥖", "Bread", "Bakery"],
31+
]
32+
let table = MarkdownTable(headers: ["", "Name", "Department"], data: data)
33+
34+
let output = """
35+
| | Name | Department |
36+
| - | ---- | ---------- |
37+
| 🍏 | Apple | Fruits |
38+
| 🍊 | Orange | Fruits |
39+
| 🥖 | Bread | Bakery |
40+
"""
41+
42+
XCTAssertEqual(table.markdown, output)
43+
}
44+
45+
func testMultilineValues() {
46+
let data: [[String]] = [
47+
["Single-line value", "Multi-line\n\nvalue"],
48+
["Single-line value", "Multi-line\n\nvalue"],
49+
["Single-line value", "Multi-line\n\nvalue"],
50+
]
51+
let table = MarkdownTable(headers: ["Single-line", "Multi-line"], data: data)
52+
53+
let output = """
54+
| Single-line | Multi-line |
55+
| ----------- | ---------- |
56+
| Single-line value | Multi-line value |
57+
| Single-line value | Multi-line value |
58+
| Single-line value | Multi-line value |
59+
"""
60+
61+
XCTAssertEqual(table.markdown, output)
62+
}
1263

1364
}

0 commit comments

Comments
 (0)