HTML: Fully escape all required entities (#89)
Both when outputting HTML, and when highlighting code blocks within a Markdown text, Splash now fully escapes all required character entities.
This commit is contained in:
parent
3a6c961de8
commit
3de0275b52
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Splash
|
||||
* Copyright (c) John Sundell 2019
|
||||
* MIT license - see LICENSE.md
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
internal extension StringProtocol {
|
||||
func escapingHTMLEntities() -> String {
|
||||
return String(flatMap { character -> String in
|
||||
switch character {
|
||||
case "&":
|
||||
return "&"
|
||||
case "<":
|
||||
return "<"
|
||||
case ">":
|
||||
return ">"
|
||||
default:
|
||||
return String(character)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ public extension HTMLOutputFormat {
|
|||
|
||||
public mutating func addPlainText(_ text: String) {
|
||||
appendPending()
|
||||
html.append(text.escaped)
|
||||
html.append(text.escapingHTMLEntities())
|
||||
}
|
||||
|
||||
public mutating func addWhitespace(_ whitespace: String) {
|
||||
|
@ -70,7 +70,7 @@ public extension HTMLOutputFormat {
|
|||
private mutating func appendPending() {
|
||||
if let pending = pendingToken {
|
||||
html.append("""
|
||||
<span class="\(classPrefix)\(pending.type.string)">\(pending.string.escaped)</span>
|
||||
<span class="\(classPrefix)\(pending.type.string)">\(pending.string.escapingHTMLEntities())</span>
|
||||
""")
|
||||
|
||||
pendingToken = nil
|
||||
|
@ -83,10 +83,3 @@ public extension HTMLOutputFormat {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension String {
|
||||
var escaped: String {
|
||||
return replacingOccurrences(of: "<", with: "<")
|
||||
.replacingOccurrences(of: ">", with: ">")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public struct MarkdownDecorator {
|
|||
|
||||
if code.hasPrefix(skipHighlightingPrefix) {
|
||||
let charactersToDrop = skipHighlightingPrefix + "\n"
|
||||
code = String(code.dropFirst(charactersToDrop.count))
|
||||
code = code.dropFirst(charactersToDrop.count).escapingHTMLEntities()
|
||||
} else {
|
||||
code = highlighter.highlight(code)
|
||||
}
|
||||
|
|
|
@ -49,13 +49,57 @@ final class MarkdownTests: SplashTestCase {
|
|||
struct Hello: Protocol {}
|
||||
```
|
||||
|
||||
Text.
|
||||
"""
|
||||
|
||||
let expectedResult = """
|
||||
Text text.
|
||||
|
||||
<pre class="splash"><code>struct Hello: Protocol {}</code></pre>
|
||||
|
||||
Text.
|
||||
"""
|
||||
|
||||
XCTAssertEqual(decorator.decorate(markdown), expectedResult)
|
||||
}
|
||||
|
||||
func testEscapingSpecialCharactersWithinHighlightedCodeBlock() {
|
||||
let markdown = """
|
||||
Text text.
|
||||
|
||||
```
|
||||
let a = "<Hello&World>"
|
||||
```
|
||||
|
||||
Text.
|
||||
"""
|
||||
|
||||
let expectedResult = """
|
||||
Text text.
|
||||
|
||||
<pre class="splash"><code>struct Hello: Protocol {}</code></pre>
|
||||
<pre class="splash"><code><span class="keyword">let</span> a = <span class="string">"<Hello&World>"</span></code></pre>
|
||||
|
||||
Text.
|
||||
"""
|
||||
|
||||
XCTAssertEqual(decorator.decorate(markdown), expectedResult)
|
||||
}
|
||||
|
||||
func testEscapingSpecialCharactersWithinSkippedCodeBlock() {
|
||||
let markdown = """
|
||||
Text text.
|
||||
|
||||
```no-highlight
|
||||
let a = "<Hello&World>"
|
||||
```
|
||||
|
||||
Text.
|
||||
"""
|
||||
|
||||
let expectedResult = """
|
||||
Text text.
|
||||
|
||||
<pre class="splash"><code>let a = "<Hello&World>"</code></pre>
|
||||
|
||||
Text.
|
||||
"""
|
||||
|
@ -72,7 +116,9 @@ extension MarkdownTests {
|
|||
static var allTests: [(String, TestClosure<MarkdownTests>)] {
|
||||
return [
|
||||
("testConvertingCodeBlock", testConvertingCodeBlock),
|
||||
("testSkippingHighlightingForCodeBlock", testSkippingHighlightingForCodeBlock)
|
||||
("testSkippingHighlightingForCodeBlock", testSkippingHighlightingForCodeBlock),
|
||||
("testEscapingSpecialCharactersWithinHighlightedCodeBlock", testEscapingSpecialCharactersWithinHighlightedCodeBlock),
|
||||
("testEscapingSpecialCharactersWithinSkippedCodeBlock", testEscapingSpecialCharactersWithinSkippedCodeBlock)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue