Skip to content

Commit 793b9ef

Browse files
committed
Render image attachments
1 parent 7e9422a commit 793b9ef

File tree

10 files changed

+108
-4
lines changed

10 files changed

+108
-4
lines changed

Package.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ let package = Package(
3939
"CommonMarkUI",
4040
"SnapshotTesting",
4141
],
42-
exclude: ["__Snapshots__"]
42+
exclude: [
43+
"__Fixtures__",
44+
"__Snapshots__",
45+
]
4346
),
4447
]
4548
)

Sources/CommonMarkUI/Shared/Configuration.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ extension NSAttributedString {
99
var font: Font
1010
var codeFont: Font?
1111
var paragraphStyle: NSParagraphStyle
12+
#if !os(watchOS)
13+
var attachments: [String: NSTextAttachment] = [:]
14+
#endif
1215
}
1316
}

Sources/CommonMarkUI/Shared/NSAttributedString+Document.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,16 @@ extension NSAttributedString {
3333
self.init(inlines: inlines, context: context.strong())
3434
case let .link(inlines, url, title):
3535
self.init(inlines: inlines, context: context.link(url, title: title))
36-
case .image:
37-
fatalError("Not implemented")
36+
case let .image(_, url, _):
37+
#if os(watchOS)
38+
self.init()
39+
#else
40+
if let attachment = context.attachment(url) {
41+
self.init(attachment: attachment)
42+
} else {
43+
self.init()
44+
}
45+
#endif
3846
}
3947
}
4048

Sources/CommonMarkUI/Shared/RenderContext.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import Foundation
22

3+
#if os(macOS)
4+
import AppKit
5+
#elseif os(iOS) || os(tvOS) || os(watchOS)
6+
import UIKit
7+
#endif
8+
39
extension NSAttributedString {
410
struct RenderContext {
511
private(set) var attributes: [Key: Any]
@@ -15,6 +21,12 @@ extension NSAttributedString {
1521
attributes = [.font: configuration.font]
1622
}
1723

24+
#if !os(watchOS)
25+
func attachment(_ url: String) -> NSTextAttachment? {
26+
configuration.attachments[url]
27+
}
28+
#endif
29+
1830
func paragraph() -> RenderContext {
1931
var newContext = self
2032
newContext.attributes[.paragraphStyle] = configuration.paragraphStyle

Tests/CommonMarkUITests/NSAttributedStringTests.swift

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ final class NSAttributedStringTests: XCTestCase {
77
private let configuration = NSAttributedString.Configuration(
88
font: .custom("Helvetica", size: 16),
99
codeFont: .custom("Menlo", size: 16),
10-
paragraphStyle: .default
10+
paragraphStyle: .default,
11+
attachments: [
12+
"https://commonmark.org/help/images/favicon.png": makeAttachment(),
13+
]
1114
)
1215

1316
#if os(macOS)
@@ -113,4 +116,51 @@ final class NSAttributedStringTests: XCTestCase {
113116

114117
assertSnapshot(matching: attributedString, as: .dump, named: platformName)
115118
}
119+
120+
func testImage() {
121+
let document = Document(
122+
#"""
123+
CommonMark favicon:
124+
125+
![](https://commonmark.org/help/images/favicon.png)
126+
"""#
127+
)!
128+
129+
let attributedString = NSAttributedString(document: document, configuration: configuration)
130+
131+
assertSnapshot(matching: attributedString, as: .dump, named: platformName)
132+
}
133+
134+
func testImageWithoutAttachment() {
135+
let document = Document(
136+
#"""
137+
This image does not have an attachment:
138+
139+
![](https://commonmark.org/help/images/unknown.png)
140+
"""#
141+
)!
142+
143+
let attributedString = NSAttributedString(document: document, configuration: configuration)
144+
145+
assertSnapshot(matching: attributedString, as: .dump, named: platformName)
146+
}
147+
}
148+
149+
private func makeAttachment() -> NSTextAttachment {
150+
#if os(macOS)
151+
let result = NSTextAttachment()
152+
result.image = NSImage(contentsOf: fixtureURL("favicon.png"))
153+
return result
154+
#elseif os(iOS) || os(tvOS) || os(watchOS)
155+
let result = NSTextAttachment()
156+
result.image = try! UIImage(data: Data(contentsOf: fixtureURL("favicon.png")))
157+
return result
158+
#endif
159+
}
160+
161+
private func fixtureURL(_ fileName: String, file: StaticString = #file) -> URL {
162+
URL(fileURLWithPath: "\(file)", isDirectory: false)
163+
.deletingLastPathComponent()
164+
.appendingPathComponent("__Fixtures__")
165+
.appendingPathComponent(fileName)
116166
}
1.07 KB
Loading
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- CommonMark favicon:{
2+
NSFont = "\"Helvetica 16.00 pt. P [] () fobj=, spc=4.45\"";
3+
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0 LineBreakStrategy 0";
4+
}
5+
{
6+
}{
7+
NSAttachment = "<NSTextAttachment>";
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- CommonMark favicon:{
2+
NSFont = "<UICTFont> font-family: \"Helvetica\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
3+
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0 LineBreakStrategy 0";
4+
}
5+
{
6+
}{
7+
NSAttachment = "<NSTextAttachment>";
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- This image does not have an attachment:{
2+
NSFont = "\"Helvetica 16.00 pt. P [] () fobj=, spc=4.45\"";
3+
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation YES, HeaderLevel 0 LineBreakStrategy 0";
4+
}
5+
{
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- This image does not have an attachment:{
2+
NSFont = "<UICTFont> font-family: \"Helvetica\"; font-weight: normal; font-style: normal; font-size: 16.00pt";
3+
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection -1, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0 LineBreakStrategy 0";
4+
}
5+
{
6+
}

0 commit comments

Comments
 (0)