Changelog
0.62.0 2021-04-23
OverUnder
atoms (\overset
, etc...).renderMathInElement()
or renderMathInDocument()
,
formulas containing styling information would get too aggressively coalesced,
dropping some styling.renderMathInElement()
or renderMathInDocument()
.Changelog
0.61.0 2021-04-22
Some format options have been renamed:
| Before | Now |
| :------------------------------- | :-------------------------------- |
| "spoken-ssml-withHighlighting"
| "spoken-ssml-with-highlighting"
|
| "mathML"
| "math-ml"
|
| "ASCIIMath"
| "ascii-math"
|
The old spelling is still accepted at runtime but it has been deprecated and you will be removed in a future update.
captureSelection
flag from being selectable.woff
fonts. This change should be transparent, as all supported
browsers support woff2
at this point.\Huge
) to math mode. TeX is inconsistent in how
it handles those. We choose to always apply them in math mode.dcases
environment: like cases
but in displaystyle
by
default.\mbox
by avoiding wrapping it with an unnecessary
\text
command.plonkSound
or keypressSound
option to null
will
suppress sound feedback.keycap
class no
longer needs to be specified for each keycap.defaultMode
property or the default-mode
attribute can be set to a
value of inline-math
to set the mathfield in inline math \textstyle
by
default.\htmlData
, \cssId
and \class
commands.\cdot
. The incorrect
styling resulted in incorrect measurement and vertical layout of some
characters.\ne
, \neq
and \not
.renderMathInElement()
or renderMathInDocument()
do not
duplicate the accessible node.e^x
and d/dx
in the functions
virtual keyboard\displaystyle
, \textstyle
, \scriptstyle
and
\scriptscriptstyle
commands: they apply to the commands to their right.\displaystyle
applies to the
current cell only (not the whole array).skipBoundary
flag would not skip it.skipBoundary
, only the first one would be
skipped.\int
now accounts for the slant of the symbol.convertLatexToMarkup()
or renderMathInDocument()
properly wrap
the generated atoms in a root atom. Without it, some atoms render differently
in static mode than in interactive mode.\overset
(they are adjacent, not over,
unlike \overbrace
).cases
environment should be in inline mode (textstyle
) by default.\overbrace
, \underbrace
, etc...Changelog
0.60.1 2021-04-13
vite
bundler, the library location could not be determined
correctly. As a result, the assets (fonts and sounds) could not be loaded when
in their default location.\enclose{roundedbox}
and other variants.setOptions()
avoid changing the selection unless
necessary (react-mathlive issue #4).Changelog
0.60.0 2021-04-12
Renamed getCaretPosition()
and setCaretPosition()
to get/set caretPoint
.
"Position" refers to where the caret/insertion point is, as an offset inside the expression. These methods return client screen coordinates and the new name better reflect the correct terminology.
Removed deprecated (April 2019) method enterCommandMode()
Replaced ignoreSpacebarInMathMode
option with mathModeSpace
. The
ignoreSpacebarInMathMode
was accidentally not working (#859). However,
the boolean form is problematic as an element attribute (it defaults to true,
but element attributes default to false). It has been replaced with
mathModeSpace
which is more flexible (you can specify which space to use)
and doesn't have the issue of the default boolean value.
Support for iframes. Multiple mathfields in a single document but in different iframes can now share a single virtual keyboard. In the main document, use:
makeSharedVirtualKeyboard({
virtualKeyboardLayout: 'dvorak',
});
And in the iframes, use the use-shared-virtual-keyboard
attribute:
<math-field use-shared-virtual-keyboard></math-field>
See examples/iframe
for more info.
Contribution by https://github.com/alexprey. Thanks!
#555 Support for IME (Input Method Engines) for Japanese, Chinese, Korean and other complex scripts.
applyStyle()
has now more options. Previously it always toggled the style of
the selection. Now it can either toggle or set the style, and modify the
selection or a specific range.
#387 find()
method to search the fragments of an expression that match a
LaTeX string or regular expression.
For example the following code snippet will add a yellow background to the fractions in the expression:
mf.find(/^\\frac{[^}]*}{[^}]*}\$/).forEach((x) => {
mf.applyStyle({ backgroundColor: 'yellow' }, x, {
suppressChangeNotifications: true,
});
});
#387 replace()
method to replace fragments of an expression.
This method is similar to the replace()
method of the String
class. The
search pattern can be specified using a string or regular expression, and the
replacement pattern can be a string or a function. If using a regular
expression, it can contain capture groups, and those can be references in the
replacement pattern.
The following snippet will invert fractions in a formula:
mf.replace(/^\\frac{([^}]*)}{([^}]*)}$/, '\\frac{$2}{$1}');
New LaTeX Mode
This mode replaces the previous Command Mode. While the Command Mode (triggered by pressing the \ or ESC key) was only intended to insert a single LaTeX command (e.g. "\aleph"), the LaTeX Mode is a more comprehensive LaTeX editing mode.
To enter the LaTeX Mode, press the ESC key or the \ key. While in this mode, a complex LaTeX expression can be edited. Press the ESC or Return key to return to regular editing mode.
To quickly peek at the LaTeX code of an expression, select it, then press ESC. Press ESC again to return to the regular editing mode.
To insert a command, press the \ key, followed by the command name. Press the TAB key to accept a suggestion, then the RETURN key to return to regular editing mode (previously pressing the TAB key would have exited the command mode).
Added soundsDirectory
option to customize the location of the sound files,
similarly to fontsDirectory
.
Enabled audio feedback by default.
#707 added support for \begin{rcases}\end{rcases}
(reverse cases
, with
brace trailing instead of leading)
#730 added new CSS variables to control the height of the virtual keyboard:
--keycap-height
--keycap-font-size
--keycap-small-font-size
(only if needed)--keycap-extra-small-font-size
(only if needed)--keycap-tt-font-size
(only if needed)#732 Support for Dvorak keyboard layout
Synchronize the virtual keyboard layout (QWERTY, AZERTY, etc...) with the physical keyboard layout.
Added \htmlData
command, which takes as argument a comma-delimited string of
key/value pairs, e.g. \htmlData{foo=green,bar=blue}
. A corresponding
data-foo
and data-bar
DOM attribute is generated to the rendered DOM.
read-only
mode, it was still possible to
delete a portion of it by pressing the backspace key.typedText
selector dropped its options argument. As a result, the sound
feedback from the virtual keyboard only played for some keys.<math-field>
element the command popover did not
display correctly.plain/text
item.alt+e
, and they are properly
displayed as a composition (side effect of the fix for #555).Complete rewrite of selection handling.
This is mostly an internal change, but it will offer some benefits for new capabilities in the public API as well.
Warning: This is a very disruptive change, and there might be some edge cases that will need to be cleaned up.
The position of the insertion point is no longer represented by a path. It is now an offset from the start of the expression, with each possible insertion point position being assigned a sequential value.
The selection is no longer represented with a path and a sibling-relative offset. It is now a range, i.e. a start and end offset. More precisely, the selection is an array of ranges (to represent discontinuous selections, for example a column in a matrix) and a direction.
These changes have these benefits:
onDelete
function now regroups all the
special handling when pressing the Backspace and Delete keys.find()
method
which returns its results as an array of ranges. It is also possible now to
query and change the current selection, and to apply styling to a portion of
the expression other than the selection.On a historical note, the reason for the original implementation with paths
was based on the TeX implementation: when rendering a tree of atoms (which TeX
calls nodes), the TeX layout algorithm never needs to find the parent of an
atom. The MathLive rendering engine was implemented in the same way. However,
for interactive editing, being able to locate the parent of an atom is
frequently necessary. The paths were a mechanism to maintain a separate data
structure from the one needed by the rendering engine. However, they were a
complex and clumsy mechanism. Now, a parent
property has been introduced in
instance of Atom
, even though it is not necessary for the rendering phase.
It does make the handling of the interactive manipulation of the formula much
easier, though.
Changes to the handling of sentinel atoms (type "first"
)
This is an internal change that does not affect the public API.
Sentinel atoms are atoms of type "first"
that are inserted as the first
element in atom branches. Their purpose is to simplify the handling of "empty"
lists, for example an empty numerator or superscript.
Previously, these atoms where added when an editable atom tree was created,
i.e. in the editor
code branch, since they are not needed for pure
rendering. However, this created situations where the tree had to be
'corrected' by inserting missing "first"
. This code was complex and resulted
in some unexpected operations having the side effect of modifying the tree.
The "first"
atoms are now created during parsing and are present in editable
and non-editable atom trees.
Refactoring of Atom classes
This is an internal change that does not affect the public API.
Each 'kind' of atom (fraction, extensible symbol, boxed expression, etc...) is
now represented by a separate class extending the Atom
base class (for
example GenfracAtom
). Each of those classes have a render()
method that
generates a set of DOM virtual nodes representing the Atom and a serialize()
method which generates a LaTeX string representing the atom.
Previously the handling of the different kind of atoms was done procedurally and all over the code base. The core code is now much smaller and easier to read, while the specialized code specific to each kind of atom is grouped in their respective classes.
Unit testing using Jest snapshot
Rewrote the unit tests to use Jest snapshots for more comprehensive validation.
Changelog
0.59.0 2020-11-04
Changelog
0.58.0 2020-10-11
#225 Added onCommit
listener to mf.options
. This listener is invoked
when the user presses Enter or Return key, or when the field loses
focus and its value has changed since it acquired it. In addition, a change
event is triggered when using a MathfieldElement
. The event previously named
change
has been renamed to input
. This mimics the behavior of <input>
and <textarea>
elements.
#225 Changed the keyboard shortcuts to add columns and rows:
| Shortcut | Command |
| :-------------------------------------------------- | :---------------- |
| ctrl/cmd + Return/Enter | addRowAfter
|
| ctrl/cmd + shift + Return/Enter | addRowBefore
|
| ctrl/cmd + ; | addRowAfter
|
| ctrl/cmd + shift + ; | addRowBefore
|
| ctrl/cmd + , | addColumnAfter
|
| ctrl/cmd + shift + , | addColumnBefore
|
Note that Enter/Return no longer create a matrix/vector when inside a parenthesized expression. Use ctrl/cmd + Return/Enter instead.
Added a commit
command to programmatically trigger the onCommit
listener
change
event.
Added mount
and unmount
events to MathfieldElement
The $text()
method, which is deprecated, was accidentally prematurely
removed. It has been added back.
x=sin
→ x\sin
instead of x=\sin
\xrightarrow
were incorrectly treated
as if they had an invisible boundary, resulting in the cursor being positioned
incorrectly when navigating with the keyboard.Changelog
0.57.0 2020-10-09
This release introduce two major new features which will require code changes. For now, the older API remains supported but it will be dropped in an upcoming release.
Support for MathfieldElement
custom element/web component and <math-field>
tag.
The makeMathField()
function is still supported, but it will be removed in an
upcoming version. You should transition to using <math-field>
or
MathfieldElement
instead.
This transition require the following changes:
MathfieldElement
or declaratively// Before
let mf = MathLive.makeMathField(document.createElement('div'), {
virtualKeyboardMode: 'manual',
});
mf.$latex('f(x) = \\sin x');
document.body.appendChild(mf.$el());
// After
let mfe = new MathfieldElement({
virtualKeyboardMode: 'manual',
});
mfe.value = 'f(x) = \\sin x';
document.body.appendChild(mfe);
or:
<math-field virtual-keyboard-mode="manual">f(x) = \sin x</math-field>
// Before
mf.setConfig({ onContentDidChange: (mf) => {
console.log(mf.$latex())
});
// After
mfe.addEventListener('input', (ev) => {
console.log(mfe.value);
});
Support for web component is an opportunity to revisit the MathLive public API and modernize it.
The goals are:
$latex()
can be used to read or change the content
of the mathfield.$selectedText()
can return the value of the
selection, but there is no way to inspect (or save/restore) the selection.getConfig()
is called getOptions()
in most Javascript text editor
libraries.Mathfield methods
The following Mathfield
methods have been renamed as indicated:
| Before | After |
| :--------------------------- | :------------------------------------- |
| $setConfig()
| setOptions()
|
| getConfig()
| getOptions()
and getOption()
|
| $text()
| getValue()
|
| $latex()
| value
, getValue()
and setValue()
|
| $insert()
| insert()
|
| $hasFocus()
| hasFocus()
|
| $focus()
| focus()
|
| $blur()
| blur()
|
| $selectedText()
| mf.getValue(mf.selection)
|
| $selectionIsCollapsed()
| mf.selection[0].collapsed
|
| $selectionDepth()
| mf.selection[0].depth
|
| $selectionAtStart()
| mf.position === 0
|
| $selectionAtEnd()
| mf.position === mf.lastPosition
|
| $select()
| select()
|
| $clearSelection()
| executeCommand('delete-backward')
|
| $keystroke()
| executeCommand()
|
| $typedText()
| executeCommand('typed-text')
|
| $perform()
| executeCommand()
|
| $revertToOriginalContent()
| n/a |
| $el()
| n/a |
| n/a | selection
|
| n/a | position
|
The methods indicated with "n/a" in the After column have been dropped.
Only the new methods are available on MathfieldElement
(i.e. when using web
components). The Mathfield
class retains both the old methods and the new ones
to facilitate the transition, but the old ones will be dropped in an upcoming
version.
There is also a new selection
property on Mathfield
and MathfieldElement
which can be used to inspect and change the selection and a position
property
to inspect and change the insertion point (caret).
The getValue()
method also now take an (optional) Range
, which is the type
of the selection
property, to extract a fragment of the expression.
Default Exports
While default exports have the benefits of expediency, particularly when converting an existing code base to ES Modules, they are problematic for effective tree shaking. Therefore the default export will be eliminated.
This means that instead of:
import MathLive from 'mathlive';
MathLive.renderMathInDocument();
you will need to use:
import { renderMathInDocument } from 'mathlive';
renderMathInDocument();
The following functions have been renamed:
| Before | After |
| :-------------------------------- | :------------------------------ |
| MathLive.latexToAST()
| Use MathJSON |
| MathLive.latexToMarkup()
| convertLatexToMarkup()
|
| MathLive.latexToMathML()
| convertLatexToMathMl()
|
| MathLive.latexToSpeakableText()
| convertLatexToSpeakableText(
) |
getCaretPosition()
and setCaretPosition()
Selector
has been improvedgetOptions()
(getConfig()
) are more accurate\enclose
is emptyupward
and downward
hooks when navigating out of the
mathfield (now also sent as a focus-out
event)tabIndex
was set to
0 on the mathfield and some area of the mathfield were clicked on. The issue
was that with tabIndex="0"
the mathfield frame would be focusable and when
that happened the focus would correctly switch to the invisible <textarea>
element which is normally focused to receive keyboard events, but this
generated an incorrect blur
event (for the container losing focus) and an
incorrect focus
event (for the <textarea>
gaining focus)config.strings
property did not reflect the state of the localization
strings@stefnotch
for contributing several of the improvements in this
releaseChangelog
0.56.0 2020-08-22
\phantom
, \vphantom
, \hphantom
and \smash[]
\ce
and
\pu
, to display chemical equationsChangelog
0.55.0 2020-08-17
WebPack issues workaround and font loading configuration
Follow up to #508. The fonts can now be loaded either statically or dynamically.
dynamic loading by default, the fonts will get loaded programmatically
when they are needed and the rendering will be deferred until the fonts are
available to avoid unnecessary redrawing. Use this technique if you have a
simple build/bundle workflow. You can still customize the relative path to
the fonts folder using the fontsDirectory
configuration option.
static loading include the mathlive-fonts.css
stylesheet in your page.
The loading of this file will trigget the font to be loaded asynchronously
by the browser. Use this technique if you are using WebPack or have a
build/bundle workflow that renames the font files or in general require the
bundler to know about the required assets.
New packaging options. The distribution files have been split between
minified and non-minified version. In the more common cases, the minified
version (mathlive.min.js
and mathlive.min.mjs
should be used). The
non-minified version (mathlive.js
and mathlive.mjs
can be used to help in
debugging issues or to apply patches).
The fonts failed to load when loading MathLive using a <script>
tag and a
CDN. The fonts folder is now resolved correctly with the following
configurations:
- `<script>` tag and CDN
- `<script>` tag and local file
- `import` and CDN
- `import` and local file