Skip to content

Commit d9bc97f

Browse files
committed
Support converting Markdown into a string without any markup.
1 parent 8f17ab3 commit d9bc97f

File tree

7 files changed

+91
-7
lines changed

7 files changed

+91
-7
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 1.1.9 (2024-08-04)
4+
5+
- Support converting Markdown into a string without any markup
6+
37
## 1.1.8 (2024-05-01)
48
- Fix `Color.hexString` on iOS to handle black correctly
59
- Clean up `Package.swift`

Sources/MarkdownKit/Block.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,42 @@ public enum Block: Equatable, CustomStringConvertible, CustomDebugStringConverti
141141
return self.description
142142
}
143143
}
144+
145+
/// Returns raw text for this block, i.e. ignoring all markup.
146+
public var string: String {
147+
switch self {
148+
case .document(let blocks):
149+
return blocks.string
150+
case .blockquote(let blocks):
151+
return blocks.string
152+
case .list(_, _, let blocks):
153+
return blocks.string
154+
case .listItem(_, _, let blocks):
155+
return blocks.string
156+
case .paragraph(let text):
157+
return text.string
158+
case .heading(_, let text):
159+
return text.string
160+
case .indentedCode(let lines):
161+
return lines.map { String($0) }.joined()
162+
case .fencedCode(_, let lines):
163+
return lines.map { String($0) }.joined(separator: "\n")
164+
case .htmlBlock(_):
165+
return ""
166+
case .referenceDef(_, _, let lines):
167+
return lines.map { String($0) }.joined(separator: " ")
168+
case .thematicBreak:
169+
return "\n\n"
170+
case .table(let headers, _, let rows):
171+
return headers.map { $0.string }.joined(separator: " | ") + "\n" +
172+
rows.map { $0.map { $0.string }.joined(separator: " | ") }
173+
.joined(separator: "\n")
174+
case .definitionList(let defs):
175+
return defs.map { $0.string }.joined(separator: "\n\n")
176+
case .custom(let obj):
177+
return obj.string
178+
}
179+
}
144180

145181
fileprivate static func string(from blocks: Blocks) -> String {
146182
var res = ""
@@ -295,6 +331,10 @@ public struct Definition: Equatable, CustomStringConvertible, CustomDebugStringC
295331
public var debugDescription: String {
296332
return self.description
297333
}
334+
335+
public var string: String {
336+
return "\(self.item.rawDescription): \(self.descriptions.string)"
337+
}
298338
}
299339

300340
public typealias Definitions = ContiguousArray<Definition>

Sources/MarkdownKit/Blocks.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,9 @@ extension Blocks {
4343
public var isSingleton: Bool {
4444
return self.count == 1
4545
}
46+
47+
/// Returns raw text for this sequence of blocks.
48+
public var string: String {
49+
return self.map { $0.string }.joined(separator: "\n")
50+
}
4651
}

Sources/MarkdownKit/CustomBlock.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Foundation
2525
/// externally (i.e. not by the MarkdownKit framework).
2626
///
2727
public protocol CustomBlock: CustomStringConvertible, CustomDebugStringConvertible {
28+
var string: String { get }
2829
func equals(to other: CustomBlock) -> Bool
2930
func parse(via parser: InlineParser) -> Block
3031
func generateHtml(via htmlGen: HtmlGenerator, tight: Bool) -> String
@@ -34,3 +35,10 @@ public protocol CustomBlock: CustomStringConvertible, CustomDebugStringConvertib
3435
tight: Bool) -> String
3536
#endif
3637
}
38+
39+
extension CustomBlock {
40+
/// By default, the custom block does not have any raw string content.
41+
public var string: String {
42+
return ""
43+
}
44+
}

Sources/MarkdownKit/Text.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,15 @@ public struct Text: Collection, Equatable, CustomStringConvertible, CustomDebugS
126126
/// Returns a raw description of this `Text` object as a string, i.e. as if the text
127127
/// would be represented in Markdown but ignoring all markup.
128128
public var rawDescription: String {
129-
var res = ""
130-
for fragment in self.fragments {
131-
res = res + fragment.rawDescription
132-
}
133-
return res
129+
return self.fragments.map { $0.rawDescription }.joined()
134130
}
135-
131+
132+
/// Returns a raw description of this `Text` object as a string for which all markup
133+
/// gets ignored.
134+
public var string: String {
135+
return self.fragments.map { $0.string }.joined()
136+
}
137+
136138
/// Returns a debug description of this `Text` object.
137139
public var debugDescription: String {
138140
var res = ""

Sources/MarkdownKit/TextFragment.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,24 @@ public enum TextFragment: Equatable, CustomStringConvertible, CustomDebugStringC
108108
return customTextFragment.rawDescription
109109
}
110110
}
111-
111+
112+
/// Returns a raw description of this `TextFragment` object as a string in which all
113+
/// markup gets ignored.
114+
public var string: String {
115+
switch self {
116+
case .html(_):
117+
return ""
118+
case .delimiter(let ch, let n, _):
119+
var res = String(ch)
120+
for _ in 1..<n {
121+
res.append(ch)
122+
}
123+
return res
124+
default:
125+
return self.rawDescription
126+
}
127+
}
128+
112129
/// Returns a debug description of this `TextFragment` object.
113130
public var debugDescription: String {
114131
switch self {

Tests/MarkdownKitTests/MarkdownBlockTests.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,14 @@ class MarkdownBlockTests: XCTestCase, MarkdownKitFactory {
325325
"</code></pre>\n"),
326326
paragraph("okay")))
327327
}
328+
329+
func testToString() {
330+
XCTAssertEqual(parseBlocks(" # First\n ## Second \n### Third").string, "First\nSecond\nThird")
331+
XCTAssertEqual(parseBlocks("> # Hello\n> Next line\n And last line").string, "Hello\nNext line And last line")
332+
XCTAssertEqual(parseBlocks("one\n\n foo\n bar\n\ntwo").string, "one\n foo\nbar\n\ntwo")
333+
XCTAssertEqual(parseBlocks("- foo\n - bar\n - baz\n - boo").string, "foo\nbar\nbaz\nboo")
334+
XCTAssertEqual(parseBlocks("- foo\n - one\n - two\n \n three").string, "foo\none\ntwo\nthree")
335+
}
328336

329337
func testDebug() {
330338

0 commit comments

Comments
 (0)