From c821c6804e947c26e5193ef267f2454726b8b64e Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Thu, 18 Apr 2024 14:55:05 -0700 Subject: [PATCH 1/2] lua - slightly revert overzealous conversion to subfigure --- .../filters/layout/pandoc3_figure.lua | 231 ++++++++++++------ src/resources/filters/modules/scope.lua | 3 +- 2 files changed, 157 insertions(+), 77 deletions(-) diff --git a/src/resources/filters/layout/pandoc3_figure.lua b/src/resources/filters/layout/pandoc3_figure.lua index b8cf9bf1930..0245cc363f5 100644 --- a/src/resources/filters/layout/pandoc3_figure.lua +++ b/src/resources/filters/layout/pandoc3_figure.lua @@ -5,6 +5,8 @@ -- never cross-referenceable but they need to be rendered as -- if they were. +local scope_utils = require("modules/scope") + function render_pandoc3_figure() local function html_handle_linked_image(figure) local div = pandoc.Div({}) @@ -70,90 +72,167 @@ function render_pandoc3_figure() end } elseif _quarto.format.isLatexOutput() then - -- split local declaration because Lua's local is not - -- a letrec - local filter - filter = function(state) - state = state or {} - local function figure_renderer(figure, is_subfig) - -- this is a figure that is not cross-referenceable - -- if this ends up in a layout without fig-pos = H, it'll fail - -- 'H' forces it to not float - if figure.identifier == "" then - figure = _quarto.ast.walk(figure, { - Image = function(image) - image.attributes['fig-pos'] = 'H' - return image - end - }) - end - local image - _quarto.ast.walk(figure, { - Image = function(img) - image = img + local function is_inside_float(scope) + for i = #scope, 1, -1 do + local s = scope[i] + local data = _quarto.ast.resolve_custom_data(s) + if data then + if (data.t == "PanelLayout" and data.is_float_reftarget == true) then + return true + elseif (data.t == "FloatRefTarget") then + return true end - }) - if image == nil then - return figure end - if figure.caption.long ~= nil then - image.caption = quarto.utils.as_inlines(figure.caption.long) - end - for k, v in pairs(figure.attributes) do - image.attributes[k] = v - end - if is_subfig then - image.attributes['quarto-caption-env'] = 'subcaption' - end - image.classes:extend(figure.classes) - if state.in_column_margin then - image.classes:insert("column-margin") + end + end + local function is_subfig(scope) + for i = #scope, 1, -1 do + local s = scope[i] + local data = _quarto.ast.resolve_custom_data(s) + if data and (data.t == "PanelLayout") then + return true end - return latexImageFigure(image) - end - local function float_renderer(float) - local count = 0 - local new_content = _quarto.ast.walk(float.content, { - Figure = function(fig) - count = count + 1 - return figure_renderer(fig, true), false + end + + return false + end + + local function figure_renderer(figure, scope) + if is_inside_float(scope) then + return nil, false + end + local subfig = is_subfig(scope) + -- this is a figure that is not cross-referenceable + -- if this ends up in a layout without fig-pos = H, it'll fail + -- 'H' forces it to not float + if figure.identifier == "" then + figure = _quarto.ast.walk(figure, { + Image = function(image) + image.attributes['fig-pos'] = 'H' + return image end }) - if count > 0 then - float.content = new_content - return float, false - end end - return { - traverse = "topdown", - PanelLayout = function(panel) - panel.rows = _quarto.ast.walk(panel.rows, { - Figure = function(fig) - return figure_renderer(fig, true), false - end - }) - return panel, false - end, - FloatRefTarget = float_renderer, - Div = function(div) - if div.classes:includes("column-margin") then - local new_state = {} - for k, v in pairs(state) do - new_state[k] = v - end - new_state.in_column_margin = true - - div.content = _quarto.ast.walk(div.content, filter(new_state)) - div.classes = div.classes:filter(function(x) return x ~= "column-margin" end) - return div - end - end, - Figure = function(figure) - return figure_renderer(figure, false) + local image + _quarto.ast.walk(figure, { + Image = function(img) + image = img end - } + }) + if image == nil then + return figure + end + if figure.caption.long ~= nil then + image.caption = quarto.utils.as_inlines(figure.caption.long) + end + for k, v in pairs(figure.attributes) do + image.attributes[k] = v + end + if subfig then + image.attributes['quarto-caption-env'] = 'subcaption' + end + image.classes:extend(figure.classes) + if scope_utils.lookup_class(scope, "column-margin") then + image.classes:insert("column-margin") + end + return latexImageFigure(image) end - return filter() + + local filter = { + Figure = function(figure, scope) + return figure_renderer(figure, scope), false + end + } + return { + Pandoc = function(doc) + _quarto.ast.scoped_walk(doc.blocks, filter) + end + } + + -- split local declaration because Lua's local is not + -- a letrec + -- local filter + -- filter = function(state) + -- state = state or {} + -- local function figure_renderer(figure, is_subfig) + -- -- this is a figure that is not cross-referenceable + -- -- if this ends up in a layout without fig-pos = H, it'll fail + -- -- 'H' forces it to not float + -- if figure.identifier == "" then + -- figure = _quarto.ast.walk(figure, { + -- Image = function(image) + -- image.attributes['fig-pos'] = 'H' + -- return image + -- end + -- }) + -- end + -- local image + -- _quarto.ast.walk(figure, { + -- Image = function(img) + -- image = img + -- end + -- }) + -- if image == nil then + -- return figure + -- end + -- if figure.caption.long ~= nil then + -- image.caption = quarto.utils.as_inlines(figure.caption.long) + -- end + -- for k, v in pairs(figure.attributes) do + -- image.attributes[k] = v + -- end + -- if is_subfig then + -- image.attributes['quarto-caption-env'] = 'subcaption' + -- end + -- image.classes:extend(figure.classes) + -- if state.in_column_margin then + -- image.classes:insert("column-margin") + -- end + -- return latexImageFigure(image) + -- end + -- local function float_renderer(float) + -- local count = 0 + -- local new_content = _quarto.ast.walk(float.content, { + -- Figure = function(fig) + -- count = count + 1 + -- return figure_renderer(fig, true), false + -- end + -- }) + -- if count > 0 then + -- float.content = new_content + -- return float, false + -- end + -- end + -- return { + -- traverse = "topdown", + -- PanelLayout = function(panel) + -- panel.rows = _quarto.ast.walk(panel.rows, { + -- Figure = function(fig) + -- return figure_renderer(fig, true), false + -- end + -- }) + -- return panel, false + -- end, + -- FloatRefTarget = float_renderer, + -- Div = function(div) + -- if div.classes:includes("column-margin") then + -- local new_state = {} + -- for k, v in pairs(state) do + -- new_state[k] = v + -- end + -- new_state.in_column_margin = true + + -- div.content = _quarto.ast.walk(div.content, filter(new_state)) + -- div.classes = div.classes:filter(function(x) return x ~= "column-margin" end) + -- return div + -- end + -- end, + -- Figure = function(figure) + -- return figure_renderer(figure, false) + -- end + -- } + -- end + -- return filter() elseif _quarto.format.isTypstOutput() then return { traverse = "topdown", diff --git a/src/resources/filters/modules/scope.lua b/src/resources/filters/modules/scope.lua index 31e8ce00f49..126562070d6 100644 --- a/src/resources/filters/modules/scope.lua +++ b/src/resources/filters/modules/scope.lua @@ -33,9 +33,10 @@ local function lookup_class(scope, class_name) else attr = scope[i].classes end - if classes:includes(class_name) then + if classes and classes:includes(class_name) then return true end + i = i - 1 end end From f5e1f532451238ff0b260ed71d1c47d0690afe22 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Thu, 18 Apr 2024 14:59:32 -0700 Subject: [PATCH 2/2] regression test --- tests/docs/smoke-all/2024/04/18/9414.qmd | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/docs/smoke-all/2024/04/18/9414.qmd diff --git a/tests/docs/smoke-all/2024/04/18/9414.qmd b/tests/docs/smoke-all/2024/04/18/9414.qmd new file mode 100644 index 00000000000..50db9666f84 --- /dev/null +++ b/tests/docs/smoke-all/2024/04/18/9414.qmd @@ -0,0 +1,21 @@ +--- +title: hello +_quarto: + tests: + latex: + ensureFileRegexMatches: + - [] + - ['\\begin{figure}\n\n.*\n\n\\begin{figure}'] +--- + +::: {#fig-1 layout=[1,2]} + +![Hanno](./hanno.png) + +![Surus](./surus.png) + +Elephants + +::: + +See @fig-1 \ No newline at end of file