desmosinc / mathquill

Magic textboxes where you can type math as easily as writing!
mathquill.com
132 stars 39 forks source link

Add `\lim` and `customLetters`, fix `\lbrack` and companions, parse `\left\lfloor` and ceil, and parse lone ampersands properly #284

Open zsakowitz opened 4 months ago

zsakowitz commented 4 months ago

In advance, I apologize for the lack of modularity in this pull request. I have added three things (now five, see later comments) which I believe to be very useful, but I will understand if I should need to split this into three pull requests, or if only some of the items are added.

Limit Node — New Node Type

Added Limit node (which can be accessed via \lim or \limit). It is special-cased (like SummationNotation) to be ignored when creating fractions or binomials. Typing / when a limit is before will exclude the limit from the numerator of the newly created fraction.

Reasoning: I would like to have a \lim node in my own projects. Currently, I export all MathQuill output variables to a module, and I add things to LatexCmds from there. However, the \lim node needs special-casing so it isn't put in fraction numerators, so I propose it be added to MathQuill core. It would also be useful to be able to type limit notation into Desmos for rendering purposes, even if it doesn't have any proper functionality.

The limit node aligns itself such that the word lim is on the baseline, as pictured below.

Screenshot 2024-05-27 at 11 25 09 AM

customCharacters option — Adds Extensibility

Added customCharacters option, to allow future special casing of characters other than f. When this option is passed, any characters it lists will have their CharCmds or LatexCmds forms used instead of the default symbol for that character. For example, if customCharacters: ['m'] is listed and CharCmds or LatexCmds has an entry for it, the character m will be displayed using that entry instead of as its default letter.

This option defaults to 'f' if not specified, so it is perfectly backwards compatible.

Reasoning: I would like to have custom single-letter commands in my own projects, and I have been adding these via the methods specified in the section about the Limit node. However, these cannot be added by autoOperatorNames, so there should be a mechanic created to allow characters to be automatically converted into custom commands.

This also makes it possible to easily disable the special-casing of 'f' (which, while already possible by using CSS overrides, is difficult and feels hacky).

Here is an example of a special-cased m variable for mouse position and a t variable for time, but also properly converts to commands and operator names when near them. This would not be possible without adjusting MathQuill core.

ezgif-4-160f8f08db

Fixes to \lbrack, \rbrack, \slash, and \vert — Minor Bug Fix

Currently, the \lbrack, \rbrack, \slash, and \vert commands show text rendered in Symbola when they are included in a MathQuill field. This is almost certainly incorrect behavior. I assume that those commands are meant to render proper characters, such as in the below image (my fix is below).

Screenshot 2024-05-27 at 11 20 10 AM

Screenshot 2024-05-27 at 11 20 22 AM

Reasoning: this is likely a bug and should be fixed.

zsakowitz commented 4 months ago

It appears I forgot a null check, as many of the tests are failing due to it. Please allow a moment to fix it.

zsakowitz commented 4 months ago

I have added two more things which must be implemented internally, and cannot be added by external software.

First, the \left and \right commands now accept \lfloor, \lceil, \rfloor, and \rceil in all the proper places. This makes implementing proper floor and ceiling commands much easier.

Second, a lone ampersand is now first checked against the CharCmds namespace, although \& is still first checked against LatexCmds. This makes it possible to start implementing things like \begin{align} and such which use ampersands other than the \& form to align items.

zsakowitz commented 4 months ago

If you would like, I have a proper implementation of \floor and \ceil already done. I have not added it here since, after my internal changes are used, it can be added externally just by appending items to LatexCmds, and thus does not need to be part of MathQuill core.

eluberoff commented 4 months ago

This is awesome -- thank you so much for sharing these contributions. We haven't yet taken outside contributions to our repo directly, so need to do a little work on our end to make sure our ducks are in a row.

One thing to start: have you signed Mathquill's CLA by chance? https://cla-assistant.io/mathquill/mathquill. I bet we can piggy-back off of that (we might need to set up our own CLA). Will review the rest of this over the next week or so with the team and decide how we want to proceed. Again, so grateful!

zsakowitz commented 4 months ago

I have just signed that CLA. The code is all my own (some copied from the templates of other MathQuill nodes, but I assume that's perfectly fine), and I'm happy to let MathQuill and Desmos use it. Let me know if you all make one. Thanks for the positive response!

zsakowitz commented 4 months ago

A question: is there a way to force a node to reevaluate spacing around binary operators and unitalicized operator names? I'm trying to implement a sort of extendable node which can dynamically change how many blocks it has, but every time I change the block order, binary operators remove any space around them and words like log turn into italicized variables. Is there a method to force a block to "reevaluate" its contents in this way?

zsakowitz commented 4 months ago

Nevermind. I have found a solution.

zsakowitz commented 4 months ago

As part of the extendable nodes, I'm using the character & as a sort of alignment node (like in LaTeX \begin{align}), so I've removed it from the automatically converted fraction and binomial top list. It shouldn't affect anything, as currently, typed ampersands have a ctrlSeq of \&, not &.

zsakowitz commented 4 months ago

Apologies if this is getting a bit large. I'm trying to merge anything I'm working on that would be difficult to implement externally.

jared-hughes commented 4 months ago

To make reviewing easier, I would greatly appreciate if this is split into a few separate PRs, since these seem to be generally unrelated changes. I'd suggest a split like this:

  1. bugfixes
  2. limit
  3. custom letters

Some feedback for now, from a quick skim:

zsakowitz commented 4 months ago

I would greatly appreciate if this is split into a few separate PRs

Sounds good. I'll also make a PR for the floor and ceil commands, which seem to work now.

I'm curious about how you mutate CharCmds to add a command for letters like m. Just adding an extra file? I wonder if this is worth making a proper API for this, then customCharacters could be treated as the keys of a configuration object.

In personal projects, I run make to get the main MathQuill file, then export anything I need to access, such as CharCmds, MathCommand, and the like. Then in the file where I load MathQuill, I add properties to CharCmds and everything seems to work properly.

This will need tests, at least for limit and custom letters. The limit test could be in typing.test.ts. The custom letters could maybe go into publicapi.test.ts.

I'm not entirely sure how to write tests, but I'll try.

It's hard to tell if anything changed in math.less other than the 15 lines at the end. Looks like Prettier was ran on it (while I would like to format everything with Prettier, mixing it in with a feature PR is not the right place). In VS Code, you there's a command "Save without formatting" to save without applying Prettier or any other formatter.

I didn't realize Prettier ran on accident, and will update the file to no longer be formatted using it.

zsakowitz commented 4 months ago

The testing framework looks wonderful to use. It shouldn't be hard to make it work.