Skip to content
Open
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
Binary file added tests/docs/smoke-all/docx/figure-captions/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 71 additions & 0 deletions tests/docs/smoke-all/docx/figure-captions/jupyter.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: DOCX figure captions and alt text (Jupyter)
format: docx
jupyter: python3
_quarto:
tests:
docx:
ensureDocxXpath:
-
# cross-referenced cell
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a01: J1 caption']"
# unlabelled cell with fig-cap
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='J2 caption']"
# fig-subcap with layout-ncol: both subcaptions and the panel caption
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='(a) J4a sub caption']"
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='(b) J4b sub caption']"
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a02: J4 caption']"
# cross-referenced cell without fig-alt
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a03: J5 caption']"
# descr of a cross-referenced cell without fig-alt is empty
- "//w:tbl[.//w:t[contains(., 'J5 caption')]]//wp:docPr[@descr='']"
-
# alt text never becomes visible text
- "//w:t[contains(., 'ALT-ONLY')]"
- "//w:tbl[.//w:t[contains(., 'J5 caption')]]//wp:docPr[@descr!='']"
---

Pins how figure captions and alt text from Jupyter cells render in DOCX.
Visible captions must stay unchanged whatever the filter pipeline does with alt text, and every alt value carries a marker that must never appear in the document text.
The image description (`descr`) is checked only for the cell without `fig-alt`.

```{python}
#| label: fig-j1
#| fig-cap: "J1 caption"
#| fig-alt: "J1 ALT-ONLY"
import matplotlib.pyplot as plt
plt.plot([1, 2])
plt.show()
```

```{python}
#| fig-cap: "J2 caption"
#| fig-alt: "J2 ALT-ONLY"
plt.plot([1, 2])
plt.show()
```

```{python}
#| fig-alt: "J3 ALT-ONLY"
plt.plot([1, 2])
plt.show()
```

```{python}
#| label: fig-j4
#| fig-cap: "J4 caption"
#| fig-subcap: ["J4a sub caption", "J4b sub caption"]
#| fig-alt: ["J4a ALT-ONLY", "J4b ALT-ONLY"]
#| layout-ncol: 2
plt.plot([1, 2])
plt.show()
plt.plot([2, 1])
plt.show()
```

```{python}
#| label: fig-j5
#| fig-cap: "J5 caption"
plt.plot([1, 2])
plt.show()
```
64 changes: 64 additions & 0 deletions tests/docs/smoke-all/docx/figure-captions/knitr.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: DOCX figure captions and alt text (knitr)
format: docx
engine: knitr
_quarto:
tests:
docx:
ensureDocxXpath:
-
# cross-referenced cell
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a01: K1 caption']"
# unlabelled cell with fig-cap
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='K2 caption']"
# fig-subcap with layout-ncol: both subcaptions and the panel caption
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='(a) K4a sub caption']"
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='(b) K4b sub caption']"
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a02: K4 caption']"
# cross-referenced cell without fig-alt
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a03: K5 caption']"
# descr of a cross-referenced cell without fig-alt is empty
- "//w:tbl[.//w:t[contains(., 'K5 caption')]]//wp:docPr[@descr='']"
-
# alt text never becomes visible text
- "//w:t[contains(., 'ALT-ONLY')]"
- "//w:tbl[.//w:t[contains(., 'K5 caption')]]//wp:docPr[@descr!='']"
---

Pins how figure captions and alt text from knitr cells render in DOCX.
Visible captions must stay unchanged whatever the filter pipeline does with alt text, and every alt value carries a marker that must never appear in the document text.
The image description (`descr`) is checked only for the cell without `fig-alt`.

```{r}
#| label: fig-k1
#| fig-cap: "K1 caption"
#| fig-alt: "K1 ALT-ONLY"
plot(1)
```

```{r}
#| fig-cap: "K2 caption"
#| fig-alt: "K2 ALT-ONLY"
plot(2)
```

```{r}
#| fig-alt: "K3 ALT-ONLY"
plot(3)
```

```{r}
#| label: fig-k4
#| fig-cap: "K4 caption"
#| fig-subcap: ["K4a sub caption", "K4b sub caption"]
#| fig-alt: ["K4a ALT-ONLY", "K4b ALT-ONLY"]
#| layout-ncol: 2
plot(4)
plot(5)
```

```{r}
#| label: fig-k5
#| fig-cap: "K5 caption"
plot(6)
```
94 changes: 94 additions & 0 deletions tests/docs/smoke-all/docx/figure-captions/markdown.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: DOCX figure captions and alt text (markdown)
format: docx
_quarto:
tests:
docx:
ensureDocxXpath:
-
# plain figure
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C03 plain caption']"
# cross-referenced figure
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a01: C04 xref caption']"
# subfigure panel: both subcaptions and the panel caption
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='(a) C05a sub caption']"
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='(b) C05b sub caption']"
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a02: C05 panel caption']"
# div float with fig-alt on the div
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='Figure\u00a03: C06 div caption']"
# non-crossref layout-ncol
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C07a layout caption']"
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C07b layout caption']"
# empty fig-alt
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C08 empty alt caption']"
# linked image
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C09 linked caption']"
# fig-alt with markdown and XML special characters
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C11 special caption']"
# cross-referenced figure with a rich caption keeps its emphasis
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][starts-with(string-join(.//w:t, ''), 'Figure\u00a04: C12 rich caption')][.//w:r[w:rPr/w:i]/w:t='rich']"
# image in a callout
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C13 callout caption']"
# both fig-alt and alt
- "//w:p[w:pPr/w:pStyle/@w:val='ImageCaption'][string-join(.//w:t, '')='C14 both caption']"
# descr of images without fig-alt: plain figure uses its caption, cross-ref figure is empty
- "//wp:docPr[@descr='C03 plain caption']"
- "//w:tbl[.//w:t[contains(., 'C04 xref caption')]]//wp:docPr[@descr='']"
# descr of the callout icon is empty
- "//w:tbl[.//w:t[.='Note']]//wp:docPr[@descr='']"
-
# alt text never becomes visible text
- "//w:t[contains(., 'ALT-ONLY')]"
- "//w:tbl[.//w:t[contains(., 'C04 xref caption')]]//wp:docPr[@descr!='']"
---

Pins how figure captions and alt text render in DOCX for every way an image can reach the document.
Visible captions must stay unchanged whatever the filter pipeline does with alt text, and every alt value carries a marker that must never appear in the document text.
The image description (`descr`) is checked only for images without `fig-alt`.

C01 inline image: text ![C01 inline caption](image.png){fig-alt="C01 ALT-ONLY"} text.

C02 inline image with alt attribute: text ![C02 inline caption](image.png){alt="C02 ALT-ONLY"} text.

![C03 plain caption](image.png)

![C04 xref caption](image.png){#fig-c04}

::: {#fig-c05 layout-ncol=2}

![C05a sub caption](image.png){#fig-c05a fig-alt="C05a ALT-ONLY"}

![C05b sub caption](image.png){#fig-c05b}

C05 panel caption
:::

::: {#fig-c06 fig-alt="C06 ALT-ONLY"}
![](image.png)

C06 div caption
:::

::: {layout-ncol=2}
![C07a layout caption](image.png){fig-alt="C07a ALT-ONLY"}

![C07b layout caption](image.png)
:::

![C08 empty alt caption](image.png){fig-alt=""}

[![C09 linked caption](image.png){fig-alt="C09 ALT-ONLY"}](https://quarto.org)

| col |
|-----|
| ![C10 table caption](image.png){fig-alt="C10 ALT-ONLY"} |

![C11 special caption](image.png){fig-alt="C11 ALT-ONLY a *b* <c> & d"}

![C12 *rich* caption $x^2$](image.png){#fig-c12 fig-alt="C12 ALT-ONLY"}

::: callout-note
![C13 callout caption](image.png){fig-alt="C13 ALT-ONLY"}
:::

![C14 both caption](image.png){fig-alt="C14 ALT-ONLY fig-alt" alt="C14 ALT-ONLY alt"}
Loading