From c70aa1f8119dbb035678e55899a12bb9c9e08b57 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 27 Sep 2024 12:05:05 +0200 Subject: [PATCH 01/10] Revert removing `.table` class from table in our test suites This reverts part of commit dd6717fd07353f7de22eaff386669f40a7944210. The `.table` is set by quarto itself and its removal in html output is a sign that something has changed and it is not set correctly anymore. We restore original test to correctly fix this. --- .../raw-blocks/interpreted/pandoc-native/document.qmd | 2 +- src/resources/formats/html/_quarto-rules.scss | 3 ++- src/resources/formats/revealjs/quarto.scss | 2 +- tests/docs/smoke-all/2023/10/10/issue-7187-b.qmd | 2 +- tests/docs/smoke-all/2023/10/10/issue-7187.qmd | 2 +- .../crossrefs/float/html/html-knitr-table-captions-1.qmd | 4 ++-- .../float/revealjs/revealjs-knitr-table-captions-1.qmd | 4 ++-- .../crossrefs/float/typst/typst-knitr-table-captions-1.qmd | 4 ++-- 8 files changed, 12 insertions(+), 11 deletions(-) diff --git a/dev-docs/feature-format-matrix/qmd-files/raw-blocks/interpreted/pandoc-native/document.qmd b/dev-docs/feature-format-matrix/qmd-files/raw-blocks/interpreted/pandoc-native/document.qmd index 24fbcfc9c5..116689039d 100644 --- a/dev-docs/feature-format-matrix/qmd-files/raw-blocks/interpreted/pandoc-native/document.qmd +++ b/dev-docs/feature-format-matrix/qmd-files/raw-blocks/interpreted/pandoc-native/document.qmd @@ -25,7 +25,7 @@ _quarto: html: ensureHtmlElements: - - - 'table' + - 'table.table' - [] typst: ensureTypstFileRegexMatches: diff --git a/src/resources/formats/html/_quarto-rules.scss b/src/resources/formats/html/_quarto-rules.scss index 66ade8da29..0c86d213e8 100644 --- a/src/resources/formats/html/_quarto-rules.scss +++ b/src/resources/formats/html/_quarto-rules.scss @@ -227,7 +227,8 @@ tr.header > th > p:last-of-type { margin-bottom: 0px; } -table { +table, +table.table { margin-top: 0.5rem; margin-bottom: 0.5rem; } diff --git a/src/resources/formats/revealjs/quarto.scss b/src/resources/formats/revealjs/quarto.scss index 0af437a67a..1a3b6bddc6 100644 --- a/src/resources/formats/revealjs/quarto.scss +++ b/src/resources/formats/revealjs/quarto.scss @@ -669,7 +669,7 @@ $panel-sidebar-padding: 0.5em; // https://github.com/quarto-dev/quarto-cli/issues/3380 -div.cell-output-display div.pagedtable-wrapper table { +div.cell-output-display div.pagedtable-wrapper table.table { font-size: 0.6em; } diff --git a/tests/docs/smoke-all/2023/10/10/issue-7187-b.qmd b/tests/docs/smoke-all/2023/10/10/issue-7187-b.qmd index aa4705aff9..cbff39bb0f 100644 --- a/tests/docs/smoke-all/2023/10/10/issue-7187-b.qmd +++ b/tests/docs/smoke-all/2023/10/10/issue-7187-b.qmd @@ -5,7 +5,7 @@ _quarto: html: ensureHtmlElements: - [] - - ["div[data-html-table-processing]"] + - ["table.table", "div[data-html-table-processing]"] --- ::: {html-table-processing="none"} diff --git a/tests/docs/smoke-all/2023/10/10/issue-7187.qmd b/tests/docs/smoke-all/2023/10/10/issue-7187.qmd index fc15f93162..61cdd1c89c 100644 --- a/tests/docs/smoke-all/2023/10/10/issue-7187.qmd +++ b/tests/docs/smoke-all/2023/10/10/issue-7187.qmd @@ -6,7 +6,7 @@ _quarto: html: ensureHtmlElements: - [] - - ["table[data-quarto-postprocess='true']"] + - ["table.table"] --- diff --git a/tests/docs/smoke-all/crossrefs/float/html/html-knitr-table-captions-1.qmd b/tests/docs/smoke-all/crossrefs/float/html/html-knitr-table-captions-1.qmd index e96736f436..adb6b32544 100644 --- a/tests/docs/smoke-all/crossrefs/float/html/html-knitr-table-captions-1.qmd +++ b/tests/docs/smoke-all/crossrefs/float/html/html-knitr-table-captions-1.qmd @@ -5,9 +5,9 @@ _quarto: html: ensureHtmlElements: - - - "figure.quarto-float-tbl div#tbl-cars figure.quarto-subfloat-tbl table" + - "figure.quarto-float-tbl div#tbl-cars figure.quarto-subfloat-tbl table.table" - "figure.quarto-float-tbl div#tbl-cars figure.quarto-subfloat-tbl figcaption.quarto-subfloat-caption" - - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-subfloat-tbl table" + - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-subfloat-tbl table.table" - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-subfloat-tbl figcaption.quarto-subfloat-caption" - "div#tbl-tables > figure.quarto-float-tbl > figcaption.quarto-float-caption" - [] diff --git a/tests/docs/smoke-all/crossrefs/float/revealjs/revealjs-knitr-table-captions-1.qmd b/tests/docs/smoke-all/crossrefs/float/revealjs/revealjs-knitr-table-captions-1.qmd index 29cb0a1e57..696aa80a43 100644 --- a/tests/docs/smoke-all/crossrefs/float/revealjs/revealjs-knitr-table-captions-1.qmd +++ b/tests/docs/smoke-all/crossrefs/float/revealjs/revealjs-knitr-table-captions-1.qmd @@ -5,9 +5,9 @@ title: Knitr Table Test # revealjs: # ensureHtmlElements: # - -# - "figure.quarto-float-tbl div#tbl-cars figure.quarto-float-tbl table" +# - "figure.quarto-float-tbl div#tbl-cars figure.quarto-float-tbl table.table" # - "figure.quarto-float-tbl div#tbl-cars figure.quarto-float-tbl figcaption.quarto-subfloat-caption" -# - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-float-tbl table" +# - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-float-tbl table.table" # - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-float-tbl figcaption.quarto-subfloat-caption" # - "div#tbl-tables > figure.quarto-float-tbl > figcaption.quarto-float-caption" # - [] diff --git a/tests/docs/smoke-all/crossrefs/float/typst/typst-knitr-table-captions-1.qmd b/tests/docs/smoke-all/crossrefs/float/typst/typst-knitr-table-captions-1.qmd index 0358d0e746..7cbc4b1902 100644 --- a/tests/docs/smoke-all/crossrefs/float/typst/typst-knitr-table-captions-1.qmd +++ b/tests/docs/smoke-all/crossrefs/float/typst/typst-knitr-table-captions-1.qmd @@ -6,9 +6,9 @@ format: typst # html: # ensureHtmlElements: # - -# - "figure.quarto-float-tbl div#tbl-cars figure.quarto-float-tbl table" +# - "figure.quarto-float-tbl div#tbl-cars figure.quarto-float-tbl table.table" # - "figure.quarto-float-tbl div#tbl-cars figure.quarto-float-tbl figcaption.quarto-subfloat-caption" -# - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-float-tbl table" +# - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-float-tbl table.table" # - "figure.quarto-float-tbl div#tbl-pressure figure.quarto-float-tbl figcaption.quarto-subfloat-caption" # - "div#tbl-tables > figure.quarto-float-tbl > figcaption.quarto-float-caption" # - [] From 83bb6bd4250b0afd2fa65c4a10c128fa4d6235d0 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 27 Sep 2024 14:37:30 +0200 Subject: [PATCH 02/10] add back odd, even, header classes from older pandoc in normalize processing --- src/resources/filters/main.lua | 1 + .../filters/normalize/astpipeline.lua | 3 +++ .../filters/normalize/pandoc-tables.lua | 26 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 src/resources/filters/normalize/pandoc-tables.lua diff --git a/src/resources/filters/main.lua b/src/resources/filters/main.lua index c39fa2d4b2..5fe1f65828 100644 --- a/src/resources/filters/main.lua +++ b/src/resources/filters/main.lua @@ -98,6 +98,7 @@ import("./quarto-finalize/typst.lua") import("./normalize/flags.lua") import("./normalize/normalize.lua") +import("./normalize/pandoc-tables.lua") import("./normalize/parsehtml.lua") import("./normalize/extractquartodom.lua") import("./normalize/astpipeline.lua") diff --git a/src/resources/filters/normalize/astpipeline.lua b/src/resources/filters/normalize/astpipeline.lua index 8777c5e307..5008f77130 100644 --- a/src/resources/filters/normalize/astpipeline.lua +++ b/src/resources/filters/normalize/astpipeline.lua @@ -22,6 +22,9 @@ function quarto_ast_pipeline() } end return { + -- identify pandoc table + { name = "normalize-pandoc-table", filter = pandoc_tables() }, + { name = "normalize-table-merge-raw-html", filter = table_merge_raw_html() }, -- this filter can't be combined with others because it's top-down processing. diff --git a/src/resources/filters/normalize/pandoc-tables.lua b/src/resources/filters/normalize/pandoc-tables.lua new file mode 100644 index 0000000000..370f898a07 --- /dev/null +++ b/src/resources/filters/normalize/pandoc-tables.lua @@ -0,0 +1,26 @@ +-- pandoc-tables.lua +-- Copyright (C) 2024 Posit Software, PBC + +-- Add back classes 'odd', (or 'header' in table header) / 'even' to table rows +-- They were removed in pandoc 3.2.1 but are useful for styling pandoc processed tables +-- Quarto detects .odd class +function pandoc_tables() + local function add_odd_even (rows, odd) + odd = odd or 'odd' + for rownum, row in ipairs(rows) do + row.classes:insert((rownum % 2) == 0 and 'even' or odd) + end + return rows + end + + return { + Table = function (tbl) + add_odd_even(tbl.head.rows, 'header') + for _, tblbody in ipairs(tbl.bodies) do + add_odd_even(tblbody.body) + end + add_odd_even(tbl.foot.rows) + return tbl + end + } +end \ No newline at end of file From f35ab2b72745d573985fffdc0695bb9be4e75fdd Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 27 Sep 2024 15:35:22 +0200 Subject: [PATCH 03/10] Add a test for this default style quarto applies --- tests/docs/playwright/html/.gitignore | 2 ++ .../docs/playwright/html/markdown-tables.qmd | 32 +++++++++++++++++++ .../playwright/tests/html-tables.spec.ts | 21 ++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 tests/docs/playwright/html/.gitignore create mode 100644 tests/docs/playwright/html/markdown-tables.qmd create mode 100644 tests/integration/playwright/tests/html-tables.spec.ts diff --git a/tests/docs/playwright/html/.gitignore b/tests/docs/playwright/html/.gitignore new file mode 100644 index 0000000000..2cca5373e9 --- /dev/null +++ b/tests/docs/playwright/html/.gitignore @@ -0,0 +1,2 @@ +*_files/ +*.html \ No newline at end of file diff --git a/tests/docs/playwright/html/markdown-tables.qmd b/tests/docs/playwright/html/markdown-tables.qmd new file mode 100644 index 0000000000..884a7e086a --- /dev/null +++ b/tests/docs/playwright/html/markdown-tables.qmd @@ -0,0 +1,32 @@ +--- +title: Markdown Tables +--- + +They should be styled by Quarto + +| Col1 | Col2 | Col3 | +|------|------|------| +| A | B | C | +| E | F | G | +| A | G | G | + +: My Caption {#tbl-letters} + +See @tbl-letters. + +## Computational table + + + +:::: cell +::: cell-output-display +| Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species | +|-------------:|------------:|-------------:|------------:|:--------| +| 5.1 | 3.5 | 1.4 | 0.2 | setosa | +| 4.9 | 3.0 | 1.4 | 0.2 | setosa | +| 4.7 | 3.2 | 1.3 | 0.2 | setosa | +| 4.6 | 3.1 | 1.5 | 0.2 | setosa | +| 5.0 | 3.6 | 1.4 | 0.2 | setosa | +| 5.4 | 3.9 | 1.7 | 0.4 | setosa | +::: +:::: \ No newline at end of file diff --git a/tests/integration/playwright/tests/html-tables.spec.ts b/tests/integration/playwright/tests/html-tables.spec.ts new file mode 100644 index 0000000000..2a9248b17f --- /dev/null +++ b/tests/integration/playwright/tests/html-tables.spec.ts @@ -0,0 +1,21 @@ +import { test, expect } from '@playwright/test'; + +test('Markdown tables are styled correct', async ({ page }) => { +await page.goto('html/markdown-tables.html'); +await expect(page.getByRole('figure', { name: 'Table 1: My Caption' })).toBeVisible(); +await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-top-style', 'solid') +await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-top-width', '1px') +await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-bottom-style', 'solid') +await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-bottom-width', '1px') +await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table tr').nth(1)).toHaveCSS('border-style', 'solid') +await expect(page.locator('a.quarto-xref[href="#tbl-letters"]')).toContainText('Table 1'); + +await expect(page.locator('#computational-table table')).toBeVisible(); +await expect(page.locator('#computational-table table')).toHaveCSS('border-top-style', 'solid') +await expect(page.locator('#computational-table table')).toHaveCSS('border-top-width', '1px') +await expect(page.locator('#computational-table table')).toHaveCSS('border-bottom-style', 'solid') +await expect(page.locator('#computational-table table')).toHaveCSS('border-bottom-width', '1px') +await expect(page.locator('#computational-table table')).toHaveCSS('border-style', /solid/) +await expect(page.locator('#computational-table table').locator('td').nth(1)).toHaveCSS('box-shadow', /rgba\(0, 0, 0, 0\.05/) + +}); \ No newline at end of file From 342381b908aafd539612be666c3a0d8dd82a5872 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 27 Sep 2024 15:50:26 +0200 Subject: [PATCH 04/10] Use screenshot test instead --- .../playwright/playwright.config.ts | 1 + .../Markdown-tables-are-styled-correctly-1.png | Bin 0 -> 1509 bytes .../Markdown-tables-are-styled-correctly-2.png | Bin 0 -> 5382 bytes .../playwright/tests/html-tables.spec.ts | 17 +++-------------- 4 files changed, 4 insertions(+), 14 deletions(-) create mode 100644 tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-1.png create mode 100644 tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-2.png diff --git a/tests/integration/playwright/playwright.config.ts b/tests/integration/playwright/playwright.config.ts index 897dbcf25f..5314c08c88 100644 --- a/tests/integration/playwright/playwright.config.ts +++ b/tests/integration/playwright/playwright.config.ts @@ -12,6 +12,7 @@ import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ /* Look for test files in the "tests" directory, relative to this configuration file. */ testDir: "./tests", + snapshotPathTemplate: "{testDir}/__screenshots__/{testFilePath}/{arg}{ext}", /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { diff --git a/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-1.png b/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f802314b27e8bdcb1eaa350b994be06a7d195f68 GIT binary patch literal 1509 zcmah}do+}37@vmLtjIV~Zt+bum{_HTSmAS9#xhA|kXs|lmd!08w+{^wMi<){Mq6k# z8bs?-={ClcYlhG?5@VQImzdop?0!47oi6*&p7Xx%^ZefPzUMs8`Tc&+Sr4MKvZ9tE z0)bE_xHx(u5ORPluR+Pl&IiC!hAga#_H?#Ku)1`_G7#k9w%-YZ#bK}^7%T-t4#ALF zn2er4EG`fm5{RV)l39T=cvF&w#ify1X|kkSwqSZWi%G^Y$stS$+?9dr%Ajr-4)u1OPM|g_4&?B3D7FAVRi5 zpvMtdJ~^4F`vk4a$hF5)YQlC>7s4+mCf`xzM$C=r>)SOJE8wVMyX_ap%F7D|tvLnW z{tD+su9XFbYFw&*>rHSJxUJ?Q8Tk&7D)#nzorg#Bp$>tX)>)4m`Hh>V;1x7CPT($= z#MU%TLiB0zAFbep}~j>#Ww44b~f8vE6u;Gq!3)gWJ=m zddy;DQ|3#~M1#H@A?0mk|I|F*C-iYEk>BNMs^VIt84Wl*%&dI`3AIMg9kr%5W!E1O zf}BFevu-4f=^}lt=2A)6yOrAS1Oz{ZjCo{l2D=cXR1D7(^_FjGbsTWBog_L}NewQ- zDFAN=&35VeDe7W2`Q&K@oH_RCJ=WyR6d(mJ(bRwLtLIk7Yo~lgm^~&MxJ&8=I+JRF zmN$$*X@G6|N*rOV&l70B!@TJ9_cjkYWPIXyMSPDQyl1_fPx7$YZLbcwh=kHz3}rXk zY;nd_DcNjRUmDvR3dGlDZQgFeyV41YDr*%x$SkUG z_~kG@Az%C!BM9*AH}SOtf}4>;*TQVb$|`x@$fh_)l{PEh>Zlr;*B|Es?11>~3C=k> z+@LMP4Z6M6p{<8vZq=k0=Lz~dD5H>ZPHXb?xp7S)UQNuM);q)VRW;vWMc~&xBDoU{ zW-TCA-DLfINeVBtW_x>z$6@r+G?Zm%HfAkTd;7H#EH z4owZ1-Q}xgff8$SE>blMw9%59?gNmjT;*9l@m=&^KIs~a<{paA85iV&Cb|y24L?5J zR?iuc!+L%U_lP1mo^6B42YAs>iF0PhX?(IXnymD_S`u0>?WROkt zKwW?r+9mt3@G{Z6i}uGi>gw|6iR<$=SW*}NtavL8RXluu?L%vEWI!2-{&2pjitZqV zj5lvr++so#&s|%%Y$Fr{)VbF_0EtJ|yg->AFoJ~poD8VUTJKQj_Sk%!GF^<<_S8xT zE4Go2o2Y1n+fvxqO;3jvuf3Eg=KQ2?_vJkMBz2Vh4JDy^*9IYs74T+ Lh>k4#ptOGgE1#U9 literal 0 HcmV?d00001 diff --git a/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-2.png b/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-2.png new file mode 100644 index 0000000000000000000000000000000000000000..3dcb971e269e847a6078c9452285872a2b8be6f5 GIT binary patch literal 5382 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 uo(LI>zl-)?l%1a-B!rEPjatIw { +test('Markdown tables are styled correctly', async ({ page }) => { await page.goto('html/markdown-tables.html'); -await expect(page.getByRole('figure', { name: 'Table 1: My Caption' })).toBeVisible(); -await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-top-style', 'solid') -await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-top-width', '1px') -await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-bottom-style', 'solid') -await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveCSS('border-bottom-width', '1px') -await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table tr').nth(1)).toHaveCSS('border-style', 'solid') +await expect(page.getByRole('figure', { name: 'Table 1: My Caption' }).locator('table')).toHaveScreenshot() await expect(page.locator('a.quarto-xref[href="#tbl-letters"]')).toContainText('Table 1'); -await expect(page.locator('#computational-table table')).toBeVisible(); -await expect(page.locator('#computational-table table')).toHaveCSS('border-top-style', 'solid') -await expect(page.locator('#computational-table table')).toHaveCSS('border-top-width', '1px') -await expect(page.locator('#computational-table table')).toHaveCSS('border-bottom-style', 'solid') -await expect(page.locator('#computational-table table')).toHaveCSS('border-bottom-width', '1px') -await expect(page.locator('#computational-table table')).toHaveCSS('border-style', /solid/) -await expect(page.locator('#computational-table table').locator('td').nth(1)).toHaveCSS('box-shadow', /rgba\(0, 0, 0, 0\.05/) +await expect(page.locator('#computational-table table')).toHaveScreenshot() }); \ No newline at end of file From 268561ceeddae957ac83a8f3902a8b9016e3613b Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 30 Sep 2024 10:16:28 +0200 Subject: [PATCH 05/10] Add missing import in crossref filter It has its own loading different than main.lua one. --- src/resources/filters/crossref/crossref.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/src/resources/filters/crossref/crossref.lua b/src/resources/filters/crossref/crossref.lua index 85973ae565..14113ae216 100644 --- a/src/resources/filters/crossref/crossref.lua +++ b/src/resources/filters/crossref/crossref.lua @@ -61,6 +61,7 @@ import("../quarto-init/resourcerefs.lua") import("../normalize/flags.lua") import("../normalize/normalize.lua") +import("../normalize/pandoc-tables.lua") import("../normalize/parsehtml.lua") import("../normalize/extractquartodom.lua") import("../normalize/astpipeline.lua") From cce4a107bd47bb9ae7492c8fc7502d5ae8d559f3 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 30 Sep 2024 10:30:58 +0200 Subject: [PATCH 06/10] tests, playwright - Add built in github CI reporter --- tests/integration/playwright/playwright.config.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/integration/playwright/playwright.config.ts b/tests/integration/playwright/playwright.config.ts index 5314c08c88..e064d3a4ec 100644 --- a/tests/integration/playwright/playwright.config.ts +++ b/tests/integration/playwright/playwright.config.ts @@ -6,6 +6,8 @@ import { defineConfig, devices } from '@playwright/test'; */ // require('dotenv').config(); +const isCI = !!process.env.CI; + /** * See https://playwright.dev/docs/test-configuration. */ @@ -25,13 +27,16 @@ export default defineConfig({ /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, + forbidOnly: isCI, /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, + retries: isCI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, + workers: isCI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: [["html", { open: "never" }]], + reporter: [ + ["html", { open: "never" }], + isCI ? ['github'] : ['line'], + ], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ @@ -92,7 +97,7 @@ export default defineConfig({ webServer: { command: 'python -m http.server 8080', url: 'http://127.0.0.1:8080', - reuseExistingServer: !process.env.CI, + reuseExistingServer: !isCI, cwd: '../../docs/playwright', }, }); From e0b526bf22d81e3a19e3367c5c408014b07b687b Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 30 Sep 2024 11:26:55 +0200 Subject: [PATCH 07/10] tests, playwright - gitignore most outputs (.html, and _files folder) --- tests/docs/playwright/ojs/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/docs/playwright/ojs/.gitignore diff --git a/tests/docs/playwright/ojs/.gitignore b/tests/docs/playwright/ojs/.gitignore new file mode 100644 index 0000000000..6b94735c9c --- /dev/null +++ b/tests/docs/playwright/ojs/.gitignore @@ -0,0 +1,2 @@ +*.html +*_files \ No newline at end of file From bbe7058bbef1d8b8830dd2be73fc0224f366dd29 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 30 Sep 2024 13:56:50 +0200 Subject: [PATCH 08/10] test, playwright - deactivate snapshot for now CI needs to be adapted to correctly run visual tests. --- tests/integration/playwright-tests.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/playwright-tests.test.ts b/tests/integration/playwright-tests.test.ts index 0dd4bb319d..2069e7eb5f 100644 --- a/tests/integration/playwright-tests.test.ts +++ b/tests/integration/playwright-tests.test.ts @@ -52,7 +52,7 @@ Deno.test({ try { // run playwright const res = await execProcess({ - cmd: [Deno.build.os == "windows" ? "npx.cmd" : "npx", "playwright", "test"], + cmd: [Deno.build.os == "windows" ? "npx.cmd" : "npx", "playwright", "test", "--ignore-snapshots"], cwd: "integration/playwright", }); if (!res.success) { From d16023f59f10a3e7d41e4fc67cac810ece21c4bc Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 30 Sep 2024 18:11:57 +0200 Subject: [PATCH 09/10] Add back the classes as part of HTML post-render-html-fixups This makes more sense to get back the behavior from previous Pandoc. --- src/resources/filters/crossref/crossref.lua | 1 - src/resources/filters/main.lua | 1 - .../filters/normalize/astpipeline.lua | 3 --- .../filters/normalize/pandoc-tables.lua | 26 ------------------- src/resources/filters/quarto-post/html.lua | 16 ++++++++++++ 5 files changed, 16 insertions(+), 31 deletions(-) delete mode 100644 src/resources/filters/normalize/pandoc-tables.lua diff --git a/src/resources/filters/crossref/crossref.lua b/src/resources/filters/crossref/crossref.lua index 14113ae216..85973ae565 100644 --- a/src/resources/filters/crossref/crossref.lua +++ b/src/resources/filters/crossref/crossref.lua @@ -61,7 +61,6 @@ import("../quarto-init/resourcerefs.lua") import("../normalize/flags.lua") import("../normalize/normalize.lua") -import("../normalize/pandoc-tables.lua") import("../normalize/parsehtml.lua") import("../normalize/extractquartodom.lua") import("../normalize/astpipeline.lua") diff --git a/src/resources/filters/main.lua b/src/resources/filters/main.lua index 5fe1f65828..c39fa2d4b2 100644 --- a/src/resources/filters/main.lua +++ b/src/resources/filters/main.lua @@ -98,7 +98,6 @@ import("./quarto-finalize/typst.lua") import("./normalize/flags.lua") import("./normalize/normalize.lua") -import("./normalize/pandoc-tables.lua") import("./normalize/parsehtml.lua") import("./normalize/extractquartodom.lua") import("./normalize/astpipeline.lua") diff --git a/src/resources/filters/normalize/astpipeline.lua b/src/resources/filters/normalize/astpipeline.lua index 5008f77130..8777c5e307 100644 --- a/src/resources/filters/normalize/astpipeline.lua +++ b/src/resources/filters/normalize/astpipeline.lua @@ -22,9 +22,6 @@ function quarto_ast_pipeline() } end return { - -- identify pandoc table - { name = "normalize-pandoc-table", filter = pandoc_tables() }, - { name = "normalize-table-merge-raw-html", filter = table_merge_raw_html() }, -- this filter can't be combined with others because it's top-down processing. diff --git a/src/resources/filters/normalize/pandoc-tables.lua b/src/resources/filters/normalize/pandoc-tables.lua deleted file mode 100644 index 370f898a07..0000000000 --- a/src/resources/filters/normalize/pandoc-tables.lua +++ /dev/null @@ -1,26 +0,0 @@ --- pandoc-tables.lua --- Copyright (C) 2024 Posit Software, PBC - --- Add back classes 'odd', (or 'header' in table header) / 'even' to table rows --- They were removed in pandoc 3.2.1 but are useful for styling pandoc processed tables --- Quarto detects .odd class -function pandoc_tables() - local function add_odd_even (rows, odd) - odd = odd or 'odd' - for rownum, row in ipairs(rows) do - row.classes:insert((rownum % 2) == 0 and 'even' or odd) - end - return rows - end - - return { - Table = function (tbl) - add_odd_even(tbl.head.rows, 'header') - for _, tblbody in ipairs(tbl.bodies) do - add_odd_even(tblbody.body) - end - add_odd_even(tbl.foot.rows) - return tbl - end - } -end \ No newline at end of file diff --git a/src/resources/filters/quarto-post/html.lua b/src/resources/filters/quarto-post/html.lua index adfe5d33a8..e61eabb6c2 100644 --- a/src/resources/filters/quarto-post/html.lua +++ b/src/resources/filters/quarto-post/html.lua @@ -23,6 +23,22 @@ function render_html_fixups() return { Table = function(tbl) + -- Add back classes 'odd', (or 'header' in table header) / 'even' to table rows + -- They were removed in pandoc 3.2.1 but are useful for styling pandoc processed tables + -- Quarto detects .odd class + local function add_odd_even (rows, odd) + odd = odd or 'odd' + for rownum, row in ipairs(rows) do + row.classes:insert((rownum % 2) == 0 and 'even' or odd) + end + return rows + end + add_odd_even(tbl.head.rows, 'header') + for _, tblbody in ipairs(tbl.bodies) do + add_odd_even(tblbody.body) + end + add_odd_even(tbl.foot.rows) + -- this requires bootstrap CSS if quarto.doc.crossref.cap_location(tbl) == "top" then tbl.classes:insert("caption-top") From 477d1d2f1b71d604cd048c13d515ff337e47a884 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 30 Sep 2024 19:01:20 +0200 Subject: [PATCH 10/10] test, playwright - Update test location to add os informaton --- .../integration/playwright/playwright.config.ts | 2 +- .../Markdown-tables-are-styled-correctly-1.png | Bin 1509 -> 0 bytes .../Markdown-tables-are-styled-correctly-2.png | Bin 5382 -> 0 bytes .../Markdown-tables-are-styled-correctly-1.png | Bin 0 -> 3456 bytes .../Markdown-tables-are-styled-correctly-2.png | Bin 0 -> 12030 bytes 5 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-1.png delete mode 100644 tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-2.png create mode 100644 tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/win32/Markdown-tables-are-styled-correctly-1.png create mode 100644 tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/win32/Markdown-tables-are-styled-correctly-2.png diff --git a/tests/integration/playwright/playwright.config.ts b/tests/integration/playwright/playwright.config.ts index e064d3a4ec..d392c298f7 100644 --- a/tests/integration/playwright/playwright.config.ts +++ b/tests/integration/playwright/playwright.config.ts @@ -14,7 +14,7 @@ const isCI = !!process.env.CI; export default defineConfig({ /* Look for test files in the "tests" directory, relative to this configuration file. */ testDir: "./tests", - snapshotPathTemplate: "{testDir}/__screenshots__/{testFilePath}/{arg}{ext}", + snapshotPathTemplate: "{testDir}/__screenshots__/{testFilePath}/{platform}/{arg}{ext}", /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { diff --git a/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-1.png b/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-1.png deleted file mode 100644 index f802314b27e8bdcb1eaa350b994be06a7d195f68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1509 zcmah}do+}37@vmLtjIV~Zt+bum{_HTSmAS9#xhA|kXs|lmd!08w+{^wMi<){Mq6k# z8bs?-={ClcYlhG?5@VQImzdop?0!47oi6*&p7Xx%^ZefPzUMs8`Tc&+Sr4MKvZ9tE z0)bE_xHx(u5ORPluR+Pl&IiC!hAga#_H?#Ku)1`_G7#k9w%-YZ#bK}^7%T-t4#ALF zn2er4EG`fm5{RV)l39T=cvF&w#ify1X|kkSwqSZWi%G^Y$stS$+?9dr%Ajr-4)u1OPM|g_4&?B3D7FAVRi5 zpvMtdJ~^4F`vk4a$hF5)YQlC>7s4+mCf`xzM$C=r>)SOJE8wVMyX_ap%F7D|tvLnW z{tD+su9XFbYFw&*>rHSJxUJ?Q8Tk&7D)#nzorg#Bp$>tX)>)4m`Hh>V;1x7CPT($= z#MU%TLiB0zAFbep}~j>#Ww44b~f8vE6u;Gq!3)gWJ=m zddy;DQ|3#~M1#H@A?0mk|I|F*C-iYEk>BNMs^VIt84Wl*%&dI`3AIMg9kr%5W!E1O zf}BFevu-4f=^}lt=2A)6yOrAS1Oz{ZjCo{l2D=cXR1D7(^_FjGbsTWBog_L}NewQ- zDFAN=&35VeDe7W2`Q&K@oH_RCJ=WyR6d(mJ(bRwLtLIk7Yo~lgm^~&MxJ&8=I+JRF zmN$$*X@G6|N*rOV&l70B!@TJ9_cjkYWPIXyMSPDQyl1_fPx7$YZLbcwh=kHz3}rXk zY;nd_DcNjRUmDvR3dGlDZQgFeyV41YDr*%x$SkUG z_~kG@Az%C!BM9*AH}SOtf}4>;*TQVb$|`x@$fh_)l{PEh>Zlr;*B|Es?11>~3C=k> z+@LMP4Z6M6p{<8vZq=k0=Lz~dD5H>ZPHXb?xp7S)UQNuM);q)VRW;vWMc~&xBDoU{ zW-TCA-DLfINeVBtW_x>z$6@r+G?Zm%HfAkTd;7H#EH z4owZ1-Q}xgff8$SE>blMw9%59?gNmjT;*9l@m=&^KIs~a<{paA85iV&Cb|y24L?5J zR?iuc!+L%U_lP1mo^6B42YAs>iF0PhX?(IXnymD_S`u0>?WROkt zKwW?r+9mt3@G{Z6i}uGi>gw|6iR<$=SW*}NtavL8RXluu?L%vEWI!2-{&2pjitZqV zj5lvr++so#&s|%%Y$Fr{)VbF_0EtJ|yg->AFoJ~poD8VUTJKQj_Sk%!GF^<<_S8xT zE4Go2o2Y1n+fvxqO;3jvuf3Eg=KQ2?_vJkMBz2Vh4JDy^*9IYs74T+ Lh>k4#ptOGgE1#U9 diff --git a/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-2.png b/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/Markdown-tables-are-styled-correctly-2.png deleted file mode 100644 index 3dcb971e269e847a6078c9452285872a2b8be6f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5382 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 literal 0 HcmV?d00001 diff --git a/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/win32/Markdown-tables-are-styled-correctly-2.png b/tests/integration/playwright/tests/__screenshots__/html-tables.spec.ts/win32/Markdown-tables-are-styled-correctly-2.png new file mode 100644 index 0000000000000000000000000000000000000000..910f7615bd7341344beebc840d1fffaa63300e84 GIT binary patch literal 12030 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