diff --git a/news/changelog-1.7.md b/news/changelog-1.7.md index 831514bbdc..550549d275 100644 --- a/news/changelog-1.7.md +++ b/news/changelog-1.7.md @@ -14,6 +14,10 @@ All changes included in 1.7: - ([#11608](https://github.com/quarto-dev/quarto-cli/pull/11608)): Do not issue error message when calling `quarto check info`. +## Typst + +- ([#11578](https://github.com/quarto-dev/quarto-cli/issues/11578)): Typst column layout widths use fractional units instead of percent units in order to fill the enclosing block and not spill outside it. + ## Lua Filters and extensions - ([#11526](https://github.com/quarto-dev/quarto-cli/pull/11526)): diff --git a/src/resources/filters/layout/layout.lua b/src/resources/filters/layout/layout.lua index dd49f3a4bb..dd5d876f60 100644 --- a/src/resources/filters/layout/layout.lua +++ b/src/resources/filters/layout/layout.lua @@ -203,9 +203,13 @@ function layout_cells(float_or_div, cells) end rows[#rows]:insert(cell) end - -- convert width units to percentages - widthsToPercent(rows, layoutCols) - + if _quarto.format.isTypstOutput() then + widthsToFraction(rows, layoutCols) + else + -- convert width units to percentages + widthsToPercent(rows, layoutCols) + end + -- check for layout elseif layout ~= nil then -- parse the layout diff --git a/src/resources/filters/layout/width.lua b/src/resources/filters/layout/width.lua index f83bc9d9d5..def532776f 100644 --- a/src/resources/filters/layout/width.lua +++ b/src/resources/filters/layout/width.lua @@ -40,12 +40,16 @@ function parseLayoutWidths(figLayout, figureCount) return cols:map(function(width) figureLayoutCount = figureLayoutCount + 1 if type(width) == "number" then - if numericTotal ~= 0 then - width = round((width / numericTotal) * 100, 2) - elseif width <= 1 then - width = round(width * 100, 2) + if _quarto.format.isTypstOutput() then + width = tostring(width) .. "fr" + else + if numericTotal ~= 0 then + width = round((width / numericTotal) * 100, 2) + elseif width <= 1 then + width = round(width * 100, 2) + end + width = tostring(width) .. "%" end - width = tostring(width) .. "%" end -- negative widths are "spacers" so we need to bump our total fig count if isSpacerWidth(width) then @@ -119,6 +123,41 @@ function widthsToPercent(layout, cols) end +-- convert widths to typst fractions +function widthsToFraction(layout, cols) + + -- for each row + for _,row in ipairs(layout) do + + -- initialize widths with 0 or length string + -- currently we assume the width unit is appropriate for the output format + local widths = pandoc.List() + for _,fig in ipairs(row) do + widths[#widths+1] = 0 + local width = attribute(fig, "width", nil) + if width then + widths[#widths] = width + end + end + + -- create virtual fig widths as needed and note the total width + local defaultWidth = "1fr" + for i=1,cols do + if (i > #widths) or widths[i] == 0 then + widths[i] = defaultWidth + end + end + -- allocate widths + for i,fig in ipairs(row) do + local width = widths[i]; + fig.attr.attributes["width"] = width + fig.attr.attributes["height"] = nil + end + + end +end + + -- elements with a percentage width and no height have a 'layout percent' -- which means then should be laid out at a higher level in the tree than -- the individual figure element diff --git a/tests/docs/smoke-all/typst/layout/fraction-layout.qmd b/tests/docs/smoke-all/typst/layout/fraction-layout.qmd new file mode 100644 index 0000000000..71d6ac9eab --- /dev/null +++ b/tests/docs/smoke-all/typst/layout/fraction-layout.qmd @@ -0,0 +1,30 @@ +--- +title: "Fraction layout" +format: + typst: + keep-typ: true +_quarto: + tests: + typst: + ensureTypstFileRegexMatches: + - + ['#grid\((\r\n?|\n)columns: \(1fr, 2fr, 2fr, 1fr, 3fr, 1fr, 1fr\), gutter: 1em, rows: 1,'] +--- + +::: {layout="[1, 2, 2, 1, 3, 1, 1]"} + +![Placeholder]({{< placeholder 200 >}}) + +![Placeholder]({{< placeholder 200 >}}) + +![Placeholder]({{< placeholder 200 >}}) + +![Placeholder]({{< placeholder 200 >}}) + +![Placeholder]({{< placeholder 200 >}}) + +![Placeholder]({{< placeholder 200 >}}) + +![Placeholder]({{< placeholder 200 >}}) + +::: \ No newline at end of file diff --git a/tests/docs/smoke-all/typst/layout/overflowing-callout-7.qmd b/tests/docs/smoke-all/typst/layout/overflowing-callout-7.qmd new file mode 100644 index 0000000000..c10e6526b5 --- /dev/null +++ b/tests/docs/smoke-all/typst/layout/overflowing-callout-7.qmd @@ -0,0 +1,35 @@ +--- +title: Test +format: typst +keep-md: true +keep-typ: true +_quarto: + tests: + typst: + ensureTypstFileRegexMatches: + - + ['#grid\((\r\n?|\n)columns: \(1fr, 1fr, 100pt, 1fr, 1fr, 1fr, 1fr\), gutter: 1em, rows: 1,'] + +--- + +::: {.callout-note} + +## Plots + +::: {layout-ncol=7} + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}){width="100pt"} + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) +::: +::: diff --git a/tests/docs/smoke-all/typst/layout/overflowing-callout.qmd b/tests/docs/smoke-all/typst/layout/overflowing-callout.qmd new file mode 100644 index 0000000000..4283cdcff3 --- /dev/null +++ b/tests/docs/smoke-all/typst/layout/overflowing-callout.qmd @@ -0,0 +1,33 @@ +--- +title: Test +format: typst +keep-md: true +keep-typ: true +_quarto: + tests: + typst: + ensureTypstFileRegexMatches: + - + ['#grid\((\r\n?|\n)columns: \(1fr, 1fr, 1fr, 1fr, 1fr\), gutter: 1em, rows: 1,'] +--- + +::: {.callout-note} + +## Plots + +::: {layout-ncol=5} + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) + +![]({{< placeholder format=svg >}}) +::: + +a) Beschreiben Sie die 5 Verteilungsformen. [5 Punkte] + +::: \ No newline at end of file