Skip to content

Add \ion, \positiveion, \negativeion commands for chemistry notation#45

Open
drdrew42 wants to merge 2 commits into
openwebwork:mainfrom
drdrew42:feature/chem-ions
Open

Add \ion, \positiveion, \negativeion commands for chemistry notation#45
drdrew42 wants to merge 2 commits into
openwebwork:mainfrom
drdrew42:feature/chem-ions

Conversation

@drdrew42

Copy link
Copy Markdown
Member

What

Adds three LaTeX commands for chemistry ion-charge notation:

  • \ion[sign]{charge} — a superscript-only command: an editable charge block followed by a fixed +/- sign, rendering e.g. the "2+" of a 2+ cation.
  • \positiveion / \negativeion — sign-bound shorthands that canonicalize to \ion[+]{…} / \ion[-]{…}.

Why

These commands existed in a downstream MathQuill fork used for WeBWorK chemistry problems — the chemistry answer-entry toolbars drive \positiveion/\negativeion for entering ion charges. They were lost when that work moved onto @openwebwork/mathquill, silently breaking those toolbar buttons. Restoring them upstream lets the downstream work drop the private fork.

How

Ion extends SupSub, mirroring the existing subscript/superscript classes in commands.tssupsub = 'sup', an htmlTemplate carrying the editable charge block plus a .mq-ion-classed sign span, and a parser() built on latexMathParser.optBlock / .block exactly like NthRoot. latex() serializes to \ion[sign]{charge}; an absent optional sign defaults to +, and an empty charge block to 1.

.mq-ion is a styling hook on the sign span — no CSS rule is added; it renders correctly with the existing mq-sup styles.

Testing

  • npm run build, npm run lint:check, and npm run format:check all pass.
  • Round-trip parse tests added to test/latex.test.ts (the ion charges test), following the existing assertParsesLatex pattern.

🤖 Generated with Claude Code

@drgrice1

Copy link
Copy Markdown
Member

I think you need to add some explanation of how to use this, and how this would work with PG. This isn't something that can be directly typed into a MathQuill input.

@drdrew42

drdrew42 commented Jun 8, 2026

Copy link
Copy Markdown
Member Author

Originally, LibreTexts wanted to implement a toolbar for chemistry problems (see repo for foundations), and looped in Davide to help improve contextReaction.pl (which includes implementation of ions, compatible with this extension of MathQuill)... and some of that work has now been folded into PG official.

They're finally pulled up to date with PG, but that migration has hit a snag -- as it seems I never submitted the ions implementation to our fork of MathQuill.

Ions are not "real" LaTeX, and it is unexpected that any student would type them in (though they could...), rather it is expected that mathquill toolbar entries be added for them (LibreTexts has macros for this already):

{ 	id: 'positiveion',
	latex: '\\positiveion',
	tooltip: 'postitive ion',
	icon: '\\text{ }^{\\text{ }+}' 
},
{ 	id: 'negativeion',
	latex: '\\negativeion',
	tooltip: 'negative ion',
	icon: '\\text{ }^{\\text{ }-}' 
},

I have a similar request to add a \sci command -- enabling the toolbar-triggering of a scientific notation entry (which I can extend on this PR, or file separately). Clearly students can individually enter the multiplication, base 10, and exponent -- but there is no way for the toolbar to facilitate a "combo move" like this without a dedicated command. Or maybe I've missed something?

@drgrice1

drgrice1 commented Jun 8, 2026

Copy link
Copy Markdown
Member

Now that the toolbar is part of this repository, you should merge in the main branch to get it and demonstrate the usage, or how to implement a toolbar button. Currently with this pull request I am not able to get anything to work with the toolbar.

@drdrew42

drdrew42 commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

Sorry, I had the triple-layer escaping going there, only need the double for input-test.js

I had no problems adding the following to input-test.js

