Skip to content

Commit fd79e62

Browse files
authored
Merge branch 'swiftlang:main' into main
2 parents cac2827 + d217140 commit fd79e62

File tree

11 files changed

+222
-29
lines changed

11 files changed

+222
-29
lines changed

CODE_OF_CONDUCT.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

Package.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.5
1+
// swift-tools-version:5.7
22
/*
33
This source file is part of the Swift.org open source project
44

@@ -28,6 +28,9 @@ let package = Package(
2828
"CAtomic",
2929
.product(name: "cmark-gfm", package: cmarkPackageName),
3030
.product(name: "cmark-gfm-extensions", package: cmarkPackageName),
31+
],
32+
exclude: [
33+
"CMakeLists.txt"
3134
]),
3235
.testTarget(
3336
name: "MarkdownTests",
@@ -43,7 +46,7 @@ let package = Package(
4346
if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
4447
// Building standalone, so fetch all dependencies remotely.
4548
package.dependencies += [
46-
.package(url: "https://github.com/apple/swift-cmark.git", branch: "gfm"),
49+
.package(url: "https://github.com/swiftlang/swift-cmark.git", branch: "gfm"),
4750
]
4851

4952
// SwiftPM command plugins are only supported by Swift version 5.6 and later.

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Swift `Markdown` is a Swift package for parsing, building, editing, and analyzin
44

55
The parser is powered by GitHub-flavored Markdown's [cmark-gfm](https://github.com/github/cmark-gfm) implementation, so it follows the spec closely. As the needs of the community change, the effective dialect implemented by this library may change.
66

7-
The markup tree provided by this package is comprised of immutable/persistent, thread-safe, copy-on-write value types that only copy substructure that has changed. Other examples of the main strategy behind this library can be seen in [SwiftSyntax](https://github.com/apple/swift-syntax).
7+
The markup tree provided by this package is comprised of immutable/persistent, thread-safe, copy-on-write value types that only copy substructure that has changed. Other examples of the main strategy behind this library can be seen in [SwiftSyntax](https://github.com/swiftlang/swift-syntax).
88

99
## Getting Started Using Markup
1010

@@ -41,10 +41,12 @@ print(document.debugDescription())
4141
// └─ Text "."
4242
```
4343

44-
Please see Swift `Markdown`'s [documentation site](https://apple.github.io/swift-markdown/documentation/markdown/)
44+
Please see Swift `Markdown`'s [documentation site](https://swiftlang.github.io/swift-markdown/documentation/markdown/)
4545
for more detailed information about the library.
4646

47-
## Getting Involved
47+
## Contributing to Swift Markdown
48+
49+
Please see the [contributing guide](https://swift.org/contributing/#contributing-code) for more information.
4850

4951
### Submitting a Bug Report
5052

@@ -62,8 +64,6 @@ or start a discussion on the [Swift Forums](https://forums.swift.org/c/developme
6264
Don't hesitate to submit a feature request if you see a way
6365
Swift Markdown can be improved to better meet your needs.
6466

65-
### Contributing to Swift Markdown
6667

67-
Please see the [contributing guide](https://swift.org/contributing/#contributing-code) for more information.
6868

6969
<!-- Copyright (c) 2021-2023 Apple Inc and the Swift Project authors. All Rights Reserved. -->

Sources/Markdown/Markdown.docc/Markdown.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Swift `Markdown` is a Swift package for parsing, building, editing, and analyzin
66

77
The parser is powered by GitHub-flavored Markdown's [cmark-gfm](https://github.com/github/cmark-gfm) implementation, so it follows the spec closely. As the needs of the community change, the effective dialect implemented by this library may change.
88

9-
The markup tree provided by this package is comprised of immutable/persistent, thread-safe, copy-on-write value types that only copy substructure that has changed. Other examples of the main strategy behind this library can be seen in [SwiftSyntax](https://github.com/apple/swift-syntax).
9+
The markup tree provided by this package is comprised of immutable/persistent, thread-safe, copy-on-write value types that only copy substructure that has changed. Other examples of the main strategy behind this library can be seen in [SwiftSyntax](https://github.com/swiftlang/swift-syntax).
1010

1111
## Topics
1212

Sources/Markdown/Markdown.docc/Markdown/DoxygenCommands.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Doxygen commands are not parsed within code blocks or block directive content.
4444

4545
### Commands
4646

47+
- ``DoxygenDiscussion``
48+
- ``DoxygenNote``
4749
- ``DoxygenParam``
4850
- ``DoxygenReturns``
4951

Sources/Markdown/Visitor/MarkupVisitor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2021 Apple Inc. and the Swift project authors
4+
Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -13,7 +13,7 @@
1313
/// - note: This interface only provides requirements for visiting each kind of element. It does not require each visit method to descend into child elements.
1414
///
1515
/// Generally, ``MarkupWalker`` is best for walking a ``Markup`` tree if the ``Result`` type is `Void` or is built up some other way, or ``MarkupRewriter`` for recursively changing a tree's structure. This type serves as a common interface to both. However, for building up other structured result types you can implement ``MarkupVisitor`` directly.
16-
public protocol MarkupVisitor {
16+
public protocol MarkupVisitor<Result> {
1717

1818
/**
1919
The result type returned when visiting a element.

Sources/Markdown/Walker/Walkers/MarkupFormatter.swift

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
4+
Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -463,7 +463,8 @@ public struct MarkupFormatter: MarkupWalker {
463463
} else if let numeralPrefix = numeralPrefix(for: parentListItem) {
464464
prefix += String(repeating: " ", count: numeralPrefix.count)
465465
}
466-
} else if element is BlockDirective {
466+
}
467+
if element.parent is BlockDirective {
467468
prefix += " "
468469
}
469470
}
@@ -1105,7 +1106,9 @@ public struct MarkupFormatter: MarkupWalker {
11051106
}
11061107

11071108
public mutating func visitBlockDirective(_ blockDirective: BlockDirective) {
1108-
ensurePrecedingNewlineCount(atLeast: 1)
1109+
if blockDirective.indexInParent > 0 {
1110+
ensurePrecedingNewlineCount(atLeast: 2)
1111+
}
11091112
print("@", for: blockDirective)
11101113
print(blockDirective.name, for: blockDirective)
11111114

@@ -1124,13 +1127,13 @@ public struct MarkupFormatter: MarkupWalker {
11241127

11251128
if blockDirective.childCount > 0 {
11261129
print(" {", for: blockDirective)
1130+
queueNewline()
11271131
}
11281132

11291133
descendInto(blockDirective)
11301134

1131-
queueNewline()
1132-
11331135
if blockDirective.childCount > 0 {
1136+
queueNewline()
11341137
print("}", for: blockDirective)
11351138
}
11361139
}
@@ -1165,15 +1168,29 @@ public struct MarkupFormatter: MarkupWalker {
11651168
}
11661169
}
11671170

1168-
public mutating func visitDoxygenParameter(_ doxygenParam: DoxygenParameter) -> () {
1169-
print("\(formattingOptions.doxygenCommandPrefix.rawValue)param", for: doxygenParam)
1170-
print(" \(doxygenParam.name) ", for: doxygenParam)
1171+
private mutating func printDoxygenStart(_ name: String, for element: Markup) {
1172+
print(formattingOptions.doxygenCommandPrefix.rawValue + name + " ", for: element)
1173+
}
1174+
1175+
public mutating func visitDoxygenDiscussion(_ doxygenDiscussion: DoxygenDiscussion) {
1176+
printDoxygenStart("discussion", for: doxygenDiscussion)
1177+
descendInto(doxygenDiscussion)
1178+
}
1179+
1180+
public mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) {
1181+
printDoxygenStart("note", for: doxygenNote)
1182+
descendInto(doxygenNote)
1183+
}
1184+
1185+
public mutating func visitDoxygenParameter(_ doxygenParam: DoxygenParameter) {
1186+
printDoxygenStart("param", for: doxygenParam)
1187+
print("\(doxygenParam.name) ", for: doxygenParam)
11711188
descendInto(doxygenParam)
11721189
}
11731190

1174-
public mutating func visitDoxygenReturns(_ doxygenReturns: DoxygenReturns) -> () {
1191+
public mutating func visitDoxygenReturns(_ doxygenReturns: DoxygenReturns) {
11751192
// FIXME: store the actual command name used in the original markup
1176-
print("\(formattingOptions.doxygenCommandPrefix.rawValue)returns ", for: doxygenReturns)
1193+
printDoxygenStart("returns", for: doxygenReturns)
11771194
descendInto(doxygenReturns)
11781195
}
11791196
}

Tests/MarkdownTests/Visitors/MarkupFormatterTests.swift

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
This source file is part of the Swift.org open source project
33

4-
Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
4+
Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
55
Licensed under Apache License v2.0 with Runtime Library Exception
66

77
See https://swift.org/LICENSE.txt for license information
@@ -289,6 +289,56 @@ class MarkupFormatterSingleElementTests: XCTestCase {
289289
XCTAssertEqual(expected, printed)
290290
}
291291

292+
func testPrintDoxygenPrefix() {
293+
let expectedSlash = #"\discussion Discussion"#
294+
let printedSlash = DoxygenDiscussion(children: Paragraph(Text("Discussion")))
295+
.format(options: .init(doxygenCommandPrefix: .backslash))
296+
XCTAssertEqual(expectedSlash, printedSlash)
297+
298+
let expectedAt = "@discussion Discussion"
299+
let printedAt = DoxygenDiscussion(children: Paragraph(Text("Discussion")))
300+
.format(options: .init(doxygenCommandPrefix: .at))
301+
XCTAssertEqual(expectedAt, printedAt)
302+
}
303+
304+
func testPrintDoxygenDiscussion() {
305+
let expected = #"\discussion Another thing."#
306+
let printed = DoxygenDiscussion(children: Paragraph(Text("Another thing."))).format()
307+
XCTAssertEqual(expected, printed)
308+
}
309+
310+
func testPrintDoxygenDiscussionMultiline() {
311+
let expected = #"""
312+
\discussion Another thing.
313+
This is an extended discussion.
314+
"""#
315+
let printed = DoxygenDiscussion(children: Paragraph(
316+
Text("Another thing."),
317+
SoftBreak(),
318+
Text("This is an extended discussion.")
319+
)).format()
320+
XCTAssertEqual(expected, printed)
321+
}
322+
323+
func testPrintDoxygenNote() {
324+
let expected = #"\note Another thing."#
325+
let printed = DoxygenNote(children: Paragraph(Text("Another thing."))).format()
326+
XCTAssertEqual(expected, printed)
327+
}
328+
329+
func testPrintDoxygenNoteMultiline() {
330+
let expected = #"""
331+
\note Another thing.
332+
This is an extended discussion.
333+
"""#
334+
let printed = DoxygenNote(children: Paragraph(
335+
Text("Another thing."),
336+
SoftBreak(),
337+
Text("This is an extended discussion.")
338+
)).format()
339+
XCTAssertEqual(expected, printed)
340+
}
341+
292342
func testPrintDoxygenParameter() {
293343
let expected = #"\param thing The thing."#
294344
let printed = DoxygenParameter(name: "thing", children: Paragraph(Text("The thing."))).format()
@@ -326,6 +376,18 @@ class MarkupFormatterSingleElementTests: XCTestCase {
326376
)).format()
327377
XCTAssertEqual(expected, printed)
328378
}
379+
380+
func testPrintBlockDirective() {
381+
let expected = #"""
382+
@Metadata {
383+
@TitleHeading(Example)
384+
}
385+
"""#
386+
let printed = BlockDirective(name: "Metadata", children: [
387+
BlockDirective(name: "TitleHeading", argumentText: "Example"),
388+
]).format()
389+
XCTAssertEqual(expected, printed)
390+
}
329391
}
330392

331393
/// Tests that formatting options work correctly.
@@ -1483,10 +1545,65 @@ class MarkupFormatterTableTests: XCTestCase {
14831545
"""
14841546

14851547
XCTAssertEqual(expected, formatted)
1486-
print(formatted)
14871548

14881549
let reparsed = Document(parsing: formatted)
1489-
print(reparsed.debugDescription())
14901550
XCTAssertTrue(document.hasSameStructure(as: reparsed))
14911551
}
14921552
}
1553+
1554+
class MarkupFormatterMixedContentTests: XCTestCase {
1555+
func testMixedContentWithBlockDirectives() {
1556+
let expected = [
1557+
#"""
1558+
# Example title
1559+
1560+
@Metadata {
1561+
@TitleHeading(example)
1562+
}
1563+
"""#,
1564+
#"""
1565+
@Tutorials(name: Foo) {
1566+
@Intro(title: Bar) {
1567+
Foobar
1568+
1569+
@Image(source: foo, alt: bar)
1570+
}
1571+
}
1572+
"""#,
1573+
#"""
1574+
# Example title
1575+
1576+
@Links(visualStyle: list) {
1577+
- ``Foo``
1578+
- ``Bar``
1579+
}
1580+
"""#,
1581+
]
1582+
let printed = [
1583+
Document(
1584+
Heading(level: 1, Text("Example title")),
1585+
BlockDirective(name: "Metadata", children: [
1586+
BlockDirective(name: "TitleHeading", argumentText: "example"),
1587+
])
1588+
).format(),
1589+
Document(
1590+
BlockDirective(name: "Tutorials", argumentText: "name: Foo", children: [
1591+
BlockDirective(name: "Intro", argumentText: "title: Bar", children: [
1592+
Paragraph(Text("Foobar")) as BlockMarkup,
1593+
BlockDirective(name: "Image", argumentText: "source: foo, alt: bar") as BlockMarkup,
1594+
]),
1595+
])
1596+
).format(),
1597+
Document(
1598+
Heading(level: 1, Text("Example title")),
1599+
BlockDirective(name: "Links", argumentText: "visualStyle: list", children: [
1600+
UnorderedList([
1601+
ListItem(Paragraph(SymbolLink(destination: "Foo"))),
1602+
ListItem(Paragraph(SymbolLink(destination: "Bar"))),
1603+
]),
1604+
])
1605+
).format(),
1606+
]
1607+
zip(expected, printed).forEach { XCTAssertEqual($0, $1) }
1608+
}
1609+
}

Tests/MarkdownTests/Visitors/MarkupTreeDumperTests.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ final class MarkupTreeDumperTests: XCTestCase {
9595
└─ HTMLBlock @42:1-42:90 #71
9696
<!-- Copyright (c) 2021 Apple Inc and the Swift Project authors. All Rights Reserved. -->
9797
"""
98-
print(everythingDocument.debugDescription(options: [.printEverything]))
9998
XCTAssertEqual(expectedDump, everythingDocument.debugDescription(options: [.printEverything]))
10099
}
101100
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2023 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See https://swift.org/LICENSE.txt for license information
8+
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import XCTest
12+
import Markdown
13+
14+
class MarkupVisitorTests: XCTestCase {
15+
struct IntegerConverter: MarkupVisitor {
16+
var value: Int
17+
18+
mutating func defaultVisit(_: Markdown.Markup) -> Int {
19+
defer { value += 1 }
20+
return value
21+
}
22+
}
23+
24+
25+
// A compile time check for PAT support
26+
func testMarkupVisitorPrimaryAssociatedType() {
27+
var visitor: some MarkupVisitor<Int> = IntegerConverter(value: 1)
28+
let markup = Text("")
29+
XCTAssertEqual(visitor.visit(markup), 1)
30+
XCTAssertEqual(visitor.visit(markup), 2)
31+
var mappedVisitor: some MarkupVisitor<Int> = visitor.map { $0 * $0 }
32+
XCTAssertEqual(mappedVisitor.visit(markup), 9)
33+
XCTAssertEqual(mappedVisitor.visit(markup), 16)
34+
XCTAssertEqual(visitor.visit(markup), 3)
35+
}
36+
}
37+
38+
struct _MappVisitor<A: MarkupVisitor, B>: MarkupVisitor {
39+
typealias Result = B
40+
init(visitor: A, _ transform: @escaping (A.Result) -> B) {
41+
self.visitor = visitor
42+
self.transform = transform
43+
}
44+
private var visitor: A
45+
private let transform: (A.Result) -> B
46+
47+
mutating func defaultVisit(_ markup: Markdown.Markup) -> B {
48+
transform(visitor.defaultVisit(markup))
49+
}
50+
}
51+
52+
extension MarkupVisitor {
53+
func map<U>(_ transform: @escaping (Self.Result) -> U) -> some MarkupVisitor<U> {
54+
_MappVisitor(visitor: self, transform)
55+
}
56+
}

0 commit comments

Comments
 (0)