From fa3c9b40c8b7a36b93448d38ec85ea089e3a5201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Fri, 6 Mar 2026 16:47:33 +0100 Subject: [PATCH 1/2] fix: Quotes with ">" inside the quote --- CDMarkdownKitTests/TestQuotes.swift | 18 ++++++++++++++++++ Source/CDMarkdownQuote.swift | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CDMarkdownKitTests/TestQuotes.swift b/CDMarkdownKitTests/TestQuotes.swift index 86ae4fe..7b957f9 100644 --- a/CDMarkdownKitTests/TestQuotes.swift +++ b/CDMarkdownKitTests/TestQuotes.swift @@ -99,4 +99,22 @@ final class TestQuotes: XCTestCase { XCTAssertEqual(TestHelpers.getQuoteLevel(testString: parsed, at: 14), 1) } + func testQuoteWithIndicator() throws { + let parser = CDMarkdownParser() + + let parsed = parser.parse("> This <-> That") + XCTAssertEqual(parsed.string, "This <-> That") + XCTAssertGreaterThan(TestHelpers.getHeadIndent(testString: parsed, at: 0), 0) + XCTAssertEqual(TestHelpers.getQuoteLevel(testString: parsed, at: 0), 0) + + let paragraphStyleStart = parsed.attribute(.paragraphStyle, at: 0, effectiveRange: nil) as? NSParagraphStyle + let paragraphStyleEnd = parsed.attribute(.paragraphStyle, at: 12, effectiveRange: nil) as? NSParagraphStyle + + XCTAssertNotNil(paragraphStyleStart) + + // Ensure the paragraphStyle is for the whole line and not split at ">" + XCTAssertEqual(paragraphStyleStart, paragraphStyleEnd) + } + + } diff --git a/Source/CDMarkdownQuote.swift b/Source/CDMarkdownQuote.swift index a4822b6..c05f331 100644 --- a/Source/CDMarkdownQuote.swift +++ b/Source/CDMarkdownQuote.swift @@ -33,7 +33,7 @@ open class CDMarkdownQuote: CDMarkdownLevelElement { - fileprivate static let regex = "(?:(?<=\\n)|^)(\\>{1,%@})\\s*(.+?)(?:(?=\\n\\n)|$|(?=\\>))" + fileprivate static let regex = "(?:(?<=\\n)|^)(\\>{1,%@})\\s*(.+?)(?:(?=\\n\\n)|$|(?=\\n\\>))" open var font: CDFont? open var maxLevel: Int From 1561c9c213d5f87eaffdffb0bdf268807b229031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Fri, 6 Mar 2026 17:14:32 +0100 Subject: [PATCH 2/2] fix: Adjust quote indicator drawing --- Source/CDMarkdownLayoutManager.swift | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Source/CDMarkdownLayoutManager.swift b/Source/CDMarkdownLayoutManager.swift index 07253f2..0458a89 100644 --- a/Source/CDMarkdownLayoutManager.swift +++ b/Source/CDMarkdownLayoutManager.swift @@ -59,15 +59,25 @@ open class CDMarkdownLayoutManager: NSLayoutManager { let textRectFirstLine = self.boundingRect(forGlyphRange: glyphRangeFirstLine, in: textContainer) // Create a rect that would later become our quote indicator (the bar on the left side of the quote) - let newRect = CGRect(x: textRectFirstLine.origin.x - 9, y: textRect.origin.y + 2, width: 4, height: textRect.size.height - 4) + let yPadding = 2.0 + let newRect = CGRect(x: textRectFirstLine.origin.x - 9, y: textRect.origin.y + yPadding, width: 4, height: textRect.size.height - (2 * yPadding)) + + var addCurrentRect = true for rectIdx in previousRects.indices.reversed() { var (level, rect) = previousRects[rectIdx] - if level < currentLevel { + let rectBottom = rect.maxY + (2 * yPadding) + + if level <= currentLevel, newRect.minY <= rectBottom { // If there are lower levels than the current one, we want to adjust the height to include the current level rect = CGRect(x: rect.origin.x, y: rect.origin.y, width: rect.size.width, height: rect.size.height + textRect.size.height) previousRects[rectIdx] = (level, rect) + + // If it's the same level, we don't want to draw the same rect twice, but we need to continue to adjust other previousRects as well + if level == currentLevel { + addCurrentRect = false + } } else { // If there are higher levels than the current one, we want to draw these rects now UIBezierPath(roundedRect: rect, cornerRadius: 2).fill() @@ -75,7 +85,9 @@ open class CDMarkdownLayoutManager: NSLayoutManager { } } - previousRects.append((currentLevel, newRect)) + if addCurrentRect { + previousRects.append((currentLevel, newRect)) + } }) // Any remaining rects need to be drawn now