splash/Sources/Splash/Output/MarkdownDecorator.swift
John Sundell 3de0275b52
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.
2019-11-23 23:59:16 +00:00

52 lines
1.8 KiB
Swift

/**
* Splash
* Copyright (c) John Sundell 2019
* MIT license - see LICENSE.md
*/
import Foundation
/// Type used to decorate a Markdown file with Splash-highlighted code blocks
public struct MarkdownDecorator {
private let highlighter: SyntaxHighlighter<HTMLOutputFormat>
private let skipHighlightingPrefix = "no-highlight"
/// Create a Markdown decorator with a given prefix to apply to all CSS
/// classes used when highlighting code blocks within a Markdown string.
public init(classPrefix: String = "") {
highlighter = SyntaxHighlighter(format: HTMLOutputFormat(classPrefix: classPrefix))
}
/// Decorate all code blocks within a given Markdown string. This API assumes
/// that the passed Markdown is valid. Each code block will be replaced by
/// Splash-highlighted HTML for that block's code. To skip highlighting for
/// any given code block, add "no-highlight" next to the opening row of
/// backticks for that block.
public func decorate(_ markdown: String) -> String {
let components = markdown.components(separatedBy: "```")
var output = ""
for (index, component) in components.enumerated() {
guard index % 2 != 0 else {
output.append(component)
continue
}
var code = component.trimmingCharacters(in: .whitespacesAndNewlines)
if code.hasPrefix(skipHighlightingPrefix) {
let charactersToDrop = skipHighlightingPrefix + "\n"
code = code.dropFirst(charactersToDrop.count).escapingHTMLEntities()
} else {
code = highlighter.highlight(code)
}
output.append("""
<pre class="splash"><code>\(code)</code></pre>
""")
}
return output
}
}