Skip to content

Commit 364b09e

Browse files
Merge pull request #6 from hebertialmeida/swift-concurrency
Migrate to Swift 6.1
2 parents 43351d3 + e9201b4 commit 364b09e

24 files changed

Lines changed: 261 additions & 231 deletions

.github/workflows/swift.yml

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
11
name: Swift
2-
on: [push, pull_request]
2+
on: [pull_request]
33

44
jobs:
55
test:
6-
runs-on: macos-latest
7-
6+
runs-on: macos-15
7+
88
steps:
9-
- uses: actions/checkout@v1
10-
- name: Run tests
11-
run: set -o pipefail && time xcodebuild clean test -scheme MarkdownSyntax -sdk macosx -enableCodeCoverage YES | xcpretty
12-
- name: Codecov
13-
uses: codecov/codecov-action@v1.0.5
14-
with:
15-
token: ${{ secrets.CODECOV_TOKEN }}
9+
- uses: actions/checkout@v4.2.2
10+
- uses: maxim-lobanov/setup-xcode@v1.6.0
11+
with:
12+
xcode-version: '16.4.0'
13+
- name: Run tests
14+
run: swift test --enable-code-coverage
15+
- name: Generate coverage report
16+
run: |
17+
CODECOV_DIR=$(find .build -name 'codecov' -type d | head -1)
18+
19+
xcrun llvm-profdata merge -sparse "$CODECOV_DIR"/*.profraw -o default.profdata
20+
PROFDATA_PATH="default.profdata"
21+
22+
ALL_OBJECT_FILES=$(find .build -name "*.o" -type f)
23+
SOURCE_OBJECT_FILES=$(echo "$ALL_OBJECT_FILES" | grep "MarkdownSyntaxTests.build")
24+
25+
xcrun llvm-cov report -instr-profile $PROFDATA_PATH $SOURCE_OBJECT_FILES
26+
xcrun llvm-cov export -format="lcov" -instr-profile $PROFDATA_PATH $SOURCE_OBJECT_FILES >> lcov.info
27+
- name: Upload coverage to Codecov
28+
uses: codecov/codecov-action@v5.4.3
29+
with:
30+
token: ${{ secrets.CODECOV_TOKEN }}
31+
files: lcov.info

Package.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
// swift-tools-version:5.3
1+
// swift-tools-version:6.1
22

33
import PackageDescription
44

55
let package = Package(
66
name: "MarkdownSyntax",
7-
platforms: [.macOS(.v10_10), .iOS(.v9), .tvOS(.v9), .watchOS(.v2)],
7+
platforms: [.macOS(.v10_13), .iOS(.v12), .tvOS(.v12), .watchOS(.v4)],
88
products: [
99
.library(name: "MarkdownSyntax", targets: ["MarkdownSyntax"]),
1010
],
1111
dependencies: [
12-
.package(name: "cmark_gfm", url: "https://github.com/hebertialmeida/swift-cmark-gfm", .upToNextMajor(from: "1.1.0"))
12+
.package(url: "https://github.com/hebertialmeida/swift-cmark-gfm", .upToNextMajor(from: "1.1.0"))
1313
],
1414
targets: [
15-
.target(name: "MarkdownSyntax", dependencies: ["cmark_gfm"]),
15+
.target(name: "MarkdownSyntax", dependencies: [.product(name: "cmark_gfm", package: "swift-cmark-gfm")]),
1616
.testTarget(name: "MarkdownSyntaxTests", dependencies: ["MarkdownSyntax"]),
1717
]
1818
)

README.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ MarkdownSyntax is a wrapper on top of the Github Flavoured Markdown that conform
99

1010
```swift
1111
let input = "Hi this is **alpha**"
12-
let tree = try Markdown(text: input).parse()
12+
let tree = try await Markdown(text: input).parse()
1313
```
1414

1515
Outputs a normalized tree:
@@ -20,41 +20,41 @@ Root(
2020
Paragraph(
2121
children: [
2222
Text(
23-
value: "Hi this is ",
23+
value: "Hi this is ",
2424
position: Position(
25-
start: Point(line: 1, column: 1, offset: 0),
26-
end: Point(line: 1, column: 11, offset: 10),
25+
start: Point(line: 1, column: 1, offset: 0),
26+
end: Point(line: 1, column: 11, offset: 10),
2727
indent: nil
2828
)
29-
),
29+
),
3030
Strong(
3131
children: [
3232
Text(
33-
value: "alpha",
33+
value: "alpha",
3434
position: Position(
35-
start: Point(line: 1, column: 14, offset: 13),
36-
end: Point(line: 1, column: 18, offset: 17),
35+
start: Point(line: 1, column: 14, offset: 13),
36+
end: Point(line: 1, column: 18, offset: 17),
3737
indent: nil
3838
)
3939
)
40-
],
40+
],
4141
position: Position(
42-
start: Point(line: 1, column: 12, offset: 11),
43-
end: Point(line: 1, column: 20, offset: 19),
42+
start: Point(line: 1, column: 12, offset: 11),
43+
end: Point(line: 1, column: 20, offset: 19),
4444
indent: nil
4545
)
4646
)
47-
],
47+
],
4848
position: Position(
49-
start: Point(line: 1, column: 1, offset: 0),
50-
end: Point(line: 1, column: 20, offset: 19),
49+
start: Point(line: 1, column: 1, offset: 0),
50+
end: Point(line: 1, column: 20, offset: 19),
5151
indent: nil
5252
)
5353
)
54-
],
54+
],
5555
position: Position(
56-
start: Point(line: 1, column: 1, offset: 0),
57-
end: Point(line: 1, column: 20, offset: 19),
56+
start: Point(line: 1, column: 1, offset: 0),
57+
end: Point(line: 1, column: 20, offset: 19),
5858
indent: nil
5959
)
6060
)
@@ -71,7 +71,7 @@ Once you have your Swift package set up, adding MarkdownSyntax as a dependency i
7171

7272
```swift
7373
dependencies: [
74-
.package(url: "https://github.com/hebertialmeida/MarkdownSyntax", from: "1.1.0")
74+
.package(url: "https://github.com/hebertialmeida/MarkdownSyntax", from: "1.2.0")
7575
]
7676
```
7777

Sources/MarkdownSyntax/CMark/CMDocument.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public enum CMDocumentError: Error {
2020
}
2121

2222
/// Represents a cmark document.
23-
public class CMDocument {
23+
public class CMDocument: @unchecked Sendable {
2424

2525
/// The root node of the document.
2626
public let node: CMNode
@@ -117,8 +117,8 @@ public extension CMDocument {
117117
/// `CMDocumentError.renderError` if there is an error rendering the HTML.
118118
/// - Returns:
119119
/// The HTML as a string.
120-
func renderHtml() throws -> String {
121-
return try node.renderHtml(options, extensions: extensions)
120+
func renderHtml() async throws -> String {
121+
try await node.renderHtml(options, extensions: extensions)
122122
}
123123

124124
/// Renders the document as XML.
@@ -127,8 +127,8 @@ public extension CMDocument {
127127
/// `CMDocumentError.renderError` if there is an error rendering the XML.
128128
/// - Returns:
129129
/// The XML as a string.
130-
func renderXml() throws -> String {
131-
return try node.renderXml(options)
130+
func renderXml() async throws -> String {
131+
try await node.renderXml(options)
132132
}
133133

134134
/// Renders the document as groff man page.
@@ -139,8 +139,8 @@ public extension CMDocument {
139139
/// `CMDocumentError.renderError` if there is an error rendering the man page.
140140
/// - Returns:
141141
/// The man page as a string.
142-
func renderMan(width: Int32) throws -> String {
143-
return try node.renderMan(options, width: width)
142+
func renderMan(width: Int32) async throws -> String {
143+
try await node.renderMan(options, width: width)
144144
}
145145

146146
/// Renders the document as common mark.
@@ -151,8 +151,8 @@ public extension CMDocument {
151151
/// `CMDocumentError.renderError` if there is an error rendering the common mark.
152152
/// - Returns:
153153
/// The common mark as a string.
154-
func renderCommonMark(width: Int32) throws -> String {
155-
return try node.renderCommonMark(options, width: width)
154+
func renderCommonMark(width: Int32) async throws -> String {
155+
try await node.renderCommonMark(options, width: width)
156156
}
157157

158158
/// Renders the document as Latex.
@@ -163,8 +163,8 @@ public extension CMDocument {
163163
/// `CMDocumentError.renderError` if there is an error rendering the Latex.
164164
/// - Returns:
165165
/// The Latex as a string.
166-
func renderLatex(width: Int32) throws -> String {
167-
return try node.renderLatex(options, width: width)
166+
func renderLatex(width: Int32) async throws -> String {
167+
try await node.renderLatex(options, width: width)
168168
}
169169

170170
/// Renders the document as plain text.
@@ -175,8 +175,8 @@ public extension CMDocument {
175175
/// `CMDocumentError.renderError` if there is an error rendering the plain text.
176176
/// - Returns:
177177
/// The plain text as a string.
178-
func renderPlainText(width: Int32) throws -> String {
179-
return try node.renderPlainText(options, width: width)
178+
func renderPlainText(width: Int32) async throws -> String {
179+
try await node.renderPlainText(options, width: width)
180180
}
181181

182182
}

Sources/MarkdownSyntax/CMark/CMDocumentOption.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import cmark_gfm
1010

1111
/// Represents a cmark document option.
12-
public struct CMDocumentOption: OptionSet {
12+
public struct CMDocumentOption: OptionSet, Sendable {
1313

1414
/// The raw value.
1515
public let rawValue: Int32

Sources/MarkdownSyntax/CMark/CMExtension.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ enum CMExtensionName: String {
3131
}
3232

3333
/// Represents a cmark extension option.
34-
public struct CMExtensionOption: OptionSet {
34+
public struct CMExtensionOption: OptionSet, Sendable {
3535

3636
/// The raw value.
3737
public let rawValue: Int32

Sources/MarkdownSyntax/CMark/CMNode+Render.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public extension CMNode {
2020
/// `CMDocumentError.renderError` if there is an error rendering the HTML.
2121
/// - Returns:
2222
/// The HTML as a string.
23-
func renderHtml(_ options: CMDocumentOption, extensions: CMExtensionOption) throws -> String {
23+
func renderHtml(_ options: CMDocumentOption, extensions: CMExtensionOption) async throws -> String {
2424
var htmlExtensions: UnsafeMutablePointer<cmark_llist>?
2525

2626
if extensions.contains(.tagfilters), let tagfilter = cmark_find_syntax_extension("tagfilter") {
@@ -35,7 +35,7 @@ public extension CMNode {
3535
free(buffer)
3636
}
3737

38-
guard let html = String(validatingUTF8: buffer) else {
38+
guard let html = String(validatingCString: buffer) else {
3939
throw CMDocumentError.renderError
4040
}
4141

@@ -50,7 +50,7 @@ public extension CMNode {
5050
/// `CMDocumentError.renderError` if there is an error rendering the XML.
5151
/// - Returns:
5252
/// The XML as a string.
53-
func renderXml(_ options: CMDocumentOption) throws -> String {
53+
func renderXml(_ options: CMDocumentOption) async throws -> String {
5454
guard let buffer = cmark_render_xml(cmarkNode, options.rawValue) else {
5555
throw CMDocumentError.renderError
5656
}
@@ -59,7 +59,7 @@ public extension CMNode {
5959
free(buffer)
6060
}
6161

62-
guard let xml = String(validatingUTF8: buffer) else {
62+
guard let xml = String(validatingCString: buffer) else {
6363
throw CMDocumentError.renderError
6464
}
6565

@@ -75,7 +75,7 @@ public extension CMNode {
7575
/// `CMDocumentError.renderError` if there is an error rendering the man page.
7676
/// - Returns:
7777
/// The man page as a string.
78-
func renderMan(_ options: CMDocumentOption, width: Int32) throws -> String {
78+
func renderMan(_ options: CMDocumentOption, width: Int32) async throws -> String {
7979
guard let buffer = cmark_render_man(cmarkNode, options.rawValue, width) else {
8080
throw CMDocumentError.renderError
8181
}
@@ -84,7 +84,7 @@ public extension CMNode {
8484
free(buffer)
8585
}
8686

87-
guard let man = String(validatingUTF8: buffer) else {
87+
guard let man = String(validatingCString: buffer) else {
8888
throw CMDocumentError.renderError
8989
}
9090

@@ -100,7 +100,7 @@ public extension CMNode {
100100
/// `CMDocumentError.renderError` if there is an error rendering the common mark.
101101
/// - Returns:
102102
/// The common mark as a string.
103-
func renderCommonMark(_ options: CMDocumentOption, width: Int32) throws -> String {
103+
func renderCommonMark(_ options: CMDocumentOption, width: Int32) async throws -> String {
104104
guard let buffer = cmark_render_commonmark(cmarkNode, options.rawValue, width) else {
105105
throw CMDocumentError.renderError
106106
}
@@ -109,7 +109,7 @@ public extension CMNode {
109109
free(buffer)
110110
}
111111

112-
guard let commonMark = String(validatingUTF8: buffer) else {
112+
guard let commonMark = String(validatingCString: buffer) else {
113113
throw CMDocumentError.renderError
114114
}
115115

@@ -125,7 +125,7 @@ public extension CMNode {
125125
/// `CMDocumentError.renderError` if there is an error rendering the Latex.
126126
/// - Returns:
127127
/// The Latex as a string.
128-
func renderLatex(_ options: CMDocumentOption, width: Int32) throws -> String {
128+
func renderLatex(_ options: CMDocumentOption, width: Int32) async throws -> String {
129129
guard let buffer = cmark_render_latex(cmarkNode, options.rawValue, width) else {
130130
throw CMDocumentError.renderError
131131
}
@@ -134,7 +134,7 @@ public extension CMNode {
134134
free(buffer)
135135
}
136136

137-
guard let latex = String(validatingUTF8: buffer) else {
137+
guard let latex = String(validatingCString: buffer) else {
138138
throw CMDocumentError.renderError
139139
}
140140

@@ -150,7 +150,7 @@ public extension CMNode {
150150
/// `CMDocumentError.renderError` if there is an error rendering the plain text.
151151
/// - Returns:
152152
/// The plain text as a string.
153-
func renderPlainText(_ options: CMDocumentOption, width: Int32) throws -> String {
153+
func renderPlainText(_ options: CMDocumentOption, width: Int32) async throws -> String {
154154
guard let buffer = cmark_render_plaintext(cmarkNode, options.rawValue, width) else {
155155
throw CMDocumentError.renderError
156156
}
@@ -159,7 +159,7 @@ public extension CMNode {
159159
free(buffer)
160160
}
161161

162-
guard let text = String(validatingUTF8: buffer) else {
162+
guard let text = String(validatingCString: buffer) else {
163163
throw CMDocumentError.renderError
164164
}
165165

Sources/MarkdownSyntax/CMark/CMNode.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import struct Foundation.URL
1010
import cmark_gfm
1111

1212
/// Represents a cmark node.
13-
public class CMNode {
13+
public final class CMNode: @unchecked Sendable {
1414

1515
/// The underlying cmark node pointer.
1616
public let cmarkNode: UnsafeMutablePointer<cmark_node>

Sources/MarkdownSyntax/CMark/CMNodeType.swift

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,38 @@
99
import cmark_gfm
1010

1111
/// Represents a cmark extension node type.
12-
public enum CMNodeExtensionType: Equatable {
12+
public enum CMNodeExtensionType: Equatable, Sendable {
1313
case strikethrough
1414
case table
1515
case tableRow
1616
case tableCell
1717
case other(UInt32)
1818

19+
/// Ideally this should be
20+
/// CMARK_NODE_STRIKETHROUGH.rawValue,
21+
/// CMARK_NODE_TABLE.rawValue,
22+
/// CMARK_NODE_TABLE_ROW.rawValue,
23+
/// CMARK_NODE_TABLE_CELL.rawValue
24+
///
25+
/// But Swift 6 strict concurrency complains about that.
26+
private struct CMarkConstants {
27+
static let strikethrough: UInt32 = 49164 // 0xBFFC
28+
static let table: UInt32 = 32780 // 0x800C
29+
static let tableRow: UInt32 = 32781 // 0x800D
30+
static let tableCell: UInt32 = 32782 // 0x800E
31+
}
32+
1933
/// The raw value.
2034
var rawValue: UInt32 {
2135
switch self {
2236
case .strikethrough:
23-
return CMARK_NODE_STRIKETHROUGH.rawValue
37+
return CMarkConstants.strikethrough
2438
case .table:
25-
return CMARK_NODE_TABLE.rawValue
39+
return CMarkConstants.table
2640
case .tableRow:
27-
return CMARK_NODE_TABLE_ROW.rawValue
41+
return CMarkConstants.tableRow
2842
case .tableCell:
29-
return CMARK_NODE_TABLE_CELL.rawValue
43+
return CMarkConstants.tableCell
3044
case let .other(rawValue):
3145
return rawValue
3246
}

0 commit comments

Comments
 (0)