@@ -5,9 +5,10 @@ local str = require('render-markdown.core.str')
55
66--- @class render.md.table.Column
77--- @field row integer
8- --- @field col integer
8+ --- @field start_col integer
9+ --- @field end_col integer
910--- @field width integer
10- --- @field free integer
11+ --- @field space { left : integer , right : integer }
1112
1213--- @class render.md.table.Row
1314--- @field info render.md.NodeInfo
@@ -80,9 +81,13 @@ function Render:setup()
8081 end
8182 -- Store the max width information in the delimiter
8283 for _ , row in ipairs (rows ) do
83- for i , r_column in ipairs (row .columns ) do
84- local d_column = delim .columns [i ]
85- d_column .width = math.max (d_column .width , r_column .width )
84+ for i , column in ipairs (row .columns ) do
85+ local delim_column , width = delim .columns [i ], column .width
86+ if self .table .cell == ' trimmed' then
87+ local space_available = column .space .left + column .space .right - (2 * self .table .padding )
88+ width = width - math.max (space_available , 0 )
89+ end
90+ delim_column .width = math.max (delim_column .width , width )
8691 end
8792 end
8893
@@ -143,19 +148,26 @@ function Render:parse_row(row, num_columns)
143148 end
144149 local columns = {}
145150 for i , cell in ipairs (cells ) do
146- local width = pipes [i + 1 ].start_col - pipes [i ].end_col
147- -- Account for double width glyphs by replacing cell spacing with width
151+ local start_col , end_col = pipes [i ].end_col , pipes [i + 1 ].start_col
152+ -- Account for double width glyphs by replacing cell range with width
153+ local width = end_col - start_col
148154 width = width - (cell .end_col - cell .start_col ) + self .context :width (cell )
149- local free = 0
150- if self . table . cell == ' trimmed ' then
151- -- Remove trailing spaces from width calculation except for 1
152- free = math.max ( str . spaces ( ' end ' , cell . text ) - 1 , 0 )
153- width = width - free
154- end
155+ local space = {
156+ -- Left space comes from the gap between the node start and the pipe start
157+ left = math.max ( cell . start_col - start_col , 0 ),
158+ -- Right space is attached to the node itself
159+ right = math.max ( str . spaces ( ' end ' , cell . text ), 0 ),
160+ }
155161 if width < 0 then
156162 return nil
157163 end
158- table.insert (columns , { row = cell .start_row , col = cell .end_col , width = width , free = free })
164+ table.insert (columns , {
165+ row = cell .start_row ,
166+ start_col = cell .start_col ,
167+ end_col = cell .end_col ,
168+ width = width ,
169+ space = space ,
170+ })
159171 end
160172 return { info = row , pipes = pipes , columns = columns }
161173end
@@ -198,22 +210,19 @@ function Render:delimiter()
198210 local delim , border = self .data .delim , self .table .border
199211
200212 local sections = Iter .list .map (delim .columns , function (column )
201- local indicator = self .table .alignment_indicator
213+ local indicator , box = self .table .alignment_indicator , border [ 11 ]
202214 -- If column is small there's no good place to put the alignment indicator
203215 -- Alignment indicator must be exactly one character wide
204216 -- Do not put an indicator for default alignment
205- if column .width < 4 or str .width (indicator ) ~= 1 or column .alignment == ' default' then
206- return border [ 11 ] :rep (column .width )
217+ if column .width < 3 or str .width (indicator ) ~= 1 or column .alignment == ' default' then
218+ return box :rep (column .width )
207219 end
208- -- Handle the various alignmnet possibilities
209- local left = border [11 ]:rep (math.floor (column .width / 2 ))
210- local right = border [11 ]:rep (math.ceil (column .width / 2 ) - 1 )
211220 if column .alignment == ' left' then
212- return indicator .. left .. right
221+ return indicator .. box : rep ( column . width - 1 )
213222 elseif column .alignment == ' right' then
214- return left .. right .. indicator
223+ return box : rep ( column . width - 1 ) .. indicator
215224 else
216- return left .. indicator .. right
225+ return indicator .. box : rep ( column . width - 2 ) .. indicator
217226 end
218227 end )
219228
@@ -246,22 +255,22 @@ function Render:row(row)
246255 end
247256 end
248257
249- -- Use low priority to include pipe marks
250258 if vim .tbl_contains ({ ' trimmed' , ' padded' }, self .table .cell ) then
251259 for i , column in ipairs (row .columns ) do
252- local offset = delim .columns [i ].width - column .width - column .free
253- if offset > 0 then
254- self .marks :add (true , column .row , column .col , {
255- priority = 0 ,
256- virt_text = { { str .pad (offset ), self .table .filler } },
257- virt_text_pos = ' inline' ,
258- })
259- elseif offset < 0 then
260- self .marks :add (true , column .row , column .col + offset , {
261- priority = 0 ,
262- end_col = column .col ,
263- conceal = ' ' ,
264- })
260+ local delim_column = delim .columns [i ]
261+ local filler = delim_column .width - column .width
262+ if delim_column .alignment == ' center' then
263+ local shift = math.floor ((filler + column .space .right - column .space .left ) / 2 )
264+ self :shift (column , ' left' , shift )
265+ self :shift (column , ' right' , filler - shift )
266+ elseif delim_column .alignment == ' right' then
267+ local shift = column .space .right - self .table .padding
268+ self :shift (column , ' left' , filler + shift )
269+ self :shift (column , ' right' , - shift )
270+ else
271+ local shift = column .space .left - self .table .padding
272+ self :shift (column , ' left' , - shift )
273+ self :shift (column , ' right' , filler + shift )
265274 end
266275 end
267276 end
@@ -276,6 +285,28 @@ function Render:row(row)
276285 end
277286end
278287
288+ --- Use low priority to include pipe marks
289+ --- @private
290+ --- @param column render.md.table.Column
291+ --- @param side ' left' | ' right'
292+ --- @param amount integer
293+ function Render :shift (column , side , amount )
294+ local col = side == ' left' and column .start_col or column .end_col
295+ if amount > 0 then
296+ self .marks :add (true , column .row , col , {
297+ priority = 0 ,
298+ virt_text = { { str .pad (amount ), self .table .filler } },
299+ virt_text_pos = ' inline' ,
300+ })
301+ elseif amount < 0 then
302+ self .marks :add (true , column .row , col + amount , {
303+ priority = 0 ,
304+ end_col = col ,
305+ conceal = ' ' ,
306+ })
307+ end
308+ end
309+
279310--- @private
280311function Render :full ()
281312 local delim , rows , border = self .data .delim , self .data .rows , self .table .border
0 commit comments