Skip to content

Commit 2c2354d

Browse files
authored
Update Aside to support custom titles (#60)
rdar://65856948
1 parent 573e9a3 commit 2c2354d

File tree

2 files changed

+101
-73
lines changed

2 files changed

+101
-73
lines changed

Sources/Markdown/Interpretive Nodes/Aside.swift

Lines changed: 87 additions & 59 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-2022 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
@@ -21,87 +21,116 @@ import Foundation
2121
/// > different meaning, as it doesn't quote speech.
2222
/// ```
2323
public struct Aside {
24-
/// The kind of aside.
25-
public enum Kind: String, CaseIterable {
24+
/// Describes the different kinds of aside.
25+
public struct Kind: RawRepresentable, CaseIterable, Equatable {
2626
/// A "note" aside.
27-
case note = "Note"
28-
27+
public static let note = Kind(rawValue: "Note")!
28+
2929
/// A "tip" aside.
30-
case tip = "Tip"
31-
30+
public static let tip = Kind(rawValue: "Tip")!
31+
3232
/// An "important" aside.
33-
case important = "Important"
34-
33+
public static let important = Kind(rawValue: "Important")!
34+
3535
/// An "experiment" aside.
36-
case experiment = "Experiment"
37-
36+
public static let experiment = Kind(rawValue: "Experiment")!
37+
3838
/// A "warning" aside.
39-
case warning = "Warning"
40-
39+
public static let warning = Kind(rawValue: "Warning")!
40+
4141
/// An "attention" aside.
42-
case attention = "Attention"
43-
42+
public static let attention = Kind(rawValue: "Attention")!
43+
4444
/// An "author" aside.
45-
case author = "Author"
46-
45+
public static let author = Kind(rawValue: "Author")!
46+
4747
/// An "authors" aside.
48-
case authors = "Authors"
49-
48+
public static let authors = Kind(rawValue: "Authors")!
49+
5050
/// A "bug" aside.
51-
case bug = "Bug"
52-
51+
public static let bug = Kind(rawValue: "Bug")!
52+
5353
/// A "complexity" aside.
54-
case complexity = "Complexity"
55-
54+
public static let complexity = Kind(rawValue: "Complexity")!
55+
5656
/// A "copyright" aside.
57-
case copyright = "Copyright"
58-
57+
public static let copyright = Kind(rawValue: "Copyright")!
58+
5959
/// A "date" aside.
60-
case date = "Date"
61-
60+
public static let date = Kind(rawValue: "Date")!
61+
6262
/// An "invariant" aside.
63-
case invariant = "Invariant"
64-
63+
public static let invariant = Kind(rawValue: "Invariant")!
64+
6565
/// A "mutatingVariant" aside.
66-
case mutatingVariant = "MutatingVariant"
67-
66+
public static let mutatingVariant = Kind(rawValue: "MutatingVariant")!
67+
6868
/// A "nonMutatingVariant" aside.
69-
case nonMutatingVariant = "NonMutatingVariant"
70-
69+
public static let nonMutatingVariant = Kind(rawValue: "NonMutatingVariant")!
70+
7171
/// A "postcondition" aside.
72-
case postcondition = "Postcondition"
73-
72+
public static let postcondition = Kind(rawValue: "Postcondition")!
73+
7474
/// A "precondition" aside.
75-
case precondition = "Precondition"
76-
75+
public static let precondition = Kind(rawValue: "Precondition")!
76+
7777
/// A "remark" aside.
78-
case remark = "Remark"
79-
78+
public static let remark = Kind(rawValue: "Remark")!
79+
8080
/// A "requires" aside.
81-
case requires = "Requires"
82-
81+
public static let requires = Kind(rawValue: "Requires")!
82+
8383
/// A "since" aside.
84-
case since = "Since"
85-
84+
public static let since = Kind(rawValue: "Since")!
85+
8686
/// A "todo" aside.
87-
case todo = "ToDo"
88-
87+
public static let todo = Kind(rawValue: "ToDo")!
88+
8989
/// A "version" aside.
90-
case version = "Version"
91-
90+
public static let version = Kind(rawValue: "Version")!
91+
9292
/// A "throws" aside.
93-
case `throws` = "Throws"
94-
93+
public static let `throws` = Kind(rawValue: "Throws")!
94+
95+
/// A collection of preconfigured aside kinds.
96+
public static var allCases: [Aside.Kind] {
97+
[
98+
note,
99+
tip,
100+
important,
101+
experiment,
102+
warning,
103+
attention,
104+
author,
105+
authors,
106+
bug,
107+
complexity,
108+
copyright,
109+
date,
110+
invariant,
111+
mutatingVariant,
112+
nonMutatingVariant,
113+
postcondition,
114+
precondition,
115+
remark,
116+
requires,
117+
since,
118+
todo,
119+
version,
120+
`throws`,
121+
]
122+
}
123+
124+
/// The underlying raw string value.
125+
public var rawValue: String
126+
127+
/// Creates an aside kind with the specified raw value.
128+
/// - Parameter rawValue: The string the aside displays as its title.
95129
public init?(rawValue: String) {
96-
// Allow lowercase aside prefixes to match.
97-
let casesAndLowercasedRawValues = Kind.allCases.map { (kind: $0, rawValue: $0.rawValue.lowercased() )}
98-
guard let matchingCaseAndRawValue = casesAndLowercasedRawValues.first(where: { $0.rawValue == rawValue.lowercased() }) else {
99-
return nil
100-
}
101-
self = matchingCaseAndRawValue.kind
130+
self.rawValue = rawValue
102131
}
103132
}
104-
133+
105134
/// The kind of aside interpreted from the initial text of the ``BlockQuote``.
106135
public var kind: Kind
107136

@@ -116,14 +145,13 @@ public struct Aside {
116145
(0, Paragraph.self),
117146
(0, Text.self),
118147
]) as? Text,
119-
let firstColonIndex = initialText.string.firstIndex(where: { $0 == ":" }),
120-
let kind = Kind(rawValue: String(initialText.string[initialText.string.startIndex..<firstColonIndex])) else {
148+
let firstColonIndex = initialText.string.firstIndex(where: { $0 == ":" }) else {
121149
// Otherwise, default to a note aside.
122150
self.kind = .note
123151
self.content = Array(blockQuote.blockChildren)
124152
return
125153
}
126-
self.kind = kind
154+
self.kind = Kind(rawValue: String(initialText.string[..<firstColonIndex]))!
127155

128156
// Trim off the aside tag prefix.
129157
let trimmedText = initialText.string[initialText.string.index(after: firstColonIndex)...].drop {

Tests/MarkdownTests/Interpretive Nodes/AsideTests.swift

Lines changed: 14 additions & 14 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-2022 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
@@ -43,13 +43,22 @@ class AsideTests: XCTestCase {
4343
XCTAssertTrue(aside.content[0].root.isIdentical(to: document))
4444
}
4545

46-
func testUnknownTag() {
47-
let source = "> Hmm: This is something..."
46+
func testCustomTag() {
47+
let source = "> Hmm: This is something"
4848
let document = Document(parsing: source)
4949
let blockQuote = document.child(at: 0) as! BlockQuote
5050
let aside = Aside(blockQuote)
51-
XCTAssertEqual(.note, aside.kind)
52-
XCTAssertTrue(aside.content[0].root.isIdentical(to: document))
51+
XCTAssertEqual(.init(rawValue: "Hmm")!, aside.kind)
52+
53+
// Note that the initial text in the paragraph has been adjusted
54+
// to after the tag.
55+
let expectedRootDump = """
56+
Document
57+
└─ BlockQuote
58+
└─ Paragraph
59+
└─ Text "This is something"
60+
"""
61+
XCTAssertEqual(expectedRootDump, aside.content[0].root.debugDescription())
5362
}
5463

5564
func testNoParagraphAtStart() {
@@ -64,13 +73,4 @@ class AsideTests: XCTestCase {
6473
XCTAssertTrue(aside.content[0].root.isIdentical(to: document))
6574
}
6675

67-
func testCaseInsensitive() {
68-
for kind in Aside.Kind.allCases {
69-
let source = "> \(kind.rawValue.lowercased()): This is a `\(kind.rawValue)` aside."
70-
let document = Document(parsing: source)
71-
let blockQuote = document.child(at: 0) as! BlockQuote
72-
let aside = Aside(blockQuote)
73-
XCTAssertEqual(kind, aside.kind)
74-
}
75-
}
7676
}

0 commit comments

Comments
 (0)