-
Notifications
You must be signed in to change notification settings - Fork 309
content: Implement Pygments Monokai, for upcoming dark theme #756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
content: Implement Pygments Monokai, for upcoming dark theme #756
Conversation
3dd63af
to
f289473
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! These changes all LGTM. One commit-message comment below.
Can you also say a few words about how you produced the list of styles? The link in the comment is to upstream, but then the comments on individual styles are in terms of CSS, which that upstream file isn't.
Oh, and I owe another pair of screenshots;
coming soonhere they are. This PR includes a commit to change light mode's plain code-block text color (used for un-highlighted code blocks) fromhsl(0deg 0% 15%)
to true black, following web.
Does this have a visible effect in the screenshots? I flipped back and forth, and couldn't spot any difference at all except in the clock at the top of the screen.
@@ -31,18 +32,34 @@ class CodeBlockTextStyles { | |||
// .err { border: 1px solid hsl(0deg 100% 50%); } | |||
err: const TextStyle(backgroundColor: Color(0xffe2706e)), | |||
|
|||
esc: null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're at it, write the TODO(#754) to update the light-theme
styles. (Hopefully to something that also has a style for all of
`CodeBlockSpanType`'s values.)
This change is fine, but there's nothing wrong with some of the values being null — that just means those spans inherit the base styling from plain
, right?
I believe the empty-string values in the upstream file:
https://github.com/pygments/pygments/blob/f64833d9d/pygments/styles/monokai.py
mean inheriting the style, so e.g. the classes w
and x
, and g
and gr
, all inherit the base style. (While e.g. cm
inherits that of c
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plain
copies a variable in web, --color-markdown-code-text
(starting at this PR's commit
content: Follow web in code-block default text color
). I don't think that variable or its light/dark values has anything to do with Pygments styles; I think it's mostly meant for plain un-syntax-highlighted code blocks.
From a Pygments doc on writing your own custom style, I think the "base style" that w
, x
, g
, and gr
are meant to inherit from is actually the Token
style, which for Monokai is #f8f8f2
. Here's from that doc:
Token
is the default style inherited by all token types.
This probably explains why web gives color: #f8f8f2;
for w
, x
, g
, and gr
, instead of letting them fall back to --color-markdown-code-text
. In zulip/zulip@f020f9eee, the switch to Monokai, it says the CSS was generated from a CLI tool from Pygments.
My process in making this commit was to follow web (minus some overrides; discussion) and then check the result against that upstream monokai.py file. So that's why our w
, x
, g
, and gr
are 0xfff8f8f2
instead of white with 85% opacity, and I think that's correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I guess having gone through all this just now, I'm now questioning some of our lines in the switch (type)
:
CodeBlockSpanType.text => null, // A span with type of text is always unstyled.
CodeBlockSpanType.unknown => null,
Maybe we should store the Token
style in a variable and return that instead of null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree with that conclusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker for merging this, though — that'd be a fine followup. I don't think this PR causes any regressions on that front.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it's a bit more complicated. In the Pygments HTML, text that is meant to get the Text
style seems to be represented without <span>
s—which is the same way text appears in plain, un-Pygmented code blocks. For example, this:
diff --git lib/widgets/content.dart lib/widgets/content.dart
index 1715d41e7..43c747232 100644
--- lib/widgets/content.dart
+++ lib/widgets/content.dart
@@ -37,6 +37,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
colorCodeBlockBackground: const HSLColor.fromAHSL(0.04, 0, 0, 0).toColor(),
colorDirectMentionBackground: const HSLColor.fromAHSL(0.2, 240, 0.7, 0.7).toColor(),
colorGlobalTimeBackground: const HSLColor.fromAHSL(1, 0, 0, 0.93).toColor(),
+ colorGlobalTimeBorder: const HSLColor.fromAHSL(1, 0, 0, 0.8).toColor(),
colorMathBlockBorder: const HSLColor.fromAHSL(0.15, 240, 0.8, 0.5).toColor(),
colorMessageMediaContainerBackground: const Color.fromRGBO(0, 0, 0, 0.03),
colorThematicBreak: const HSLColor.fromAHSL(1, 0, 0, .87).toColor(),
@@ -61,6 +62,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
colorCodeBlockBackground: const HSLColor.fromAHSL(0.04, 0, 0, 1).toColor(),
colorDirectMentionBackground: const HSLColor.fromAHSL(0.25, 240, 0.52, 0.6).toColor(),
colorGlobalTimeBackground: const HSLColor.fromAHSL(0.2, 0, 0, 0).toColor(),
+ colorGlobalTimeBorder: const HSLColor.fromAHSL(0.4, 0, 0, 0).toColor(),
colorMathBlockBorder: const HSLColor.fromAHSL(1, 240, 0.4, 0.4).toColor(),
colorMessageMediaContainerBackground: const HSLColor.fromAHSL(0.03, 0, 0, 1).toColor(),
colorThematicBreak: const HSLColor.fromAHSL(1, 0, 0, .87).toColor().withOpacity(0.2),
The diff-untouched lines are just text-node children of the <code>
, not wrapped in spans. (They start with a .w
span with a single space, not sure why.)
<p><span class="user-mention" data-user-id="13313">@Chris Bobbe</span></p>
<p><span class="user-mention" data-user-id="17327">@Chris Bobbe (Test Account)</span></p><p><span class="user-mention" data-user-id="17327">@Chris Bobbe (Test Account)</span></p><div class="spoiler-block"><div class="spoiler-header">
<p>regular <strong>bold</strong></p>
</div><div class="spoiler-content" aria-hidden="true">
<p>content</p>
</div></div><h1><del><strong>bold</strong></del></h1><div class="spoiler-block"><div class="spoiler-header">
<p><em>italic <strong>bold</strong></em></p>
</div><div class="spoiler-content" aria-hidden="true">
<p>content</p>
</div></div><h1><span class="user-mention silent" data-user-id="13313">Chris Bobbe</span></h1><div class="spoiler-block"><div class="spoiler-header">
<h1>h1: regular <strong>bold</strong></h1>
</div><div class="spoiler-content" aria-hidden="true">
<p>content</p>
</div></div><div class="spoiler-block"><div class="spoiler-header">
<h1>h1</h1>
</div><div class="spoiler-content" aria-hidden="true">
<p>content</p>
</div></div><div class="codehilite" data-code-language="Dart"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">ContentExample</span><span class="w"> </span><span class="p">{</span>
</code></pre></div><div class="codehilite" data-code-language="Diff"><pre><span></span><code><span class="gh">diff --git lib/widgets/content.dart lib/widgets/content.dart</span>
<span class="gh">index 1715d41e7..43c747232 100644</span>
<span class="gd">--- lib/widgets/content.dart</span>
<span class="gi">+++ lib/widgets/content.dart</span>
<span class="gu">@@ -37,6 +37,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {</span>
<span class="w"> </span> colorCodeBlockBackground: const HSLColor.fromAHSL(0.04, 0, 0, 0).toColor(),
<span class="w"> </span> colorDirectMentionBackground: const HSLColor.fromAHSL(0.2, 240, 0.7, 0.7).toColor(),
<span class="w"> </span> colorGlobalTimeBackground: const HSLColor.fromAHSL(1, 0, 0, 0.93).toColor(),
<span class="gi">+ colorGlobalTimeBorder: const HSLColor.fromAHSL(1, 0, 0, 0.8).toColor(),</span>
<span class="w"> </span> colorMathBlockBorder: const HSLColor.fromAHSL(0.15, 240, 0.8, 0.5).toColor(),
<span class="w"> </span> colorMessageMediaContainerBackground: const Color.fromRGBO(0, 0, 0, 0.03),
<span class="w"> </span> colorThematicBreak: const HSLColor.fromAHSL(1, 0, 0, .87).toColor(),
<span class="gu">@@ -61,6 +62,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {</span>
<span class="w"> </span> colorCodeBlockBackground: const HSLColor.fromAHSL(0.04, 0, 0, 1).toColor(),
<span class="w"> </span> colorDirectMentionBackground: const HSLColor.fromAHSL(0.25, 240, 0.52, 0.6).toColor(),
<span class="w"> </span> colorGlobalTimeBackground: const HSLColor.fromAHSL(0.2, 0, 0, 0).toColor(),
<span class="gi">+ colorGlobalTimeBorder: const HSLColor.fromAHSL(0.4, 0, 0, 0).toColor(),</span>
<span class="w"> </span> colorMathBlockBorder: const HSLColor.fromAHSL(1, 240, 0.4, 0.4).toColor(),
<span class="w"> </span> colorMessageMediaContainerBackground: const HSLColor.fromAHSL(0.03, 0, 0, 1).toColor(),
<span class="w"> </span> colorThematicBreak: const HSLColor.fromAHSL(1, 0, 0, .87).toColor().withOpacity(0.2),
</code></pre></div>
That's the same way "foo" appears in an unstyled code block:
foo
<div class="codehilite"><pre><span></span><code>foo
</code></pre></div>
So when we see text like that, we'll want to apply Text
/ Token
style if it's a syntax-highlighted block (and I guess ditto for unknown tokens), and Zulip's own --color-markdown-code-text
otherwise.
Web doesn't seem to handle this wrinkle. With a color meter, I can see the diff-untouched lines in the highlighted block are the same color as "foo" in the unhighlighted block. Link to those messages: https://chat.zulip.org/#narrow/stream/7-test-here/topic/content/near/1841644
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can check if a code block is syntax-highlighted by looking for a data-code-language
in the codehilite.zulip-code-block
div.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, you know what, it's probably --color-markdown-code-text
that we should ignore, and just use the Pygments Text
/ Token
color wherever we were using that. That'll be way simpler in code.
It's very subtle. The plain, unstyled code block text is now true black, instead of |
I looked at web's (Then I started applying the "non-color Zulip customizations" from |
Oh wow, OK — yeah, if I bring my face right up a few inches from the screen and then flip back and forth, I do see the difference. |
Cool, makes sense. I think a few words saying these came from web/styles/pygments.css like that would be helpful. Maybe just have this comment: // Pygments Monokai:
// https://github.com/pygments/pygments/blob/f64833d9d/pygments/styles/monokai.py
factory CodeBlockTextStyles.dark(BuildContext context) { mention that, in addition to the upstream Pygments link (that the current revision has) for whence the colors were ultimately derived. |
f289473
to
af6add9
Compare
Thanks for the review! Revision pushed, and I've made a note about the followup you mentioned: #756 (comment) |
Web uses black instead of hsl(0deg 0% 15%), the default message text color.
The dark-theme styles, which we'll add soon, have something for all of `CodeBlockSpanType`'s values. While we're at it, write the TODO(zulip#754) to update the light-theme styles. (Hopefully to something that also has a style for all of `CodeBlockSpanType`'s values.)
We might reasonably have declared them alphabetized by the first element in the "packages" list ('Noto Color Emoji', 'Source Code Pro', etc.; the first argument passed to LicenseEntryWithLineBreaks). But I didn't think that would be best in a future where we add something with more than one item in that "packages" list.
For dark theme, web currently uses a mix of Pygments Monokai and Pygments Default. Mixing in Pygments Default seems accidental, so here we just use pure Pygments Monokai. Discussion: https://chat.zulip.org/#narrow/stream/431-redesign-project/topic/code.20span.20colors/near/1832283 LICENSE and AUTHORS files downloaded from: https://github.com/pygments/pygments/blob/f64833d9d/LICENSE https://github.com/pygments/pygments/blob/f64833d9d/AUTHORS (I've included AUTHORS because LICENSE refers to it.) Fixes: zulip#749 Related: zulip#95
af6add9
to
3aaebdb
Compare
Just resolved the conflicts from #759 |
Thanks! Looks good; merging. |
For dark theme, web currently uses a mix of Pygments Monokai and Pygments Default. Mixing in Pygments Default seems accidental, so here we just use pure Pygments Monokai. Discussion.
I've included screenshots, below, of just Pygments Monokai, and of Pygments Monokai with web's adjustments. (Except for the adjustment of putting a border around
err
text; that's hard in Flutter.)Compare with Pygments's own demonstration of Pygments Monokai here: https://pygments.org/styles/
(To make these screenshots, I plugged in dark-theme colors for the code-block background and message background. So just focus on the code blocks and disregard the jarring appearance of light-theme-styled elements elsewhere. When we implement dark theme #95, we'll do it coherently.)
Fixes: #749