Merge pull request #46 from JohnSundell/html-merging
HTMLOutputFormat: Merge same-type tokens along with whitespace
This commit is contained in:
commit
73ffdd2e0c
@ -27,26 +27,60 @@ public extension HTMLOutputFormat {
|
|||||||
struct Builder: OutputBuilder {
|
struct Builder: OutputBuilder {
|
||||||
private let classPrefix: String
|
private let classPrefix: String
|
||||||
private var html = ""
|
private var html = ""
|
||||||
|
private var pendingToken: (string: String, type: TokenType)?
|
||||||
|
private var pendingWhitespace: String?
|
||||||
|
|
||||||
fileprivate init(classPrefix: String) {
|
fileprivate init(classPrefix: String) {
|
||||||
self.classPrefix = classPrefix
|
self.classPrefix = classPrefix
|
||||||
}
|
}
|
||||||
|
|
||||||
public mutating func addToken(_ token: String, ofType type: TokenType) {
|
public mutating func addToken(_ token: String, ofType type: TokenType) {
|
||||||
html.append("<span class=\"\(classPrefix)\(type.string)\">\(token.escaped)</span>")
|
if var pending = pendingToken {
|
||||||
|
guard pending.type != type else {
|
||||||
|
pendingWhitespace.map { pending.string += $0 }
|
||||||
|
pendingWhitespace = nil
|
||||||
|
pending.string += token
|
||||||
|
pendingToken = pending
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appendPending()
|
||||||
|
pendingToken = (token, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
public mutating func addPlainText(_ text: String) {
|
public mutating func addPlainText(_ text: String) {
|
||||||
|
appendPending()
|
||||||
html.append(text.escaped)
|
html.append(text.escaped)
|
||||||
}
|
}
|
||||||
|
|
||||||
public mutating func addWhitespace(_ whitespace: String) {
|
public mutating func addWhitespace(_ whitespace: String) {
|
||||||
html.append(whitespace)
|
if pendingToken != nil {
|
||||||
|
pendingWhitespace = (pendingWhitespace ?? "") + whitespace
|
||||||
|
} else {
|
||||||
|
html.append(whitespace)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func build() -> String {
|
public mutating func build() -> String {
|
||||||
|
appendPending()
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private mutating func appendPending() {
|
||||||
|
if let pending = pendingToken {
|
||||||
|
html.append("""
|
||||||
|
<span class="\(classPrefix)\(pending.type.string)">\(pending.string.escaped)</span>
|
||||||
|
""")
|
||||||
|
|
||||||
|
pendingToken = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let whitespace = pendingWhitespace {
|
||||||
|
html.append(whitespace)
|
||||||
|
pendingWhitespace = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,5 +21,5 @@ public protocol OutputBuilder {
|
|||||||
/// Add some whitespace to the builder
|
/// Add some whitespace to the builder
|
||||||
mutating func addWhitespace(_ whitespace: String)
|
mutating func addWhitespace(_ whitespace: String)
|
||||||
/// Build the final output based on the builder's current state
|
/// Build the final output based on the builder's current state
|
||||||
func build() -> Output
|
mutating func build() -> Output
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,20 @@ final class HTMLOutputFormatTests: SplashTestCase {
|
|||||||
highlighter = SyntaxHighlighter(format: HTMLOutputFormat())
|
highlighter = SyntaxHighlighter(format: HTMLOutputFormat())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testBasicGeneration() {
|
||||||
|
let html = highlighter.highlight("""
|
||||||
|
public struct Test: SomeProtocol {
|
||||||
|
func hello() -> Int { return 7 }
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
|
XCTAssertEqual(html, """
|
||||||
|
<span class="keyword">public struct</span> Test: <span class="type">SomeProtocol</span> {
|
||||||
|
<span class="keyword">func</span> hello() -> <span class="type">Int</span> { <span class="keyword">return</span> <span class="number">7</span> }
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
|
||||||
func testStrippingGreaterAndLessThanCharactersFromOutput() {
|
func testStrippingGreaterAndLessThanCharactersFromOutput() {
|
||||||
let html = highlighter.highlight("Array<String>")
|
let html = highlighter.highlight("Array<String>")
|
||||||
|
|
||||||
@ -18,6 +32,14 @@ final class HTMLOutputFormatTests: SplashTestCase {
|
|||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testCommentMerging() {
|
||||||
|
let html = highlighter.highlight("// Hey I'm a comment!")
|
||||||
|
|
||||||
|
XCTAssertEqual(html, """
|
||||||
|
<span class="comment">// Hey I'm a comment!</span>
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
|
||||||
func testAllTestsRunOnLinux() {
|
func testAllTestsRunOnLinux() {
|
||||||
XCTAssertTrue(TestCaseVerifier.verifyLinuxTests((type(of: self)).allTests))
|
XCTAssertTrue(TestCaseVerifier.verifyLinuxTests((type(of: self)).allTests))
|
||||||
}
|
}
|
||||||
@ -26,7 +48,9 @@ final class HTMLOutputFormatTests: SplashTestCase {
|
|||||||
extension HTMLOutputFormatTests {
|
extension HTMLOutputFormatTests {
|
||||||
static var allTests: [(String, TestClosure<HTMLOutputFormatTests>)] {
|
static var allTests: [(String, TestClosure<HTMLOutputFormatTests>)] {
|
||||||
return [
|
return [
|
||||||
("testStrippingGreaterAndLessThanCharactersFromOutput", testStrippingGreaterAndLessThanCharactersFromOutput)
|
("testBasicGeneration", testBasicGeneration),
|
||||||
|
("testStrippingGreaterAndLessThanCharactersFromOutput", testStrippingGreaterAndLessThanCharactersFromOutput),
|
||||||
|
("testCommentMerging", testCommentMerging)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user