mathField.options.addToolbarButtons([                                                                                                                                                                                                                                                
    { id: 'sci', latex: '\\sci', tooltip: 'scientific notation', icon: '\\times10^\\text{ }' },                                                                                                                                                                                        
    { id: 'positiveion', latex: '\\positiveion', tooltip: 'positive ion', icon: '\\text{ }^{\\text{ }+}' },                                                                                                                                                                            
    { id: 'negativeion', latex: '\\negativeion', tooltip: 'negative ion', icon: '\\text{ }^{\\text{ }-}' }                                                                                                                                                                             
]);                                                                                                                                                                                                                                                                                  

Well, I say no problems -- there's some issue with the appearance of the icons, I'm working on that. With the ions, it's a matter of combining whitespace with another glyph...

  1. Do you want these buttons actually added to input-test.js in this PR?
  2. Do you want me to fix the whitespace+glyph spacing?

@drgrice1

drgrice1 commented Jun 9, 2026

Copy link
Copy Markdown
Member

No, I think those buttons shouldn't be added to the input-test.html file. I only added the subscript button to demonstrate the way to add buttons.

I figured out how to use this. What was confusing me was that since these define from SupSubs the supSubsRequireOperand applies. So something needs to be typed first to use these.

One thing that is going to be needed for these is mathspeak.

@drdrew42

drdrew42 commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

Okay, I've added mathspeak for \sci and the ions. But in writing the corresponding tests, I found that the unit-test.html wasn't running the suite -- so I added that fix as a follow-up commit.

@drgrice1 drgrice1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The general code for the ion charges and scientific notation is looking okay now. I think it is a bit odd to derive scientific notation from a supsub, but that is okay for now.

There is one thing that bothers me with this pull request in general. This is adding code for these chemistry elements that are not in any official PG macro or internal PG code. This is instead for unofficial code and macros in https://github.com/WeBWorK-for-Chemistry/WeBWorKChemistry. It seems that the things in that repository should be submitted for review to PG, and made official before changes needed for that should be added here.

Comment thread public/input-test.js Outdated
{ id: 'positiveion', latex: '\\positiveion', tooltip: 'positive ion', icon: '\\text{ }^{\\text{ }+}' },
{ id: 'negativeion', latex: '\\negativeion', tooltip: 'negative ion', icon: '\\text{ }^{\\text{ }-}' }
]);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I said not to add these. In general, input-test.html is set up to have the default options that are used by PG. The exception is the addition of the subscript button to demonstrate the usage of the the addToolBarButtons method, and don't entirely like that I did that. I was planning to eventually add a user interface element to the page to allow dynamically adding and removing buttons from the toolbar. I don't like these buttons that are non-standard being added to this.

