diff --git a/Sources/SwiftParser/Languages/MarkdownLanguage.swift b/Sources/SwiftParser/Languages/MarkdownLanguage.swift index b739ea5..76f7cbe 100644 --- a/Sources/SwiftParser/Languages/MarkdownLanguage.swift +++ b/Sources/SwiftParser/Languages/MarkdownLanguage.swift @@ -660,7 +660,31 @@ public struct MarkdownLanguage: CodeLanguage { else { text += tok.text; context.index += 1 } } else { context.index += 1 } } - context.currentNode.addChild(CodeNode(type: Element.entity, value: text)) + let decoded = decode(text) + context.currentNode.addChild(CodeNode(type: Element.entity, value: decoded)) + } + + private func decode(_ entity: String) -> String { + switch entity { + case "amp": return "&" + case "lt": return "<" + case "gt": return ">" + case "quot": return "\"" + case "apos": return "'" + default: + if entity.hasPrefix("#x") || entity.hasPrefix("#X") { + let hex = entity.dropFirst(2) + if let value = UInt32(hex, radix: 16), let scalar = UnicodeScalar(value) { + return String(Character(scalar)) + } + } else if entity.hasPrefix("#") { + let num = entity.dropFirst() + if let value = UInt32(num), let scalar = UnicodeScalar(value) { + return String(Character(scalar)) + } + } + return "&" + entity + ";" + } } } diff --git a/Tests/SwiftParserTests/SwiftParserTests.swift b/Tests/SwiftParserTests/SwiftParserTests.swift index a50f974..46a6d27 100644 --- a/Tests/SwiftParserTests/SwiftParserTests.swift +++ b/Tests/SwiftParserTests/SwiftParserTests.swift @@ -109,6 +109,17 @@ final class SwiftParserTests: XCTestCase { XCTAssertEqual(result.root.children.first?.value, "*not italic*") } + func testMarkdownEntityDecoding() { + let parser = SwiftParser() + let source = "&#A" + let result = parser.parse(source, language: MarkdownLanguage()) + XCTAssertEqual(result.errors.count, 0) + XCTAssertEqual(result.root.children.count, 3) + XCTAssertEqual(result.root.children[0].value, "&") + XCTAssertEqual(result.root.children[1].value, "#") + XCTAssertEqual(result.root.children[2].value, "A") + } + func testPrattExpression() { let parser = SwiftParser() let source = "x = 1 + 2 * 3"