
struct HeadlineLink: HtmlProducer {

    /// The type of headline, e.g. `2` for `<h2>`
    let level: Int

    let title: String

    var id: String {
        title.validHtmlId()
    }

    func populate(_ result: inout String) {
        result += "<h\(level) id='\(id)'>"
        result += "<a href='#\(id)'>\(title)</a>"
        result += "</h\(level)>"
    }
}

private extension String {

    static let characterReplacements: [Character: String] = [
        "ä": "ae", "ö": "oe", "ü": "ue", "ß": "ss",
        "Ä": "Ae", "Ö": "Oe", "Ü": "Ue",
        " ": "-", "/": "-", "&": "and"
    ]

    func validHtmlId() -> String {
        var result = self.lowercased()

        for (char, replacement) in String.characterReplacements {
            result = result.replacingOccurrences(of: String(char), with: replacement)
        }

        result = result.filter { $0.isLetter || $0.isNumber || $0 == "-" }

        return result
            .components(separatedBy: "-")
            .filter { $0 != "" }
            .joined(separator: "-")
    }
}
