fix: insert list body text after hidden separators

This commit is contained in:
Valdemar Lorenzen
2026-10-19 13:34:18 +02:00
parent ac28b6dd61
commit bbee699cc8
4 changed files with 72 additions and 4 deletions
@@ -979,3 +979,62 @@ func renderedListMarkersPaintBulletsAndNumbersInsideTheirGlyphFrames() throws {
#expect(editor.markdownString == source)
}
}
@Test @MainActor
func listBodyInsertionUsesVisiblePositionForTypingPasteAndReplacementRanges() throws {
_ = NSApplication.shared
let editor = NotesTextView(frame: NSRect(x: 0, y: 0, width: 520, height: 200))
editor.isRichText = true
editor.allowsUndo = true
let window = NSWindow(contentRect: editor.frame, styleMask: .borderless, backing: .buffered, defer: false)
window.contentView = editor
defer { window.orderOut(nil) }
window.makeFirstResponder(editor)
let board = NSPasteboard.withUniqueName()
defer { board.releaseGlobally() }
board.setString("pasted", forType: .string)
for marker in ["-", "*", "+", "1.", "123)", "- []", "- [ ]", "- [X]", "\t12) []"] {
let separator = " \t "
let original = marker + separator + "tail"
for offset in 0...separator.utf16.count {
for explicitRange in [false, true] {
editor.setMarkdownContents(NSAttributedString(string: original))
let token = (editor.string as NSString).range(of: "\u{fffc}")
let insertion = NSRange(location: NSMaxRange(token) + offset, length: 0)
editor.setSelectedRange(insertion)
editor.breakUndoCoalescing()
editor.undoManager?.removeAllActions()
editor.insertText("🦊", replacementRange: explicitRange ? insertion : NSRange(location: NSNotFound, length: 0))
#expect(editor.markdownString == marker + separator + "🦊tail")
#expect((editor.string as NSString).range(of: "\u{fffc}").location != NSNotFound)
#expect(editor.selectedRange().location == NSMaxRange(token) + separator.utf16.count + 2)
editor.breakUndoCoalescing()
editor.undoManager?.undo()
#expect(editor.markdownString == original)
editor.undoManager?.redo()
#expect(editor.markdownString == marker + separator + "🦊tail")
}
editor.setMarkdownContents(NSAttributedString(string: original))
let token = (editor.string as NSString).range(of: "\u{fffc}")
editor.setSelectedRange(NSRange(location: NSMaxRange(token) + offset, length: 0))
#expect(editor.readSelection(from: board))
#expect(editor.markdownString == marker + separator + "pastedtail")
}
editor.setMarkdownContents(NSAttributedString(string: ""))
editor.setSelectedRange(NSRange(location: 0, length: 0))
for character in marker + " " {
editor.insertText(String(character), replacementRange: editor.selectedRange())
}
let token = (editor.string as NSString).range(of: "\u{fffc}")
#expect(editor.selectedRange().location == NSMaxRange(token) + 1)
editor.insertText("text", replacementRange: NSRange(location: NSNotFound, length: 0))
#expect(editor.markdownString == marker + " text")
}
editor.setMarkdownContents(NSAttributedString(string: "- ab🦊cd"))
let emoji = (editor.string as NSString).range(of: "🦊")
editor.insertText("X", replacementRange: emoji)
#expect(editor.markdownString == "- abXcd")
let separator = NSRange(location: 1, length: 3)
editor.insertText("!", replacementRange: separator)
#expect(editor.markdownString == "-!abXcd")
}