From fa23cf4da970af5dfb091cb7c622ebd0cefb64f9 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Sat, 8 Nov 2025 18:13:56 +1100 Subject: [PATCH] Fix chomping images when TODO is typed and converts to a checkbox --- CHANGELOG.md | 4 +++ bouquin/markdown_editor.py | 69 +++++++++++++++----------------------- pyproject.toml | 2 +- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2024eb..f2961b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.2.0.1 + + * Fix chomping images when TODO is typed and converts to a checkbox + # 0.2.0 * Switch back to Markdown editor diff --git a/bouquin/markdown_editor.py b/bouquin/markdown_editor.py index ce73b6f..760507b 100644 --- a/bouquin/markdown_editor.py +++ b/bouquin/markdown_editor.py @@ -245,53 +245,38 @@ class MarkdownEditor(QTextEdit): self._updating = True try: - # Convert checkbox markdown to Unicode for display - cursor = self.textCursor() - pos = cursor.position() + c = self.textCursor() + block = c.block() + line = block.text() + pos_in_block = c.position() - block.position() - text = self.toPlainText() - - # Convert lines that START with "TODO " into an unchecked checkbox. - # Keeps any leading indentation. - todo_re = re.compile(r"(?m)^([ \t]*)TODO\s") - if todo_re.search(text): - modified_text = todo_re.sub( + # Transform only this line: + # - "TODO " at start (with optional indent) -> "- ☐ " + # - "- [ ] " -> "- ☐ " and "- [x] " -> "- ☑ " + def transform_line(s: str) -> str: + s = s.replace("- [x] ", f"- {self._CHECK_CHECKED_DISPLAY} ") + s = s.replace("- [ ] ", f"- {self._CHECK_UNCHECKED_DISPLAY} ") + s = re.sub( + r'^([ \t]*)TODO\b[:\-]?\s+', lambda m: f"{m.group(1)}- {self._CHECK_UNCHECKED_DISPLAY} ", - text, + s, ) - else: - modified_text = text + return s - # Replace checkbox markdown with Unicode (for display only) - modified_text = modified_text.replace( - "- [x] ", f"- {self._CHECK_CHECKED_DISPLAY} " - ) - modified_text = modified_text.replace( - "- [ ] ", f"- {self._CHECK_UNCHECKED_DISPLAY} " - ) - - if modified_text != text: - # Count replacements before cursor to adjust position - text_before = text[:pos] - x_count = text_before.count("- [x] ") - space_count = text_before.count("- [ ] ") - # Each markdown checkbox -> unicode shortens by 2 chars ([x]/[ ] -> ☑/☐) - checkbox_delta = (x_count + space_count) * 2 - # Each "TODO " -> "- ☐ " shortens by 1 char - todo_count = len(list(todo_re.finditer(text_before))) - todo_delta = todo_count * 1 - new_pos = pos - checkbox_delta - todo_delta - - # Update the text - self.blockSignals(True) - self.setPlainText(modified_text) - self.blockSignals(False) - - # Restore cursor position - cursor = self.textCursor() - cursor.setPosition(max(0, min(new_pos, len(modified_text)))) - self.setTextCursor(cursor) + new_line = transform_line(line) + if new_line != line: + # Replace just the current block + bc = QTextCursor(block) + bc.beginEditBlock() + bc.select(QTextCursor.BlockUnderCursor) + bc.insertText(new_line) + bc.endEditBlock() + # Restore cursor near its original visual position in the edited line + new_pos = min(block.position() + len(new_line), + block.position() + pos_in_block) + c.setPosition(new_pos) + self.setTextCursor(c) finally: self._updating = False diff --git a/pyproject.toml b/pyproject.toml index d3e82ce..870eb0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "bouquin" -version = "0.2.0" +version = "0.2.0.1" description = "Bouquin is a simple, opinionated notebook application written in Python, PyQt and SQLCipher." authors = ["Miguel Jacq "] readme = "README.md"