Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect *-cap-location everywhere #7449

Merged
merged 1 commit into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/resources/filters/crossref/crossref.lua
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ local quarto_normalize_filters = {
return quarto_global_state.active_filters.normalization
end, normalize_filter()) },

{ name = "normalize-capture-reader-state", filter = normalize_capture_reader_state() },

{ name = "pre-table-merge-raw-html",
filter = table_merge_raw_html()
},
Expand Down
23 changes: 15 additions & 8 deletions src/resources/filters/customnodes/floatreftarget.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,28 @@ _quarto.ast.add_handler({
end
})

function cap_location(float)
local ref = refType(float.identifier)
function cap_location(float_or_layout)
local ref = refType(float_or_layout.identifier)
-- layouts might not have good identifiers, but they might have
-- ref-parents
if ref == nil then
ref = refType(float_or_layout.attributes["ref-parent"] or "")
end
-- last resort, pretend we're a figure
if ref == nil then
ref = "fig"
end
local qualified_key = ref .. '-cap-location'
local result = (
float.attributes[qualified_key] or
float.attributes['cap-location'] or
float_or_layout.attributes[qualified_key] or
float_or_layout.attributes['cap-location'] or
option_as_string(qualified_key) or
option_as_string('cap-location') or
capLocation(ref) or
crossref.categories.by_ref_type[ref].default_caption_location)

if result ~= "margin" and result ~= "top" and result ~= "bottom" then
-- luacov: disable
error("Invalid caption location for float: " .. float.identifier ..
error("Invalid caption location for float: " .. float_or_layout.identifier ..
" requested " .. result ..
".\nOnly 'top', 'bottom', and 'margin' are supported. Assuming 'bottom'.")
result = "bottom"
Expand Down Expand Up @@ -203,9 +211,8 @@ end, function(float)
local figEnv = latexFigureEnv(float)
local figPos = latexFigurePosition(float, figEnv)
local float_type = refType(float.identifier)
local crossref_category = crossref.categories.by_ref_type[float_type] or crossref.categories.by_name.Figure

local capLoc = capLocation(float_type, crossref_category.default_caption_location)
local capLoc = cap_location(float)
local caption_cmd_name = latexCaptionEnv(float)

if float.parent_id then
Expand Down
6 changes: 3 additions & 3 deletions src/resources/filters/layout/html.lua
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ end)
-- captionPara.content:insert(pandoc.RawInline("html", figcaption))
-- tappend(captionPara.content, caption.content)
-- captionPara.content:insert(pandoc.RawInline("html", "</figcaption>"))
-- if capLocation('fig', 'bottom') == 'bottom' then
-- if cap_location_from_option('fig', 'bottom') == 'bottom' then
-- panel.content:insert(captionPara)
-- else
-- tprepend(panel.content, { captionPara })
Expand All @@ -198,7 +198,7 @@ end)
-- local panelCaption = pandoc.Div(caption, pandoc.Attr("", { "panel-caption" }))
-- if hasTableRef(divEl) then
-- panelCaption.attr.classes:insert("table-caption")
-- if capLocation('tbl', 'top') == 'bottom' then
-- if cap_location_from_option('tbl', 'top') == 'bottom' then
-- panel.content:insert(panelCaption)
-- else
-- tprepend(panel.content, { panelCaption })
Expand Down Expand Up @@ -312,7 +312,7 @@ function renderHtmlFigure(el, render)
))
tappend(figureCaption.content, captionInlines)
figureCaption.content:insert(pandoc.RawInline("html", "</figcaption>"))
if capLocation('fig', 'bottom') == 'top' then
if cap_location_from_option('fig', 'bottom') == 'top' then
figureDiv.content:insert(figureCaption)
tappend(figureDiv.content, figure)
else
Expand Down
10 changes: 2 additions & 8 deletions src/resources/filters/layout/latex.lua
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,7 @@ function latexCell(cell, vAlign, endOfRow, endOfTable)
local miniPageVAlign = latexMinipageValign(vAlign)
latexAppend(prefix, "\\begin{minipage}" .. miniPageVAlign .. "{" .. width .. "}\n")

