diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd52a22..5966eb0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
# 0.1.10
* Improve search results window and highlight in calendar when there are matches.
+ * Fix styling issue with text that comes after a URL, so it doesn't appear as part of the URL.
# 0.1.9
diff --git a/bouquin/editor.py b/bouquin/editor.py
index 07ef6d3..b7fc341 100644
--- a/bouquin/editor.py
+++ b/bouquin/editor.py
@@ -349,7 +349,7 @@ class Editor(QTextEdit):
if source.hasImage():
img = self._to_qimage(source.imageData())
if img is not None:
- self._insert_qimage_at_cursor(self, img, autoscale=True)
+ self._insert_qimage_at_cursor(img, autoscale=True)
return
# 2) File URLs (drag/drop or paste)
@@ -496,12 +496,21 @@ class Editor(QTextEdit):
cur_fmt = self.textCursor().charFormat()
# Do nothing unless either side indicates we're in/propagating an anchor
- if not (ins_fmt.isAnchor() or cur_fmt.isAnchor()):
+ if not (
+ ins_fmt.isAnchor()
+ or cur_fmt.isAnchor()
+ or ins_fmt.fontUnderline()
+ or ins_fmt.foreground().style() != Qt.NoBrush
+ ):
return
nf = QTextCharFormat(ins_fmt)
+ # stop the link itself
nf.setAnchor(False)
nf.setAnchorHref("")
+ # also stop the link *styling*
+ nf.setFontUnderline(False)
+ nf.clearForeground()
self.setCurrentCharFormat(nf)
diff --git a/tests/test_editor.py b/tests/test_editor.py
index cd5855d..6935143 100644
--- a/tests/test_editor.py
+++ b/tests/test_editor.py
@@ -4,6 +4,8 @@ from PySide6.QtTest import QTest
from bouquin.editor import Editor
+import re
+
def _move_cursor_to_first_image(editor: Editor) -> QTextImageFormat | None:
c = editor.textCursor()
@@ -21,6 +23,57 @@ def _move_cursor_to_first_image(editor: Editor) -> QTextImageFormat | None:
return None
+def _fmt_at(editor: Editor, pos: int):
+ c = editor.textCursor()
+ c.setPosition(pos)
+ c.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, 1)
+ return c.charFormat()
+
+
+def test_space_breaks_link_anchor_and_styling(qtbot):
+ e = Editor()
+ e.resize(600, 300)
+ e.show()
+ qtbot.waitExposed(e)
+
+ # Type a URL, which should be linkified (anchor + underline + blue)
+ url = "https://mig5.net"
+ QTest.keyClicks(e, url)
+ qtbot.waitUntil(lambda: e.toPlainText() == url)
+
+ # Sanity: characters within the URL are anchors
+ for i in range(len(url)):
+ assert _fmt_at(e, i).isAnchor()
+
+ # Hit Space – Editor.keyPressEvent() should call _break_anchor_for_next_char()
+ QTest.keyClick(e, Qt.Key_Space)
+
+ # Type some normal text; it must not inherit the link formatting
+ tail = "this is a test"
+ QTest.keyClicks(e, tail)
+ qtbot.waitUntil(lambda: e.toPlainText().endswith(tail))
+
+ txt = e.toPlainText()
+ # Find where our 'tail' starts
+ start = txt.index(tail)
+ end = start + len(tail)
+
+ # None of the trailing characters should be part of an anchor or visually underlined
+ for i in range(start, end):
+ fmt = _fmt_at(e, i)
+ assert not fmt.isAnchor(), f"char {i} unexpectedly still has an anchor"
+ assert not fmt.fontUnderline(), f"char {i} unexpectedly still underlined"
+
+ # Optional: ensure the HTML only wraps the URL in , not the trailing text
+ html = e.document().toHtml()
+ assert re.search(
+ r']*href="https?://mig5\.net"[^>]*>(?:]*>)?https?://mig5\.net(?:)?\s+this is a test',
+ html,
+ re.S,
+ ), html
+ assert "this is a test" not in html
+
+
def test_embed_qimage_saved_as_data_url(qtbot):
e = Editor()
e.resize(600, 400)