Skip to content

feat: add code-line-fragment-indices for Reveal.js line highlights - #15293

Merged
cderv merged 13 commits into
quarto-dev:mainfrom
mcanouil:feat/code-line-fragment-index-7378
Nov 6, 2026
Merged

cderv merged 13 commits into
quarto-dev:mainfrom
mcanouil:feat/code-line-fragment-index-7378

Conversation

@mcanouil

@mcanouil mcanouil commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Stepped line highlighting in Reveal.js gives each highlight step the next free fragment index.
So a highlight can't sit between other fragments on the slide, such as a note on each line.
This adds a code-line-fragment-indices attribute and cell option that sets the index of each step after the first.
The first step is the code block itself, so it still shows when the slide opens.

::: {.fragment fragment-index=1}
First note.
:::

```{.python code-line-numbers="|1|2" code-line-fragment-indices="2,4"}
x = [1, 2, 3]
print(x)
```

::: {.fragment fragment-index=3}
Second note.
:::

The video steps the same slide through four clicks, without the attribute on the left and with "2,4" on the right.
On the left, both notes appear before any line is highlighted.
On the right, note 1, line 1, note 2 and line 2 appear in turn.

code-line-fragment-indices.mp4

The list must hold one non-negative integer for each step after the first, in strictly increasing order.
If it doesn't, the render prints a warning and the slide keeps the current order.
In a cell, the option can be a comma-separated string, a single number or a YAML list.
The Lua filter keeps the attribute only for Reveal.js with stepped code-line-numbers, and knitr, Jupyter and OJS cells pass the option through.
Without the attribute, decks behave as before.

Highlighted lines meet the 4.5:1 contrast ratio.
Dimmed lines are at 2.26:1, from the existing 0.4 opacity, which this doesn't change.

Closes #7378.
Closes #11585.

Docs: quarto-dev/quarto-web#2340.

Checklist

I have (if applicable):

AI-assisted PR
  • AI tool used: Claude Code.
  • Codebase grounding: local clone.
  • Human review: I have reviewed, tested, and verified the AI-generated content before submitting.

Note: autonomous AI agents submitting PRs without human oversight are not permitted — see the Code of Conduct.

@mcanouil mcanouil added enhancement New feature or request revealjs Issues with the revealjs format labels Nov 4, 2026
@mcanouil mcanouil self-assigned this Nov 4, 2026
@mcanouil mcanouil changed the title feat: add code-line-fragment-indices for stepped code line highlighting in Reveal.js feat: add code-line-fragment-indices for Reveal.js line highlights Nov 4, 2026
@posit-snyk-bot

posit-snyk-bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@mcanouil
mcanouil marked this pull request as ready for review November 4, 2026 16:49

@cderv cderv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, the approach looks good to me. I have two questions before going further.

Indices out of order

Upstream reveal.js only has a start index for the steps (data-fragment-index on <code>, then +1 for each step, see hakimel/reveal.js#3055), so this goes further and we need to decide how an arbitrary list behaves.

The list is accepted in any order, but the clones are stacked in the order of code-line-numbers, and a later clone covers the earlier ones once visible. With this

```{.r code-line-numbers="|1|2" code-line-fragment-indices="4,2"}
x <- 1
y <- 2
```

line 2 is highlighted first, then at index 4 the line 1 clone becomes visible but stays under the line 2 one, so the line 1 highlight never shows. With "2,2" both clones show at the same time and only line 2 is seen. The render gives no warning in both cases.

Should we warn and fall back like for a wrong count, when the indices are not strictly increasing ? Or do you want to support any order by appending the clones sorted by index (the hidden handler scrolls to previousSibling, so it would need the same order) ?

Number and list values in cell options

For a cell with a single step, the natural way to write it is

#| code-line-numbers: "|1"
#| code-line-fragment-indices: 2

but YAML gives a number, and the schema only accepts a string, so the render fails with Field "code-line-fragment-indices" has value 2, which must instead be a comma-separated list of non-negative integers. Same for [2, 4]. It is a hard error for knitr and Jupyter cells, not the warning and fallback the PR description mentions (that one applies to the code block attribute).

Did you consider accepting a number, and maybe a list of numbers, like code-line-numbers accepts a boolean or a string ? knitr and Jupyter would then need to turn it into the comma-separated string for the attribute.

One smaller thing, the OJS path has no fixture. I checked by hand that an {ojs} cell does get data-code-line-fragment-indices on the source block, so adding it to the smoke-all tests would keep it covered.

@mcanouil

mcanouil commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator Author

Thanks.

For the order, I'll require strictly increasing indices.
Equal values hide the earlier step just as decreasing ones do, and sorting the clones would break the link between a step and its entry in code-line-numbers.
Anything else will warn and fall back to the default order, as a wrong count does, in both the Lua filter and the JavaScript.

You're right about cell options too.
I'll accept a string, a non-negative integer or a list of them, like code-line-numbers accepts a boolean or a string, and knitr, Jupyter and OJS will turn it into the comma-separated attribute.

I'll add tests for "4,2", "2,2", the number and list forms, and an {ojs} cell, and push it all in one go.

@mcanouil
mcanouil marked this pull request as draft November 5, 2026 19:16
…s and lists

Indices that are not strictly increasing hid a highlight step, so they now trigger the warning and fall back to the default order.
Cell options accept a number or a list of numbers as well as a string, and knitr, Jupyter and OJS turn them into the comma-separated attribute.
Tests cover decreasing and equal indices, number and list values, and an OJS cell.
@mcanouil
mcanouil marked this pull request as ready for review November 5, 2026 20:16

@cderv cderv left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the strict ordering check and the number and list forms look good to me. Ready to merge.

@cderv
cderv merged commit 7039273 into quarto-dev:main Nov 6, 2026
52 checks passed
@mcanouil
mcanouil deleted the feat/code-line-fragment-index-7378 branch November 6, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request revealjs Issues with the revealjs format

Projects

None yet

Development

Successfully merging this pull request may close these issues.

code-line-numbers and fragments not working as expected/hoped in revealjs Feature request: fragment-index for code-line-numbers

3 participants