diff --git a/news/changelog-1.9.md b/news/changelog-1.9.md index c8facf76c43..0f6d777234a 100644 --- a/news/changelog-1.9.md +++ b/news/changelog-1.9.md @@ -89,6 +89,7 @@ All changes included in 1.9: ### `pdf` - ([#4426](https://github.com/quarto-dev/quarto-cli/issues/4426)): Add `pdf-standard` option for PDF/A, PDF/UA, and PDF version control. Supports standards like `a-2b`, `ua-1`, and versions `1.7`, `2.0`. Works with both LaTeX and Typst formats. +- ([#9091](https://github.com/quarto-dev/quarto-cli/issues/9091)): Fix vertical alignment div has no effect for pdf output - ([#10291](https://github.com/quarto-dev/quarto-cli/issues/10291)): Fix detection of babel hyphenation warnings with straight-quote format instead of backtick-quote format. - ([#13248](https://github.com/quarto-dev/quarto-cli/issues/13248)): Fix image alt text not being passed to LaTeX `\includegraphics[alt={...}]` for PDF accessibility. Markdown image captions and `fig-alt` attributes are now preserved for PDF/UA compliance. - ([#13661](https://github.com/quarto-dev/quarto-cli/issues/13661)): Fix LaTeX compilation errors when using `mermaid-format: svg` with PDF/LaTeX output. SVG diagrams are now written directly without HTML script tags. Note: `mermaid-format: png` is recommended for best compatibility. SVG format requires `rsvg-convert` (or Inkscape with `use-rsvg-convert: false`) in PATH for conversion to PDF, and may experience text clipping in diagrams with multi-line labels. diff --git a/src/resources/filters/layout/latex.lua b/src/resources/filters/layout/latex.lua index 1728c48a4ba..58e4dd9165e 100644 --- a/src/resources/filters/layout/latex.lua +++ b/src/resources/filters/layout/latex.lua @@ -67,9 +67,14 @@ function latexPanel(layout) end local caption = create_latex_caption(layout) - -- read vertical alignment and strip attribute - local vAlign = validatedVAlign(layout.attributes[kLayoutVAlign]) - layout.attributes[kLayoutVAlign] = nil + -- convert valign_class to latex notation, read vertical alignment and strip attribute + local vAlign = "top" + if layout.valign_class ~= nil then + local vAlignClass = layout.valign_class + vAlign = vAlignClass:gsub("quarto%-layout%-valign%-","") + end + + vAlign = validatedVAlign(vAlign) for i, row in ipairs(layout.rows.content) do diff --git a/tests/README.md b/tests/README.md index 090a251247b..ef401eddaad 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,7 +6,7 @@ We run several type of tests - Unit tests, located in `unit/` folder - Integration tests, located in `integration/` folder -- smoke tests localed in `smoke` folder +- smoke tests located in `smoke` folder Tests are run in our CI workflow on GHA at each commit, and for each PR. diff --git a/tests/docs/smoke-all/2023/11/02/7262.qmd b/tests/docs/smoke-all/2023/11/02/7262.qmd index 841c575a53d..a274632cf2e 100644 --- a/tests/docs/smoke-all/2023/11/02/7262.qmd +++ b/tests/docs/smoke-all/2023/11/02/7262.qmd @@ -10,11 +10,11 @@ _quarto: # Verify outer figure environment wraps the layout - '\\begin\{figure\}[\s\S]*\\begin\{minipage\}' # Verify two minipages with equal width - - '\\begin\{minipage\}\{0\.50\\linewidth\}' + - '\\begin\{minipage\}\[b\]\{0\.50\\linewidth\}' # Verify figure[H] inside first minipage with caption and label - - '\\begin\{minipage\}[\s\S]*\\begin\{figure\}\[H\][\s\S]*\\caption\{\\label\{fig-example\}Figure caption\}' + - '\\begin\{minipage\}\[b\][\s\S]*\\begin\{figure\}\[H\][\s\S]*\\caption\{\\label\{fig-example\}Figure caption\}' # Verify longtable (NOT wrapped in table environment) inside second minipage - - '\\begin\{minipage\}\{0\.50\\linewidth\}[\s\S]*\\begin\{longtable\}' + - '\\begin\{minipage\}\[b\]\{0\.50\\linewidth\}[\s\S]*\\begin\{longtable\}' # Verify table caption with label - '\\caption\{\\label\{tbl-example\}Table caption\}' # Verify minipage ends before outer figure ends diff --git a/tests/docs/smoke-all/2024/01/19/8354.qmd b/tests/docs/smoke-all/2024/01/19/8354.qmd index d2c4e1ca252..90d3925a9e3 100644 --- a/tests/docs/smoke-all/2024/01/19/8354.qmd +++ b/tests/docs/smoke-all/2024/01/19/8354.qmd @@ -1,12 +1,16 @@ --- title: "Untitled" -format: latex +format: + pdf: + keep-tex: true execute: warning: false _quarto: tests: - latex: - ensureSnapshotMatches: true + pdf: + ensureLatexFileRegexMatches: + - ['\\begin\{minipage\}\[t\]\{0\.50\\linewidth\}'] + - [] --- ```{r} diff --git a/tests/docs/smoke-all/2024/01/19/8354.tex.snapshot b/tests/docs/smoke-all/2024/01/19/8354.tex.snapshot deleted file mode 100644 index 5ba8345fa2a..00000000000 --- a/tests/docs/smoke-all/2024/01/19/8354.tex.snapshot +++ /dev/null @@ -1,278 +0,0 @@ -% Options for packages loaded elsewhere -% Options for packages loaded elsewhere -\PassOptionsToPackage{unicode}{hyperref} -\PassOptionsToPackage{hyphens}{url} -\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor} -% -\documentclass[ - letterpaper, - DIV=11, - numbers=noendperiod]{scrartcl} -\usepackage{xcolor} -\usepackage{amsmath,amssymb} -\setcounter{secnumdepth}{-\maxdimen} % remove section numbering -\usepackage{iftex} -\ifPDFTeX - \usepackage[T1]{fontenc} - \usepackage[utf8]{inputenc} - \usepackage{textcomp} % provide euro and other symbols -\else % if luatex or xetex - \usepackage{unicode-math} % this also loads fontspec - \defaultfontfeatures{Scale=MatchLowercase} - \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} -\fi -\usepackage{lmodern} -\ifPDFTeX\else - % xetex/luatex font selection -\fi -% Use upquote if available, for straight quotes in verbatim environments -\IfFileExists{upquote.sty}{\usepackage{upquote}}{} -\IfFileExists{microtype.sty}{% use microtype if available - \usepackage[]{microtype} - \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts -}{} -\makeatletter -\@ifundefined{KOMAClassName}{% if non-KOMA class - \IfFileExists{parskip.sty}{% - \usepackage{parskip} - }{% else - \setlength{\parindent}{0pt} - \setlength{\parskip}{6pt plus 2pt minus 1pt}} -}{% if KOMA class - \KOMAoptions{parskip=half}} -\makeatother -% Make \paragraph and \subparagraph free-standing -\makeatletter -\ifx\paragraph\undefined\else - \let\oldparagraph\paragraph - \renewcommand{\paragraph}{ - \@ifstar - \xxxParagraphStar - \xxxParagraphNoStar - } - \newcommand{\xxxParagraphStar}[1]{\oldparagraph*{#1}\mbox{}} - \newcommand{\xxxParagraphNoStar}[1]{\oldparagraph{#1}\mbox{}} -\fi -\ifx\subparagraph\undefined\else - \let\oldsubparagraph\subparagraph - \renewcommand{\subparagraph}{ - \@ifstar - \xxxSubParagraphStar - \xxxSubParagraphNoStar - } - \newcommand{\xxxSubParagraphStar}[1]{\oldsubparagraph*{#1}\mbox{}} - \newcommand{\xxxSubParagraphNoStar}[1]{\oldsubparagraph{#1}\mbox{}} -\fi -\makeatother - -\usepackage{color} -\usepackage{fancyvrb} -\newcommand{\VerbBar}{|} -\newcommand{\VERB}{\Verb[commandchars=\\\{\}]} -\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} -% Add ',fontsize=\small' for more characters per line -\usepackage{framed} -\definecolor{shadecolor}{RGB}{241,243,245} -\newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}} -\newcommand{\AlertTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} -\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} -\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.40,0.45,0.13}{#1}} -\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} -\newcommand{\BuiltInTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} -\newcommand{\CharTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} -\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} -\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}} -\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}} -\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{\textbf{#1}}} -\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} -\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} -\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}} -\newcommand{\ErrorTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} -\newcommand{\ExtensionTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} -\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} -\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.28,0.35,0.67}{#1}} -\newcommand{\ImportTok}[1]{\textcolor[rgb]{0.00,0.46,0.62}{#1}} -\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} -\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{\textbf{#1}}} -\newcommand{\NormalTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} -\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} -\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} -\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.68,0.00,0.00}{#1}} -\newcommand{\RegionMarkerTok}[1]{\textcolor[rgb]{0.00,0.23,0.31}{#1}} -\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{#1}} -\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} -\newcommand{\StringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} -\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.07,0.07,0.07}{#1}} -\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.13,0.47,0.30}{#1}} -\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.37,0.37,0.37}{\textit{#1}}} - -\usepackage{longtable,booktabs,array} -\newcounter{none} % for unnumbered tables -\usepackage{calc} % for calculating minipage widths -% Correct order of tables after \paragraph or \subparagraph -\usepackage{etoolbox} -\makeatletter -\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} -\makeatother -% Allow footnotes in longtable head/foot -\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} -\makesavenoteenv{longtable} -\usepackage{graphicx} -\makeatletter -\newsavebox\pandoc@box -\newcommand*\pandocbounded[1]{% scales image to fit in text height/width - \sbox\pandoc@box{#1}% - \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}% - \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}% - \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both - \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}% - \else\usebox{\pandoc@box}% - \fi% -} -% Set default figure placement to htbp -\def\fps@figure{htbp} -\makeatother - - - - - -\setlength{\emergencystretch}{3em} % prevent overfull lines - -\providecommand{\tightlist}{% - \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} - - - - - - -\KOMAoption{captions}{tableheading} -\makeatletter -\@ifpackageloaded{caption}{}{\usepackage{caption}} -\AtBeginDocument{% -\ifdefined\contentsname - \renewcommand*\contentsname{Table of contents} -\else - \newcommand\contentsname{Table of contents} -\fi -\ifdefined\listfigurename - \renewcommand*\listfigurename{List of Figures} -\else - \newcommand\listfigurename{List of Figures} -\fi -\ifdefined\listtablename - \renewcommand*\listtablename{List of Tables} -\else - \newcommand\listtablename{List of Tables} -\fi -\ifdefined\figurename - \renewcommand*\figurename{Figure} -\else - \newcommand\figurename{Figure} -\fi -\ifdefined\tablename - \renewcommand*\tablename{Table} -\else - \newcommand\tablename{Table} -\fi -} -\@ifpackageloaded{float}{}{\usepackage{float}} -\floatstyle{ruled} -\@ifundefined{c@chapter}{\newfloat{codelisting}{h}{lop}}{\newfloat{codelisting}{h}{lop}[chapter]} -\floatname{codelisting}{Listing} -\newcommand*\listoflistings{\listof{codelisting}{List of Listings}} -\makeatother -\makeatletter -\makeatother -\makeatletter -\@ifpackageloaded{caption}{}{\usepackage{caption}} -\@ifpackageloaded{subcaption}{}{\usepackage{subcaption}} -\makeatother -\usepackage{bookmark} -\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available -\urlstyle{same} -\hypersetup{ - pdftitle={Untitled}, - colorlinks=true, - linkcolor={blue}, - filecolor={Maroon}, - citecolor={Blue}, - urlcolor={Blue}, - pdfcreator={LaTeX via pandoc}} - - -\title{Untitled} -\author{} -\date{} -\begin{document} -\maketitle - - -\begin{Shaded} -\begin{Highlighting}[] -\FunctionTok{library}\NormalTok{(knitr)} -\FunctionTok{kable}\NormalTok{(}\FunctionTok{head}\NormalTok{(cars))} -\FunctionTok{kable}\NormalTok{(}\FunctionTok{head}\NormalTok{(pressure))} -\end{Highlighting} -\end{Shaded} - -\begin{table} - -\caption{\label{tbl-tables}Tables} - -\begin{minipage}{0.50\linewidth} - -\subcaption{\label{tbl-tables-1}cars} - -\centering{ - -\begin{tabular}{rr} -\toprule -speed & dist\\ -\midrule -4 & 2\\ -4 & 10\\ -7 & 4\\ -7 & 22\\ -8 & 16\\ -9 & 10\\ -\bottomrule -\end{tabular} - -} - -\end{minipage}% -% -\begin{minipage}{0.50\linewidth} - -\subcaption{\label{tbl-tables-2}pressure} - -\centering{ - -\begin{tabular}{rr} -\toprule -temperature & pressure\\ -\midrule -0 & 0.0002\\ -20 & 0.0012\\ -40 & 0.0060\\ -60 & 0.0300\\ -80 & 0.0900\\ -100 & 0.2700\\ -\bottomrule -\end{tabular} - -} - -\end{minipage}% - -\end{table}% - -See Table~\ref{tbl-tables} for examples. In particular, -Table~\ref{tbl-tables-2}. - - - - -\end{document} diff --git a/tests/docs/smoke-all/2025/11/08/9109-center.qmd b/tests/docs/smoke-all/2025/11/08/9109-center.qmd new file mode 100644 index 00000000000..189c3a9689b --- /dev/null +++ b/tests/docs/smoke-all/2025/11/08/9109-center.qmd @@ -0,0 +1,30 @@ +--- +title: "Untitled" +format: + pdf: + keep-tex: true +execute: + warning: false +_quarto: + tests: + pdf: + ensureLatexFileRegexMatches: + - ['\\begin\{minipage\}\[c\]\{0\.50\\linewidth\}'] + - [] +--- + +```{r} +#| label: tbl-tables +#| tbl-cap: "Tables" +#| tbl-subcap: +#| - cars +#| - pressure +#| layout-ncol: 2 +#| layout-valign: center + +library(knitr) +kable(head(cars)) +kable(head(pressure)) +``` + +See @tbl-tables for examples. In particular, @tbl-tables-2. diff --git a/tests/docs/smoke-all/2025/11/08/9109-markdown.qmd b/tests/docs/smoke-all/2025/11/08/9109-markdown.qmd new file mode 100644 index 00000000000..29c24ee5ce2 --- /dev/null +++ b/tests/docs/smoke-all/2025/11/08/9109-markdown.qmd @@ -0,0 +1,19 @@ +--- +format: + pdf: + keep-tex: true +_quarto: + tests: + pdf: + ensureLatexFileRegexMatches: + - ['\\begin\{minipage\}\[t\]'] + - [] +--- + +::: {layout="[40, -2, 40]" layout-valign="top"} + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit + +::: diff --git a/tests/docs/smoke-all/2025/11/08/9109.qmd b/tests/docs/smoke-all/2025/11/08/9109.qmd new file mode 100644 index 00000000000..ecdc43d249f --- /dev/null +++ b/tests/docs/smoke-all/2025/11/08/9109.qmd @@ -0,0 +1,30 @@ +--- +title: "Untitled" +format: + pdf: + keep-tex: true +execute: + warning: false +_quarto: + tests: + pdf: + ensureLatexFileRegexMatches: + - ['\\begin\{minipage\}\[b\]\{0\.50\\linewidth\}'] + - [] +--- + +```{r} +#| label: tbl-tables +#| tbl-cap: "Tables" +#| tbl-subcap: +#| - cars +#| - pressure +#| layout-ncol: 2 +#| layout-valign: bottom + +library(knitr) +kable(head(cars)) +kable(head(pressure)) +``` + +See @tbl-tables for examples. In particular, @tbl-tables-2.