@@ -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
3853fileprivate 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,48 +1201,47 @@ public struct MarkupFormatter: MarkupWalker {
11731201 print ( formattingOptions. doxygenCommandPrefix. rawValue + name + " " , for: element)
11741202 }
11751203
1176- public mutating func visitDoxygenDiscussion( _ doxygenDiscussion: DoxygenDiscussion ) {
1177- if doxygenDiscussion. indexInParent > 0 {
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 {
11781210 ensurePrecedingNewlineCount ( atLeast: 2 )
1211+ return
11791212 }
11801213
1214+ let newlineCount = previousSibling. isDoxygenCommand ? 1 : 2
1215+ ensurePrecedingNewlineCount ( atLeast: newlineCount)
1216+ }
1217+
1218+ public mutating func visitDoxygenDiscussion( _ doxygenDiscussion: DoxygenDiscussion ) {
1219+ ensureDoxygenCommandPrecedingNewline ( for: doxygenDiscussion)
11811220 printDoxygenStart ( " discussion " , for: doxygenDiscussion)
11821221 descendInto ( doxygenDiscussion)
11831222 }
11841223
11851224 public mutating func visitDoxygenAbstract( _ doxygenAbstract: DoxygenAbstract ) {
1186- if doxygenAbstract. indexInParent > 0 {
1187- ensurePrecedingNewlineCount ( atLeast: 2 )
1188- }
1189-
1225+ ensureDoxygenCommandPrecedingNewline ( for: doxygenAbstract)
11901226 printDoxygenStart ( " abstract " , for: doxygenAbstract)
11911227 descendInto ( doxygenAbstract)
11921228 }
11931229
11941230 public mutating func visitDoxygenNote( _ doxygenNote: DoxygenNote ) {
1195- if doxygenNote. indexInParent > 0 {
1196- ensurePrecedingNewlineCount ( atLeast: 2 )
1197- }
1198-
1231+ ensureDoxygenCommandPrecedingNewline ( for: doxygenNote)
11991232 printDoxygenStart ( " note " , for: doxygenNote)
12001233 descendInto ( doxygenNote)
12011234 }
12021235
12031236 public mutating func visitDoxygenParameter( _ doxygenParam: DoxygenParameter ) {
1204- if doxygenParam. indexInParent > 0 {
1205- ensurePrecedingNewlineCount ( atLeast: 2 )
1206- }
1207-
1237+ ensureDoxygenCommandPrecedingNewline ( for: doxygenParam)
12081238 printDoxygenStart ( " param " , for: doxygenParam)
12091239 print ( " \( doxygenParam. name) " , for: doxygenParam)
12101240 descendInto ( doxygenParam)
12111241 }
12121242
12131243 public mutating func visitDoxygenReturns( _ doxygenReturns: DoxygenReturns ) {
1214- if doxygenReturns. indexInParent > 0 {
1215- ensurePrecedingNewlineCount ( atLeast: 2 )
1216- }
1217-
1244+ ensureDoxygenCommandPrecedingNewline ( for: doxygenReturns)
12181245 // FIXME: store the actual command name used in the original markup
12191246 printDoxygenStart ( " returns " , for: doxygenReturns)
12201247 descendInto ( doxygenReturns)
0 commit comments