Skip to content

Commit 7ac9a1f

Browse files
authored
Support unescaped html (#181)
* Introduce htmlstring to support unescaped html * Make the comments more explicit
1 parent ba62209 commit 7ac9a1f

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

Sources/HTMLKit/Framework/Rendering/Encoder.swift renamed to Sources/HTMLKit/Framework/Rendering/Encoding/Encoder.swift

File renamed without changes.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/// A type that remains unescaped during rendering.
2+
///
3+
/// > Warning: Use with caution, as this may lead to security vulnerabilities
4+
/// > if the argument is not properly validated or not trusted.
5+
@_documentation(visibility: internal)
6+
public struct HtmlString: Content {
7+
8+
/// The wrapped string
9+
internal let value: String
10+
11+
/// Initializes an html string
12+
public init(_ value: String) {
13+
self.value = value
14+
}
15+
}

Sources/HTMLKit/Framework/Rendering/Renderer.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ public struct Renderer {
155155
case let string as EnvironmentString:
156156
try render(envstring: string, on: &result)
157157

158+
case let string as HtmlString:
159+
result += string.value
160+
158161
case let doubleValue as Double:
159162
result += String(doubleValue)
160163

@@ -501,6 +504,9 @@ public struct Renderer {
501504
case let string as EnvironmentString:
502505
try render(envstring: string, on: &result)
503506

507+
case let string as HtmlString:
508+
result += string.value
509+
504510
case let string as String:
505511
result += escape(content: string)
506512

Tests/HTMLKitTests/SecurityTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,25 @@ final class SecurityTests: XCTestCase {
111111
"""
112112
)
113113
}
114+
115+
/// Tests the renderers behaviour when handling a desired unescaped string.
116+
///
117+
/// The renderer is expected to emit the string as-is.
118+
func testIgnoringHtmlString() throws {
119+
120+
let html = "<script></script>"
121+
122+
let view = TestView {
123+
Paragraph {
124+
HtmlString(html)
125+
}
126+
}
127+
128+
XCTAssertEqual(try renderer.render(view: view),
129+
"""
130+
<p><script></script></p>
131+
"""
132+
)
133+
}
114134
}
115135

0 commit comments

Comments
 (0)