Comment thread public/unit-test.html Outdated
};
// Run after window load so the test bundle (mathquill.test.js, included at
// the end of the body) has registered its suites before mocha.run().
window.addEventListener('load', () => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems to be an issue that is specific to Google Chrome (and maybe some others), but it does not occur in Firefox, and only happens when the dev server hot reloads. On initial page load the unit tests work as they should, but when the dev server hot reloads they don't. You need to refresh the page to get the unit tests to run again. I have noticed this before, but didn't care enough to look into it and fix it.

Don't use a load event for this though. Instead just reorganize the script tags. End the first script tag on line 31 above. Then move the lines

		<!-- include the library with the tests inlined -->
		<script id="mathquill" src="mathquill.test.js"></script>

after that. Then start a new script tag after that.

@drdrew42 drdrew42 force-pushed the feature/chem-ions branch from 14575de to 5d55ecf Compare July 3, 2026 18:32
@drdrew42

drdrew42 commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

I've rebuilt this from main to address everything cleanly — it's now two focused commits (ions, then \sci), and input-test.js / unit-test.html are untouched.

On whether this belongs upstream of official PG: the ion MathObject is official PG now, macros/contexts/contextReaction.pl implements a Context for reactions "composed of sums of integer multiples of elements, molecules, ions, compounds, and complexes." So the ion commands here aren't propping up unofficial code; they're the input/rendering side of an already-official PG capability. \sci is the one piece still specific to the LibreTexts toolbar, but scientific notation is arguably PG (though there's still discrepancy with the macro that requires x for multiplication)

\sci reparented to MathCommand: you were right that building it on SupSub was odd. It's now a MathCommand, which also drops the "type something first" quirk while still rendering/navigating the exponent as a superscript. Its mathspeak test needs no supSubsRequireOperand override now, confirming it stands on its own.

@drgrice1

drgrice1 commented Jul 3, 2026

Copy link
Copy Markdown
Member

In that case, remove the comment on lines 254 - 255 of the code. Don't refer to external repositories in the code. You can reference it in the commentary in this pull request, but please don't put it into the code.

@drdrew42 drdrew42 force-pushed the feature/chem-ions branch from 5d55ecf to 3eafdb1 Compare July 3, 2026 19:41

@drgrice1 drgrice1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks good now.

One thing that would be nice would be if an answer is in the contextReactions.pl context, then the buttons would be automatically added to the toolbar for that answer. This is done for the parserLogb.pl macro. But that is done essentially here. If the logsChangeBase option is set, then the toolbar includes the subscript button. It would take something different for this, since there is not option that enabled or disables it. Perhaps this could be done by creating JavaScript in PG that is added when the Reaction context is used.

@drgrice1

drgrice1 commented Jul 3, 2026

Copy link
Copy Markdown
Member

Once this is merged, then I will create another pull request to bump the version and publish it. I also will fix the npm security vulnerabilities and new script warnings. Then I will add a pull request to PG to switch to the new version.

drdrew42 and others added 2 commits July 3, 2026 16:07
Add a superscript-only Ion command that renders an editable charge block
followed by a fixed +/- sign: \ion[+]{2} renders as the "2+" of a 2+
cation. \positiveion and \negativeion are sign-bound shorthands.

These support chemistry answer entry -- the ion MathObject is part of
official PG via contextReaction.pl, and the LibreTexts chemistry toolbars
insert these commands.

Includes mathspeak ("charge <n> positive|negative"), toolbar-icon CSS so
the charge glyph renders in a button, and latex/aria tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a \sci{exp} command that renders a fixed ×10 followed by an editable
superscript exponent block: \sci{8} renders as the "×10⁸" of 3.5×10⁸.

Model it as a MathCommand rather than a SupSub. Scientific notation is a
"×10 to a power" operator, not a superscript, so deriving it from SupSub
brought along supSubsRequireOperand (the "type something first" quirk)
and the superscript-merging machinery, neither of which applies here.
The exponent still renders and navigates as a superscript via the mq-sup
markup and the up/down wiring in finalizeTree.

text() serializes the explicit operations (*10^8), not E-notation, so
the multiplication and power survive into the answer string. Includes
ordinal mathspeak ("times ten to the 8th power") and latex/aria tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@drdrew42 drdrew42 force-pushed the feature/chem-ions branch from 3eafdb1 to 69be2c3 Compare July 3, 2026 20:09
@drdrew42

drdrew42 commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

One thing that would be nice would be if an answer is in the contextReactions.pl context, then the buttons would be automatically added to the toolbar for that answer. This is done for the parserLogb.pl macro. But that is done essentially here. If the logsChangeBase option is set, then the toolbar includes the subscript button. It would take something different for this, since there is not option that enabled or disables it. Perhaps this could be done by creating JavaScript in PG that is added when the Reaction context is used.

Yeah, this occurred to me as well (kind of same if/when we update for ScientificNotation) -- generally speaking the surface between PG problem <--> mathquill toolbar and how do we cleanly enable the answer object to inform the corresponding toolbar (without giving away too much about the structure of the right answer)?

@drgrice1

drgrice1 commented Jul 4, 2026

Copy link
Copy Markdown
Member

I was thinking that if you want to add an option like includeIonButtons, that would be acceptable. Then the existing mechanism in PG for a correct to set MathQuill options could be utilized for the ReactionContext to add the buttons.

@drgrice1

drgrice1 commented Jul 4, 2026

Copy link
Copy Markdown
Member

I guess the subscript button is actually added in the mqeditor.js code, and not here. Perhaps an option the the actual MathQuill code ignores could do that for the ion buttons there.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants