-
Notifications
You must be signed in to change notification settings - Fork 321
KaTeX(8/n): Support colored text in KaTeX content #1670
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
Conversation
6a377e0
to
ad2a745
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.
lib/model/katex.dart
Outdated
if (valueStr.startsWith('#')) { | ||
color = parseCssHexColor(valueStr); | ||
if (color != null) continue; | ||
} | ||
|
||
color = _cssNamedColorsMap[valueStr]; | ||
if (color != null) continue; |
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.
On its face, this looks like even if the value starts with #
it could overwrite that with what it finds in the map.
That won't happen in practice, because no names start with #
. But it'd be cleaner to not have to think about that — once we decide it looks like hex notation, we stick with that and don't try something else. Maybe just wrap this second case in an else
?
lib/model/katex.dart
Outdated
case 'color': | ||
// `package:csslib` parser emits a HexColorTerm for the `color` | ||
// attribute. It automatically resolves the named CSS colors to | ||
// their hex values. The `HexColorTerm.value` is the hex | ||
// encoded in an integer in the same sequence as the input hex |
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.
This is a helpful comment, thanks.
Since the logic in this case gets somewhat long, let's push all that logic, along with this accompanying comment, into a dedicated private helper function. That will help keep it easy to read in isolation, and also keep this surrounding code easy to read when not thinking specifically about colors.
lib/model/katex.dart
Outdated
String? _getRawValue(css_visitor.Expression expression) { | ||
return expression.span?.text; |
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.
This name doesn't seem quite right — this isn't really the value of the expression, so much as the source code of the expression.
When we call this, it does represent the value of a property… but only because this expression is the value of a property. So that's not a fact that this method itself expresses.
I think "get raw text" would be a good name. Or just inline it — that's not really longer, and makes transparent what it does.
lib/model/katex.dart
Outdated
if (match == null) return null; | ||
|
||
String hexValue = match.group(1)!; | ||
hexValue = hexValue.toLowerCase(); |
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.
Is this line needed? I'd have thought that hex.decode
would accept upper as well as lower case.
lib/model/katex.dart
Outdated
/// Parses the CSS hex color notation. | ||
/// | ||
/// See: https://drafts.csswg.org/css-color/#hex-notation | ||
KatexSpanColor? parseCssHexColor(String hexStr) { |
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 for including that spec link — very helpful!
lib/model/katex.dart
Outdated
// Also the generated integer value will be in 0xRRGGBBAA | ||
// sequence (CSS notation), whereas `dart:ui` Color | ||
// requires 0xAARRGGBB. |
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.
This doesn't seem material — even in this version, we break it up into bytes and then say
Color.fromARGB(color.a, color.r, color.g, color.b)
, which isn't a single integer anyway.
For this and the other TeX content PRs, would you also include two things in the PR description:
|
ad2a745
to
4fdd366
Compare
Thanks for the review @gnprice! Pushed an update, PTAL. |
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 for the revision! All looks good modulo a few nits below.
test/model/katex_test.dart
Outdated
static final mathBlockKatexColorFunction = KatexExample.block( | ||
'math block, KaTeX color function, hex color', | ||
// https://chat.zulip.org/#narrow/channel/7-test-here/topic/Rajesh/near/2232197 | ||
r'\color{#f00} 0', |
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.
nit: TeX has no concept of "function"; \color
here is a LaTeX command, which is a type of TeX macro.
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 just sent #1767 to simplify a different aspect of these tests' names and descriptions. Combining that and my comment above, one good version of this would be:
static final mathBlockKatexColorFunction = KatexExample.block( | |
'math block, KaTeX color function, hex color', | |
// https://chat.zulip.org/#narrow/channel/7-test-here/topic/Rajesh/near/2232197 | |
r'\color{#f00} 0', | |
static final color = KatexExample.block( | |
r'\color: 3-digit hex color', | |
// https://chat.zulip.org/#narrow/channel/7-test-here/topic/Rajesh/near/2232197 | |
r'\color{#f00} 0', |
static final mathBlockKatexPhantomFunction = KatexExample.block( | ||
'math block, KaTeX phantom function', | ||
// https://chat.zulip.org/#narrow/channel/7-test-here/topic/Rajesh/near/2229515 | ||
r'\phantom{*}', |
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.
For example (apropos of the "function" question): one fun TeX fact is that \phantom{*}
means exactly the same thing as \phantom *
would; in both cases, *
is the argument consumed by \phantom
.
Similarly, one can write \frac12
— \frac{1}{2}
. With or without curly braces, the \frac
command will consume the next two things as its arguments; the braces just serve to group a whole string of characters and/or commands into a single item, so that they get consumed together as a single argument.
r'\phantom{*}', | |
r'\phantom{*}', |
test/model/katex_test.dart
Outdated
KatexStrutNode(heightEm: 0.6444, verticalAlignEm: null), | ||
KatexSpanNode( | ||
styles: KatexSpanStyles(color: KatexSpanColor(255, 0, 0, 255)), | ||
text: '0', nodes: 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.
nit:
text: '0', nodes: null), | |
text: '0'), |
test/model/katex_test.dart
Outdated
'<span class="base">' | ||
'<span class="strut" style="height:0.6444em;"></span>' | ||
'<span class="mord" style="color:#f00;">0</span></span></span></span></span></p>', [ | ||
KatexSpanNode(styles: KatexSpanStyles(), text: null, nodes: [ |
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.
nit: simplify
KatexSpanNode(styles: KatexSpanStyles(), text: null, nodes: [ | |
KatexSpanNode(nodes: [ |
@@ -604,4 +685,49 @@ void main() async { | |||
}, skip: Platform.isWindows, // [intended] purely analyzes source, so | |||
// any one platform is enough; avoid dealing with Windows file paths | |||
); | |||
|
|||
group('parseCssHexColor', () { |
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.
nit: let's keep the "all examples are tested" test at the end — it's a rather special kind of test, in that it reads the test file's own source code
4fdd366
to
ed53544
Compare
Thanks for the review @gnprice! Pushed an update, PTAL. |
Thanks! Looks good; merging. Made a tweak to clarify one test name: // KaTeX custom color macros, see https://github.com/KaTeX/KaTeX/blob/9fb63136e/src/macros.js#L977-L1033
static final customColorMacro = KatexExample.block(
- r'\red: custom color macro',
+ r'\red, custom KaTeX color macro: CSS 6-digit hex color', since the meaning of "custom" here is that it's something KaTeX made up (according to that handy link you included in the comment). |
Oh and also tweaked the commit message:
Now that we've got the KaTeX logic all into its own files, I think a corresponding specific prefix is helpful. |
ed53544
to
f9ea6c9
Compare
Survey results
Fixes: #1679