local capType = "fig"
local locDefault = "bottom"
if isTable then
capType = "tbl"
locDefault = "top"
end
local capLoc = capLocation(capType, locDefault)
local capLoc = cap_location(cell)

if (capLoc == "top") then
tappend(prefix, subcap)
Expand Down Expand Up @@ -653,7 +647,7 @@ function renderLatexFigure(el, render)
-- get the figure content and caption inlines
local figureContent, captionInlines = render(figure)

local capLoc = capLocation("fig", "bottom")
local capLoc = cap_location_from_option("fig", "bottom")

-- surround caption w/ appropriate latex (and end the figure)
if captionInlines and inlinesToString(captionInlines) ~= "" then
Expand Down
2 changes: 1 addition & 1 deletion src/resources/filters/quarto-pre/options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function parseOption(name, options, def)
end
end

function capLocation(scope, default)
function cap_location_from_option(scope, default)
local loc = option(scope .. '-cap-location', option('cap-location', nil))
if loc ~= nil then
return inlinesToString(loc)
Expand Down
73 changes: 73 additions & 0 deletions src/resources/filters/quarto-pre/parsefiguredivs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@

local patterns = require("modules/patterns")

local function process_div_caption_classes(div)
-- knitr forwards "cap-location: top" as `.caption-top`...
-- and in that case we don't know if it's a fig- or a tbl- :facepalm:
-- so we have to use cap-locatin generically in the attribute
if div.classes:find_if(
function(class) return class:match("caption%-.+") end) then
local matching_classes = div.classes:filter(function(class)
return class:match("caption%-.+")
end)
div.classes = div.classes:filter(function(class)
return not class:match("caption%-.+")
end)
for i, c in ipairs(matching_classes) do
div.attributes["cap-location"] = c:match("caption%-(.+)")
end
return true
end
return false
end

local function coalesce_code_blocks(content)
local result = pandoc.Blocks({})
local state = "start"
Expand Down Expand Up @@ -134,6 +154,7 @@ function parse_reftargets()
end

local function parse_float_div(div)
process_div_caption_classes(div)
local ref = refType(div.identifier)
if ref == nil then
fail("Float div without crossref identifier?")
Expand All @@ -151,6 +172,24 @@ function parse_reftargets()
local content = div.content
local caption_attr_key = ref .. "-cap"

-- caption location handling

-- .*-cap-location
local caption_location_attr_key = ref .. "-cap-location"
local caption_location_class_pattern = ".*cap%-location%-(.*)"
local caption_location_classes = div.classes:filter(function(class)
return class:match(caption_location_class_pattern)
end)

if #caption_location_classes then
div.classes = div.classes:filter(function(class)
return not class:match(caption_location_class_pattern)
end)
for _, class in ipairs(caption_location_classes) do
local c = class:match(caption_location_class_pattern)
div.attributes[caption_location_attr_key] = c
end
end
local caption = refCaptionFromDiv(div)
if caption ~= nil then
div.content:remove(#div.content)
Expand Down Expand Up @@ -381,6 +420,40 @@ function parse_reftargets()
elseif is_theorem_div(div) then
return parse_theorem_div(div)
end

if div.classes:includes("cell") then
process_div_caption_classes(div)
-- forward cell attributes to potential FloatRefTargets
div = _quarto.ast.walk(div, {
Figure = function(fig)
if div.attributes["cap-location"] then
fig.attributes["cap-location"] = div.attributes["cap-location"]
end
for i, c in ipairs(div.classes) do
local c = c:match(".*%-?cap%-location%-(.*)")
if c then
fig.attributes["cap-location"] = c
end
end
return fig
end,
CodeBlock = function(block)
for _, k in ipairs({"cap-location", "lst-cap-location"}) do
if div.attributes[k] then
block.attributes[k] = div.attributes[k]
end
end
for i, c in ipairs(div.classes) do
local c = c:match(".*%-?cap%-location%-(.*)")
if c then
block.attributes["cap-location"] = c
end
end
return block
end,
})
return div
end
end,

Para = function(para)
Expand Down