Skip to content

Commit f7a8472

Browse files
committed
fix(table): compute wrapped widths from content
1 parent 1805b41 commit f7a8472

1 file changed

Lines changed: 18 additions & 22 deletions

File tree

lua/render-markdown/render/markdown/table.lua

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ local str = require('render-markdown.lib.str')
1717

1818
---@class render.md.table.Col
1919
---@field width integer
20+
---@field delimiter_width integer
2021
---@field alignment render.md.table.col.Alignment
2122

2223
---@enum render.md.table.col.Alignment
@@ -185,17 +186,20 @@ function Render:compute_layout()
185186
local overhead = (num_cols + 1) + (num_cols * 2 * padding)
186187
local text_budget = available - overhead
187188

189+
---@param cell render.md.table.row.Cell
190+
---@return integer
191+
local function content_width(cell)
192+
return math.max(cell.width - cell.space.left - cell.space.right, 0)
193+
end
194+
188195
-- Collect the natural text-area width for each column (max content width across all rows)
189196
local max_content = {} ---@type integer[]
190197
for i = 1, num_cols do
191-
max_content[i] = math.max(
192-
self.data.cols[i].width - 2 * padding,
193-
self.config.min_width
194-
)
198+
max_content[i] = self.data.cols[i].delimiter_width
195199
end
196200
for _, row in ipairs(self.data.rows) do
197201
for i, cell in ipairs(row.cells) do
198-
max_content[i] = math.max(max_content[i], cell.width)
202+
max_content[i] = math.max(max_content[i], content_width(cell))
199203
end
200204
end
201205

@@ -233,35 +237,26 @@ function Render:compute_layout()
233237
col_widths[i] = locked[i] and max_content[i] or math.max(share, 1)
234238
end
235239

236-
-- Compute per-row heights based on how many lines each cell needs.
237-
-- Also account for the raw (unrendered) buffer line wrapping: if the source
238-
-- text is longer than the rendered text (e.g. a long concealed URL), the
239-
-- buffer line may wrap onto more screen lines than the rendered content
240-
-- requires. We must cover all of those screen lines with overlay marks,
241-
-- so the effective height is max(rendered_lines, raw_screen_lines).
240+
-- Compute per-row heights based on how many rendered lines each cell needs.
241+
-- Long delimiter cells can also force wrapping even when row contents fit.
242242
local row_heights = {} ---@type integer[]
243243
local needs_wrap = false
244+
for i, width in ipairs(max_content) do
245+
needs_wrap = needs_wrap or width > col_widths[i]
246+
end
244247
for r, row in ipairs(self.data.rows) do
245248
local max_lines = 1
246249
for i, cell in ipairs(row.cells) do
247250
local w = col_widths[i]
248-
if w > 0 and cell.width > w then
249-
local lines = math.ceil(cell.width / w)
251+
local width = content_width(cell)
252+
if w > 0 and width > w then
253+
local lines = math.ceil(width / w)
250254
if lines > max_lines then
251255
max_lines = lines
252256
end
253257
needs_wrap = true
254258
end
255259
end
256-
-- Raw buffer line screen-wrap: ceil(display_width_of_source / win_width)
257-
local _, line = row.node:line('first', 0)
258-
line = line or ''
259-
local raw_screen_lines =
260-
math.max(1, math.ceil(str.width(line) / win_width))
261-
if raw_screen_lines > max_lines then
262-
max_lines = raw_screen_lines
263-
needs_wrap = true
264-
end
265260
row_heights[r] = max_lines
266261
end
267262

@@ -293,6 +288,7 @@ function Render:parse_cols(node)
293288
end
294289
cols[#cols + 1] = {
295290
width = width,
291+
delimiter_width = math.max(width, self.config.min_width),
296292
alignment = Render.alignment(cell),
297293
}
298294
end

0 commit comments

Comments
 (0)