Skip to content

Commit

Permalink
Merge pull request #7957 from quarto-dev/bugfix/table-fixups
Browse files Browse the repository at this point in the history
LaTeX: more table fixups
  • Loading branch information
cscheid authored Dec 19, 2023
2 parents 646ab9a + 3dc7cf7 commit afea9dc
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 11 deletions.
60 changes: 55 additions & 5 deletions src/resources/filters/customnodes/floatreftarget.lua
Original file line number Diff line number Diff line change
Expand Up @@ -363,21 +363,48 @@ end, function(float)
-- we need Pandoc to render its table ahead of time in order to
-- do the longtable fixups below
float.content = _quarto.ast.walk(quarto.utils.as_blocks(float.content), {
traverse = "topdown",
Div = function(div)
if div.classes:find_if(isStarEnv) then
return _quarto.ast.walk(div, {
Table = function(tbl)
if float.type == "Table" then
figEnv = "table*"
else
figEnv = "figure*"
end
local result = latexTabular(tbl)
return result
end
}), false
end
end,
Table = function(tbl)
return pandoc.RawBlock("latex", pandoc.write(pandoc.Pandoc({tbl}), "latex"))
end
})

if float_type == "tbl" then
local raw
local is_star_env = false
local function set_raw(el)
if _quarto.format.isRawLatex(el) and el.text:match(_quarto.patterns.latexLongtablePattern) then
raw = el
end
end
-- have to call as_blocks() again here because assigning to float.content
-- goes through our AST metaclasses which coalesce a singleton list to a single AST element
_quarto.ast.walk(quarto.utils.as_blocks(float.content), {
RawBlock = function(el)
if _quarto.format.isRawLatex(el) and el.text:match(_quarto.patterns.latexLongtablePattern) then
raw = el
traverse = "topdown",
Div = function(div)
if div.classes:find_if(isStarEnv) then
is_star_env = true
return _quarto.ast.walk(div, {
RawBlock = set_raw
}), false
end
end
end,
RawBlock = set_raw
})
-- special case for singleton longtable floats
if raw then
Expand Down Expand Up @@ -410,6 +437,29 @@ end, function(float)
fatal("longtables are not supported in subtables.\n" ..
"This is not a Quarto bug - the LaTeX longtable environment doesn't support subcaptions.\n")
return {}
end
if is_star_env then
-- content: table payload
-- start: \\begin{longtable}... command
-- longtable_preamble: everything that came before the \\begin{longtable} command
-- longtable_postamble: everything that came after the \\end{longtable} command
local result = pandoc.Blocks({
pandoc.RawBlock("latex", longtable_preamble),
pandoc.RawBlock("latex", "\\begin{table*}"),
-- caption here if cap_loc == "top"
pandoc.RawBlock("latex", start .. "\n" .. content .. "\n\\end{longtable}"),
-- caption here if cap_loc ~= "top"
pandoc.RawBlock("latex", "\\end{table*}"),
pandoc.RawBlock("latex", longtable_postamble),
})
if cap_loc == "top" then
result:insert(3, latex_caption)
-- gets around the padding that longtable* adds
result:insert(4, pandoc.RawBlock("latex", "\\vspace{-1em}"))
else
result:insert(4, latex_caption)
end
return result
else
local result = pandoc.Blocks({latex_caption, pandoc.RawInline("latex", "\\tabularnewline")})
-- if cap_loc is top, insert content on bottom
Expand All @@ -423,7 +473,7 @@ end, function(float)
result:insert(pandoc.RawBlock("latex", "\\end{longtable}"))
result:insert(pandoc.RawBlock("latex", longtable_postamble))
return result
end
end
end
end

Expand Down
40 changes: 35 additions & 5 deletions src/resources/filters/layout/columns.lua
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,46 @@ function renderDivColumn(el)
-- wrap table divs
latexWrapEnvironment(contentEl, latexTableEnv(el), false)
figOrTable = true
el.classes = el.classes:filter(function(clz)
return not isStarEnv(clz)
end)
elseif contentEl.attr ~= nil and hasFigureRef(contentEl) then
-- wrap figure divs
latexWrapEnvironment(contentEl, latexFigureEnv(el), false)
figOrTable = true
el.classes = el.classes:filter(function(clz)
return not isStarEnv(clz)
end)
elseif contentEl.t == 'Table' then
-- wrap the table in a div and wrap the table environment around it
local tableDiv = pandoc.Div({contentEl})
latexWrapEnvironment(tableDiv, latexTableEnv(el), false)
el.content[j] = tableDiv
figOrTable = true
-- TODO do-not-create-environment is hack we add on parsefiguredivs.lua
-- to handle floatreftarget that have layout elements. we need
-- this to not doubly-emit table* environments, because in this
-- specific case, the floatreftarget renderer will handle the
-- environment creation.
--
-- it's likely that the lines around here which create environments also
-- need to get the same treatment
if contentEl.classes:includes("do-not-create-environment") then
contentEl.classes = contentEl.classes:filter(function(clz)
return clz ~= "do-not-create-environment"
end)
else
-- wrap the table in a div and wrap the table environment around it
contentEl.classes:insert("render-as-tabular")
local tableDiv = pandoc.Div({contentEl})
latexWrapEnvironment(tableDiv, latexTableEnv(el), false)
el.content[j] = tableDiv
figOrTable = true

-- In this case, we need to remove the class from the parent element
-- It also means that divs that want to be both a figure* and a table*
-- will never work and we won't get the column-* treatment for
-- everything, just for the table.
el.classes = el.classes:filter(function(clz)
return not isStarEnv(clz)
end)
print(el)
end
elseif is_custom_node(contentEl, "FloatRefTarget") then
-- forward the columns class from the output div
-- onto the float ref target, which prevents
Expand Down
3 changes: 3 additions & 0 deletions src/resources/filters/quarto-post/latex.lua
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ function render_latex()
endColumnComment()
}
end
if table.classes:includes("render-as-tabular") then
return latexTabular(table)
end
end


Expand Down
9 changes: 8 additions & 1 deletion src/resources/filters/quarto-pre/parsefiguredivs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,20 @@ function parse_floatreftargets()
if #layout_classes then
attr.classes = attr.classes:filter(
function(c) return not layout_classes:includes(c) end)
div.classes = div.classes:filter(
function(c) return not layout_classes:includes(c) end)
-- if the div is a cell, then all layout attributes need to be
-- forwarded to the cell .cell-output-display content divs
content = _quarto.ast.walk(content, {
Div = function(div)
if div.classes:includes("cell-output-display") then
div.classes:extend(layout_classes)
return div
return _quarto.ast.walk(div, {
Table = function(tbl)
tbl.classes:insert("do-not-create-environment")
return tbl
end
})
end
end
})
Expand Down

0 comments on commit afea9dc

Please sign in to comment.