-- column-fit.lua  (robust, 2025-06-05)
-- Auto-sizes every table so columns get a width proportional to the
-- longest word/line they contain.  Works on Pandoc 2.17 → 3.x.

local stringify = (require 'pandoc.utils').stringify
local hasRCW    = type(pandoc.RelativeColumnWidth) == "function"

-- UTF-8 code-point length (pure Lua)
local function ulen(s)
  local _, n = s:gsub('[\0-\127\194-\244][\128-\191]*', '')
  return n
end

-- ensure arrays are long enough ----------------------------------------
local function ensure(tbl, i, v)
  if not tbl[i] then tbl[i] = v end
end

-- walk every cell ------------------------------------------------------
local function each_cell(t, fn)
  local function rows(block)
    if block then
      for _, row in ipairs(block) do
        for c, cell in ipairs(row.cells) do fn(cell, c) end
      end
    end
  end
  rows(t.head.rows)
  for _, body in ipairs(t.bodies) do rows(body.body) end
  rows(t.foot.rows)
end

function Table(t)
  local max = {}                                -- longest token per col

  -- pass 1  – measure --------------------------------------------------
  each_cell(t, function (cell, col)
    ensure(max, col, 0)
    ensure(t.colspecs, col, {pandoc.AlignDefault, 0})

    local txt = stringify(cell.contents or cell)
    for line in txt:gmatch('[^\n]+') do
      for word in line:gmatch('%S+') do
        local len = ulen(word)
        if len > max[col] then max[col] = len end
      end
    end
  end)

  local total = 0
  for _, v in ipairs(max) do total = total + v end
  if total == 0 then return nil end             -- empty table

  -- pass 2  – write widths back ----------------------------------------
  for c, spec in ipairs(t.colspecs) do
    local rel = max[c] / total
    spec[2] = hasRCW and pandoc.RelativeColumnWidth(rel) or rel
  end
  return t
end

