Skip to content

ansi_html() bug when strings with the same style have been pasted together #752

Description

@trevorld

I'm observing an error with ansi_html() when strings with the same styles have been pasted together. An example:

library("cli")
asf <- combine_ansi_styles(bg_blue, col_br_yellow)
s <- paste(rep_len(asf(" "), 10L), collapse = "")
h_cli <- ansi_html(s)
print(h_cli)
[1] "<span class=\"ansi ansi-color-3 ansi-bg-color-4\"> </span>         "

Note only the first space is styled with the correct background color and the remaining nine spaces are unstyled. In contrast I believe the right output should instead be:

[1] "<span class=\"ansi ansi-color-3 ansi-bg-color-4\">          </span>"

(note the different placement of the </span>). In contrast fansi::sgr_to_html() seems to correctly preserve a style for all ten spaces:

h_fansi <- fansi::sgr_to_html(s)
print(h_fansi)
[1] "<span style='color: #FFFF55; background-color: #0000BB;'>          </span>"

Activity

  1. added
    bugan unexpected problem or unintended behavior
    on Apr 25, 2025
  2. trevorld commented on May 9, 2025

    @trevorld
    Author

    A possible test case for tests/testthat/test-ansi-html.R:

    # https://github.com/r-lib/cli/issues/752
    expect_equal(
      ansi_html("\033[91mR\033[39m\033[91mR\033[39m"),
      "<span class=\"ansi ansi-color-1\">RR</span>"
    )

    where

    > paste0(col_br_red("R"), col_br_red("R"))
    [1] "\033[91mR\033[39m\033[91mR\033[39m"
  3. added 2 commits that reference this issue on Feb 14, 2026
    2bc1992
    69393e8
  4. trevorld commented on Feb 14, 2026

    @trevorld
    Author

    Claude Code claims:

    I see the bug. In html_cb_text(), each text segment opens a <span> and closes it. But clic__html_start() at line 934 sets state->old = state->new, so when the next text segment has the same style (after a reset+re-apply like \033[39m\033[91m), the comparison sees no difference and skips the span.

    The fix: after closing the span in html_cb_text(), reset state->old so the next text segment correctly detects it needs styling.

    I also observe that things seem to work if you first apply ansi_simplify() before ansi_html().

  5. added a commit that references this issue on Apr 2, 2026
    c7bc654
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugan unexpected problem or unintended behavior

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions