diff --git a/packages/ios-enriched-markdown/Sources/EnrichedMarkdown/Rendering/RendererFactory.swift b/packages/ios-enriched-markdown/Sources/EnrichedMarkdown/Rendering/RendererFactory.swift index d17cbd61..ed424c4d 100644 --- a/packages/ios-enriched-markdown/Sources/EnrichedMarkdown/Rendering/RendererFactory.swift +++ b/packages/ios-enriched-markdown/Sources/EnrichedMarkdown/Rendering/RendererFactory.swift @@ -43,6 +43,8 @@ final class RendererFactory { return HeadingRenderer(factory: self, config: config) case .link: return LinkRenderer(factory: self, config: config) + case .lineBreak: + return LineBreakRenderer() default: return childrenOnlyRenderer } diff --git a/packages/ios-enriched-markdown/Sources/EnrichedMarkdown/Rendering/Renderers/LineBreakRenderer.swift b/packages/ios-enriched-markdown/Sources/EnrichedMarkdown/Rendering/Renderers/LineBreakRenderer.swift new file mode 100644 index 00000000..1a7d5324 --- /dev/null +++ b/packages/ios-enriched-markdown/Sources/EnrichedMarkdown/Rendering/Renderers/LineBreakRenderer.swift @@ -0,0 +1,13 @@ +import UIKit + +final class LineBreakRenderer: NodeRenderer { + private static let lineSeparator = "\u{2028}" + + func render(node: MarkdownASTNode, into output: NSMutableAttributedString, context: RenderContext) { + let lineBreak = NSAttributedString( + string: Self.lineSeparator, + attributes: context.getTextAttributes() + ) + output.append(lineBreak) + } +} diff --git a/packages/ios-enriched-markdown/Tests/EnrichedMarkdownTests/RendererTests.swift b/packages/ios-enriched-markdown/Tests/EnrichedMarkdownTests/RendererTests.swift index 8812eeb2..8f0ec4c9 100644 --- a/packages/ios-enriched-markdown/Tests/EnrichedMarkdownTests/RendererTests.swift +++ b/packages/ios-enriched-markdown/Tests/EnrichedMarkdownTests/RendererTests.swift @@ -300,6 +300,21 @@ final class RendererTests: XCTestCase { A paragraph with a [link](https://example.com) and **bold** nearby. """ + + + func testHardLineBreakUsesLineSeparator() { + let result = MarkdownRenderer.render("Line one \nLine two", config: config) + XCTAssertTrue(result.string.contains("Line one")) + XCTAssertTrue(result.string.contains("Line two")) + XCTAssertTrue(result.string.contains("\u{2028}")) + + let separatorRange = (result.string as NSString).range(of: "\u{2028}") + XCTAssertNotEqual(separatorRange.location, NSNotFound) + + var effectiveRange = NSRange() + let attributes = result.attributes(at: separatorRange.location, effectiveRange: &effectiveRange) + XCTAssertNotNil(attributes[.font] as? UIFont) + } } private extension String {