diff --git a/Modules/Parser/Sources/SAX/HTMLEntityDecoder.swift b/Modules/Parser/Sources/SAX/HTMLEntityDecoder.swift new file mode 100644 index 000000000..5f37fe593 --- /dev/null +++ b/Modules/Parser/Sources/SAX/HTMLEntityDecoder.swift @@ -0,0 +1,51 @@ +// +// HTMLEntityDecoder.swift +// +// +// Created by Brent Simmons on 9/14/24. +// + +import Foundation + +public final class HTMLEntityDecoder { + + static func decodedString(withEncodedString encodedString: String) -> String { + + let scanner = Scanner(string: encodedString) + scanner.charactersToBeSkipped = nil + var result = "" + var didDecodeAtLeastOneEntity = false + + while true { + + var scannedString = nil + if scanner.scanUpToString("&" intoString: &scannedString) { + result.append(scannedString) + } + if scanner.isAtEnd { + break + } + + let savedScanLocation = scanner.scanLocation + + var decodedEntity: String? = nil + if scanner.scanEntityValue(&decodedEntity) { + result.append(decodedEntity) + didDecodeAtLeastOneEntity = true + } + else { + result.append("&") + scanner.scanLocation = savedScanLocation + 1 + } + + if scanner.isAtEnd { + break + } + } + + if !didDecodeAtLeastOneEntity { // No changes made? + return encodedString + } + return result + } +}