More fixes to code blocks
This commit is contained in:
parent
1b706dec18
commit
43c31a1d97
4 changed files with 280 additions and 37 deletions
|
|
@ -6,12 +6,29 @@ from bouquin.markdown_editor import MarkdownEditor
|
|||
from bouquin.theme import ThemeManager, ThemeConfig, Theme
|
||||
|
||||
|
||||
def text(editor) -> str:
|
||||
return editor.toPlainText()
|
||||
|
||||
|
||||
def lines_keep(editor):
|
||||
"""Split preserving a trailing empty line if the text ends with '\\n'."""
|
||||
return text(editor).split("\n")
|
||||
|
||||
|
||||
def press_backtick(qtbot, widget, n=1):
|
||||
"""Send physical backtick key events (avoid IME/dead-key issues)."""
|
||||
for _ in range(n):
|
||||
qtbot.keyClick(widget, Qt.Key_QuoteLeft)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def editor(app, qtbot):
|
||||
themes = ThemeManager(app, ThemeConfig(theme=Theme.LIGHT))
|
||||
ed = MarkdownEditor(themes)
|
||||
qtbot.addWidget(ed)
|
||||
ed.show()
|
||||
qtbot.waitExposed(ed)
|
||||
ed.setFocus()
|
||||
return ed
|
||||
|
||||
|
||||
|
|
@ -56,24 +73,6 @@ def test_insert_image_from_path(editor, tmp_path):
|
|||
assert "data:image/image/png;base64" in md
|
||||
|
||||
|
||||
def test_apply_code_inline(editor):
|
||||
editor.from_markdown("alpha beta")
|
||||
editor.selectAll()
|
||||
editor.apply_code()
|
||||
md = editor.to_markdown()
|
||||
assert ("`" in md) or ("```" in md)
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_auto_close_code_fence(editor, qtbot):
|
||||
# Place caret at start and type exactly `` then ` to trigger expansion
|
||||
editor.setPlainText("")
|
||||
qtbot.keyClicks(editor, "``")
|
||||
qtbot.keyClicks(editor, "`") # third backtick triggers fence insertion
|
||||
txt = editor.toPlainText()
|
||||
assert "```" in txt and txt.count("```") >= 2
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_checkbox_toggle_by_click(editor, qtbot):
|
||||
# Load a markdown checkbox
|
||||
|
|
@ -143,3 +142,131 @@ def test_enter_on_empty_list_marks_empty(qtbot, editor):
|
|||
ev = QKeyEvent(QKeyEvent.KeyPress, Qt.Key_Return, Qt.NoModifier, "\n")
|
||||
editor.keyPressEvent(ev)
|
||||
assert editor.toPlainText().startswith("- \n")
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_triple_backtick_autoexpands(editor, qtbot):
|
||||
editor.from_markdown("")
|
||||
press_backtick(qtbot, editor, 2)
|
||||
press_backtick(qtbot, editor, 1) # triggers expansion
|
||||
qtbot.wait(0)
|
||||
|
||||
t = text(editor)
|
||||
assert t.count("```") == 2
|
||||
assert t.startswith("```\n\n```")
|
||||
assert t.endswith("\n")
|
||||
# caret is on the blank line inside the block
|
||||
assert editor.textCursor().blockNumber() == 1
|
||||
assert lines_keep(editor)[1] == ""
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_toolbar_inserts_block_on_own_lines(editor, qtbot):
|
||||
editor.from_markdown("hello")
|
||||
editor.moveCursor(QTextCursor.End)
|
||||
editor.apply_code() # </> action
|
||||
qtbot.wait(0)
|
||||
|
||||
t = text(editor)
|
||||
assert "hello```" not in t # never inline
|
||||
assert t.startswith("hello\n```")
|
||||
assert t.endswith("```\n")
|
||||
# caret inside block (blank line)
|
||||
assert editor.textCursor().blockNumber() == 2
|
||||
assert lines_keep(editor)[2] == ""
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_toolbar_inside_block_does_not_insert_inline_fences(editor, qtbot):
|
||||
editor.from_markdown("")
|
||||
editor.apply_code() # create a block (caret now on blank line inside)
|
||||
qtbot.wait(0)
|
||||
|
||||
pos_before = editor.textCursor().position()
|
||||
t_before = text(editor)
|
||||
|
||||
editor.apply_code() # pressing </> inside should be a no-op
|
||||
qtbot.wait(0)
|
||||
|
||||
assert text(editor) == t_before
|
||||
assert editor.textCursor().position() == pos_before
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_toolbar_on_opening_fence_jumps_inside(editor, qtbot):
|
||||
editor.from_markdown("")
|
||||
editor.apply_code()
|
||||
qtbot.wait(0)
|
||||
|
||||
# Go to opening fence (line 0)
|
||||
editor.moveCursor(QTextCursor.Start)
|
||||
editor.apply_code() # should jump inside the block
|
||||
qtbot.wait(0)
|
||||
|
||||
assert editor.textCursor().blockNumber() == 1
|
||||
assert lines_keep(editor)[1] == ""
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_toolbar_on_closing_fence_jumps_out(editor, qtbot):
|
||||
editor.from_markdown("")
|
||||
editor.apply_code()
|
||||
qtbot.wait(0)
|
||||
|
||||
# Go to closing fence line (template: 0 fence, 1 blank, 2 fence, 3 blank-after)
|
||||
editor.moveCursor(QTextCursor.End) # blank-after
|
||||
editor.moveCursor(QTextCursor.Up) # closing fence
|
||||
editor.moveCursor(QTextCursor.StartOfLine)
|
||||
|
||||
editor.apply_code() # jump to the line after the fence
|
||||
qtbot.wait(0)
|
||||
|
||||
# Now on the blank line after the block
|
||||
assert editor.textCursor().block().text() == ""
|
||||
assert editor.textCursor().block().previous().text().strip() == "```"
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_down_escapes_from_last_code_line(editor, qtbot):
|
||||
editor.from_markdown("```\nLINE\n```\n")
|
||||
# Put caret at end of "LINE"
|
||||
editor.moveCursor(QTextCursor.Start)
|
||||
editor.moveCursor(QTextCursor.Down) # "LINE"
|
||||
editor.moveCursor(QTextCursor.EndOfLine)
|
||||
|
||||
qtbot.keyPress(editor, Qt.Key_Down) # hop after closing fence
|
||||
qtbot.wait(0)
|
||||
|
||||
# caret now on the blank line after the fence
|
||||
assert editor.textCursor().block().text() == ""
|
||||
assert editor.textCursor().block().previous().text().strip() == "```"
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_down_on_closing_fence_at_eof_creates_line(editor, qtbot):
|
||||
editor.from_markdown("```\ncode\n```") # no trailing newline
|
||||
# caret on closing fence line
|
||||
editor.moveCursor(QTextCursor.End)
|
||||
editor.moveCursor(QTextCursor.StartOfLine)
|
||||
|
||||
qtbot.keyPress(editor, Qt.Key_Down) # should append newline and move there
|
||||
qtbot.wait(0)
|
||||
|
||||
# Do NOT use splitlines() here—preserve trailing blank line
|
||||
assert text(editor).endswith("\n")
|
||||
assert editor.textCursor().block().text() == "" # on the new blank line
|
||||
assert editor.textCursor().block().previous().text().strip() == "```"
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def test_no_orphan_two_backticks_lines_after_edits(editor, qtbot):
|
||||
editor.from_markdown("")
|
||||
# create a block via typing
|
||||
press_backtick(qtbot, editor, 3)
|
||||
qtbot.keyClicks(editor, "x")
|
||||
qtbot.keyPress(editor, Qt.Key_Down) # escape
|
||||
editor.apply_code() # add second block via toolbar
|
||||
qtbot.wait(0)
|
||||
|
||||
# ensure there are no stray "``" lines
|
||||
assert not any(ln.strip() == "``" for ln in lines_keep(editor))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue