Skip to content
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

Implicit \color, explicitly grouped \textcolor #619

Merged
merged 5 commits into from Jun 13, 2017

Conversation

edemaine
Copy link
Member

@edemaine edemaine commented Jan 10, 2017

I've implemented \color and \textcolor to behave as they do in LaTeX (specifically, the color package):

{\color{red}This is red.}
\textcolor{red}{This is also red}

Sadly, this differs from current KaTeX and MathJax which would only make the T red in the first example (as if \color were actually \textcolor). So this change may break some existing code. But I think it's for the better, as LaTeX should be the master reference here.

@edemaine edemaine mentioned this pull request Jan 10, 2017
@kevinbarabash
Copy link
Member

kevinbarabash commented Jan 10, 2017

I didn't realize there was a color package. I forgot that there's a color package. It's too bad about the difference in behavior. I think we want this, we just need to communicate the breaking change along with suggested workarounds.

@kevinbarabash
Copy link
Member

@edemaine
Copy link
Member Author

edemaine commented Jan 10, 2017

As I understand it, this is the only way to change color in LaTeX. There are other packages, e.g. xcolor, but they build on the same basic interface.

@xymostech
Copy link
Contributor

This is admittedly selfish, but KA has a ton of math expressions that would break because of this change. Also, our previous \color function was compatible with MathJax, which was the reason we implemented it the way we did.

@edemaine
Copy link
Member Author

edemaine commented Jan 11, 2017

FWIW, MathJax defines a color extension that changes the behavior to match LaTeX. I suppose KaTeX could do the same... though personally I think it makes more sense to match LaTeX and MathJax+color.

(Also FWIW, to fix those KA expression, you just need to replace \color with \textcolor... But I don't know how hard that is to do globally.)

@kevinbarabash
Copy link
Member

@xymostech we're already preprocessing our math so it shouldn't be hard to replace \color with \textcolor.

@edemaine
Copy link
Member Author

@xymostech Another thing we could do is add an oldColor or colorIsTextColor option to the options set, to enable backwards compatibility mode...

@gagern
Copy link
Collaborator

gagern commented Jan 20, 2017

I guess you could also declare a macro \color which expands to \textcolor. That way you don't have to go poking around in some string literal which might one day contain things like \verb and \def and whatnot, but could still override \color to behave like \textcolor on a per-size basis.

Nevertheless, this change should come with a bump to 0.8.0, not in the 0.7 line of releases.

nolatex: different syntax and different scope
ColorSpacing: \color{red}{\displaystyle \int x} + 1
ColorSpacing: \textcolor{red}{\displaystyle \int x} + 1
ColorImplicit: \color{red}red\color{blue}blue
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this test should ensure that a) ending a group restores previous color and b) ending a \textcolor does return to the previous implicit color. Something like

bl{ack\color{red}red\textcolor{green}{green}red\color{blue}blue}black

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point, and nice test! Changed.

@edemaine
Copy link
Member Author

@gagern Good idea. We could suggest defining a macro '\color': '\textcolor' in release notes to 0.8.0, assuming it gets approved at all. I'll just reiterate that I think it's good to use LaTeX as the reference model. Even if MathJax is the reference model, it offers both options.

@gagern
Copy link
Collaborator

gagern commented Jan 20, 2017

Code looks good to me. I'd like a go-ahead from @xymostech, though, to make sure the workaround for the incompatibility is feasible for KA.

@edemaine
Copy link
Member Author

@xymostech or @kevinbarabash, could we make a decision here? I see two reasonable options:

  1. Leave \color as is (two-argument function) because it's compatible with MathJax without any flags. But provide an option that switches \color to behave as in LaTeX, just like MathJax does.
  2. Change \color to make it compatible with LaTeX (one-argument function changing current group). But provide an option that switches \color to behave as in MathJax (i.e. old behavior) for (somewhat manual) backwards compatibility.

