Skip to content

Commit f7a559e

Browse files
Revert "Revert "Add preceding newlines before Doxygen commands" (#248)" (#249)
This reverts commit 679b531.
1 parent 679b531 commit f7a559e

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

Sources/Markdown/Walker/Walkers/MarkupFormatter.swift

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ fileprivate extension Markup {
3333
}
3434
return nil
3535
}
36+
37+
/// Previous sibling of this element in its parent, or `nil` if it's the first child.
38+
var previousSibling: Markup? {
39+
guard let parent, indexInParent > 0 else {
40+
return nil
41+
}
42+
43+
return parent.child(at: indexInParent - 1)
44+
}
45+
46+
/// Whether this element is a Doxygen command.
47+
var isDoxygenCommand: Bool {
48+
return self is DoxygenDiscussion || self is DoxygenNote || self is DoxygenAbstract
49+
|| self is DoxygenParameter || self is DoxygenReturns
50+
}
3651
}
3752

3853
fileprivate extension String {
@@ -239,6 +254,15 @@ public struct MarkupFormatter: MarkupWalker {
239254
case at = "@"
240255
}
241256

257+
/// The spacing to use when formatting adjacent Doxygen commands.
258+
public enum AdjacentDoxygenCommandsSpacing: String, CaseIterable {
259+
/// Separate adjacent Doxygen commands with a single newline.
260+
case singleNewline = "single-newline"
261+
262+
/// Keep a blank line between adjacent Doxygen commands creating separate paragraphs.
263+
case separateParagraphs = "separate-paragraphs"
264+
}
265+
242266
// MARK: Option Properties
243267

244268
var orderedListNumerals: OrderedListNumerals
@@ -253,6 +277,7 @@ public struct MarkupFormatter: MarkupWalker {
253277
var preferredLineLimit: PreferredLineLimit?
254278
var customLinePrefix: String
255279
var doxygenCommandPrefix: DoxygenCommandPrefix
280+
var adjacentDoxygenCommandsSpacing: AdjacentDoxygenCommandsSpacing
256281

257282
/**
258283
Create a set of formatting options to use when printing an element.
@@ -270,6 +295,7 @@ public struct MarkupFormatter: MarkupWalker {
270295
- preferredLineLimit: The preferred maximum line length and method for splitting ``Text`` elements in an attempt to maintain that line length.
271296
- customLinePrefix: An addition prefix to print at the start of each line, useful for adding documentation comment markers.
272297
- doxygenCommandPrefix: The command command prefix, which defaults to ``DoxygenCommandPrefix/backslash``.
298+
- adjacentDoxygenCommandsSpacing: The spacing to use when formatting adjacent Doxygen commands.
273299
*/
274300
public init(unorderedListMarker: UnorderedListMarker = .dash,
275301
orderedListNumerals: OrderedListNumerals = .allSame(1),
@@ -282,7 +308,8 @@ public struct MarkupFormatter: MarkupWalker {
282308
preferredHeadingStyle: PreferredHeadingStyle = .atx,
283309
preferredLineLimit: PreferredLineLimit? = nil,
284310
customLinePrefix: String = "",
285-
doxygenCommandPrefix: DoxygenCommandPrefix = .backslash) {
311+
doxygenCommandPrefix: DoxygenCommandPrefix = .backslash,
312+
adjacentDoxygenCommandsSpacing: AdjacentDoxygenCommandsSpacing = .singleNewline) {
286313
self.unorderedListMarker = unorderedListMarker
287314
self.orderedListNumerals = orderedListNumerals
288315
self.useCodeFence = useCodeFence
@@ -297,6 +324,7 @@ public struct MarkupFormatter: MarkupWalker {
297324
self.thematicBreakLength = max(3, thematicBreakLength)
298325
self.customLinePrefix = customLinePrefix
299326
self.doxygenCommandPrefix = doxygenCommandPrefix
327+
self.adjacentDoxygenCommandsSpacing = adjacentDoxygenCommandsSpacing
300328
}
301329

302330
/// The default set of formatting options.
@@ -1173,28 +1201,47 @@ public struct MarkupFormatter: MarkupWalker {
11731201
print(formattingOptions.doxygenCommandPrefix.rawValue + name + " ", for: element)
11741202
}
11751203

1204+
private mutating func ensureDoxygenCommandPrecedingNewline(for element: Markup) {
1205+
guard let previousSibling = element.previousSibling else {
1206+
return
1207+
}
1208+
1209+
guard formattingOptions.adjacentDoxygenCommandsSpacing == .singleNewline else {
1210+
ensurePrecedingNewlineCount(atLeast: 2)
1211+
return
1212+
}
1213+
1214+
let newlineCount = previousSibling.isDoxygenCommand ? 1 : 2
1215+
ensurePrecedingNewlineCount(atLeast: newlineCount)
1216+
}
1217+
11761218
public mutating func visitDoxygenDiscussion(_ doxygenDiscussion: DoxygenDiscussion) {
1219+
ensureDoxygenCommandPrecedingNewline(for: doxygenDiscussion)
11771220
printDoxygenStart("discussion", for: doxygenDiscussion)
11781221
descendInto(doxygenDiscussion)
11791222
}
11801223

11811224
public mutating func visitDoxygenAbstract(_ doxygenAbstract: DoxygenAbstract) {
1225+
ensureDoxygenCommandPrecedingNewline(for: doxygenAbstract)
11821226
printDoxygenStart("abstract", for: doxygenAbstract)
11831227
descendInto(doxygenAbstract)
11841228
}
11851229

11861230
public mutating func visitDoxygenNote(_ doxygenNote: DoxygenNote) {
1231+
ensureDoxygenCommandPrecedingNewline(for: doxygenNote)
11871232
printDoxygenStart("note", for: doxygenNote)
11881233
descendInto(doxygenNote)
11891234
}
11901235

11911236
public mutating func visitDoxygenParameter(_ doxygenParam: DoxygenParameter) {
1237+
ensureDoxygenCommandPrecedingNewline(for: doxygenParam)
11921238
printDoxygenStart("param", for: doxygenParam)
11931239
print("\(doxygenParam.name) ", for: doxygenParam)
11941240
descendInto(doxygenParam)
11951241
}
11961242

11971243
public mutating func visitDoxygenReturns(_ doxygenReturns: DoxygenReturns) {
1244+
ensureDoxygenCommandPrecedingNewline(for: doxygenReturns)
11981245
// FIXME: store the actual command name used in the original markup
11991246
printDoxygenStart("returns", for: doxygenReturns)
12001247
descendInto(doxygenReturns)

Tests/MarkdownTests/Visitors/MarkupFormatterTests.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,4 +1626,58 @@ class MarkupFormatterMixedContentTests: XCTestCase {
16261626
]
16271627
zip(expected, printed).forEach { XCTAssertEqual($0, $1) }
16281628
}
1629+
1630+
func testDoxygenCommandsPrecedingNewlinesWithSingleNewline() {
1631+
let expected = #"""
1632+
Does something.
1633+
1634+
\abstract abstract
1635+
\param x first param
1636+
\returns result
1637+
\note note
1638+
\discussion discussion
1639+
"""#
1640+
1641+
let formattingOptions = MarkupFormatter.Options(
1642+
adjacentDoxygenCommandsSpacing: .singleNewline)
1643+
let printed = Document(
1644+
Paragraph(Text("Does something.")),
1645+
DoxygenAbstract(children: Paragraph(Text("abstract"))),
1646+
DoxygenParameter(name: "x", children: Paragraph(Text("first param"))),
1647+
DoxygenReturns(children: Paragraph(Text("result"))),
1648+
DoxygenNote(children: Paragraph(Text("note"))),
1649+
DoxygenDiscussion(children: Paragraph(Text("discussion")))
1650+
).format(options: formattingOptions)
1651+
1652+
XCTAssertEqual(expected, printed)
1653+
}
1654+
1655+
func testDoxygenCommandsPrecedingNewlinesAsSeparateParagraphs() {
1656+
let expected = #"""
1657+
Does something.
1658+
1659+
\abstract abstract
1660+
1661+
\param x first param
1662+
1663+
\returns result
1664+
1665+
\note note
1666+
1667+
\discussion discussion
1668+
"""#
1669+
1670+
let formattingOptions = MarkupFormatter.Options(
1671+
adjacentDoxygenCommandsSpacing: .separateParagraphs)
1672+
let printed = Document(
1673+
Paragraph(Text("Does something.")),
1674+
DoxygenAbstract(children: Paragraph(Text("abstract"))),
1675+
DoxygenParameter(name: "x", children: Paragraph(Text("first param"))),
1676+
DoxygenReturns(children: Paragraph(Text("result"))),
1677+
DoxygenNote(children: Paragraph(Text("note"))),
1678+
DoxygenDiscussion(children: Paragraph(Text("discussion")))
1679+
).format(options: formattingOptions)
1680+
1681+
XCTAssertEqual(expected, printed)
1682+
}
16291683
}

0 commit comments

Comments
 (0)