From 14b9f535cff53cd9f8bb21584c6675f45d57dc1d Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 5 Mar 2026 14:30:21 +0100 Subject: [PATCH 1/4] Replace prerelease-link-subdomain with version-aware shortcode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `prerelease-link-subdomain` variable is phase-aware but not version-aware — on the next RC cycle, old blog posts would incorrectly point to prerelease.quarto.org even though those docs already moved to quarto.org. Add a `prerelease-docs-url` shortcode extension that compares a version argument against the `version` key in `_quarto.yml` to decide whether docs live on quarto.org or prerelease.quarto.org. On the prerelease site (prerelease-docs profile), it always returns "prerelease." regardless of version. Follow-up to #1932, relates to #1934. --- README.md | 17 +++++----- .../prerelease-docs-url/_extension.yml | 6 ++++ .../prerelease-docs-url.lua | 32 +++++++++++++++++++ _quarto-prerelease-docs.yml | 5 ++- _quarto-rc.yml | 3 +- _quarto.yml | 2 +- 6 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 _extensions/prerelease-docs-url/_extension.yml create mode 100644 _extensions/prerelease-docs-url/prerelease-docs-url.lua diff --git a/README.md b/README.md index 1f39df0869..50fcbea7df 100644 --- a/README.md +++ b/README.md @@ -132,16 +132,17 @@ The group order determines which phase is active on **quarto.org** (the main sit |---|---| | `_quarto-prerelease-docs.yml` | Site-specific configuration for prerelease.quarto.org | -### Subdomain variables +### Subdomain variable and shortcode -Two variables control how links resolve across builds. Both use the same pattern — `https://{{< meta VAR >}}quarto.org/...` — but serve different purposes: +**`prerelease-subdomain`** — site identity variable ("am I the prerelease site?"). Default `''` in `_quarto.yml`, set to `prerelease.` in `_quarto-prerelease-docs.yml`. Use for self-referential links (e.g. RevealJS demo links back to its own site). -| Variable | Purpose | Default | Set by `rc` | Set by `prerelease-docs` | -|---|---|---|---|---| -| `prerelease-subdomain` | **Site identity** — "am I the prerelease site?" | `''` | — | `prerelease.` | -| `prerelease-link-subdomain` | **Content linking** — "where do prerelease docs live right now?" | `''` | `prerelease.` | `prerelease.` | +**`prerelease-docs-url`** — version-aware shortcode for content linking. Use in blog posts that reference docs only available on prerelease: -Use `prerelease-subdomain` for self-referential links (e.g. RevealJS demo links back to its own site). Use `prerelease-link-subdomain` for content on `main` that references docs only available on prerelease during RC phase (e.g. blog posts announcing upcoming features). +```markdown +[PDF Accessibility](https://{{< prerelease-docs-url 1.9 >}}quarto.org/docs/output-formats/pdf-accessibility.html) +``` + +The shortcode compares its version argument to the `version` key in `_quarto.yml` (which tracks the current stable release on `main`). If they match, docs are on quarto.org (`""`); if not, they're still on prerelease.quarto.org (`"prerelease."`). On the prerelease site (`prerelease-docs` profile), it always returns `"prerelease."`. ### Release lifecycle @@ -149,7 +150,7 @@ Use `prerelease-subdomain` for self-referential links (e.g. RevealJS demo links 2. **RC phase:** flip group to `[rc, prerelease]` — main site shows "Release Candidate" 3. **Release:** flip back to `[prerelease, rc]` for the next development cycle -These flips only affect quarto.org. The prerelease site CI explicitly activates `prerelease,prerelease-docs`, so it always shows "Pre-release" regardless of group order. +These flips only affect quarto.org. The prerelease site CI activates `prerelease-docs`, and the group order determines the phase branding on the prerelease site too. ### Local preview diff --git a/_extensions/prerelease-docs-url/_extension.yml b/_extensions/prerelease-docs-url/_extension.yml new file mode 100644 index 0000000000..dabdf77cf6 --- /dev/null +++ b/_extensions/prerelease-docs-url/_extension.yml @@ -0,0 +1,6 @@ +title: Prerelease Docs URL +author: Quarto +version: 0.0.1 +contributes: + shortcodes: + - prerelease-docs-url.lua diff --git a/_extensions/prerelease-docs-url/prerelease-docs-url.lua b/_extensions/prerelease-docs-url/prerelease-docs-url.lua new file mode 100644 index 0000000000..40ead159bf --- /dev/null +++ b/_extensions/prerelease-docs-url/prerelease-docs-url.lua @@ -0,0 +1,32 @@ +-- Version-aware shortcode for linking to prerelease docs. +-- +-- Usage: {{< prerelease-docs-url 1.9 >}} +-- +-- Returns "prerelease." when the referenced version's docs live on +-- prerelease.quarto.org, or "" when they're on quarto.org. + +local function handler(args, kwargs, meta) + local ref_version = quarto.shortcode.read_arg(args, 1) + if ref_version == nil then + quarto.log.error("prerelease-docs-url requires a version argument, e.g. {{< prerelease-docs-url \"1.9\" >}}") + return pandoc.Str("") + end + -- Strip surrounding quotes that may be preserved in text contexts + ref_version = ref_version:gsub('^"(.*)"$', '%1'):gsub("^'(.*)'$", '%1') + + -- On the prerelease site, always link to prerelease + if quarto.project.profile:includes("prerelease-docs") then + return pandoc.Str("prerelease.") + end + + -- Compare referenced version to this branch's version + local branch_version = pandoc.utils.stringify(meta["version"]) + + if ref_version == branch_version then + return pandoc.Str("") + else + return pandoc.Str("prerelease.") + end +end + +return {["prerelease-docs-url"] = handler} diff --git a/_quarto-prerelease-docs.yml b/_quarto-prerelease-docs.yml index 6944203867..9e0bc6fe09 100644 --- a/_quarto-prerelease-docs.yml +++ b/_quarto-prerelease-docs.yml @@ -1,8 +1,7 @@ # Pre-release version number -version: v1.9 +version: '1.9' prerelease-subdomain: prerelease. -prerelease-link-subdomain: prerelease. website: title: "Quarto (Pre-release)" @@ -11,7 +10,7 @@ website: repo-branch: prerelease announcement: dismissable: false - content: "Pre-release ({{< meta version >}}) Documentation: [Download {{< meta version >}}](/docs/download/prerelease.qmd), [Current Release Docs](http://quarto.org) " + content: "Pre-release (v{{< meta version >}}) Documentation: [Download v{{< meta version >}}](/docs/download/prerelease.qmd), [Current Release Docs](http://quarto.org) " navbar: pinned: true search: diff --git a/_quarto-rc.yml b/_quarto-rc.yml index 7d68f7fe2d..3084566f05 100644 --- a/_quarto-rc.yml +++ b/_quarto-rc.yml @@ -1,4 +1,3 @@ prerelease-title: Release Candidate prerelease-lower: release candidate -prerelease-mode: Release Candidate -prerelease-link-subdomain: prerelease. \ No newline at end of file +prerelease-mode: Release Candidate \ No newline at end of file diff --git a/_quarto.yml b/_quarto.yml index 1bbd0d773b..c39a8ec698 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -706,8 +706,8 @@ filters: - at: post-quarto path: filters/include-dark.lua +version: '1.8' prerelease-subdomain: '' -prerelease-link-subdomain: '' freeze: true From 6bc8b7f4ba3bde90689d85dfb2e1a5822f7df0ac Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 5 Mar 2026 15:00:35 +0100 Subject: [PATCH 2/4] Use version comparison (<=) instead of equality check pandoc.types.Version provides element-wise comparison so older version args (e.g. 1.8 when main is at 1.9) correctly resolve to quarto.org instead of prerelease.quarto.org. --- _extensions/prerelease-docs-url/prerelease-docs-url.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/_extensions/prerelease-docs-url/prerelease-docs-url.lua b/_extensions/prerelease-docs-url/prerelease-docs-url.lua index 40ead159bf..04476e4a09 100644 --- a/_extensions/prerelease-docs-url/prerelease-docs-url.lua +++ b/_extensions/prerelease-docs-url/prerelease-docs-url.lua @@ -19,10 +19,12 @@ local function handler(args, kwargs, meta) return pandoc.Str("prerelease.") end - -- Compare referenced version to this branch's version - local branch_version = pandoc.utils.stringify(meta["version"]) + -- Compare referenced version to this branch's version using + -- pandoc.types.Version for correct element-wise comparison (1.12 > 1.9) + local branch_version = pandoc.types.Version(pandoc.utils.stringify(meta["version"])) + local ref = pandoc.types.Version(ref_version) - if ref_version == branch_version then + if ref <= branch_version then return pandoc.Str("") else return pandoc.Str("prerelease.") From 9a4c7aad32c58ac82b2afef1232e8138c2df699a Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 5 Mar 2026 16:39:24 +0100 Subject: [PATCH 3/4] Update PDF accessibility blog post to use prerelease-docs-url shortcode --- .../2026-03-05-pdf-accessibility-and-standards/index.qmd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/blog/posts/2026-03-05-pdf-accessibility-and-standards/index.qmd b/docs/blog/posts/2026-03-05-pdf-accessibility-and-standards/index.qmd index 5d852b8f58..3de0ba61b8 100644 --- a/docs/blog/posts/2026-03-05-pdf-accessibility-and-standards/index.qmd +++ b/docs/blog/posts/2026-03-05-pdf-accessibility-and-standards/index.qmd @@ -83,9 +83,9 @@ Quarto's Markdown-based workflow handles many accessibility requirements automat But you do need to make sure your document has: * A **title** in the YAML front matter. -* **Alt text for every image**, specified with `fig-alt`. See [Figures](https://{{< meta prerelease-link-subdomain >}}quarto.org/docs/authoring/figures.html#alt-text) for details. +* **Alt text for every image**, specified with `fig-alt`. See [Figures](https://{{< prerelease-docs-url 1.9 >}}quarto.org/docs/authoring/figures.html#alt-text) for details. -See the [LaTeX](https://{{< meta prerelease-link-subdomain >}}quarto.org/docs/output-formats/pdf-basics.html#accessibility-requirements) and [Typst](https://{{< meta prerelease-link-subdomain >}}quarto.org/docs/output-formats/typst.html#accessibility-requirements) documentation for more details. +See the [LaTeX](https://{{< prerelease-docs-url 1.9 >}}quarto.org/docs/output-formats/pdf-basics.html#accessibility-requirements) and [Typst](https://{{< prerelease-docs-url 1.9 >}}quarto.org/docs/output-formats/typst.html#accessibility-requirements) documentation for more details. ## If your document fails validation @@ -101,7 +101,7 @@ We ran our test suite -- 188 LaTeX examples and 317 Typst examples -- to find wh Margin content is the biggest structural blocker. If you use `.column-margin` divs, `cap-location: margin`, `reference-location: margin`, or `citation-location: margin`, the resulting PDF will not pass UA-2. The underlying `sidenotes` and `marginnote` LaTeX packages [do not cooperate with PDF tagging](https://github.com/quarto-dev/quarto-cli/issues/14103). -(Margin content does work with Typst and passes UA-1 -- see [Typst Article Layout](https://{{< meta prerelease-link-subdomain >}}quarto.org/docs/output-formats/typst.html#article-layout).) +(Margin content does work with Typst and passes UA-1 -- see [Typst Article Layout](https://{{< prerelease-docs-url 1.9 >}}quarto.org/docs/output-formats/typst.html#article-layout).) There are smaller upstream issues in Pandoc, LaTeX, and LaTeX packages, [documented here](https://github.com/quarto-dev/quarto-cli/pull/14097#issuecomment-3947653207). @@ -111,7 +111,7 @@ In our tests, Typst catches every UA-1 violation, and fails to generate the PDF. Typst also seems to do a very good job of generating UA-1 compliant output by default -- almost all errors were due to missing titles or missing alt text. -However, we did discover that [Typst books](https://{{< meta prerelease-link-subdomain >}}quarto.org/docs/books/book-output.html#typst-output) are not yet compliant. There is a [structural problem with the Typst orange-book package](https://github.com/flavio20002/typst-orange-template/issues/38) and we'll work with the maintainers to correct it. +However, we did discover that [Typst books](https://{{< prerelease-docs-url 1.9 >}}quarto.org/docs/books/book-output.html#typst-output) are not yet compliant. There is a [structural problem with the Typst orange-book package](https://github.com/flavio20002/typst-orange-template/issues/38) and we'll work with the maintainers to correct it. ## Conclusion From 25b325ffa8e37a8569b23f4610343371473f3e2e Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Thu, 5 Mar 2026 17:54:18 +0100 Subject: [PATCH 4/4] Add error handling to prerelease-docs-url shortcode Use quarto.shortcode.error_output() for clear error messages when version metadata is missing or version arguments are malformed. Fix missing trailing newline in _quarto-rc.yml. --- .../prerelease-docs-url.lua | 38 ++++++++++++++++--- _quarto-rc.yml | 2 +- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/_extensions/prerelease-docs-url/prerelease-docs-url.lua b/_extensions/prerelease-docs-url/prerelease-docs-url.lua index 04476e4a09..6e4fd947f2 100644 --- a/_extensions/prerelease-docs-url/prerelease-docs-url.lua +++ b/_extensions/prerelease-docs-url/prerelease-docs-url.lua @@ -5,11 +5,14 @@ -- Returns "prerelease." when the referenced version's docs live on -- prerelease.quarto.org, or "" when they're on quarto.org. -local function handler(args, kwargs, meta) +local function handler(args, kwargs, meta, raw_args, context) local ref_version = quarto.shortcode.read_arg(args, 1) if ref_version == nil then - quarto.log.error("prerelease-docs-url requires a version argument, e.g. {{< prerelease-docs-url \"1.9\" >}}") - return pandoc.Str("") + return quarto.shortcode.error_output( + "prerelease-docs-url", + "requires a version argument, e.g. {{< prerelease-docs-url 1.9 >}}", + context + ) end -- Strip surrounding quotes that may be preserved in text contexts ref_version = ref_version:gsub('^"(.*)"$', '%1'):gsub("^'(.*)'$", '%1') @@ -19,10 +22,35 @@ local function handler(args, kwargs, meta) return pandoc.Str("prerelease.") end + -- Guard against missing or invalid version metadata + local version_str = meta["version"] and pandoc.utils.stringify(meta["version"]) or nil + if not version_str or version_str == "" then + return quarto.shortcode.error_output( + "prerelease-docs-url", + "missing 'version' in document metadata", + context + ) + end + -- Compare referenced version to this branch's version using -- pandoc.types.Version for correct element-wise comparison (1.12 > 1.9) - local branch_version = pandoc.types.Version(pandoc.utils.stringify(meta["version"])) - local ref = pandoc.types.Version(ref_version) + local ok_branch, branch_version = pcall(pandoc.types.Version, version_str) + local ok_ref, ref = pcall(pandoc.types.Version, ref_version) + + if not ok_branch then + return quarto.shortcode.error_output( + "prerelease-docs-url", + "invalid metadata version '" .. version_str .. "'", + context + ) + end + if not ok_ref then + return quarto.shortcode.error_output( + "prerelease-docs-url", + "invalid version argument '" .. ref_version .. "'", + context + ) + end if ref <= branch_version then return pandoc.Str("") diff --git a/_quarto-rc.yml b/_quarto-rc.yml index 3084566f05..17cc19221f 100644 --- a/_quarto-rc.yml +++ b/_quarto-rc.yml @@ -1,3 +1,3 @@ prerelease-title: Release Candidate prerelease-lower: release candidate -prerelease-mode: Release Candidate \ No newline at end of file +prerelease-mode: Release Candidate