diff --git a/markdown-table-wrap.el b/markdown-table-wrap.el index 29fcb08..24b7d35 100644 --- a/markdown-table-wrap.el +++ b/markdown-table-wrap.el @@ -832,7 +832,13 @@ monotonic — widening the terminal never shrinks any column." (total-natural (+ (markdown-table-wrap--vsum natural-widths) border-overhead))) (if (<= total-natural available-width) - (append natural-widths nil) + ;; Guarantee each column at least 1, matching the shrinking + ;; path's `max 1' floor below. An all-empty column has a + ;; natural width of 0; returning 0 misaligns renderers (the + ;; separator draws a dash where the row draws nothing), since + ;; the separator's `max 1' and the row's raw width disagree. + (mapcar (lambda (w) (max 1 w)) + (append natural-widths nil)) (let* ((col-w (make-vector num-cols 0)) ;; Precompute sqrt weights. (weights (vconcat diff --git a/test/markdown-table-wrap-test.el b/test/markdown-table-wrap-test.el index fedea5b..664d214 100644 --- a/test/markdown-table-wrap-test.el +++ b/test/markdown-table-wrap-test.el @@ -759,6 +759,34 @@ subtract marker overhead (which is invisible)." (should (>= (nth 0 widths) 1)) (should (>= (nth 1 widths) 1)))) +(ert-deftest markdown-table-wrap-test-widths-empty-column-min-1 () + "An all-empty column gets width at least 1, not 0. +A column whose header and every cell are empty has natural width 0. +Returning 0 misaligns renderers: the separator draws a dash (via its +own `max 1' floor) where the row draws nothing, so every line after +the separator drifts by one character per empty column. The shrinking +path already floors at 1; this test pins the fits path to the same +contract (see `markdown-table-wrap-test-widths-fit-naturally')." + (let ((widths (markdown-table-wrap-compute-widths + '("A" "" "B") '(("x" "" "y")) 20 3))) + (should (= (length widths) 3)) + (should (>= (nth 0 widths) 1)) + (should (>= (nth 1 widths) 1)) + (should (>= (nth 2 widths) 1)) + ;; The empty middle column is exactly 1, not 0. + (should (= (nth 1 widths) 1)))) + +(ert-deftest markdown-table-wrap-test-empty-column-row-separator-align () + "Rendering a table with an all-empty column keeps rows and separator aligned. +Before the fix, the separator was one char wider than each row per +empty column, so columns after an empty column drifted right." + (let* ((text "| a | | b |\n|---|---|---|\n| 1 | | 2 |\n") + (out (markdown-table-wrap text 40)) + (lines (split-string out "\n" t "[ \t\r]*")) + (widths (mapcar #'length lines))) + ;; Every rendered line (header, separator, row) has the same width. + (should (cl-every (lambda (w) (= w (car widths))) widths)))) + (ert-deftest markdown-table-wrap-test-widths-shrinking () "Columns shrink proportionally when table exceeds available width." (let ((widths (markdown-table-wrap-compute-widths