How to support syntax highlighting for HTML dark theme in v0.14.0-rc.1?

I have a webiste supporting light and dark themes. It has many raw code blocks, and I want their colors be readable in each theme.
I’ve implemented the following in typst v0.13, and I’m trying to migrate to typst v0.14.

Typst’s default theme:

Typst’s default theme on dark background:

My tuned theme on dark background:

My previous design

In typst v0.13.1, I use the following show text rule to capture the default syntax highlighting color and make them accessible in CSS.

Typst document:

#show text: it => {
  if text.fill == black {
    it // Ignore default color
  } else {
    let fill = text.fill.to-hex()
    html.elem("span", it, attrs: (data-fill: fill, style: "--data-fill:" + fill))
  }
}

CSS:

.example [data-fill] {
  color: var(--data-fill);
}
.dark .example {
  [data-fill="#1d6c76"] {
    color: #36bfce;
  }
  [data-fill="#298e0d"] {
    color: #38be13;
  }
  /* List all colors that need to be changed for the dark theme… */
}

Generated HTML:

<pre>
  <span data-fill="#d73a49" style="--data-fill:#d73a49">let</span>
  x
  <span data-fill="#d73a49" style="--data-fill:#d73a49">=</span>
  <span data-fill="#b60157" style="--data-fill:#b60157">1</span>
  ;
</pre>

(just for example; there’s no extra new lines in the real html. same below.)

Full code

clreq/typ/templates/html-fix.typ at 34aad79fe4d31b5e116b176980377ecaa2b3fe83 · typst-doc-cn/clreq · GitHub

clreq/src/show-example.css at 34aad79fe4d31b5e116b176980377ecaa2b3fe83 · typst-doc-cn/clreq · GitHub

Typst v0.14.0-rc.1 breaks it

Typst v0.14.0-rc.1 has just released.
Now the raw element have native syntax highlighting support. (#6691)
However, my show text rule no longer matches colored texts.

#show text: it => {
  if text.fill == black {
    it
  } else {
    panic(
      [
        v0.13/SVG, v0.13/HTML, v0.14.0-rc.1/SVG will reach here,
        but v0.14.0-rc.1/HTML never.
      ],
    )
  }
}

```rust
let x = 1;
```

What should I do now?

So how to support syntax highlighting for the dark theme now?

Typst now generates the following HTML. How can I reserve text.fill for CSS now? Is it possible to override style="color: …" in CSS?

<pre>
  <code data-lang="rust">
    <span style="color: #d73948">let</span>
    x
    <span style="color: #d73948">=</span>
    <span style="color: #b60157">1</span>
    ;
  </code>
</pre>

Thanks in advance! Even partial solutions/ideas are welcome.

Yes, same way as you already did, but it’s now rather hacky:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Title</title>
    <style>
      html {
        background: black;
        color: white;
      }
      span[style="color: #d73948"] {
        color: #00ff00 !important;
      }
      span[style="color: #b60157"] {
        color: aqua !important;
      }
    </style>
  </head>
  <body>
    <pre>
  <code data-lang="rust">
    <span style="color: #d73948">let</span> x <span style="color: #d73948">=</span> <span style="color: #b60157">1</span>;
  </code>
</pre>
  </body>
</html>

image

Hmm, I guess you can make it pretty much reliable with a better selector:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Title</title>
    <style>
      html {
        background: black;
        color: white;
      }
      span[style*="color: #d73948"] {
        color: #00ff00 !important;
      }
      span[style*="color: #b60157"] {
        color: aqua !important;
      }
    </style>
  </head>
  <body>
    <pre>
  <code data-lang="rust">
    <span style="color: #d73948; background: red;">let</span> x <span style="color: #d73948">=</span> <span style="color: #b60157">1</span>;
  </code>
</pre>
  </body>
</html>

image

However, with Dark Reader, the color override doesn’t work, it uses its own ones.

1 Like

Thank you!

Some other suggests creating two raw elements and toggle between them in CSS:

This approach has a caveat that the user selection will be lost when theme changes automatically in the morning or at twilight.
(And I haven’t test Dark Reader’s behavior yet.)

I am not sure which approach is less dirty. They look equally complex, just putting the complexity in different places…

1 Like

Uhh, well, if you have time, you can try both. If you think they are equally complex, no reason to spend time deciding on one or another. Considering you already had some CSS overrides, it sounds like the new CSS override shouldn’t be complex at all, just changing the selectors a bit.

(Yeah, I played for a while with both, and ended up with !important)