diff --git a/internal/block/kanban.go b/internal/block/kanban.go index 66f6073..ac7623d 100644 --- a/internal/block/kanban.go +++ b/internal/block/kanban.go @@ -51,6 +51,10 @@ func ParseKanban(body string) []KanbanColumn { for _, raw := range strings.Split(body, "\n") { line := strings.TrimRight(raw, " \t") if line == "" { + if lastCard != nil && raw != "" { + lastCard.Text += "\n" + continue + } lastCard = nil // blank line breaks card continuation continue } diff --git a/internal/block/kanban_test.go b/internal/block/kanban_test.go index 08f2c7c..9d8c9bb 100644 --- a/internal/block/kanban_test.go +++ b/internal/block/kanban_test.go @@ -160,6 +160,24 @@ func TestKanbanMultilineCardRoundTrip(t *testing.T) { } } +func TestKanbanMultilineCardWithBlankLineRoundTrip(t *testing.T) { + cols := []KanbanColumn{{Title: "Todo", Cards: []KanbanCard{ + {Text: "First line\n\nThird line"}, + {Text: "next card"}, + }}} + md := SerializeKanban(cols) + got := ParseKanban(md) + if len(got) != 1 || len(got[0].Cards) != 2 { + t.Fatalf("shape lost: %+v", got) + } + if got[0].Cards[0].Text != "First line\n\nThird line" { + t.Errorf("blank-line text lost: %q", got[0].Cards[0].Text) + } + if got[0].Cards[1].Text != "next card" { + t.Errorf("second card = %+v", got[0].Cards[1]) + } +} + func TestKanbanDoneColumnAutoMarks(t *testing.T) { cols := []KanbanColumn{ {Title: "Done", Cards: []KanbanCard{{Text: "shipped"}}}, diff --git a/internal/editor/kanban_test.go b/internal/editor/kanban_test.go index e7a148f..7f06639 100644 --- a/internal/editor/kanban_test.go +++ b/internal/editor/kanban_test.go @@ -452,6 +452,32 @@ func TestKanbanPasteIntoCardEdit(t *testing.T) { } } +func TestKanbanCardBlankLineSurvivesFocusAwayAndBack(t *testing.T) { + md := sampleKanbanMD + "\n\nbelow" + m := New(Config{Title: "test", Content: md, Save: func(string) error { return nil }}) + out, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40}) + m = out.(Model) + + idx := firstKanban(m) + if idx < 0 || m.kanban == nil { + t.Fatalf("kanban not initialized") + } + m.kanban.col = 0 + m.kanban.card = 0 + m = pressKey(m, "enter") + if !m.kanban.edit { + t.Fatalf("enter should put us in edit mode") + } + m.kanban.editTA.SetValue("First line\n\nThird line") + + m.focusBlock(idx + 1) + m.focusBlock(idx) + + if c := m.kanban.selectedCard(); c == nil || c.Text != "First line\n\nThird line" { + t.Fatalf("card text after focus round-trip = %+v", c) + } +} + func TestKanbanSwallowsPlainPrintableKeys(t *testing.T) { // In selection mode, typing a plain printable character (one with no // modifier) must NOT mutate the underlying textarea — that would