Option 1 has the advantage of backwards compatibility without option changing. Option 2 is preferable to me because KaTeX's mantra is/should be "renders just like LaTeX". But it would probably require a significant version increment.

In both cases, we can provide \textcolor which behaves just like LaTeX, because that should unambiguously be a two-argument function.

@kevinbarabash
Copy link
Member

@edemaine let's go with option 2. Will want to bump the version number to 0.8.x when we do a publish that includes this change.

@edemaine
Copy link
Member Author

Cool, thanks, @kevinbarabash ! That's almost what this PR does. Preference on calling the option oldColor or colorIsTextColor or something else?

@kevinbarabash
Copy link
Member

kevinbarabash commented Jun 10, 2017

colorIsTextColor is more descriptive so my vote would be for that.

@edemaine
Copy link
Member Author

4dd21a7 adds a colorIsTextColor, documentation in README, and parsesLike tests that confirm the exact behavior of \color in the three cases (no specification, and colorIsTextColor set to false or true).

Copy link
Member

@kevinbarabash kevinbarabash left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -49,6 +49,7 @@ You can provide an object of options as the last argument to `katex.render` and
- `throwOnError`: `boolean`. If `true`, KaTeX will throw a `ParseError` when it encounters an unsupported command. If `false`, KaTeX will render the unsupported command as text in the color given by `errorColor`. (default: `true`)
- `errorColor`: `string`. A color string given in the format `"#XXX"` or `"#XXXXXX"`. This option determines the color which unsupported commands are rendered in. (default: `#cc0000`)
- `macros`: `object`. A collection of custom macros. Each macro is a property with a name like `\name` (written `"\\name"` in JavaScript) which maps to a string that describes the expansion of the macro.
- `colorIsTextColor`: `boolean`. If `true`, `\color` will work like LaTeX's `\textcolor`, and take two arguments (e.g., `\color{blue}{hello}`), which restores the old behavior of KaTeX (pre-0.8.0). If `false` (the default), `\color` will work like LaTeX's `\color`, and take one argument (e.g., `\color{blue}hello`). In both cases, `\textcolor` works as in LaTeX (e.g., `\textcolor{blue}{hello}`).
Copy link
Member

Choose a reason for hiding this comment

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

nice

@@ -166,6 +166,14 @@ defineFunction("\\color", {
};
});

// \color is handled in Parser.js's parseImplicitGroup
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for commenting this. It would be nice to have a way to mark functions in this file as to whether or not the parser needs to the parse an implicit group for them.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. @gagern and I had discussed this at some point, and it felt like all the implicit group parsing could be moved to functions.js. Worth considering in the future...

" \\color{#̲f̲f̲f̲f̲f̲f̲{̲t̲e̲x̲t̲}");
expect("\\textcolor{#ffffff{text}").toFailWithParseError(
"Invalid color: '#ffffff{text' at position 12:" +
" \\textcolor{#̲f̲f̲f̲f̲f̲f̲{̲t̲e̲x̲t̲}");
Copy link
Member

Choose a reason for hiding this comment

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

I don't even know what that character is, lol.

it("should use two-argument \\color if requested", function() {
expect(oldColorExpression).toParseLike("\\textcolor{#fA6}{x}y", {
colorIsTextColor: true,
});
Copy link
Member

Choose a reason for hiding this comment

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

Nice tests!

nolatex: different syntax and different scope
ColorSpacing: \color{red}{\displaystyle \int x} + 1
ColorSpacing: \textcolor{red}{\displaystyle \int x} + 1
ColorImplicit: bl{ack\color{red}red\textcolor{green}{green}red\color{blue}blue}black
Copy link
Member

Choose a reason for hiding this comment

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

nice

@kevinbarabash kevinbarabash merged commit 25dde7f into KaTeX:master Jun 13, 2017
@kevinbarabash
Copy link
Member

@edemaine thanks for the PR. Sorry for taking so long to make a decision regarding \color's behavior.

@edemaine
Copy link
Member Author

No worries -- big decisions are hard! Thanks for reviewing + merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants