Socket
Socket
Sign inDemoInstall

mathlive

Package Overview
Dependencies
Maintainers
1
Versions
171
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mathlive - npm Package Compare versions

Comparing version 0.33.2 to 0.34.0

47

CHANGELOG.md

@@ -0,1 +1,26 @@

##
### Bug Fixes
- Fix #364: Some expressions containing placeholders, when inserted, would not have the placeholder selected. For example, when using the "differentialD" key in the virtual keyboard.
- Fix #349:
- 'latex-expanded' format no longer returns `\mleft` and `\mright`. This
format is intended for inter-exchange with other TeX-compatible renderers
and the `\mleft` and `\mright` commands are not widely deployed.
- The content exported to the clipboard is now surrounded by `$$` to more
clearly indicate that the content is using TeX format.
- When pasting content that begins/ends with `$` or `$$`, assume LaTeX format
- Fix keyboard shortcuts, e.g. "alt+(" or "alt+v"
- Fix #354: The argument of `\operatorname` is of type 'math', not 'text'. This means that using the '\text' command inside the argument is valid and that spaces should be ignored by default (but the `~` character can be used to insert a space in that context).
- Fix #282: Some keys from the virtual keyboards ('e', 'i') produce an incorrect input.
- Fix #227: An operator (`\sin`) following some text is incorrectly considered
to be part of the text.
### Features / Improvements
- Documented `suppressChangeNotifications` options for `$insert()`
- Document `config.smartMode` (#312)
- The 'surd' (root) and 'leftright' (fences) elements now change color when the caret is inside their body. This helps distinguish the case where the caret position may be ambiguous, for example when it is either after the last element of the body of a 'surd' or the first element after the 'surd'.
- #339: Read-only mode. Set the mode to read-only with `mf.$setConfig({readOnly: true})`. When this mode is activated, the formula can be selected (so it can be copied), but it cannot be modified by the user. Progammatic modification is still possible.
## 0.33 (December 16, 2019)

@@ -227,3 +252,3 @@

config.inlineShortcuts = {
in: "\\in"
in: '\\in',
};

@@ -237,6 +262,6 @@ ```

in: {
mode: "math",
after: "space+letter+digit+symbol+fence",
value: "\\in"
}
mode: 'math',
after: 'space+letter+digit+symbol+fence',
value: '\\in',
},
};

@@ -297,3 +322,3 @@ ```

- #132: Support for smart fence with `{}`, and `\langle`.
- Pressing the spacebar next to a closing smartfence will close it. Useful
- Pressing the spacebar next to a closing smartFence will close it. Useful
for semi-open fences.

@@ -389,6 +414,6 @@ - Improved rendering performance by 8%

```javascript
MathLive.makeMathField("input", {
MathLive.makeMathField('input', {
onContentDidChange: mf => {
document.getElementById("output").innerHTML = mf.latex();
}
document.getElementById('output').innerHTML = mf.latex();
},
});

@@ -434,3 +459,3 @@ ```

<script type="module">
import MathLive from "../../dist/mathlive.mjs";
import MathLive from '../../dist/mathlive.mjs';
</script>

@@ -470,3 +495,3 @@ ```

```javascript
import MathLive from "../../dist/src/mathlive.js";
import MathLive from '../../dist/src/mathlive.js';
MathLive.makeMathField(/*...*/);

@@ -473,0 +498,0 @@ ```

@@ -41,2 +41,3 @@ /**

@property {string} plonkSound?
@property {boolean} readOnly?
@property {"mathlive" | "sre"} textToSpeechRules?

@@ -103,2 +104,3 @@ @property {"ssml" | "mac"} textToSpeechMarkup?

plonkSound?: string;
readOnly?: boolean;
textToSpeechRules?: "mathlive" | "sre";

@@ -461,2 +463,4 @@ textToSpeechMarkup?: "ssml" | "mac";

*
* @param {object} options.style
*
* @param {boolean} options.resetStyle - If true, the style after the insertion

@@ -466,2 +470,9 @@ * is the same as the style before. If false, the style after the

*
* @param {boolean} options.smartFence - If true, promote plain fences, e.g. `(`,
* as `\left...\right` or `\mleft...\mright`
*
* @param {boolean} options.suppressChangeNotifications - If true, the
* handlers for the contentWillChange, contentDidChange, selectionWillChange and
* selectionDidChange notifications will not be invoked. Default `false`.
*
* @category Changing the Content

@@ -477,3 +488,6 @@ * @method MathField#$insert

mode: "text" | "math" | "";
style: any;
resetStyle: boolean;
smartFence: boolean;
suppressChangeNotifications: boolean;
}): void;

@@ -787,3 +801,3 @@ /**

* used at the end of repeating digits. **Default** = `"}"`
*
*
* @return {string} The LaTeX representation of the Abstract Syntax Tree, if valid.

@@ -790,0 +804,0 @@ * @category Converting

@@ -16,4 +16,6 @@ /* eslint no-console:0 */

if (braceLevel <= 0 &&
text.slice(index, index + delimLength) === delimiter) {
if (
braceLevel <= 0 &&
text.slice(index, index + delimLength) === delimiter
) {
return index;

@@ -51,3 +53,3 @@ } else if (character === '\\') {

type: 'text',
data: text.slice(0, currIndex)
data: text.slice(0, currIndex),
});

@@ -68,3 +70,3 @@ }

type: 'text',
data: text.slice(currIndex, nextIndex)
data: text.slice(currIndex, nextIndex),
});

@@ -78,3 +80,4 @@ }

text,
currIndex + leftDelim.length);
currIndex + leftDelim.length
);
if (nextIndex === -1) {

@@ -89,7 +92,9 @@ done = true;

currIndex + leftDelim.length,
nextIndex),
nextIndex
),
rawData: text.slice(
currIndex,
nextIndex + rightDelim.length),
mathstyle: mathstyle
nextIndex + rightDelim.length
),
mathstyle: mathstyle,
});

@@ -105,3 +110,3 @@

type: 'text',
data: text.slice(currIndex)
data: text.slice(currIndex),
});

@@ -118,7 +123,6 @@ }

function splitWithDelimiters(text, delimiters) {
let data = [{type: 'text', data: text}];
let data = [{ type: 'text', data: text }];
for (let i = 0; i < delimiters.inline.length; i++) {
const delimiter = delimiters.inline[i];
data = splitAtDelimiters(
data, delimiter[0], delimiter[1], 'textstyle');
data = splitAtDelimiters(data, delimiter[0], delimiter[1], 'textstyle');
}

@@ -128,3 +132,7 @@ for (let i = 0; i < delimiters.display.length; i++) {

data = splitAtDelimiters(
data, delimiter[0], delimiter[1], 'displaystyle');
data,
delimiter[0],
delimiter[1],
'displaystyle'
);
}

@@ -135,3 +143,2 @@

function createMathMLNode(latex, options) {

@@ -142,7 +149,8 @@ // Create a node for AT (Assistive Technology, e.g. screen reader) to speak, etc.

try {
span.innerHTML = "<math xmlns='http://www.w3.org/1998/Math/MathML'>" +
options.renderToMathML(latex, options) +
"</math>";
span.innerHTML =
"<math xmlns='http://www.w3.org/1998/Math/MathML'>" +
options.renderToMathML(latex, options) +
'</math>';
} catch (e) {
console.error( 'Could not convert\'' + latex + '\' to MathML with ', e );
console.error("Could not convert'" + latex + "' to MathML with ", e);
span.textContent = latex;

@@ -161,7 +169,13 @@ }

let span = document.createElement('span');
span.setAttribute('aria-hidden','true');
span.setAttribute('aria-hidden', 'true');
if (options.preserveOriginalContent) {
span.setAttribute('data-' + options.namespace + 'original-content', text);
span.setAttribute(
'data-' + options.namespace + 'original-content',
text
);
if (mathstyle) {
span.setAttribute('data-' + options.namespace + 'original-mathstyle', mathstyle);
span.setAttribute(
'data-' + options.namespace + 'original-mathstyle',
mathstyle
);
}

@@ -171,5 +185,10 @@ }

try {
span.innerHTML = options.renderToMarkup(text, mathstyle || 'displaystyle', 'html', options.macros);
} catch (e) {
console.error( 'Could not parse\'' + text + '\' with ', e );
span.innerHTML = options.renderToMarkup(
text,
mathstyle || 'displaystyle',
'html',
options.macros
);
} catch (e) {
console.error("Could not parse'" + text + "' with ", e);
if (createNodeOnFailure) {

@@ -184,16 +203,35 @@ span = document.createTextNode(text);

function createAccessibleMarkupPair(text, mathstyle, options, createNodeOnFailure) {
function createAccessibleMarkupPair(
text,
mathstyle,
options,
createNodeOnFailure
) {
// Create a math node (a span with an accessible component and a visual component)
// If there is an error in parsing the latex, 'createNodeOnFailure' controls whether
// 'null' is returned or an accessible node with the text used.
const markupNode = createMarkupNode(text, options, mathstyle, createNodeOnFailure);
const markupNode = createMarkupNode(
text,
options,
mathstyle,
createNodeOnFailure
);
if (markupNode && /\b(mathml|speakable-text)\b/i.test(options.renderAccessibleContent)) {
if (
markupNode &&
/\b(mathml|speakable-text)\b/i.test(options.renderAccessibleContent)
) {
const fragment = document.createDocumentFragment();
if (/\bmathml\b/i.test(options.renderAccessibleContent) && options.renderToMathML) {
if (
/\bmathml\b/i.test(options.renderAccessibleContent) &&
options.renderToMathML
) {
fragment.appendChild(createMathMLNode(text, options));
}
if (/\bspeakable-text\b/i.test(options.renderAccessibleContent) && options.renderToSpeakableText) {
if (
/\bspeakable-text\b/i.test(options.renderAccessibleContent) &&
options.renderToSpeakableText
) {
const span = document.createElement('span');
span.innerHTML = options.renderToSpeakableText(text, options);
span.innerHTML = options.renderToSpeakableText(text, options);
span.className = 'sr-only';

@@ -215,3 +253,5 @@ fragment.appendChild(span);

fragment = document.createDocumentFragment();
fragment.appendChild(createAccessibleMarkupPair(text, undefined, options, true));
fragment.appendChild(
createAccessibleMarkupPair(text, undefined, options, true)
);
} else {

@@ -229,3 +269,10 @@ const data = splitWithDelimiters(text, options.TeX.delimiters);

} else {
fragment.appendChild(createAccessibleMarkupPair(data[i].data, data[i].mathstyle, options, true));
fragment.appendChild(
createAccessibleMarkupPair(
data[i].data,
data[i].mathstyle,
options,
true
)
);
}

@@ -238,7 +285,15 @@ }

function scanElement(elem, options) {
const originalContent = elem.getAttribute('data-' + options.namespace +
'original-content');
const originalContent = elem.getAttribute(
'data-' + options.namespace + 'original-content'
);
if (originalContent) {
const mathstyle = elem.getAttribute('data-' + options.namespace + 'mathstyle');
const span = createAccessibleMarkupPair(originalContent, mathstyle, options, false);
const mathstyle = elem.getAttribute(
'data-' + options.namespace + 'mathstyle'
);
const span = createAccessibleMarkupPair(
originalContent,
mathstyle,
options,
false
);
if (span != null) {

@@ -251,3 +306,2 @@ elem.textContent = '';

if (elem.childNodes.length === 1 && elem.childNodes[0].nodeType === 3) {

@@ -259,3 +313,5 @@ // This is a node with textual content only. Perhaps an opportunity

elem.textContent = '';
elem.appendChild( createAccessibleMarkupPair(text, undefined, options, true) );
elem.appendChild(
createAccessibleMarkupPair(text, undefined, options, true)
);
return;

@@ -269,3 +325,10 @@ }

elem.textContent = '';
elem.appendChild( createAccessibleMarkupPair(data[0].data, data[0].mathstyle, options, true) );
elem.appendChild(
createAccessibleMarkupPair(
data[0].data,
data[0].mathstyle,
options,
true
)
);
return;

@@ -292,6 +355,8 @@ } else if (data.length === 1 && data[0].type === 'text') {

const tag = childNode.nodeName.toLowerCase();
if (tag === 'script' &&
options.processScriptTypePattern.test(childNode.type)) {
if (
tag === 'script' &&
options.processScriptTypePattern.test(childNode.type)
) {
let style = 'displaystyle';
for (const l of childNode.type.split(';')) {
for (const l of childNode.type.split(';')) {
const v = l.split('=');

@@ -304,8 +369,11 @@ if (v[0].toLowerCase() === 'mode') {

}
}
}
const span = createAccessibleMarkupPair(childNode.textContent,
style, options, true)
const span = createAccessibleMarkupPair(
childNode.textContent,
style,
options,
true
);
childNode.parentNode.replaceChild(span, childNode);

@@ -316,4 +384,6 @@ } else {

options.processClassPattern.test(childNode.className) ||
!(options.skipTags.includes(tag) ||
options.ignoreClassPattern.test(childNode.className));
!(
options.skipTags.includes(tag) ||
options.ignoreClassPattern.test(childNode.className)
);

@@ -334,15 +404,22 @@ if (shouldRender) {

// Name of tags whose content will not be scanned for math delimiters
skipTags: ['noscript', 'style', 'textarea', 'pre', 'code',
'annotation', 'annotation-xml'],
skipTags: [
'noscript',
'style',
'textarea',
'pre',
'code',
'annotation',
'annotation-xml',
],
// <script> tags of the following types will be processed. Others, ignored.
processScriptType: "math/tex",
processScriptType: 'math/tex',
// Regex pattern of the class name of elements whose contents should not
// be processed
ignoreClass: "tex2jax_ignore",
ignoreClass: 'tex2jax_ignore',
// Regex pattern of the class name of elements whose contents should
// be processed when they appear inside ones that are ignored.
processClass: "tex2jax_process",
processClass: 'tex2jax_process',

@@ -358,9 +435,12 @@ // Indicate whether to preserve or discard the original content of the

disabled: false,
processEnvironments : true,
processEnvironments: true,
delimiters: {
inline: [['\\(','\\)']],
display: [['$$', '$$'], ['\\[', '\\]']],
}
}
}
inline: [['\\(', '\\)']],
display: [
['$$', '$$'],
['\\[', '\\]'],
],
},
},
};

@@ -372,3 +452,5 @@ function renderMathInElement(elem, options) {

options.processClassPattern = new RegExp(options.processClass);
options.processScriptTypePattern = new RegExp(options.processScriptType);
options.processScriptTypePattern = new RegExp(
options.processScriptType
);
options.macros = Definitions.MACROS;

@@ -379,6 +461,8 @@

if (!/^[a-z]+[-]?$/.test(options.namespace)) {
throw Error('options.namespace must be a string of lowercase characters only');
throw Error(
'options.namespace must be a string of lowercase characters only'
);
}
if (!/-$/.test(options.namespace)) {
options.namespace += '-';
options.namespace += '-';
}

@@ -388,7 +472,10 @@ }

scanElement(elem, options);
} catch(e) {
} catch (e) {
if (e instanceof Error) {
console.error('renderMathInElement(): ' + e.message);
} else {
console.error('renderMathInElement(): Could not render math for element ' + elem);
console.error(
'renderMathInElement(): Could not render math for element ' +
elem
);
}

@@ -398,5 +485,4 @@ }

export default {
renderMathInElement,
}
export default {
renderMathInElement,
};

@@ -19,3 +19,7 @@ /**

const mathlist = ParserModule.parseTokens(
Lexer.tokenize(latex), mode, null, null);
Lexer.tokenize(latex),
mode,
null,
null
);

@@ -26,3 +30,3 @@ return toASCIIMath(mathlist);

export function asciiMathToLatex(ascii) {
return parseMathString(ascii, {format: 'ASCIIMath'});
return parseMathString(ascii, { format: 'ASCIIMath' });
}

@@ -44,4 +48,4 @@

if (Array.isArray(symbol)) {
childSymbol = symbol.slice(); // Clone the array
symbol = childSymbol.shift(); // Get the first element and remove it from the array
childSymbol = symbol.slice(); // Clone the array
symbol = childSymbol.shift(); // Get the first element and remove it from the array
}

@@ -85,3 +89,3 @@

* @private
*/
*/
function getType(spans, symbol) {

@@ -99,3 +103,3 @@ const s = getSymbol(spans, symbol);

* @private
*/
*/
function getTag(spans, symbol) {

@@ -107,3 +111,2 @@ const s = getSymbol(spans, symbol);

function getStyle(spans, symbol, prop) {

@@ -121,3 +124,2 @@ const s = getSymbol(spans, symbol);

function hasClass(spans, symbol, cls) {

@@ -172,3 +174,4 @@ let classes = getClasses(spans, symbol);

if (span.children && span.children.length > 0) {
result += indent + 'children:' + spanToString(span.children, indent);
result +=
indent + 'children:' + spanToString(span.children, indent);
}

@@ -189,3 +192,5 @@ result += indent + '}';

} else if (Array.isArray(value)) {
return indent + prop + ':' + mathlistToString(value, indent + '\t') + ',\n';
return (
indent + prop + ':' + mathlistToString(value, indent + '\t') + ',\n'
);
}

@@ -272,3 +277,4 @@ return '';

if (span.classes && span.classes.length > 0) {
result += '&nbsp;<span class="classes">' + span.classes + '</span>';
result +=
'&nbsp;<span class="classes">' + span.classes + '</span>';
}

@@ -285,4 +291,8 @@ if (span.isTight) {

if (Object.prototype.hasOwnProperty.call(span.style, s)) {
result += '&nbsp;<span class="styleprop">' + s + ':</span>';
result += '<span class="stylevalue"> ' + span.style[s] + '</span>;&nbsp;';
result +=
'&nbsp;<span class="styleprop">' + s + ':</span>';
result +=
'<span class="stylevalue"> ' +
span.style[s] +
'</span>;&nbsp;';
}

@@ -296,6 +306,13 @@ }

} else if (span) {
result += '<br>' + indent + 'table ' + span.array[0].length + '&times;' + span.array.length;
result +=
'<br>' +
indent +
'table ' +
span.array[0].length +
'&times;' +
span.array.length;
for (let i = 0; i < span.array.length; i++) {
for (let j = 0; j < span.array[i].length; j++) {
result += '<br>' + indent + '[' + (i + 1) + ', ' + (j + 1) + '] ';
result +=
'<br>' + indent + '[' + (i + 1) + ', ' + (j + 1) + '] ';
result += spanToMarkup(span.array[i][j], '');

@@ -312,3 +329,6 @@ }

result += '<span class="styleprop">' + propname + '=</span>';
result += '<span style="font-size:2em;vertical-align:middle;color:' + mathlist[propname] + '">&#9632;</span>';
result +=
'<span style="font-size:2em;vertical-align:middle;color:' +
mathlist[propname] +
'">&#9632;</span>';
result += '<span class="stylevalue">';

@@ -326,3 +346,3 @@ result += mathlist[propname];

result += '<span class="stylevalue">';
result += mathlist[propname]
result += mathlist[propname];
result += '</span>" ';

@@ -348,4 +368,7 @@ }

result += mathlist.caret ? ' caret' : '';
result += '">' + mathlist.type +
(mathlist.caret ? ' caret ' : '') + '</span>';
result +=
'">' +
mathlist.type +
(mathlist.caret ? ' caret ' : '') +
'</span>';
}

@@ -355,6 +378,11 @@ if (typeof mathlist.body === 'string' && mathlist.body.length > 0) {

result += mathlist.body;
if (mathlist.body.charCodeAt(0) < 32
|| mathlist.body.charCodeAt(0) > 127) {
result += '&nbsp;U+' + ('000000' +
mathlist.body.charCodeAt(0).toString(16)).substr(-6);
if (
mathlist.body.charCodeAt(0) < 32 ||
mathlist.body.charCodeAt(0) > 127
) {
result +=
'&nbsp;U+' +
(
'000000' + mathlist.body.charCodeAt(0).toString(16)
).substr(-6);
}

@@ -398,3 +426,3 @@ result += '</span>&nbsp;';

result += mathListPropToMarkup(mathlist, 'position');
// Type 'overunder'

@@ -412,5 +440,14 @@ result += mathlistToMarkup(mathlist.overscript, indent + '↑');

for (let i = 0; i < mathlist.array.length; i++) {
result += '<br>' + indent + '\u2317 row ' + (i + 1) + '/' + mathlist.array.length;
result +=
'<br>' +
indent +
'\u2317 row ' +
(i + 1) +
'/' +
mathlist.array.length;
for (let j = 0; j < mathlist.array[i].length; j++) {
result += mathlistToMarkup(mathlist.array[i][j], indent + '\u2317\u232A');
result += mathlistToMarkup(
mathlist.array[i][j],
indent + '\u2317\u232A'
);
}

@@ -423,7 +460,2 @@ }

// Export the public interface for this module

@@ -436,3 +468,3 @@ export default {

spanToString,
hasClass,

@@ -447,5 +479,2 @@ getClasses,

asciiMathToLatex,
}
};

@@ -17,10 +17,18 @@ /**

while (atoms[i]) {
if (atoms[i].type !== 'mop' &&
(atoms[i].fontFamily || atoms[i].baseFontFamily) !== value) break
if (
atoms[i].type !== 'mop' &&
(atoms[i].fontFamily || atoms[i].baseFontFamily) !== value
) {
break;
}
i++;
}
} else if (property === 'mode') {
while (atoms[i]) {
if (atoms[i][property] !== value) break;
i++;
}
} else {
while (atoms[i]) {
if (atoms[i].type !== 'mop' &&
atoms[i][property] !== value) break
if (atoms[i].type !== 'mop' && atoms[i][property] !== value) break;
i++;

@@ -54,3 +62,5 @@ }

let propValue = atoms[0][prop];
if (prop === 'fontFamily') propValue = atoms[0].fontFamily || atoms[0].baseFontFamily;
if (prop === 'fontFamily') {
propValue = atoms[0].fontFamily || atoms[0].baseFontFamily;
}

@@ -62,12 +72,12 @@ const i = findLongestRun(atoms, prop, propValue);

if (atoms[0].fontShape === 'it') {
prefix = '\\textit{'
prefix = '\\textit{';
suffix = '}';
} else if (atoms[0].fontShape === 'sl') {
prefix = '\\textsl{'
prefix = '\\textsl{';
suffix = '}';
} else if (atoms[0].fontShape === 'sc') {
prefix = '\\textsc{'
prefix = '\\textsc{';
suffix = '}';
} else if (atoms[0].fontShape === 'n') {
prefix = '\\textup{'
prefix = '\\textup{';
suffix = '}';

@@ -80,9 +90,9 @@ } else {

if (atoms[0].fontSeries === 'b') {
prefix = '\\textbf{'
prefix = '\\textbf{';
suffix = '}';
} else if (atoms[0].fontSeries === 'l') {
prefix = '\\textlf{'
prefix = '\\textlf{';
suffix = '}';
} else if (atoms[0].fontSeries === 'm') {
prefix = '\\textmd{'
prefix = '\\textmd{';
suffix = '}';

@@ -96,6 +106,8 @@ } else {

for (let j = 0; j < i; j++) {
if (!atoms[j].fontSeries &&
if (
!atoms[j].fontSeries &&
!atoms[j].fontShape &&
!atoms[j].fontFamily &&
!atoms[j].baseFontFamily) {
!atoms[j].baseFontFamily
) {
allAtomsHaveShapeOrSeriesOrFontFamily = false;

@@ -113,26 +125,32 @@ break;

} else if (prop === 'fontSize' && atoms[0].fontSize) {
const command = {
'size1': 'tiny',
'size2': 'scriptsize',
'size3': 'footnotesize',
'size4': 'small',
'size5': 'normalsize',
'size6': 'large',
'size7': 'Large',
'size8': 'LARGE',
'size9': 'huge',
'size10': 'Huge'
}[atoms[0].fontSize] || '';
const command =
{
size1: 'tiny',
size2: 'scriptsize',
size3: 'footnotesize',
size4: 'small',
size5: 'normalsize',
size6: 'large',
size7: 'Large',
size8: 'LARGE',
size9: 'huge',
size10: 'Huge',
}[atoms[0].fontSize] || '';
prefix = '{\\' + command + ' ';
suffix = '}';
} else if (prop === 'fontFamily' &&
(atoms[0].fontFamily || atoms[0].baseFontFamily)) {
const command = {
'cmr': 'textrm',
'cmtt': 'texttt',
'cmss': 'textsf'
}[atoms[0].fontFamily || atoms[0].baseFontFamily] || '';
} else if (
prop === 'fontFamily' &&
(atoms[0].fontFamily || atoms[0].baseFontFamily)
) {
const command =
{
cmr: 'textrm',
cmtt: 'texttt',
cmss: 'textsf',
}[atoms[0].fontFamily || atoms[0].baseFontFamily] || '';
if (!command) {
prefix += '{\\fontfamily{' + (atoms[0].fontFamily || atoms[0].baseFontFamily) + '}';
prefix +=
'{\\fontfamily{' +
(atoms[0].fontFamily || atoms[0].baseFontFamily) +
'}';
suffix = '}';

@@ -164,30 +182,30 @@ } else {

}
} else if (prop === 'fontSize' && atoms[0].fontSize) {
const command = {
'size1': 'tiny',
'size2': 'scriptsize',
'size3': 'footnotesize',
'size4': 'small',
'size5': 'normalsize',
'size6': 'large',
'size7': 'Large',
'size8': 'LARGE',
'size9': 'huge',
'size10': 'Huge'
}[atoms[0].fontSize] || '';
const command =
{
size1: 'tiny',
size2: 'scriptsize',
size3: 'footnotesize',
size4: 'small',
size5: 'normalsize',
size6: 'large',
size7: 'Large',
size8: 'LARGE',
size9: 'huge',
size10: 'Huge',
}[atoms[0].fontSize] || '';
prefix = '{\\' + command + ' ';
suffix = '}';
} else if (prop === 'fontFamily' && atoms[0].fontFamily) {
if (!/^(math|main)$/.test(atoms[0].fontFamily)) {
const command = {
'cal': 'mathcal',
'frak': 'mathfrak',
'bb': 'mathbb',
'scr': 'mathscr',
'cmr': 'mathrm',
'cmtt': 'mathtt',
'cmss': 'mathsf'
}[atoms[0].fontFamily] || '';
const command =
{
cal: 'mathcal',
frak: 'mathfrak',
bb: 'mathbb',
scr: 'mathscr',
cmr: 'mathrm',
cmtt: 'mathtt',
cmss: 'mathsf',
}[atoms[0].fontFamily] || '';
if (!command) {

@@ -198,3 +216,11 @@ prefix += '{\\fontfamily{' + atoms[0].fontFamily + '}';

if (/^\\operatorname{/.test(atoms[0].latex)) {
return atoms[0].latex + latexifyArray(parent, properties, atoms.slice(i), expandMacro);
return (
atoms[0].latex +
latexifyArray(
parent,
properties,
atoms.slice(i),
expandMacro
)
);
}

@@ -216,11 +242,12 @@ if (!atoms[0].isFunction) {

} else {
const command = {
'cal': 'mathcal',
'frak': 'mathfrak',
'bb': 'mathbb',
'scr': 'mathscr',
'cmr': 'mathrm',
'cmtt': 'mathtt',
'cmss': 'mathsf'
}[atoms[0].baseFontFamily] || '';
const command =
{
cal: 'mathcal',
frak: 'mathfrak',
bb: 'mathbb',
scr: 'mathscr',
cmr: 'mathrm',
cmtt: 'mathtt',
cmss: 'mathsf',
}[atoms[0].baseFontFamily] || '';
if (command) {

@@ -234,5 +261,8 @@ prefix = '\\' + command + '{';

if (prop === 'color' && atoms[0].color &&
atoms[0].color !== 'none' &&
(!parent || parent.color !== atoms[0].color)) {
if (
prop === 'color' &&
atoms[0].color &&
atoms[0].color !== 'none' &&
(!parent || parent.color !== atoms[0].color)
) {
prefix = '\\textcolor{' + Color.colorToString(atoms[0].color) + '}{';

@@ -242,6 +272,12 @@ suffix = '}';

if (prop === 'backgroundColor' && atoms[0].backgroundColor &&
atoms[0].backgroundColor !== 'none' &&
(!parent || parent.backgroundColor !== atoms[0].backgroundColor)) {
prefix = '\\colorbox{' + Color.colorToString(atoms[0].backgroundColor) + '}{';
if (
prop === 'backgroundColor' &&
atoms[0].backgroundColor &&
atoms[0].backgroundColor !== 'none' &&
(!parent || parent.backgroundColor !== atoms[0].backgroundColor)
) {
prefix =
'\\colorbox{' +
Color.colorToString(atoms[0].backgroundColor) +
'}{';
suffix = '}';

@@ -252,6 +288,8 @@ }

result += latexifyArray(parent,
result += latexifyArray(
parent,
properties.slice(1),
atoms.slice(0, i),
expandMacro);
expandMacro
);

@@ -266,4 +304,2 @@ result += suffix;

/**

@@ -284,15 +320,19 @@ * Given an atom or an array of atoms, return a LaTeX string representation

result = latexifyArray(parent, [
'mode',
'color',
'backgroundColor',
'fontSize',
'fontFamily',
'fontShape',
'fontSeries',
], value, expandMacro);
result = latexifyArray(
parent,
[
'mode',
'color',
'backgroundColor',
'fontSize',
'fontFamily',
'fontShape',
'fontSeries',
],
value,
expandMacro
);
// if (result.startsWith('{') && result.endsWith('}')) {
// result = result.slice(1, result.length - 1);
// }
} else if (typeof value === 'number' || typeof value === 'boolean') {

@@ -308,4 +348,2 @@ result = value.toString();

/**

@@ -324,3 +362,4 @@ * Return a LaTeX representation of the atom.

let result = '';
let col, row = 0;
let col,
row = 0;
let i = 0;

@@ -331,5 +370,6 @@ const m = !this.latex ? null : this.latex.match(/^(\\[^{\s0-9]+)/);

// this.mode=='text' is handled in the switch by looking at this.type===''
switch(this.type) {
switch (this.type) {
case 'group':
result += this.latexOpen || ((this.cssId || this.cssClass) ? '' : '{');
result +=
this.latexOpen || (this.cssId || this.cssClass ? '' : '{');

@@ -339,8 +379,10 @@ if (this.cssId) result += '\\cssId{' + this.cssId + '}{';

if (this.cssClass === 'ML__emph') {
result += '\\emph{' + latexify(this, this.body, expandMacro) + '}';
result +=
'\\emph{' + latexify(this, this.body, expandMacro) + '}';
} else {
if (this.cssClass) result += '\\class{' + this.cssClass + '}{';
result += expandMacro ? latexify(this, this.body, true) :
(this.latex || latexify(this, this.body, false));
result += expandMacro
? latexify(this, this.body, true)
: this.latex || latexify(this, this.body, false);

@@ -351,3 +393,4 @@ if (this.cssClass) result += '}';

result += this.latexClose || ((this.cssId || this.cssClass) ? '' : '}');
result +=
this.latexClose || (this.cssId || this.cssClass ? '' : '}');
break;

@@ -391,3 +434,3 @@

result += '{';
result += latexify(this, this.numer, expandMacro)
result += latexify(this, this.numer, expandMacro);
result += '\\' + this.body + ' ';

@@ -399,3 +442,7 @@ result += latexify(this, this.denom, expandMacro);

result += command;
result += `{${latexify(this, this.numer, expandMacro)}}{${latexify(this, this.denom, expandMacro)}}`;
result += `{${latexify(
this,
this.numer,
expandMacro
)}}{${latexify(this, this.denom, expandMacro)}}`;
}

@@ -420,9 +467,28 @@ break;

result += '\\right' + (this.rightDelim || '.');
if (this.rightDelim && this.rightDelim.length > 1) result += ' ';
if (this.rightDelim && this.rightDelim.length > 1) {
result += ' ';
}
} else {
result += '\\mleft' + (this.leftDelim || '.');
if (this.leftDelim && this.leftDelim.length > 1) result += ' ';
result += latexify(this, this.body, expandMacro);
result += '\\mright' + (this.rightDelim || '.');
if (this.rightDelim && this.rightDelim.length > 1) result += ' ';
if (
expandMacro &&
this.leftDelim === '(' &&
this.rightDelim === ')'
) {
// If we're in 'expandMacro' mode (i.e. interchange format
// used, e.g., on the clipboard for maximum compatibility
// with other LaTeX renderers), drop the `\mleft(` and `\mright`)
// commands
result +=
'(' + latexify(this, this.body, expandMacro) + ')';
} else {
result += '\\mleft' + (this.leftDelim || '.');
if (this.leftDelim && this.leftDelim.length > 1) {
result += ' ';
}
result += latexify(this, this.body, expandMacro);
result += '\\mright' + (this.rightDelim || '.');
if (this.rightDelim && this.rightDelim.length > 1) {
result += ' ';
}
}
}

@@ -441,3 +507,7 @@ break;

}
result += `{${latexify(this, this.width, expandMacro)}em}{${latexify(this, this.height, expandMacro)}em}`;
result += `{${latexify(
this,
this.width,
expandMacro
)}em}{${latexify(this, this.height, expandMacro)}em}`;
break;

@@ -452,3 +522,7 @@

case 'overunder':
result += `${command}{${latexify(this, this.overscript || this.underscript, expandMacro)}}{${latexify(parent, this.body, expandMacro)}}`;
result += `${command}{${latexify(
this,
this.overscript || this.underscript,
expandMacro
)}}{${latexify(parent, this.body, expandMacro)}}`;
break;

@@ -464,5 +538,13 @@

case 'textord':
case '': // mode = text
if (/^\\(mathbin|mathrel|mathopen|mathclose|mathpunct|mathord|mathinner)/.test(command)) {
result += command + '{' + latexify(this, this.body, expandMacro) + '}';
case '': // mode = text
if (
/^\\(mathbin|mathrel|mathopen|mathclose|mathpunct|mathord|mathinner)/.test(
command
)
) {
result +=
command +
'{' +
latexify(this, this.body, expandMacro) +
'}';
} else if (command === '\\char"') {

@@ -472,3 +554,5 @@ result += this.latex + ' ';

result += '\\unicode{"';
result += ('000000' + this.body.charCodeAt(0).toString(16)).toUpperCase().substr(-6);
result += ('000000' + this.body.charCodeAt(0).toString(16))
.toUpperCase()
.substr(-6);
result += '}';

@@ -485,3 +569,4 @@ } else if (this.latex || typeof this.body === 'string') {

} else {
result += this.body !== '\u200b' ? (this.latex || this.body) : '';
result +=
this.body !== '\u200b' ? this.latex || this.body : '';
}

@@ -496,6 +581,14 @@ }

// The argument to mathop is math, therefor this.body can be an expression
result += command + '{' + latexify(this, this.body, expandMacro) + '}';
result +=
command +
'{' +
latexify(this, this.body, expandMacro) +
'}';
} else if (command === '\\operatorname') {
// The argument to operator name is text, therefore this.body is a string
result += command + '{' + this.body + '}';
// The argument to `\operatorname` is 'math' and needs to be latexified
result +=
command +
'{' +
latexify(this, this.body, expandMacro) +
'}';
} else {

@@ -510,3 +603,6 @@ if (this.latex && this.latex[0] === '\\') {

} else {
result += this.body !== '\u200b' ? (this.latex || this.body) : '';
result +=
this.body !== '\u200b'
? this.latex || this.body
: '';
}

@@ -521,12 +617,15 @@ }

case 'box':
if (command === '\\bbox') {
result += command;
if (isFinite(this.padding) ||
if (
isFinite(this.padding) ||
typeof this.border !== 'undefined' ||
typeof this.backgroundcolor !== 'undefined') {
typeof this.backgroundcolor !== 'undefined'
) {
const bboxParams = [];
if (isFinite(this.padding)) {
bboxParams.push(Math.floor(1e2 * this.padding) / 1e2 + 'em')
bboxParams.push(
Math.floor(1e2 * this.padding) / 1e2 + 'em'
);
}

@@ -537,3 +636,5 @@ if (this.border) {

if (this.backgroundcolor) {
bboxParams.push(Color.colorToString(this.backgroundcolor));
bboxParams.push(
Color.colorToString(this.backgroundcolor)
);
}

@@ -569,3 +670,3 @@ result += `[${bboxParams.join(',')}]`;

} else {
result += '0em'
result += '0em';
}

@@ -580,3 +681,2 @@ result += '}';

break;

@@ -590,4 +690,9 @@

for (const notation in this.notation) {
if (Object.prototype.hasOwnProperty.call(this.notation, notation) &&
this.notation[notation]) {
if (
Object.prototype.hasOwnProperty.call(
this.notation,
notation
) &&
this.notation[notation]
) {
result += sep + notation;

@@ -602,4 +707,11 @@ sep = ' ';

sep = '';
if (this.backgroundcolor && this.backgroundcolor !== 'transparent') {
style += sep + 'mathbackground="' + Color.colorToString(this.backgroundcolor) + '"';
if (
this.backgroundcolor &&
this.backgroundcolor !== 'transparent'
) {
style +=
sep +
'mathbackground="' +
Color.colorToString(this.backgroundcolor) +
'"';
sep = ',';

@@ -614,8 +726,14 @@ }

sep = ',';
} else if (this.strokeColor && this.strokeColor !== 'currentColor') {
style += sep + 'mathcolor="' + Color.colorToString(this.strokeColor) + '"';
} else if (
this.strokeColor &&
this.strokeColor !== 'currentColor'
) {
style +=
sep +
'mathcolor="' +
Color.colorToString(this.strokeColor) +
'"';
sep = ',';
}
if (style) {

@@ -649,8 +767,11 @@ result += `[${style}]`;

default:
console.warn('Unexpected atom type "' + this.type +
'" in "' + (this.latex || this.value) + '"');
console.warn(
'Unexpected atom type "' +
this.type +
'" in "' +
(this.latex || this.value) +
'"'
);
break;
}

@@ -660,5 +781,7 @@ if (this.superscript) {

if (sup.length === 1) {
if (sup === '\u2032') { // PRIME
if (sup === '\u2032') {
// PRIME
sup = '\\prime ';
} else if (sup === '\u2033') { // DOUBLE-PRIME
} else if (sup === '\u2033') {
// DOUBLE-PRIME
sup = '\\doubleprime ';

@@ -680,10 +803,5 @@ }

return result;
}
};
// Export the public interface for this module
export default {
}
export default {};

@@ -14,3 +14,2 @@ /**

const SPECIAL_OPERATORS = {

@@ -41,13 +40,14 @@ '\\pm': '&PlusMinus;',

'\\check': '&#x02c7;',
'\\hat': '&#x005e;'
'\\hat': '&#x005e;',
};
function xmlEscape(str) {
return str
// .replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
return (
str
// .replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
);
}

@@ -62,3 +62,2 @@

function scanIdentifier(stream, final, options) {

@@ -73,5 +72,7 @@ let result = false;

if (stream.index < final &&
if (
stream.index < final &&
(atom.type === 'mord' || atom.type === 'textord') &&
'0123456789,.'.indexOf(atom.body) < 0) {
'0123456789,.'.indexOf(atom.body) < 0
) {
body = atom.toMathML(options);

@@ -102,4 +103,10 @@ if (atom.superscript) {

mathML = '<msubsup>' + body;
mathML += toMathML(stream.atoms[subscript].subscript, 0, 0, options).mathML;
mathML += toMathML(stream.atoms[superscript].superscript, 0, 0, options).mathML;
mathML += toMathML(stream.atoms[subscript].subscript, 0, 0, options)
.mathML;
mathML += toMathML(
stream.atoms[superscript].superscript,
0,
0,
options
).mathML;
mathML += '</msubsup>';

@@ -110,9 +117,25 @@ } else if (superscript >= 0) {

// There's another superscript after this one. Maybe double-prime?
const sup = toMathML(stream.atoms[superscript].superscript, 0, 0, options).mathML;
const sup = toMathML(
stream.atoms[superscript].superscript,
0,
0,
options
).mathML;
const sup2 = toMathML(stream.atoms[superscript + 1].superscript, 0, 0, options).mathML;
if ((sup === '<mi>\u2032</mi>' || sup === '<mi>&#x2032;</mi>') &&
(sup2 === '<mi>\u2032</mi>' || sup2 === '<mi>&#x2032;</mi>')) {
const sup2 = toMathML(
stream.atoms[superscript + 1].superscript,
0,
0,
options
).mathML;
if (
(sup === '<mi>\u2032</mi>' ||
sup === '<mi>&#x2032;</mi>') &&
(sup2 === '<mi>\u2032</mi>' || sup2 === '<mi>&#x2032;</mi>')
) {
mathML += '<mi>&#x2033;</mi>';
} else if (sup === '<mi>\u2032</mi>' || sup === '<mi>&#x2032;</mi>') {
} else if (
sup === '<mi>\u2032</mi>' ||
sup === '<mi>&#x2032;</mi>'
) {
mathML += '<mi>&#x2032;</mi>';

@@ -122,5 +145,9 @@ } else {

}
} else {
mathML += toMathML(stream.atoms[superscript].superscript, 0, 0, options).mathML;
mathML += toMathML(
stream.atoms[superscript].superscript,
0,
0,
options
).mathML;
}

@@ -130,3 +157,4 @@ mathML += '</msup>';

mathML = '<msub>' + body;
mathML += toMathML(stream.atoms[subscript].subscript, 0, 0, options).mathML;
mathML += toMathML(stream.atoms[subscript].subscript, 0, 0, options)
.mathML;
mathML += '</msub>';

@@ -137,7 +165,9 @@ } else {

if ((stream.lastType === 'mi' ||
stream.lastType === 'mn' ||
stream.lastType === 'mtext' ||
stream.lastType === 'fence') &&
!/^<mo>(.*)<\/mo>$/.test(mathML)) {
if (
(stream.lastType === 'mi' ||
stream.lastType === 'mn' ||
stream.lastType === 'mtext' ||
stream.lastType === 'fence') &&
!/^<mo>(.*)<\/mo>$/.test(mathML)
) {
mathML = '<mo>&InvisibleTimes;</mo>' + mathML;

@@ -159,4 +189,2 @@ }

/**

@@ -171,19 +199,18 @@ * Return true if the current atom is a standalone superscript atom

function isSuperscriptAtom(stream) {
return stream.index < stream.atoms.length &&
return (
stream.index < stream.atoms.length &&
stream.atoms[stream.index].superscript &&
stream.atoms[stream.index].type === 'msubsup'
);
}
function isSubscriptAtom(stream) {
return stream.index < stream.atoms.length &&
return (
stream.index < stream.atoms.length &&
stream.atoms[stream.index].subscript &&
stream.atoms[stream.index].type === 'msubsup'
);
}
function indexOfSuperscriptInNumber(stream) {
let result = -1;

@@ -194,6 +221,7 @@ let i = stream.index;

while (i < stream.atoms.length && !done && !found) {
done = stream.atoms[i].type !== 'mord' ||
done =
stream.atoms[i].type !== 'mord' ||
'0123456789,.'.indexOf(stream.atoms[i].body) < 0;
found = !done && stream.atoms[i].superscript;
i++
i++;
}

@@ -208,4 +236,2 @@

function parseSubsup(base, stream, options) {

@@ -249,3 +275,2 @@ let result = false;

function scanText(stream, final, options) {

@@ -256,6 +281,6 @@ let result = false;

let mathML = '';
while (stream.index < final &&
stream.atoms[stream.index].mode === 'text'
) {
mathML += stream.atoms[stream.index].body ? stream.atoms[stream.index].body : ' ';
while (stream.index < final && stream.atoms[stream.index].mode === 'text') {
mathML += stream.atoms[stream.index].body
? stream.atoms[stream.index].body
: ' ';
stream.index += 1;

@@ -266,3 +291,8 @@ }

result = true;
mathML = '<mtext' + makeID(stream.atoms[initial].id, options) + '>' + mathML + '</mtext>';
mathML =
'<mtext' +
makeID(stream.atoms[initial].id, options) +
'>' +
mathML +
'</mtext>';

@@ -287,3 +317,4 @@ stream.mathML += mathML;

while (stream.index < final &&
while (
stream.index < final &&
stream.atoms[stream.index].type === 'mord' &&

@@ -296,6 +327,10 @@ '0123456789,.'.indexOf(stream.atoms[stream.index].body) >= 0

if (mathML.length > 0) {
result = true;
mathML = '<mn' + makeID(stream.atoms[initial].id, options) + '>' + mathML + '</mn>';
mathML =
'<mn' +
makeID(stream.atoms[initial].id, options) +
'>' +
mathML +
'</mn>';

@@ -309,3 +344,8 @@ if (superscript < 0 && isSuperscriptAtom(stream)) {

mathML = '<msup>' + mathML;
mathML += toMathML(stream.atoms[superscript].superscript, 0, 0, options).mathML;
mathML += toMathML(
stream.atoms[superscript].superscript,
0,
0,
options
).mathML;
mathML += '</msup>';

@@ -327,4 +367,3 @@ }

if (stream.index < final &&
stream.atoms[stream.index].type === 'mopen') {
if (stream.index < final && stream.atoms[stream.index].type === 'mopen') {
let found = false;

@@ -352,3 +391,4 @@ let depth = 0;

mathML += toMathML(stream.atoms, openIndex + 1, closeIndex, options).mathML;
mathML += toMathML(stream.atoms, openIndex + 1, closeIndex, options)
.mathML;

@@ -359,6 +399,8 @@ // TODO: could add attribute indicating it's a fence (fence=true)

if (stream.lastType === 'mi' ||
if (
stream.lastType === 'mi' ||
stream.lastType === 'mn' ||
stream.lastType === 'mfrac' ||
stream.lastType === 'fence') {
stream.lastType === 'fence'
) {
mathML = '<mo>&InvisibleTimes;</mo>' + mathML;

@@ -394,4 +436,6 @@ }

if (stream.index < final && (
atom.type === 'mbin' || atom.type === 'mrel')) {
if (
stream.index < final &&
(atom.type === 'mbin' || atom.type === 'mrel')
) {
mathML += stream.atoms[stream.index].toMathML(options);

@@ -403,3 +447,3 @@ stream.index += 1;

if ((atom.limits === 'limits') && (atom.superscript || atom.subscript)) {
if (atom.limits === 'limits' && (atom.superscript || atom.subscript)) {
// Operator with limits, e.g. \sum

@@ -409,25 +453,34 @@ const op = toMo(atom, options);

// Both superscript and subscript
mathML += (atom.limits !== 'nolimits' ? '<munderover>' : '<msubsup>') + op;
mathML +=
(atom.limits !== 'nolimits'
? '<munderover>'
: '<msubsup>') + op;
mathML += toMathML(atom.subscript, 0, 0, options).mathML;
mathML += toMathML(atom.superscript, 0, 0, options).mathML;
mathML += (atom.limits !== 'nolimits' ? '</munderover>' : '</msubsup>');
mathML +=
atom.limits !== 'nolimits' ? '</munderover>' : '</msubsup>';
} else if (atom.superscript) {
// Superscript only
mathML += (atom.limits !== 'nolimits' ? '<mover>' : '<msup>') + op;
mathML +=
(atom.limits !== 'nolimits' ? '<mover>' : '<msup>') + op;
mathML += toMathML(atom.superscript, 0, 0, options).mathML;
mathML += (atom.limits !== 'nolimits' ? '</mover>' : '</msup>');
mathML += atom.limits !== 'nolimits' ? '</mover>' : '</msup>';
} else {
// Subscript only
mathML += (atom.limits !== 'nolimits' ? '<munder>' : '<msub>') + op;
mathML +=
(atom.limits !== 'nolimits' ? '<munder>' : '<msub>') + op;
mathML += toMathML(atom.subscript, 0, 0, options).mathML;
mathML += (atom.limits !== 'nolimits' ? '</munder>' : '</msub>');
mathML += atom.limits !== 'nolimits' ? '</munder>' : '</msub>';
}
lastType = 'mo';
} else {
const atom = stream.atoms[stream.index];
const isUnit = atom.latex.indexOf('\\operatorname') === 0;
const op = isUnit ?
'<mi class="MathML-Unit"' + makeID(atom.id, options) + '>' + toString(atom.body) + '</mi>' :
toMo(atom, options);
const op = isUnit
? '<mi class="MathML-Unit"' +
makeID(atom.id, options) +
'>' +
toString(atom.body) +
'</mi>'
: toMo(atom, options);
mathML += op;

@@ -442,3 +495,3 @@ stream.index += 1;

if (!isUnit && !/^<mo>(.*)<\/mo>$/.test(op)) {
mathML += '<mo>&#x2061;</mo>'; // APPLY FUNCTION
mathML += '<mo>&#x2061;</mo>'; // APPLY FUNCTION
// mathML += scanArgument(stream);

@@ -452,4 +505,6 @@ lastType = 'applyfunction';

if ((stream.lastType === 'mi' || stream.lastType === 'mn') &&
!/^<mo>(.*)<\/mo>$/.test(mathML)) {
if (
(stream.lastType === 'mi' || stream.lastType === 'mn') &&
!/^<mo>(.*)<\/mo>$/.test(mathML)
) {
mathML = '<mo>&InvisibleTimes;</mo>' + mathML;

@@ -469,3 +524,2 @@ }

/**

@@ -485,3 +539,3 @@ * Given an atom or an array of atoms, return their MathML representation as

mathML: '',
lastType: ''
lastType: '',
};

@@ -500,12 +554,17 @@ final = final || (input ? input.length : 0);

while (result.index < final) {
if (scanText(result, final, options) ||
if (
scanText(result, final, options) ||
scanNumber(result, final, options) ||
scanIdentifier(result, final, options) ||
scanOperator(result, final, options) ||
scanFence(result, final, options)) {
count += 1;
scanFence(result, final, options)
) {
count += 1;
} else if (result.index < final) {
let mathML = result.atoms[result.index].toMathML(options);
if (result.lastType === 'mn' && mathML.length > 0 &&
result.atoms[result.index].type === 'genfrac') {
if (
result.lastType === 'mn' &&
mathML.length > 0 &&
result.atoms[result.index].type === 'genfrac'
) {
// If this is a fraction preceded by a number (e.g. 2 1/2),

@@ -561,3 +620,2 @@ // add an "invisible plus" (U+0264) character in front of it

/**

@@ -577,4 +635,4 @@ * Return a MathML fragment representation of a single atom

'\\pi': '&#x03c0;',
'\\infty' : '&#x221e;',
'\\forall' : '&#x2200;',
'\\infty': '&#x221e;',
'\\forall': '&#x2200;',
'\\nexists': '&#x2204;',

@@ -589,23 +647,23 @@ '\\exists': '&#x2203;',

'\\ldotp': '\u002e',
// TODO: include all the 'textord' that are identifiers, not operators.
// TODO: include all the 'textord' that are identifiers, not operators.
};
const MATH_VARIANTS = {
'cal': 'script',
'frak': 'fraktur',
'bb': 'double-struck',
'scr': 'script',
'cmtt': 'monospace',
'cmss': 'sans-serif'
cal: 'script',
frak: 'fraktur',
bb: 'double-struck',
scr: 'script',
cmtt: 'monospace',
cmss: 'sans-serif',
};
const SPACING = {
'\\!': -3 / 18,
'\\ ': 6 / 18,
'\\,': 3 / 18,
'\\:': 4 / 18,
'\\;': 5 / 18,
'\\enspace': .5,
'\\quad': 1,
'\\qquad': 2,
'\\enskip': .5,
'\\!': -3 / 18,
'\\ ': 6 / 18,
'\\,': 3 / 18,
'\\:': 4 / 18,
'\\;': 5 / 18,
'\\enspace': 0.5,
'\\quad': 1,
'\\qquad': 2,
'\\enskip': 0.5,
};

@@ -626,5 +684,5 @@

} else {
switch(this.type) {
switch (this.type) {
case 'first':
break; // nothing to do
break; // nothing to do
case 'group':

@@ -634,9 +692,14 @@ case 'root':

break;
case 'array':
if ((this.lFence && this.lFence !== '.') ||
(this.rFence && this.rFence !== '.')) {
if (
(this.lFence && this.lFence !== '.') ||
(this.rFence && this.rFence !== '.')
) {
result += '<mrow>';
if ((this.lFence && this.lFence !== '.')) {
result += '<mo>' + (SPECIAL_OPERATORS[this.lFence] || this.lFence) + '</mo>';
if (this.lFence && this.lFence !== '.') {
result +=
'<mo>' +
(SPECIAL_OPERATORS[this.lFence] || this.lFence) +
'</mo>';
}

@@ -649,3 +712,6 @@ }

if (this.colFormat[i].align) {
result += {l:'left', c:'center', r:'right'}[this.colFormat[i].align] + ' ';
result +=
{ l: 'left', c: 'center', r: 'right' }[
this.colFormat[i].align
] + ' ';
}

@@ -655,3 +721,3 @@ }

}
result += '>';

@@ -661,13 +727,22 @@ for (row = 0; row < this.array.length; row++) {

for (col = 0; col < this.array[row].length; col++) {
result += '<mtd>' + toMathML(this.array[row][col], 0, 0, options).mathML + '</mtd>';
result +=
'<mtd>' +
toMathML(this.array[row][col], 0, 0, options)
.mathML +
'</mtd>';
}
result += '</mtr>';
}
result += '</mtable>';
if ((this.lFence && this.lFence !== '.') ||
(this.rFence && this.rFence !== '.')) {
if ((this.rFence && this.rFence !== '.')) {
result += '<mo>' + (SPECIAL_OPERATORS[this.lFence] || this.rFence) + '</mo>';
if (
(this.lFence && this.lFence !== '.') ||
(this.rFence && this.rFence !== '.')
) {
if (this.rFence && this.rFence !== '.') {
result +=
'<mo>' +
(SPECIAL_OPERATORS[this.lFence] || this.rFence) +
'</mo>';
}

@@ -677,3 +752,3 @@ result += '</mrow>';

break;
case 'genfrac':

@@ -684,8 +759,17 @@ if (this.leftDelim || this.rightDelim) {

if (this.leftDelim && this.leftDelim !== '.') {
result += '<mo' + makeID(this.id, options) + '>' + (SPECIAL_OPERATORS[this.leftDelim] || this.leftDelim) + '</mo>';
result +=
'<mo' +
makeID(this.id, options) +
'>' +
(SPECIAL_OPERATORS[this.leftDelim] || this.leftDelim) +
'</mo>';
}
if (this.hasBarLine) {
result += '<mfrac>';
result += toMathML(this.numer, 0, 0, options).mathML || '<mi>&nbsp;</mi>';
result += toMathML(this.denom, 0, 0, options).mathML || '<mi>&nbsp;</mi>';
result +=
toMathML(this.numer, 0, 0, options).mathML ||
'<mi>&nbsp;</mi>';
result +=
toMathML(this.denom, 0, 0, options).mathML ||
'<mi>&nbsp;</mi>';
result += '</mfrac>';

@@ -695,8 +779,20 @@ } else {

result += '<mtable' + makeID(this.id, options) + '>';
result += '<mtr>' + toMathML(this.numer, 0, 0, options).mathML + '</mtr>';
result += '<mtr>' + toMathML(this.denom, 0, 0, options).mathML + '</mtr>';
result +=
'<mtr>' +
toMathML(this.numer, 0, 0, options).mathML +
'</mtr>';
result +=
'<mtr>' +
toMathML(this.denom, 0, 0, options).mathML +
'</mtr>';
result += '</mtable>';
}
if (this.rightDelim && this.rightDelim !== '.') {
result += '<mo' + makeID(this.id, options) + '>' + (SPECIAL_OPERATORS[this.rightDelim] || this.rightDelim) + '</mo>';
result +=
'<mo' +
makeID(this.id, options) +
'>' +
(SPECIAL_OPERATORS[this.rightDelim] ||
this.rightDelim) +
'</mo>';
}

@@ -706,4 +802,4 @@ if (this.leftDelim || this.rightDelim) {

}
break;
break;
case 'surd':

@@ -721,3 +817,3 @@ if (this.index) {

break;
case 'leftright':

@@ -727,28 +823,48 @@ // TODO: could add fence=true attribute

if (this.leftDelim && this.leftDelim !== '.') {
result += '<mo' + makeID(this.id, options) + '>' + (SPECIAL_OPERATORS[this.leftDelim] || this.leftDelim) + '</mo>';
result +=
'<mo' +
makeID(this.id, options) +
'>' +
(SPECIAL_OPERATORS[this.leftDelim] || this.leftDelim) +
'</mo>';
}
if (this.body) result += toMathML(this.body, 0, 0, options).mathML;
if (this.body)
result += toMathML(this.body, 0, 0, options).mathML;
if (this.rightDelim && this.rightDelim !== '.') {
result += '<mo' + makeID(this.id, options) + '>' + (SPECIAL_OPERATORS[this.rightDelim] || this.rightDelim) + '</mo>';
result +=
'<mo' +
makeID(this.id, options) +
'>' +
(SPECIAL_OPERATORS[this.rightDelim] ||
this.rightDelim) +
'</mo>';
}
result += '</mrow>';
break;
case 'sizeddelim':
case 'delim':
result += '<mo separator="true"' + makeID(this.id, options) + '>' + (SPECIAL_OPERATORS[this.delim] || this.delim) + '</mo>';
result +=
'<mo separator="true"' +
makeID(this.id, options) +
'>' +
(SPECIAL_OPERATORS[this.delim] || this.delim) +
'</mo>';
break;
case 'accent':
result += '<mover accent="true"' + makeID(this.id, options) + '>';
result +=
'<mover accent="true"' + makeID(this.id, options) + '>';
result += toMathML(this.body, 0, 0, options).mathML;
result += '<mo>' + (SPECIAL_OPERATORS[command] || this.accent) + '</mo>';
result += '</mover>'
result +=
'<mo>' +
(SPECIAL_OPERATORS[command] || this.accent) +
'</mo>';
result += '</mover>';
break;
case 'line':
case 'overlap':
break;
case 'overunder':

@@ -764,3 +880,8 @@ overscript = this.overscript;

body = this.body[0].body;
} else if (this.body[0] && this.body[0].type === 'first' && this.body[1] && this.body[1].underscript) {
} else if (
this.body[0] &&
this.body[0].type === 'first' &&
this.body[1] &&
this.body[1].underscript
) {
underscript = this.body[1].underscript;

@@ -774,3 +895,8 @@ body = this.body[1].body;

body = this.body[0].body;
} else if (this.body[0] && this.body[0].type === 'first' && this.body[1] && this.body[1].overscript) {
} else if (
this.body[0] &&
this.body[0].type === 'first' &&
this.body[1] &&
this.body[1].overscript
) {
overscript = this.body[1].overscript;

@@ -780,5 +906,10 @@ body = this.body[1].body;

}
if (overscript && underscript) {
result += '<munderover' + variant + makeID(this.id, options) + '>' + toMathML(body, 0, 0, options).mathML;
result +=
'<munderover' +
variant +
makeID(this.id, options) +
'>' +
toMathML(body, 0, 0, options).mathML;
result += toMathML(underscript, 0, 0, options).mathML;

@@ -788,7 +919,17 @@ result += toMathML(overscript, 0, 0, options).mathML;

} else if (overscript) {
result += '<mover' + variant + makeID(this.id, options) + '>' + toMathML(body, 0, 0, options).mathML;
result +=
'<mover' +
variant +
makeID(this.id, options) +
'>' +
toMathML(body, 0, 0, options).mathML;
result += toMathML(overscript, 0, 0, options).mathML;
result += '</mover>';
} else if (underscript) {
result += '<munder' + variant + makeID(this.id, options) + '>' + toMathML(body, 0, 0, options).mathML;
result +=
'<munder' +
variant +
makeID(this.id, options) +
'>' +
toMathML(body, 0, 0, options).mathML;
result += toMathML(underscript, 0, 0, options).mathML;

@@ -798,16 +939,28 @@ result += '</munder>';

break;
case 'placeholder': // no real equivalent in MathML -- will generate a '?'qq
case 'placeholder': // no real equivalent in MathML -- will generate a '?'qq
case 'mord': {
result = SPECIAL_IDENTIFIERS[command] || command || (typeof this.body === 'string' ? this.body : '');
const m = command ? command.match(/[{]?\\char"([0-9abcdefABCDEF]*)[}]?/) : null;
result =
SPECIAL_IDENTIFIERS[command] ||
command ||
(typeof this.body === 'string' ? this.body : '');
const m = command
? command.match(/[{]?\\char"([0-9abcdefABCDEF]*)[}]?/)
: null;
if (m) {
// It's a \char command
result = '&#x' + m[1] + ';'
result = '&#x' + m[1] + ';';
} else if (result.length > 0 && result.charAt(0) === '\\') {
// This is an identifier with no special handling. Use the
// Unicode value
if (typeof this.body === 'string' && this.body.charCodeAt(0) > 255) {
result = '&#x' + ('000000' +
this.body.charCodeAt(0).toString(16)).substr(-4) + ';';
if (
typeof this.body === 'string' &&
this.body.charCodeAt(0) > 255
) {
result =
'&#x' +
(
'000000' + this.body.charCodeAt(0).toString(16)
).substr(-4) +
';';
} else if (typeof this.body === 'string') {

@@ -820,3 +973,12 @@ result = this.body.charAt(0);

const tag = /\d/.test(result) ? 'mn' : 'mi';
result = '<' + tag + variant + makeID(this.id, options) + '>' + xmlEscape(result) + '</' + tag + '>';
result =
'<' +
tag +
variant +
makeID(this.id, options) +
'>' +
xmlEscape(result) +
'</' +
tag +
'>';
break;

@@ -830,5 +992,15 @@ }

// Some 'textord' are actually identifiers. Check them here.
result = '<mi' + makeID(this.id, options) + '>' + SPECIAL_IDENTIFIERS[command] + '</mi>';
result =
'<mi' +
makeID(this.id, options) +
'>' +
SPECIAL_IDENTIFIERS[command] +
'</mi>';
} else if (command && SPECIAL_OPERATORS[command]) {
result = '<mo' + makeID(this.id, options) + '>' + SPECIAL_OPERATORS[command] + '</mo>';
result =
'<mo' +
makeID(this.id, options) +
'>' +
SPECIAL_OPERATORS[command] +
'</mo>';
} else {

@@ -838,7 +1010,12 @@ result = toMo(this, options);

break;
case 'mpunct':
result = '<mo separator="true"' + makeID(this.id, options) + '>' + (SPECIAL_OPERATORS[command] || command) + '</mo>';
result =
'<mo separator="true"' +
makeID(this.id, options) +
'>' +
(SPECIAL_OPERATORS[command] || command) +
'</mo>';
break;
case 'mop':

@@ -856,3 +1033,3 @@ if (this.body !== '\u200b') {

break;
case 'mathstyle':

@@ -868,20 +1045,32 @@ // TODO: mathstyle is a switch. Need to figure out its scope to properly wrap it around a <mstyle> tag

break;
case 'box':
result = '<menclose notation="box"';
if (this.backgroundcolor) {
result += ' mathbackground="' + Color.stringToColor(this.backgroundcolor) + '"';
result +=
' mathbackground="' +
Color.stringToColor(this.backgroundcolor) +
'"';
}
result += makeID(this.id, options) + '>' + toMathML(this.body, 0, 0, options).mathML + '</menclose>';
result +=
makeID(this.id, options) +
'>' +
toMathML(this.body, 0, 0, options).mathML +
'</menclose>';
break;
case 'spacing':
result += '<mspace width="' + (SPACING[command] || 0) + 'em"/>';
break;
case 'enclose':
result = '<menclose notation="';
for (const notation in this.notation) {
if (Object.prototype.hasOwnProperty.call(this.notation, notation) &&
this.notation[notation]) {
if (
Object.prototype.hasOwnProperty.call(
this.notation,
notation
) &&
this.notation[notation]
) {
result += sep + notation;

@@ -891,26 +1080,26 @@ sep = ' ';

}
result += makeID(this.id, options) + '">' + toMathML(this.body, 0, 0, options).mathML + '</menclose>';
result +=
makeID(this.id, options) +
'">' +
toMathML(this.body, 0, 0, options).mathML +
'</menclose>';
break;
case 'space':
result += '&nbsp;'
result += '&nbsp;';
break;
default:
console.log("In conversion to MathML, unknown type : " + this.type);
console.log(
'In conversion to MathML, unknown type : ' + this.type
);
}
}
return result;
}
};
MathAtom.toMathML = function(atoms, options) {
return toMathML(atoms, 0, 0, options).mathML;
}
};
// Export the public interface for this module
export default {
}
export default {};

@@ -25,87 +25,92 @@ import MathAtom from '../core/mathAtom.js';

const PRONUNCIATION = {
'\\alpha': 'alpha ',
'\\mu': 'mew ',
'\\sigma': 'sigma ',
'\\pi': 'pie ',
'\\alpha': 'alpha ',
'\\mu': 'mew ',
'\\sigma': 'sigma ',
'\\pi': 'pie ',
'\\imaginaryI': 'eye ',
'\\sum': 'Summation ',
'\\prod': 'Product ',
'\\sum': 'Summation ',
'\\prod': 'Product ',
'a': '<phoneme alphabet="ipa" ph="eɪ">a</phoneme>',
'A': 'capital <phoneme alphabet="ipa" ph="eɪ">A</phoneme>',
'+': 'plus ',
'-': 'minus ',
';': '<break time="150ms"/> semi-colon <break time="150ms"/>',
',': '<break time="150ms"/> comma <break time="150ms"/>',
'|': '<break time="150ms"/>Vertical bar<break time="150ms"/>',
'(': '<break time="150ms"/>Open paren. <break time="150ms"/>',
')': '<break time="150ms"/> Close paren. <break time="150ms"/>',
'=': 'equals ',
'<': 'is less than ',
'\\lt': 'is less than ',
'<=': 'is less than or equal to ',
'\\le': 'is less than or equal to ',
'\\gt': 'is greater than ',
'>': 'is greater than ',
'\\ge': 'is greater than or equal to ',
'\\geq': 'is greater than or equal to ',
'\\leq': 'is less than or equal to ',
'!': 'factorial ',
'\\sin': 'sine ',
'\\cos': 'cosine ',
'\u200b': '',
'\u2212': 'minus ',
':': '<break time="150ms"/> such that <break time="200ms"/> ',
'\\colon': '<break time="150ms"/> such that <break time="200ms"/> ',
'\\hbar': 'etch bar ',
'\\iff': '<break time="200ms"/>if, and only if, <break time="200ms"/>',
'\\Longleftrightarrow': '<break time="200ms"/>if, and only if, <break time="200ms"/>',
'\\land': 'and ',
'\\lor': 'or ',
'\\neg': 'not ',
'\\div': 'divided by ',
a: '<phoneme alphabet="ipa" ph="eɪ">a</phoneme>',
A: 'capital <phoneme alphabet="ipa" ph="eɪ">A</phoneme>',
'+': 'plus ',
'-': 'minus ',
';': '<break time="150ms"/> semi-colon <break time="150ms"/>',
',': '<break time="150ms"/> comma <break time="150ms"/>',
'|': '<break time="150ms"/>Vertical bar<break time="150ms"/>',
'(': '<break time="150ms"/>Open paren. <break time="150ms"/>',
')': '<break time="150ms"/> Close paren. <break time="150ms"/>',
'=': 'equals ',
'<': 'is less than ',
'\\lt': 'is less than ',
'<=': 'is less than or equal to ',
'\\le': 'is less than or equal to ',
'\\gt': 'is greater than ',
'>': 'is greater than ',
'\\ge': 'is greater than or equal to ',
'\\geq': 'is greater than or equal to ',
'\\leq': 'is less than or equal to ',
'!': 'factorial ',
'\\sin': 'sine ',
'\\cos': 'cosine ',
'\u200b': '',
'\u2212': 'minus ',
':': '<break time="150ms"/> such that <break time="200ms"/> ',
'\\colon': '<break time="150ms"/> such that <break time="200ms"/> ',
'\\hbar': 'etch bar ',
'\\iff': '<break time="200ms"/>if, and only if, <break time="200ms"/>',
'\\Longleftrightarrow':
'<break time="200ms"/>if, and only if, <break time="200ms"/>',
'\\land': 'and ',
'\\lor': 'or ',
'\\neg': 'not ',
'\\div': 'divided by ',
'\\forall': 'for all ',
'\\exists': 'there exists ',
'\\nexists': 'there does not exists ',
'\\forall': 'for all ',
'\\exists': 'there exists ',
'\\nexists': 'there does not exists ',
'\\in': 'element of ',
'\\in': 'element of ',
'\\N': 'the set <break time="150ms"/><say-as interpret-as="character">n</say-as>',
'\\C': 'the set <break time="150ms"/><say-as interpret-as="character">c</say-as>',
'\\Z': 'the set <break time="150ms"/><say-as interpret-as="character">z</say-as>',
'\\Q': 'the set <break time="150ms"/><say-as interpret-as="character">q</say-as>',
'\\N':
'the set <break time="150ms"/><say-as interpret-as="character">n</say-as>',
'\\C':
'the set <break time="150ms"/><say-as interpret-as="character">c</say-as>',
'\\Z':
'the set <break time="150ms"/><say-as interpret-as="character">z</say-as>',
'\\Q':
'the set <break time="150ms"/><say-as interpret-as="character">q</say-as>',
'\\infty': 'infinity ',
'\\infty': 'infinity ',
'\\nabla': 'nabla ',
'\\nabla': 'nabla ',
'\\partial': 'partial derivative of ',
'\\partial': 'partial derivative of ',
'\\cdots': 'dot dot dot ',
'\\cdots': 'dot dot dot ',
'\\Rightarrow': 'implies ',
'\\lbrace': '<break time="150ms"/>open brace<break time="150ms"/>',
'\\{': '<break time="150ms"/>open brace<break time="150ms"/>',
'\\rbrace': '<break time="150ms"/>close brace<break time="150ms"/>',
'\\}': '<break time="150ms"/>close brace<break time="150ms"/>',
'\\langle': '<break time="150ms"/>left angle bracket<break time="150ms"/>',
'\\rangle': '<break time="150ms"/>right angle bracket<break time="150ms"/>',
'\\lfloor': '<break time="150ms"/>open floor<break time="150ms"/>',
'\\rfloor': '<break time="150ms"/>close floor<break time="150ms"/>',
'\\lceil': '<break time="150ms"/>open ceiling<break time="150ms"/>',
'\\rceil': '<break time="150ms"/>close ceiling<break time="150ms"/>',
'\\vert': '<break time="150ms"/>vertical bar<break time="150ms"/>',
'\\mvert': '<break time="150ms"/>divides<break time="150ms"/>',
'\\lvert': '<break time="150ms"/>left vertical bar<break time="150ms"/>',
'\\rvert': '<break time="150ms"/>right vertical bar<break time="150ms"/>',
'\\lbrace': '<break time="150ms"/>open brace<break time="150ms"/>',
'\\{': '<break time="150ms"/>open brace<break time="150ms"/>',
'\\rbrace': '<break time="150ms"/>close brace<break time="150ms"/>',
'\\}': '<break time="150ms"/>close brace<break time="150ms"/>',
'\\langle': '<break time="150ms"/>left angle bracket<break time="150ms"/>',
'\\rangle': '<break time="150ms"/>right angle bracket<break time="150ms"/>',
'\\lfloor': '<break time="150ms"/>open floor<break time="150ms"/>',
'\\rfloor': '<break time="150ms"/>close floor<break time="150ms"/>',
'\\lceil': '<break time="150ms"/>open ceiling<break time="150ms"/>',
'\\rceil': '<break time="150ms"/>close ceiling<break time="150ms"/>',
'\\vert': '<break time="150ms"/>vertical bar<break time="150ms"/>',
'\\mvert': '<break time="150ms"/>divides<break time="150ms"/>',
'\\lvert': '<break time="150ms"/>left vertical bar<break time="150ms"/>',
'\\rvert': '<break time="150ms"/>right vertical bar<break time="150ms"/>',
// '\\lbrack': 'left bracket',
// '\\rbrack': 'right bracket',
'\\lbrack': '<break time="150ms"/> open square bracket <break time="150ms"/>',
'\\rbrack': '<break time="150ms"/> close square bracket <break time="150ms"/>',
'\\lbrack':
'<break time="150ms"/> open square bracket <break time="150ms"/>',
'\\rbrack':
'<break time="150ms"/> close square bracket <break time="150ms"/>',

@@ -116,9 +121,8 @@ // need to add code to detect singluar/plural. Until then spoken as plural since that is vastly more common

// note: need to do this for <msup>
'mm': 'millimeters',
'cm': 'centimeters',
'km': 'kilometers',
'kg': 'kilograms',
}
mm: 'millimeters',
cm: 'centimeters',
km: 'kilometers',
kg: 'kilograms',
};
function getSpokenName(latex) {

@@ -139,3 +143,2 @@ let result = Popover.NOTES[latex];

function platform(p) {

@@ -150,5 +153,7 @@ let result = 'other';

result = 'android';
} else if (/(iphone)/i.test(navigator.userAgent) ||
/(ipod)/i.test(navigator.userAgent) ||
/(ipad)/i.test(navigator.userAgent)) {
} else if (
/(iphone)/i.test(navigator.userAgent) ||
/(ipod)/i.test(navigator.userAgent) ||
/(ipad)/i.test(navigator.userAgent)
) {
result = 'ios';

@@ -163,3 +168,2 @@ } else if (/\bCrOS\b/i.test(navigator.userAgent)) {

function isAtomic(mathlist) {

@@ -200,6 +204,2 @@ let count = 0;

MathAtom.toSpeakableFragment = function(atom, options) {

@@ -218,3 +218,4 @@ function letter(c) {

if (/[a-z]/.test(c)) {
result += ' <say-as interpret-as="character">' + c + '</say-as>';
result +=
' <say-as interpret-as="character">' + c + '</say-as>';
} else if (/[A-Z]/.test(c)) {

@@ -242,17 +243,34 @@ result += 'capital ' + c.toLowerCase() + '';

if (Array.isArray(atom)) {
let isInDigitRun = false; // need to group sequence of digits
let isInDigitRun = false; // need to group sequence of digits
let isInTextRun = false; // need to group text
for (let i = 0; i < atom.length; i++) {
if (i < atom.length - 2 &&
if (atom[i].mode !== 'text') {
isInTextRun = false;
}
if (
i < atom.length - 2 &&
atom[i].type === 'mopen' &&
atom[i + 2].type === 'mclose' &&
atom[i + 1].type === 'mord') {
atom[i + 1].type === 'mord'
) {
result += ' of ';
result += emph(MathAtom.toSpeakableFragment(atom[i + 1], options));
result += emph(
MathAtom.toSpeakableFragment(atom[i + 1], options)
);
i += 2;
// '.' and ',' should only be allowed if prev/next entry is a digit
// However, if that isn't the case, this still works because 'toSpeakableFragment' is called in either case.
} else if (atom[i].mode === 'text') {
result += atom[i].body ? atom[i].body : ' ';
} else if (atom[i].type === 'mord' && /[0123456789,.]/.test(atom[i].body)) {
if (isInDigitRun) {
} else if (atom[i].mode === 'text') {
if (isInTextRun) {
result += atom[i].body ? atom[i].body : ' ';
} else {
isInTextRun = true;
result += MathAtom.toSpeakableFragment(atom[i], options);
}
// '.' and ',' should only be allowed if prev/next entry is a digit
// However, if that isn't the case, this still works because 'toSpeakableFragment' is called in either case.
// Note: the first char in a digit/text run potentially needs to have a 'mark', hence the call to 'toSpeakableFragment'
} else if (
atom[i].type === 'mord' &&
/[0123456789,.]/.test(atom[i].body)
) {
if (isInDigitRun) {
result += atom[i].body;

@@ -264,3 +282,3 @@ } else {

} else {
isInDigitRun = false
isInDigitRun = false;
result += MathAtom.toSpeakableFragment(atom[i], options);

@@ -270,3 +288,3 @@ }

} else if (atom.mode === 'text') {
result = atom.body;
result += atom.body;
} else {

@@ -277,3 +295,3 @@ let numer = '';

let supsubHandled = false;
switch(atom.type) {
switch (atom.type) {
case 'group':

@@ -289,23 +307,23 @@ case 'root':

const COMMON_FRACTIONS = {
'1/2': ' half ',
'1/3': ' one third ',
'2/3': ' two third',
'1/4': ' one quarter ',
'3/4': ' three quarter ',
'1/5': ' one fifth ',
'2/5': ' two fifths ',
'3/5': ' three fifths ',
'4/5': ' four fifths ',
'1/6': ' one sixth ',
'5/6': ' five sixths ',
'1/8': ' one eight ',
'3/8': ' three eights ',
'5/8': ' five eights ',
'7/8': ' seven eights ',
'1/9': ' one ninth ',
'2/9': ' two ninths ',
'4/9': ' four ninths ',
'5/9': ' five ninths ',
'7/9': ' seven ninths ',
'8/9': ' eight ninths ',
'1/2': ' half ',
'1/3': ' one third ',
'2/3': ' two third',
'1/4': ' one quarter ',
'3/4': ' three quarter ',
'1/5': ' one fifth ',
'2/5': ' two fifths ',
'3/5': ' three fifths ',
'4/5': ' four fifths ',
'1/6': ' one sixth ',
'5/6': ' five sixths ',
'1/8': ' one eight ',
'3/8': ' three eights ',
'5/8': ' five eights ',
'7/8': ' seven eights ',
'1/9': ' one ninth ',
'2/9': ' two ninths ',
'4/9': ' four ninths ',
'5/9': ' five ninths ',
'7/9': ' seven ninths ',
'8/9': ' eight ninths ',
// '1/10': ' one tenth ',

@@ -315,4 +333,8 @@ // '1/12': ' one twelfth ',

};
const commonFraction = COMMON_FRACTIONS[
atomicValue(atom.numer) + '/' + atomicValue(atom.denom)];
const commonFraction =
COMMON_FRACTIONS[
atomicValue(atom.numer) +
'/' +
atomicValue(atom.denom)
];
if (commonFraction) {

@@ -324,3 +346,8 @@ result = commonFraction;

} else {
result += ' the fraction <break time="150ms"/>' + numer + ', over <break time="150ms"/>' + denom + '.<break time="150ms"/> End fraction.<break time="150ms"/>';
result +=
' the fraction <break time="150ms"/>' +
numer +
', over <break time="150ms"/>' +
denom +
'.<break time="150ms"/> End fraction.<break time="150ms"/>';
}

@@ -336,14 +363,31 @@

} else {
result += ' the square root of <break time="200ms"/>' + body + '. <break time="200ms"/> End square root';
result +=
' the square root of <break time="200ms"/>' +
body +
'. <break time="200ms"/> End square root';
}
} else {
let index = MathAtom.toSpeakableFragment(atom.index, options);
let index = MathAtom.toSpeakableFragment(
atom.index,
options
);
index = index.trim();
const index2 = index.replace(/<mark([^/]*)\/>/g, '')
const index2 = index.replace(/<mark([^/]*)\/>/g, '');
if (index2 === '3') {
result += ' the cube root of <break time="200ms"/>' + body + '. <break time="200ms"/> End cube root';
result +=
' the cube root of <break time="200ms"/>' +
body +
'. <break time="200ms"/> End cube root';
} else if (index2 === 'n') {
result += ' the nth root of <break time="200ms"/>' + body + '. <break time="200ms"/> End root';
result +=
' the nth root of <break time="200ms"/>' +
body +
'. <break time="200ms"/> End root';
} else {
result += ' the root with index: <break time="200ms"/>' + index + ', of <break time="200ms"/>' + body + '. <break time="200ms"/> End root';
result +=
' the root with index: <break time="200ms"/>' +
index +
', of <break time="200ms"/>' +
body +
'. <break time="200ms"/> End root';
}

@@ -383,9 +427,13 @@ }

case 'mclose':
case 'textord':
{
const command = atom.latex ? atom.latex.trim() : '' ;
if (command === '\\mathbin' || command === '\\mathrel' ||
command === '\\mathopen' || command === '\\mathclose' ||
command === '\\mathpunct' || command === '\\mathord' ||
command === '\\mathinner') {
case 'textord': {
const command = atom.latex ? atom.latex.trim() : '';
if (
command === '\\mathbin' ||
command === '\\mathrel' ||
command === '\\mathopen' ||
command === '\\mathclose' ||
command === '\\mathpunct' ||
command === '\\mathord' ||
command === '\\mathinner'
) {
result = MathAtom.toSpeakableFragment(atom.body, options);

@@ -408,14 +456,23 @@ break;

if (atomValue) {
const value = PRONUNCIATION[atomValue] ||
(latexValue ? PRONUNCIATION[latexValue.trim()] : '');
const value =
PRONUNCIATION[atomValue] ||
(latexValue
? PRONUNCIATION[latexValue.trim()]
: '');
if (value) {
result += ' ' + value;
} else {
const spokenName = latexValue ?
getSpokenName(latexValue.trim()) : '';
const spokenName = latexValue
? getSpokenName(latexValue.trim())
: '';
result += spokenName ? spokenName : letter(atomValue);
result += spokenName
? spokenName
: letter(atomValue);
}
} else {
result += MathAtom.toSpeakableFragment(atom.body, options);
result += MathAtom.toSpeakableFragment(
atom.body,
options
);
}

@@ -429,18 +486,35 @@ if (atom.type === 'mbin') {

case 'mop':
// @todo
// @todo
if (atom.body !== '\u200b') {
// Not ZERO-WIDTH
const trimLatex = atom.latex ? atom.latex.trim() : '' ;
const trimLatex = atom.latex ? atom.latex.trim() : '';
if (trimLatex === '\\sum') {
if (atom.superscript && atom.subscript) {
let sup = MathAtom.toSpeakableFragment(atom.superscript, options);
let sup = MathAtom.toSpeakableFragment(
atom.superscript,
options
);
sup = sup.trim();
let sub = MathAtom.toSpeakableFragment(atom.subscript, options);
let sub = MathAtom.toSpeakableFragment(
atom.subscript,
options
);
sub = sub.trim();
result += ' the summation from <break time="200ms"/>' + sub + '<break time="200ms"/> to <break time="200ms"/>' + sup + '<break time="200ms"/> of <break time="150ms"/>';
result +=
' the summation from <break time="200ms"/>' +
sub +
'<break time="200ms"/> to <break time="200ms"/>' +
sup +
'<break time="200ms"/> of <break time="150ms"/>';
supsubHandled = true;
} else if (atom.subscript) {
let sub = MathAtom.toSpeakableFragment(atom.subscript, options);
} else if (atom.subscript) {
let sub = MathAtom.toSpeakableFragment(
atom.subscript,
options
);
sub = sub.trim();
result += ' the summation from <break time="200ms"/>' + sub + '<break time="200ms"/> of <break time="150ms"/>';
result +=
' the summation from <break time="200ms"/>' +
sub +
'<break time="200ms"/> of <break time="150ms"/>';
supsubHandled = true;

@@ -452,12 +526,29 @@ } else {

if (atom.superscript && atom.subscript) {
let sup = MathAtom.toSpeakableFragment(atom.superscript, options);
let sup = MathAtom.toSpeakableFragment(
atom.superscript,
options
);
sup = sup.trim();
let sub = MathAtom.toSpeakableFragment(atom.subscript, options);
let sub = MathAtom.toSpeakableFragment(
atom.subscript,
options
);
sub = sub.trim();
result += ' the product from <break time="200ms"/>' + sub + '<break time="200ms"/> to <break time="200ms"/>' + sup + '<break time="200ms"/> of <break time="150ms"/>';
result +=
' the product from <break time="200ms"/>' +
sub +
'<break time="200ms"/> to <break time="200ms"/>' +
sup +
'<break time="200ms"/> of <break time="150ms"/>';
supsubHandled = true;
} else if (atom.subscript) {
let sub = MathAtom.toSpeakableFragment(atom.subscript, options);
let sub = MathAtom.toSpeakableFragment(
atom.subscript,
options
);
sub = sub.trim();
result += ' the product from <break time="200ms"/>' + sub + '<break time="200ms"/> of <break time="150ms"/>';
result +=
' the product from <break time="200ms"/>' +
sub +
'<break time="200ms"/> of <break time="150ms"/>';
supsubHandled = true;

@@ -469,7 +560,18 @@ } else {

if (atom.superscript && atom.subscript) {
let sup = MathAtom.toSpeakableFragment(atom.superscript, options);
let sup = MathAtom.toSpeakableFragment(
atom.superscript,
options
);
sup = sup.trim();
let sub = MathAtom.toSpeakableFragment(atom.subscript, options);
let sub = MathAtom.toSpeakableFragment(
atom.subscript,
options
);
sub = sub.trim();
result += ' the integral from <break time="200ms"/>' + emph(sub) + '<break time="200ms"/> to <break time="200ms"/>' + emph(sup) + ' <break time="200ms"/> of ';
result +=
' the integral from <break time="200ms"/>' +
emph(sub) +
'<break time="200ms"/> to <break time="200ms"/>' +
emph(sup) +
' <break time="200ms"/> of ';
supsubHandled = true;

@@ -480,3 +582,4 @@ } else {

} else if (typeof atom.body === 'string') {
const value = PRONUNCIATION[atom.body] ||
const value =
PRONUNCIATION[atom.body] ||
PRONUNCIATION[atom.latex.trim()];

@@ -514,6 +617,4 @@ if (value) {

break;
}
if (!supsubHandled && atom.superscript) {
let sup = MathAtom.toSpeakableFragment(atom.superscript, options);

@@ -538,3 +639,6 @@ sup = sup.trim();

} else {
result += ' to the <say-as interpret-as="ordinal">' + sup2 + '</say-as> power; ';
result +=
' to the <say-as interpret-as="ordinal">' +
sup2 +
'</say-as> power; ';
}

@@ -545,3 +649,6 @@ } else {

} else {
result += ' raised to the <say-as interpret-as="ordinal">' + sup2 + '</say-as> power; ';
result +=
' raised to the <say-as interpret-as="ordinal">' +
sup2 +
'</say-as> power; ';
}

@@ -561,7 +668,5 @@ }

return result;
}
};
/**

@@ -572,8 +677,10 @@ * @param {MathAtom[]} atoms The atoms to represent as speakable text.

* @private
*/
*/
MathAtom.toSpeakableText = function(atoms, speechOptions) {
const options = speechOptions ? JSON.parse(JSON.stringify(speechOptions)) : {
textToSpeechMarkup: '', // no markup
textToSpeechRules: 'mathlive'
};
const options = speechOptions
? JSON.parse(JSON.stringify(speechOptions))
: {
textToSpeechMarkup: '', // no markup
textToSpeechRules: 'mathlive',
};
options.speechMode = 'math';

@@ -586,11 +693,16 @@

if (options.textToSpeechMarkup) {
options.textToSpeechRulesOptions = options.textToSpeechRulesOptions || {};
options.textToSpeechRulesOptions.markup = options.textToSpeechMarkup;
options.textToSpeechRulesOptions =
options.textToSpeechRulesOptions || {};
options.textToSpeechRulesOptions.markup =
options.textToSpeechMarkup;
if (options.textToSpeechRulesOptions.markup === 'ssml') {
options.textToSpeechRulesOptions.markup = 'ssml_step';
}
options.textToSpeechRulesOptions.rate = options.speechEngineRate;
options.textToSpeechRulesOptions.rate =
options.speechEngineRate;
}
if (options.textToSpeechRulesOptions) {
window.sre.System.getInstance().setupEngine(options.textToSpeechRulesOptions);
window.sre.System.getInstance().setupEngine(
options.textToSpeechRulesOptions
);
}

@@ -607,16 +719,21 @@ return window.sre.System.getInstance().toSpeech(mathML);

if (options.speechEngineRate) {
prosody = '<prosody rate="' + options.speechEngineRate + '">'
prosody = '<prosody rate="' + options.speechEngineRate + '">';
}
result = `<?xml version="1.0"?><speak version="1.1" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">` +
'<amazon:auto-breaths>' +
prosody +
'<p><s>' +
result +
'</s></p>' +
(prosody ? '</prosody>' : '') +
'</amazon:auto-breaths>' +
'</speak>';
} else if (options.textToSpeechMarkup === 'mac' && platform('mac') === 'mac') {
result =
`<?xml version="1.0"?><speak version="1.1" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">` +
'<amazon:auto-breaths>' +
prosody +
'<p><s>' +
result +
'</s></p>' +
(prosody ? '</prosody>' : '') +
'</amazon:auto-breaths>' +
'</speak>';
} else if (
options.textToSpeechMarkup === 'mac' &&
platform('mac') === 'mac'
) {
// Convert SSML to Mac markup
result = result.replace(/<mark([^/]*)\/>/g, '')
result = result
.replace(/<mark([^/]*)\/>/g, '')
.replace(/<emphasis>/g, '[[emph+]]')

@@ -631,11 +748,8 @@ .replace(/<\/emphasis>/g, '')

// Strip out the SSML markup
result = result.replace(/<[^>]*>/g, '')
.replace(/\s{2,}/g, ' ');
result = result.replace(/<[^>]*>/g, '').replace(/\s{2,}/g, ' ');
}
return result;
};
}
// Export the public interface for this module
export default {}
export default {};

@@ -1,3 +0,1 @@

/**

@@ -11,3 +9,2 @@ * This module contains some color dictionaries and algorithms to

/*

@@ -27,66 +24,65 @@ {\color{apricot}\blacksquare}{\color{aquamarine}\blacksquare}{\color{bittersweet}\blacksquare}{\color{black}\blacksquare}{\color{blue}\blacksquare}{\color{blueGreen}\blacksquare}{\color{blueviolet}\blacksquare}{\color{brickred}\blacksquare}{\color{brown}\blacksquare}{\color{burntorange}\blacksquare}{\color{cadetblue}\blacksquare}{\color{carnationpink}\blacksquare}{\color{cerulean}\blacksquare}{\color{cornflowerblue}\blacksquare}{\color{cyan}\blacksquare}{\color{dandelion}\blacksquare}{\color{darkorchid}\blacksquare}{\color{emerald}\blacksquare}{\color{forestgreen}\blacksquare}{\color{fuchsia}\blacksquare}{\color{goldenrod}\blacksquare}{\color{gray}\blacksquare}{\color{green}\blacksquare}{\color{greenyellow}\blacksquare}{\color{junglegreen}\blacksquare}{\color{lavender}\blacksquare}{\color{limegreen}\blacksquare}{\color{magenta}\blacksquare}{\color{mahogany}\blacksquare}{\color{maroon}\blacksquare}{\color{melon}\blacksquare}{\color{midnightblue}\blacksquare}{\color{mulberry}\blacksquare}{\color{navyblue}\blacksquare}{\color{olivegreen}\blacksquare}{\color{orange}\blacksquare}{\color{orangered}\blacksquare}{\color{orchid}\blacksquare}{\color{peach}\blacksquare}{\color{periwinkle}\blacksquare}{\color{pinegreen}\blacksquare}{\color{plum}\blacksquare}{\color{processblue}\blacksquare}{\color{purple}\blacksquare}{\color{rawsienna}\blacksquare}{\color{red}\blacksquare}{\color{redorange}\blacksquare}{\color{redviolet}\blacksquare}{\color{rhodamine}\blacksquare}{\color{royalblue}\blacksquare}{\color{royalpurple}\blacksquare}{\color{rubinered}\blacksquare}{\color{salmon}\blacksquare}{\color{seagreen}\blacksquare}{\color{sepia}\blacksquare}{\color{skyblue}\blacksquare}{\color{springgreen}\blacksquare}{\color{tan}\blacksquare}{\color{tealblue}\blacksquare}{\color{thistle}\blacksquare}{\color{turquoise}\blacksquare}{\color{violet}\blacksquare}{\color{violetred}\blacksquare}{\color{white}\blacksquare}{\color{wildstrawberry}\blacksquare}{\color{yellow}\blacksquare}{\color{yellowgreen}\blacksquare}{\color{yelloworange}\blacksquare}

const MATHEMATICA_COLORS = {
'm0': '#3f3d99', // strong blue
'm1': '#993d71', // strong cerise
'm2': '#998b3d', // strong gold
'm3': '#3d9956', // malachite green
'm4': '#3d5a99', // strong cobalt blue
'm5': '#993d90', // strong orchid
'm6': '#996d3d', // strong orange
'm7': '#43993d', // strong sap green
'm8': '#3d7999', // cornflower blue
'm9': '#843d99' // mulberry
}
// ColorData97 (Mathematica standard lines)
// rgb(0.368417, 0.506779, 0.709798), #5e81b5
// rgb(0.880722, 0.611041, 0.142051),
// rgb(0.560181, 0.691569, 0.194885),
// rgb(0.922526, 0.385626, 0.209179),
// rgb(0.528488, 0.470624, 0.701351),
// rgb(0.772079, 0.431554, 0.102387),
// rgb(0.363898, 0.618501, 0.782349),
// rgb(1, 0.75, 0),
// rgb(0.647624, 0.37816, 0.614037),
// rgb(0.571589, 0.586483, 0.),
// rgb(0.915, 0.3325, 0.2125),
// rgb(0.40082222609352647, 0.5220066643438841, 0.85),
// rgb(0.9728288904374106, 0.621644452187053, 0.07336199581899142),
// rgb(0.736782672705901, 0.358, 0.5030266573755369),
// rgb(0.28026441037696703, 0.715, 0.4292089322474965)
m0: '#3f3d99', // strong blue
m1: '#993d71', // strong cerise
m2: '#998b3d', // strong gold
m3: '#3d9956', // malachite green
m4: '#3d5a99', // strong cobalt blue
m5: '#993d90', // strong orchid
m6: '#996d3d', // strong orange
m7: '#43993d', // strong sap green
m8: '#3d7999', // cornflower blue
m9: '#843d99', // mulberry
};
// ColorData97 (Mathematica standard lines)
// rgb(0.368417, 0.506779, 0.709798), #5e81b5
// rgb(0.880722, 0.611041, 0.142051),
// rgb(0.560181, 0.691569, 0.194885),
// rgb(0.922526, 0.385626, 0.209179),
// rgb(0.528488, 0.470624, 0.701351),
// rgb(0.772079, 0.431554, 0.102387),
// rgb(0.363898, 0.618501, 0.782349),
// rgb(1, 0.75, 0),
// rgb(0.647624, 0.37816, 0.614037),
// rgb(0.571589, 0.586483, 0.),
// rgb(0.915, 0.3325, 0.2125),
// rgb(0.40082222609352647, 0.5220066643438841, 0.85),
// rgb(0.9728288904374106, 0.621644452187053, 0.07336199581899142),
// rgb(0.736782672705901, 0.358, 0.5030266573755369),
// rgb(0.28026441037696703, 0.715, 0.4292089322474965)
// MathLab colors
// '#0072bd' // [0, 0.4470, 0.7410] blue
// '#d95319' // [0.8500, 0.3250, 0.0980] orange
// '#edb120', // [0.9290, 0.6940, 0.1250] yellow
// '#7e2f8e', // [0.4940, 0.1840, 0.5560] purple
// '#77ac30', // [0.4660, 0.6740, 0.1880] green
// '#4dbeee', // [0.3010, 0.7450, 0.9330] cyan
// '#a2142f' // [0.6350, 0.0780, 0.1840] dark red
// MathLab colors
// '#0072bd' // [0, 0.4470, 0.7410] blue
// '#d95319' // [0.8500, 0.3250, 0.0980] orange
// '#edb120', // [0.9290, 0.6940, 0.1250] yellow
// '#7e2f8e', // [0.4940, 0.1840, 0.5560] purple
// '#77ac30', // [0.4660, 0.6740, 0.1880] green
// '#4dbeee', // [0.3010, 0.7450, 0.9330] cyan
// '#a2142f' // [0.6350, 0.0780, 0.1840] dark red
/* Area colors are most appropriate to color a large area */
const AREA_COLORS = [
'#d35d60', // red
'#7293cb', // cobalt blue
'#e1974d', // orange
'#84bb5d', // pistachio
'#9066a7', // purple
'#aD6a58', // vermilion
'#f5a4ce', // pale rose
'#fff590', // pale gold
'#212121', // Black
'#818787', // dark grey
'#d4d5d2', // light grey
'#ffffff' // white
]
'#d35d60', // red
'#7293cb', // cobalt blue
'#e1974d', // orange
'#84bb5d', // pistachio
'#9066a7', // purple
'#aD6a58', // vermilion
'#f5a4ce', // pale rose
'#fff590', // pale gold
'#212121', // Black
'#818787', // dark grey
'#d4d5d2', // light grey
'#ffffff', // white
];
/* Line colors are most appropriate to color as a stroke color */
const LINE_COLORS = [
'#cc2428', // red
'#3769b1', // cobalt blue
'#da7e30', // orange
'#409852', // malachite green
'#6b4c9a', // blue violet
'#922426', // red
'#e7298a', // brilliant rose
'#ffe907', // vivid gold
'#cc2428', // red
'#3769b1', // cobalt blue
'#da7e30', // orange
'#409852', // malachite green
'#6b4c9a', // blue violet
'#922426', // red
'#e7298a', // brilliant rose
'#ffe907', // vivid gold
'#000000',

@@ -96,3 +92,3 @@ '#525055',

'#ffffff',
]
];

@@ -114,73 +110,72 @@ /**

const NAMED_COLORS = {
'apricot': '#FBB982',
'aquamarine': '#00B5BE',
'bittersweet': '#C04F17',
'black': '#221E1F', // Indeed.
'blue': '#2D2F92',
'bluegreen': '#00B3B8',
'blueviolet': '#473992',
'brickred': '#B6321C',
'brown': '#792500',
'burntorange': '#F7921D',
'cadetblue': '#74729A',
'carnationpink': '#F282B4',
'cerulean': '#00A2E3',
'cornflowerblue': '#41B0E4',
'cyan': '#00AEEF',
'dandelion': '#FDBC42',
'darkorchid': '#A4538A',
'emerald': '#00A99D',
'forestgreen': '#009B55',
'fuchsia': '#8C368C',
'goldenrod': '#FFDF42',
'gray': '#949698',
'green': '#00A64F',
'greenyellow': '#DFE674',
'junglegreen': '#00A99A',
'lavender': '#F49EC4',
'limegreen': '#8DC73E',
'magenta': '#EC008C',
'mahogany': '#A9341F',
'maroon': '#AF3235',
'melon': '#F89E7B',
'midnightblue': '#006795',
'mulberry': '#A93C93',
'navyblue': '#006EB8',
'olivegreen': '#3C8031',
'orange': '#F58137',
'orangered': '#ED135A',
'orchid': '#AF72B0',
'peach': '#F7965A',
'periwinkle': '#7977B8',
'pinegreen': '#008B72',
'plum': '#92268F',
'processblue': '#00B0F0',
'purple': '#99479B',
'rawsienna': '#974006',
'red': '#ED1B23',
'redorange': '#F26035',
'redviolet': '#A1246B',
'rhodamine': '#EF559F',
'royalblue': '#0071BC',
'royalpurple': '#613F99',
'rubinered': '#ED017D',
'salmon': '#F69289',
'seagreen': '#3FBC9D',
'sepia': '#671800',
'skyblue': '#46C5DD',
'springgreen': '#C6DC67',
'tan': '#DA9D76',
'tealblue': '#00AEB3',
'thistle': '#D883B7',
'turquoise': '#00B4CE',
'violet': '#58429B',
'violetred': '#EF58A0',
'white': '#FFFFFF',
'wildstrawberry': '#EE2967',
'yellow': '#FFF200',
'yellowgreen': '#98CC70',
'yelloworange': '#FAA21A',
apricot: '#FBB982',
aquamarine: '#00B5BE',
bittersweet: '#C04F17',
black: '#221E1F', // Indeed.
blue: '#2D2F92',
bluegreen: '#00B3B8',
blueviolet: '#473992',
brickred: '#B6321C',
brown: '#792500',
burntorange: '#F7921D',
cadetblue: '#74729A',
carnationpink: '#F282B4',
cerulean: '#00A2E3',
cornflowerblue: '#41B0E4',
cyan: '#00AEEF',
dandelion: '#FDBC42',
darkorchid: '#A4538A',
emerald: '#00A99D',
forestgreen: '#009B55',
fuchsia: '#8C368C',
goldenrod: '#FFDF42',
gray: '#949698',
green: '#00A64F',
greenyellow: '#DFE674',
junglegreen: '#00A99A',
lavender: '#F49EC4',
limegreen: '#8DC73E',
magenta: '#EC008C',
mahogany: '#A9341F',
maroon: '#AF3235',
melon: '#F89E7B',
midnightblue: '#006795',
mulberry: '#A93C93',
navyblue: '#006EB8',
olivegreen: '#3C8031',
orange: '#F58137',
orangered: '#ED135A',
orchid: '#AF72B0',
peach: '#F7965A',
periwinkle: '#7977B8',
pinegreen: '#008B72',
plum: '#92268F',
processblue: '#00B0F0',
purple: '#99479B',
rawsienna: '#974006',
red: '#ED1B23',
redorange: '#F26035',
redviolet: '#A1246B',
rhodamine: '#EF559F',
royalblue: '#0071BC',
royalpurple: '#613F99',
rubinered: '#ED017D',
salmon: '#F69289',
seagreen: '#3FBC9D',
sepia: '#671800',
skyblue: '#46C5DD',
springgreen: '#C6DC67',
tan: '#DA9D76',
tealblue: '#00AEB3',
thistle: '#D883B7',
turquoise: '#00B4CE',
violet: '#58429B',
violetred: '#EF58A0',
white: '#FFFFFF',
wildstrawberry: '#EE2967',
yellow: '#FFF200',
yellowgreen: '#98CC70',
yelloworange: '#FAA21A',
};
// Other color lists: SVG colors, x11 colors

@@ -377,6 +372,6 @@ /*

// If the string is prefixed with a '-', use the complementary color
const complementary = colorSpec.length > 0 && colorSpec[0].charAt(0) === '-';
const complementary =
colorSpec.length > 0 && colorSpec[0].charAt(0) === '-';
if (complementary) colorSpec[0] = colorSpec[0].slice(1);
for (let i = 0; i < colorSpec.length; i++) {

@@ -400,3 +395,3 @@ baseRed = red;

} else {
m = color.match(/^#([0-9a-f]{3})$/i)
m = color.match(/^#([0-9a-f]{3})$/i);
if (m && m[1]) {

@@ -406,3 +401,3 @@ // It's a three-digit hex number

const g1 = parseInt(m[1][1], 16);
const b1 = parseInt(m[1][2], 16)
const b1 = parseInt(m[1][2], 16);
red = Math.max(0, Math.min(255, r1 * 16 + r1));

@@ -413,3 +408,5 @@ green = Math.max(0, Math.min(255, g1 * 16 + g1));

// It's a rgb functional
m = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
m = color.match(
/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i
);
if (m && m[1] && m[2] && m[3]) {

@@ -425,3 +422,3 @@ red = Math.max(0, Math.min(255, parseInt(m[1])));

if (mix >= 0) {
red = (1.0 - mix) * red + mix * baseRed;
red = (1.0 - mix) * red + mix * baseRed;
green = (1.0 - mix) * green + mix * baseGreen;

@@ -448,6 +445,8 @@ blue = (1.0 - mix) * blue + mix * baseBlue;

return '#' +
return (
'#' +
('00' + Math.round(red).toString(16)).slice(-2) +
('00' + Math.round(green).toString(16)).slice(-2) +
('00' + Math.round(blue).toString(16)).slice(-2);
('00' + Math.round(blue).toString(16)).slice(-2)
);
}

@@ -481,5 +480,2 @@

LINE_COLORS,
}
};

@@ -1,2 +0,1 @@

import Mathstyle from './mathstyle.js';

@@ -41,4 +40,6 @@

this.mathstyle = Mathstyle.toMathstyle(from.mathstyle || 'displaystyle');
this.size = from.size || 'size5'; // medium size
this.mathstyle = Mathstyle.toMathstyle(
from.mathstyle || 'displaystyle'
);
this.size = from.size || 'size5'; // medium size

@@ -78,3 +79,2 @@ this.parentMathstyle = from.parentMathstyle || this.mathstyle;

/**

@@ -95,9 +95,9 @@ * Change the mathstyle of this context

cramp() {
return this.clone({'mathstyle': this.mathstyle.cramp()});
return this.clone({ mathstyle: this.mathstyle.cramp() });
}
sup() {
return this.clone({'mathstyle': this.mathstyle.sup()});
return this.clone({ mathstyle: this.mathstyle.sup() });
}
sub() {
return this.clone({'mathstyle': this.mathstyle.sup()});
return this.clone({ mathstyle: this.mathstyle.sup() });
}

@@ -107,3 +107,3 @@ }

export default {
Context
}
Context,
};

@@ -35,4 +35,2 @@ /**

/**

@@ -48,10 +46,19 @@ * Makes a small delimiter. This is a delimiter that comes in the Main-Regular

const span = Span.makeStyleWrap(type, text, context.mathstyle, style, classes);
const span = Span.makeStyleWrap(
type,
text,
context.mathstyle,
style,
classes
);
if (center) {
span.setTop((1 - context.mathstyle.sizeMultiplier / style.sizeMultiplier) *
context.mathstyle.metrics.axisHeight);
span.setTop(
(1 - context.mathstyle.sizeMultiplier / style.sizeMultiplier) *
context.mathstyle.metrics.axisHeight
);
}
span.setStyle('color', context.color);
if (typeof context.opacity === 'number') span.setStyle('opacity', context.opacity);
if (typeof context.opacity === 'number')
span.setStyle('opacity', context.opacity);

@@ -68,15 +75,24 @@ return span;

function makeLargeDelim(type, delim, size, center, context, classes) {
const inner = makeSymbol('Size' + size + '-Regular',
Definitions.getValue('math', delim));
const inner = makeSymbol(
'Size' + size + '-Regular',
Definitions.getValue('math', delim)
);
const result = Span.makeStyleWrap( type,
makeSpan(inner, 'delimsizing size' + size),
context.mathstyle, Mathstyle.TEXT, classes);
const result = Span.makeStyleWrap(
type,
makeSpan(inner, 'delimsizing size' + size),
context.mathstyle,
Mathstyle.TEXT,
classes
);
if (center) {
result.setTop((1 - context.mathstyle.sizeMultiplier) *
context.mathstyle.metrics.axisHeight);
result.setTop(
(1 - context.mathstyle.sizeMultiplier) *
context.mathstyle.metrics.axisHeight
);
}
result.setStyle('color', context.color);
if (typeof context.opacity === 'number') result.setStyle('opacity', context.opacity);
if (typeof context.opacity === 'number')
result.setStyle('opacity', context.opacity);

@@ -103,4 +119,6 @@ return result;

// be simplified
const inner = makeSpan(makeSymbol(font,
Definitions.getValue('math', symbol)), 'delimsizinginner' + sizeClass);
const inner = makeSpan(
makeSymbol(font, Definitions.getValue('math', symbol)),
'delimsizinginner' + sizeClass
);

@@ -116,4 +134,3 @@ return inner;

*/
function makeStackedDelim(type, delim, heightTotal, center, context,
classes) {
function makeStackedDelim(type, delim, heightTotal, center, context, classes) {
// There are four parts, the top, an optional middle, a repeated part, and a

@@ -133,6 +150,17 @@ // bottom.

// repeats of the arrows
if (delim === '\\vert' || delim === '\\lvert' || delim === '\\rvert' || delim === '\\mvert' || delim === '\\mid') {
if (
delim === '\\vert' ||
delim === '\\lvert' ||
delim === '\\rvert' ||
delim === '\\mvert' ||
delim === '\\mid'
) {
repeat = top = bottom = '\u2223';
} else if (delim === '\\Vert' || delim === '\\lVert' ||
delim === '\\rVert' || delim === '\\mVert' || delim === '\\|') {
} else if (
delim === '\\Vert' ||
delim === '\\lVert' ||
delim === '\\rVert' ||
delim === '\\mVert' ||
delim === '\\|'
) {
repeat = top = bottom = '\u2225';

@@ -244,9 +272,15 @@ } else if (delim === '\\uparrow') {

const topMetrics = FontMetrics.getCharacterMetrics(
Definitions.getValue('math', top), font);
Definitions.getValue('math', top),
font
);
const topHeightTotal = topMetrics.height + topMetrics.depth;
const repeatMetrics = FontMetrics.getCharacterMetrics(
Definitions.getValue('math', repeat), font);
Definitions.getValue('math', repeat),
font
);
const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
const bottomMetrics = FontMetrics.getCharacterMetrics(
Definitions.getValue('math', bottom), font);
Definitions.getValue('math', bottom),
font
);
const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;

@@ -257,3 +291,5 @@ let middleHeightTotal = 0;

const middleMetrics = FontMetrics.getCharacterMetrics(
Definitions.getValue('math', middle), font);
Definitions.getValue('math', middle),
font
);
middleHeightTotal = middleMetrics.height + middleMetrics.depth;

@@ -269,3 +305,4 @@ middleFactor = 2; // repeat symmetrically above and below middle

const repeatCount = Math.ceil(
(heightTotal - minHeight) / (middleFactor * repeatHeightTotal));
(heightTotal - minHeight) / (middleFactor * repeatHeightTotal)
);

@@ -318,6 +355,12 @@ // Compute the total height of the delimiter including all the symbols

inner.setStyle('color', context.color);
if (typeof context.opacity === 'number') inner.setStyle('opacity', context.opacity);
if (typeof context.opacity === 'number')
inner.setStyle('opacity', context.opacity);
return Span.makeStyleWrap(type, makeSpan(inner, 'delimsizing mult'),
context.mathstyle, Mathstyle.TEXT, classes);
return Span.makeStyleWrap(
type,
makeSpan(inner, 'delimsizing mult'),
context.mathstyle,
Mathstyle.TEXT,
classes
);
}

@@ -328,5 +371,16 @@

const stackLargeDelimiters = [
'(', ')', '[', '\\lbrack', ']', '\\rbrack',
'\\{', '\\lbrace', '\\}', '\\rbrace',
'\\lfloor', '\\rfloor', '\\lceil', '\\rceil',
'(',
')',
'[',
'\\lbrack',
']',
'\\rbrack',
'\\{',
'\\lbrace',
'\\}',
'\\rbrace',
'\\lfloor',
'\\rfloor',
'\\lceil',
'\\rceil',
'\\surd',

@@ -337,8 +391,22 @@ ];

const stackAlwaysDelimiters = [
'\\uparrow', '\\downarrow', '\\updownarrow',
'\\Uparrow', '\\Downarrow', '\\Updownarrow',
'|', '\\|', '\\vert', '\\Vert',
'\\lvert', '\\rvert', '\\lVert', '\\rVert',
'\\mvert', '\\mid',
'\\lgroup', '\\rgroup', '\\lmoustache', '\\rmoustache',
'\\uparrow',
'\\downarrow',
'\\updownarrow',
'\\Uparrow',
'\\Downarrow',
'\\Updownarrow',
'|',
'\\|',
'\\vert',
'\\Vert',
'\\lvert',
'\\rvert',
'\\lVert',
'\\rVert',
'\\mvert',
'\\mid',
'\\lgroup',
'\\rgroup',
'\\lmoustache',
'\\rmoustache',
];

@@ -348,3 +416,10 @@

const stackNeverDelimiters = [
'<', '>', '\\langle', '\\rangle', '/', '\\backslash', '\\lt', '\\gt',
'<',
'>',
'\\langle',
'\\rangle',
'/',
'\\backslash',
'\\lt',
'\\gt',
];

@@ -378,10 +453,18 @@

// Sized delimiters are never centered.
if (stackLargeDelimiters.includes(delim) ||
stackNeverDelimiters.includes(delim)) {
if (
stackLargeDelimiters.includes(delim) ||
stackNeverDelimiters.includes(delim)
) {
return makeLargeDelim(type, delim, size, false, context, classes);
} else if (stackAlwaysDelimiters.includes(delim)) {
return makeStackedDelim(
type, delim, sizeToMaxHeight[size], false, context, classes);
type,
delim,
sizeToMaxHeight[size],
false,
context,
classes
);
}
console.assert(false, 'Unknown delimiter \'' + delim + '\'');
console.assert(false, "Unknown delimiter '" + delim + "'");
return null;

@@ -404,9 +487,9 @@ }

const stackNeverDelimiterSequence = [
{type: 'small', mathstyle: Mathstyle.SCRIPTSCRIPT},
{type: 'small', mathstyle: Mathstyle.SCRIPT},
{type: 'small', mathstyle: Mathstyle.TEXT},
{type: 'large', size: 1},
{type: 'large', size: 2},
{type: 'large', size: 3},
{type: 'large', size: 4},
{ type: 'small', mathstyle: Mathstyle.SCRIPTSCRIPT },
{ type: 'small', mathstyle: Mathstyle.SCRIPT },
{ type: 'small', mathstyle: Mathstyle.TEXT },
{ type: 'large', size: 1 },
{ type: 'large', size: 2 },
{ type: 'large', size: 3 },
{ type: 'large', size: 4 },
];

@@ -416,6 +499,6 @@

const stackAlwaysDelimiterSequence = [
{type: 'small', mathstyle: Mathstyle.SCRIPTSCRIPT},
{type: 'small', mathstyle: Mathstyle.SCRIPT},
{type: 'small', mathstyle: Mathstyle.TEXT},
{type: 'stack'},
{ type: 'small', mathstyle: Mathstyle.SCRIPTSCRIPT },
{ type: 'small', mathstyle: Mathstyle.SCRIPT },
{ type: 'small', mathstyle: Mathstyle.TEXT },
{ type: 'stack' },
];

@@ -426,10 +509,10 @@

const stackLargeDelimiterSequence = [
{type: 'small', mathstyle: Mathstyle.SCRIPTSCRIPT},
{type: 'small', mathstyle: Mathstyle.SCRIPT},
{type: 'small', mathstyle: Mathstyle.TEXT},
{type: 'large', size: 1},
{type: 'large', size: 2},
{type: 'large', size: 3},
{type: 'large', size: 4},
{type: 'stack'},
{ type: 'small', mathstyle: Mathstyle.SCRIPTSCRIPT },
{ type: 'small', mathstyle: Mathstyle.SCRIPT },
{ type: 'small', mathstyle: Mathstyle.TEXT },
{ type: 'large', size: 1 },
{ type: 'large', size: 2 },
{ type: 'large', size: 3 },
{ type: 'large', size: 4 },
{ type: 'stack' },
];

@@ -470,8 +553,9 @@

const metrics = FontMetrics.getCharacterMetrics(
delim,
delimTypeToFont(sequence[i]));
delim,
delimTypeToFont(sequence[i])
);
if (metrics.defaultMetrics) {
// If we don't have metrics info for this character,
// assume we'll construct as a small delimiter
return {type: 'small', mathstyle: Mathstyle.SCRIPT};
return { type: 'small', mathstyle: Mathstyle.SCRIPT };
}

@@ -497,3 +581,2 @@ let heightDepth = metrics.height + metrics.depth;

/**

@@ -534,4 +617,8 @@ * Make a delimiter of a given height+depth, with optional centering. Here, we

// Look through the sequence
const delimType = traverseSequence(Definitions.getValue('math', delim),
height, sequence, context);
const delimType = traverseSequence(
Definitions.getValue('math', delim),
height,
sequence,
context
);

@@ -541,7 +628,19 @@ // Depending on the sequence element we decided on, call the appropriate

if (delimType.type === 'small') {
return makeSmallDelim(type, delim, delimType.mathstyle, center, context,
classes);
return makeSmallDelim(
type,
delim,
delimType.mathstyle,
center,
context,
classes
);
} else if (delimType.type === 'large') {
return makeLargeDelim(type, delim, delimType.size, center, context,
classes);
return makeLargeDelim(
type,
delim,
delimType.size,
center,
context,
classes
);
}

@@ -570,4 +669,4 @@ console.assert(delimType.type === 'stack');

// Taken from TeX source, tex.web, function make_left_right
const delimiterFactor = 901; // plain.tex:327
const delimiterShortfall = 5.0 / FontMetrics.METRICS.ptPerEm; // plain.tex:345
const delimiterFactor = 901; // plain.tex:327
const delimiterShortfall = 5.0 / FontMetrics.METRICS.ptPerEm; // plain.tex:345

@@ -578,4 +677,4 @@ let delta2 = depth + axisHeight;

let delta = (delta1 * delimiterFactor) / 500;
delta2 = 2 * delta1 - delimiterShortfall;
let delta = (delta1 * delimiterFactor) / 500;
delta2 = 2 * delta1 - delimiterShortfall;
delta = Math.max(delta, delta2);

@@ -610,13 +709,13 @@

function makeNullFence(type, context, classes) {
return Span.makeSpanOfType(type, '',
'sizing' + // @todo not useful, redundant with 'nulldelimiter'
return Span.makeSpanOfType(
type,
'',
'sizing' + // @todo not useful, redundant with 'nulldelimiter'
// 'reset-' + context.size, 'size5', // @todo: that seems like a lot of resizing... do we need both?
context.mathstyle.adjustTo(Mathstyle.TEXT) +
' nulldelimiter ' // The null delimiter has a width, specified by class 'nulldelimiter'
+ (classes || '')
' nulldelimiter ' + // The null delimiter has a width, specified by class 'nulldelimiter'
(classes || '')
);
}
// Export the public interface for this module

@@ -626,6 +725,3 @@ export default {

makeCustomSizedDelim,
makeLeftRightDelim
}
makeLeftRightDelim,
};

@@ -25,6 +25,4 @@ /* eslint no-unused-vars:0 */

// Notably missing are half width Katakana and Romaji glyphs.
const cjkRegex =
/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/;
const cjkRegex = /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/;
/*

@@ -58,24 +56,24 @@ *

export const SIGMAS = {
slant: [0.250, 0.250, 0.250], // sigma1
space: [0.000, 0.000, 0.000], // sigma2
stretch: [0.000, 0.000, 0.000], // sigma3
shrink: [0.000, 0.000, 0.000], // sigma4
xHeight: [0.431, 0.431, 0.431], // sigma5
quad: [1.000, 1.171, 1.472], // sigma6
extraSpace: [0.000, 0.000, 0.000], // sigma7
num1: [0.677, 0.732, 0.925], // sigma8
num2: [0.394, 0.384, 0.387], // sigma9
num3: [0.444, 0.471, 0.504], // sigma10
denom1: [0.686, 0.752, 1.025], // sigma11
denom2: [0.345, 0.344, 0.532], // sigma12
sup1: [0.413, 0.503, 0.504], // sigma13
sup2: [0.363, 0.431, 0.404], // sigma14
sup3: [0.289, 0.286, 0.294], // sigma15
sub1: [0.150, 0.143, 0.200], // sigma16
sub2: [0.247, 0.286, 0.400], // sigma17
supDrop: [0.386, 0.353, 0.494], // sigma18
subDrop: [0.050, 0.071, 0.100], // sigma19
delim1: [2.390, 1.700, 1.980], // sigma20
delim2: [1.010, 1.157, 1.420], // sigma21
axisHeight: [0.250, 0.250, 0.250], // sigma22
slant: [0.25, 0.25, 0.25], // sigma1
space: [0.0, 0.0, 0.0], // sigma2
stretch: [0.0, 0.0, 0.0], // sigma3
shrink: [0.0, 0.0, 0.0], // sigma4
xHeight: [0.431, 0.431, 0.431], // sigma5
quad: [1.0, 1.171, 1.472], // sigma6
extraSpace: [0.0, 0.0, 0.0], // sigma7
num1: [0.677, 0.732, 0.925], // sigma8
num2: [0.394, 0.384, 0.387], // sigma9
num3: [0.444, 0.471, 0.504], // sigma10
denom1: [0.686, 0.752, 1.025], // sigma11
denom2: [0.345, 0.344, 0.532], // sigma12
sup1: [0.413, 0.503, 0.504], // sigma13
sup2: [0.363, 0.431, 0.404], // sigma14
sup3: [0.289, 0.286, 0.294], // sigma15
sub1: [0.15, 0.143, 0.2], // sigma16
sub2: [0.247, 0.286, 0.4], // sigma17
supDrop: [0.386, 0.353, 0.494], // sigma18
subDrop: [0.05, 0.071, 0.1], // sigma19
delim1: [2.39, 1.7, 1.98], // sigma20
delim2: [1.01, 1.157, 1.42], // sigma21
axisHeight: [0.25, 0.25, 0.25], // sigma22
};

@@ -123,3 +121,3 @@

ptPerEm: ptPerEm,
pxPerEm: ptPerEm * 4.0 / 3.0, // A CSS pt is fixed at 1.333px
pxPerEm: (ptPerEm * 4.0) / 3.0, // A CSS pt is fixed at 1.333px
doubleRuleSep: 2.0 / ptPerEm,

@@ -129,7 +127,6 @@ arraycolsep: 5.0 / ptPerEm,

arrayrulewidth: 0.4 / ptPerEm,
fboxsep: 3 / ptPerEm, // From letter.dtx:1626
fboxrule: 0.4 / ptPerEm, // From letter.dtx:1627
fboxsep: 3 / ptPerEm, // From letter.dtx:1626
fboxrule: 0.4 / ptPerEm, // From letter.dtx:1627
};
// These are very rough approximations. We default to Times New Roman which

@@ -143,81 +140,79 @@ // should have Latin-1 and Cyrillic characters, but may not depending on the

const extraCharacterMap = {
'\u00a0': '\u0020', // NON-BREAKING SPACE is like space
'\u200b': '\u0020', // ZERO WIDTH SPACE is like space
'\u00a0': '\u0020', // NON-BREAKING SPACE is like space
'\u200b': '\u0020', // ZERO WIDTH SPACE is like space
// Latin-1
'Å': 'A',
'Ç': 'C',
'Ð': 'D',
'Þ': 'o',
'å': 'a',
'ç': 'c',
'ð': 'd',
'þ': 'o',
Å: 'A',
Ç: 'C',
Ð: 'D',
Þ: 'o',
å: 'a',
ç: 'c',
ð: 'd',
þ: 'o',
// Cyrillic
'А': 'A',
'Б': 'B',
'В': 'B',
'Г': 'F',
'Д': 'A',
'Е': 'E',
'Ж': 'K',
'З': '3',
'И': 'N',
'Й': 'N',
'К': 'K',
'Л': 'N',
'М': 'M',
'Н': 'H',
'О': 'O',
'П': 'N',
'Р': 'P',
'С': 'C',
'Т': 'T',
'У': 'y',
'Ф': 'O',
'Х': 'X',
'Ц': 'U',
'Ч': 'h',
'Ш': 'W',
'Щ': 'W',
'Ъ': 'B',
'Ы': 'X',
'Ь': 'B',
'Э': '3',
'Ю': 'X',
'Я': 'R',
'а': 'a',
'б': 'b',
'в': 'a',
'г': 'r',
'д': 'y',
'е': 'e',
'ж': 'm',
'з': 'e',
'и': 'n',
'й': 'n',
'к': 'n',
'л': 'n',
'м': 'm',
'н': 'n',
'о': 'o',
'п': 'n',
'р': 'p',
'с': 'c',
'т': 'o',
'у': 'y',
'ф': 'b',
'х': 'x',
'ц': 'n',
'ч': 'n',
'ш': 'w',
'щ': 'w',
'ъ': 'a',
'ы': 'm',
'ь': 'a',
'э': 'e',
'ю': 'm',
'я': 'r',
А: 'A',
Б: 'B',
В: 'B',
Г: 'F',
Д: 'A',
Е: 'E',
Ж: 'K',
З: '3',
И: 'N',
Й: 'N',
К: 'K',
Л: 'N',
М: 'M',
Н: 'H',
О: 'O',
П: 'N',
Р: 'P',
С: 'C',
Т: 'T',
У: 'y',
Ф: 'O',
Х: 'X',
Ц: 'U',
Ч: 'h',
Ш: 'W',
Щ: 'W',
Ъ: 'B',
Ы: 'X',
Ь: 'B',
Э: '3',
Ю: 'X',
Я: 'R',
а: 'a',
б: 'b',
в: 'a',
г: 'r',
д: 'y',
е: 'e',
ж: 'm',
з: 'e',
и: 'n',
й: 'n',
к: 'n',
л: 'n',
м: 'm',
н: 'n',
о: 'o',
п: 'n',
р: 'p',
с: 'c',
т: 'o',
у: 'y',
ф: 'b',
х: 'x',
ц: 'n',
ч: 'n',
ш: 'w',
щ: 'w',
ъ: 'a',
ы: 'm',
ь: 'a',
э: 'e',
ю: 'm',
я: 'r',
};

@@ -237,13 +232,14 @@

const getCharacterMetrics = function(character, fontCode) {
const fontName = {
'cal': 'Caligraphic-Regular',
'ams': 'AMS-Regular',
'frak': 'Fraktur-Regular',
'bb': 'AMS-Regular',
'scr': 'Script-Regular',
'cmr': 'Main-Regular',
'cmtt': 'Typewriter-Regular',
'cmss': 'SansSerif-Regular'
}[fontCode] || fontCode;
const fontName =
{
cal: 'Caligraphic-Regular',
ams: 'AMS-Regular',
frak: 'Fraktur-Regular',
bb: 'AMS-Regular',
scr: 'Script-Regular',
cmr: 'Main-Regular',
cmtt: 'Typewriter-Regular',
cmss: 'SansSerif-Regular',
}[fontCode] || fontCode;
// console.assert(character.length === 1);

@@ -270,7 +266,7 @@ // console.assert(metricMap[fontName], 'Unknown font "' + fontName + '"');

defaultMetrics: true,
depth: .20,
height: .70,
depth: 0.2,
height: 0.7,
italic: 0,
skew: 0
}
skew: 0,
};
}

@@ -283,10 +279,9 @@

italic: metrics[2],
skew: metrics[3]
}
skew: metrics[3],
};
}
return null;
}
};
/**

@@ -312,17 +307,17 @@ *

// If the units are missing, TeX assumes 'pt'
const f = {
'pt': 1.0,
'mm': 7227 / 2540,
'cm': 7227 / 254,
'ex': 35271 / 8192,
'px': 3.0 / 4.0,
'em': METRICS.ptPerEm,
'bp': 803 / 800,
'dd': 1238 / 1157,
'pc': 12.0,
'in': 72.27,
'mu': 10 / 18,
const f =
{
pt: 1.0,
mm: 7227 / 2540,
cm: 7227 / 254,
ex: 35271 / 8192,
px: 3.0 / 4.0,
em: METRICS.ptPerEm,
bp: 803 / 800,
dd: 1238 / 1157,
pc: 12.0,
in: 72.27,
mu: 10 / 18,
}[unit] || 1.0;
}[unit] || 1.0
if (isFinite(precision)) {

@@ -340,9 +335,8 @@ const factor = Math.pow(10, precision);

export default {
toEm : convertDimenToEm,
toEm: convertDimenToEm,
toPx: convertDimenToPx,
METRICS,
SIGMAS,
getCharacterMetrics
}
getCharacterMetrics,
};

@@ -12,8 +12,6 @@ /**

* {@link ftp://tug.ctan.org/pub/tex-archive/systems/knuth/dist/lib/plain.tex|plain.tex}
*/
*/
import GraphemeSplitter from './grapheme-splitter.js';
/**

@@ -118,3 +116,3 @@ *

return /[ \f\n\r\t\v\xA0\u2028\u2029]/.test(this.s[this.pos]);
/*
/*
Note that browsers are inconsistent in their definitions of the

@@ -179,3 +177,3 @@ `\s` metacharacter, so we use an explicit pattern instead.

}
result = new Token('command', command);
result = new Token('command', command);
}

@@ -248,6 +246,2 @@ }

/**

@@ -265,3 +259,3 @@ * Create Tokens from a stream of LaTeX

const lines = s.toString().split(/\r?\n/);
let stream = '';
let stream = '';
let sep = '';

@@ -286,8 +280,4 @@ for (const line of lines) {

export default {
tokenize
}
tokenize,
};

@@ -19,3 +19,3 @@ /**

import {SIGMAS} from './fontMetrics.js';
import { SIGMAS } from './fontMetrics.js';

@@ -125,11 +125,2 @@ const metrics = [{}, {}, {}]; /* textstyle, scriptstyle, scriptscriptstyle */

// IDs of the different styles

@@ -154,3 +145,3 @@ const D = 0;

new Mathstyle(SS, 3, 0.5, false),
new Mathstyle(SSc, 3, 0.5, true)
new Mathstyle(SSc, 3, 0.5, true),
];

@@ -171,7 +162,7 @@

const STYLE_NAMES = {
'displaystyle': styles[D],
'textstyle': styles[T],
'scriptstyle': styles[S],
'scriptscriptstyle': styles[SS]
}
displaystyle: styles[D],
textstyle: styles[T],
scriptstyle: styles[S],
scriptscriptstyle: styles[SS],
};

@@ -182,4 +173,2 @@ console.assert(STYLE_NAMES[s], 'unknown style: "', s, '"');

// String names for the different sizes

@@ -190,6 +179,5 @@ const sizeNames = [

'scriptstyle',
'scriptscriptstyle'
'scriptscriptstyle',
];
const ADJUST_NAMES = [

@@ -200,3 +188,3 @@ [

'reset-textstyle scriptstyle',
'reset-textstyle scriptscriptstyle'
'reset-textstyle scriptscriptstyle',
],

@@ -206,5 +194,5 @@

'reset-textstyle displaystyle textstyle',
'', // 'reset-textstyle textstyle',
'', // 'reset-textstyle textstyle',
'reset-textstyle scriptstyle',
'reset-textstyle scriptscriptstyle'
'reset-textstyle scriptscriptstyle',
],

@@ -216,3 +204,3 @@

'', // 'reset-scriptstyle scriptstyle',
'reset-scriptstyle scriptscriptstyle'
'reset-scriptstyle scriptscriptstyle',
],

@@ -224,7 +212,6 @@

'reset-scriptscriptstyle scriptstyle',
'' // 'reset-scriptscriptstyle scriptscriptstyle'
'', // 'reset-scriptscriptstyle scriptscriptstyle'
],
];
// Lookup tables for switching from one style to another

@@ -244,6 +231,3 @@ const sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];

SCRIPTSCRIPT: styles[SS],
toMathstyle
}
toMathstyle,
};

@@ -1,2 +0,1 @@

/**

@@ -89,3 +88,5 @@ * @module core/parser

this.endCount = 0;
return this.index < this.tokens.length ? this.tokens[this.index++] : null;
return this.index < this.tokens.length
? this.tokens[this.index++]
: null;
}

@@ -103,4 +104,6 @@ peek(offset) {

lastMathAtom() {
const lastType = this.mathList.length === 0 ? 'none' :
this.mathList[this.mathList.length - 1].type;
const lastType =
this.mathList.length === 0
? 'none'
: this.mathList[this.mathList.length - 1].type;
if (lastType !== 'mop' && lastType !== 'msubsup') {

@@ -122,4 +125,5 @@ // ZERO WIDTH SPACE

const index = this.index;
return index < this.tokens.length ?
this.tokens[index].type === type : false;
return index < this.tokens.length
? this.tokens[index].type === type
: false;
}

@@ -136,5 +140,6 @@ /**

const index = this.index;
return index < this.tokens.length ?
this.tokens[index].type === 'literal' &&
(!value || this.tokens[index].value === value) : false;
return index < this.tokens.length
? this.tokens[index].type === 'literal' &&
(!value || this.tokens[index].value === value)
: false;
}

@@ -149,17 +154,29 @@ /**

hasLiteralPattern(pattern) {
return this.hasToken('literal') &&
pattern.test(this.tokens[this.index].value);
return (
this.hasToken('literal') &&
pattern.test(this.tokens[this.index].value)
);
}
hasCommand(command) {
console.assert(command === '\\' || command.charAt(0) !== '\\', 'hasCommand() does not require a \\');
console.assert(
command === '\\' || command.charAt(0) !== '\\',
'hasCommand() does not require a \\'
);
const index = this.index;
return index < this.tokens.length ?
this.tokens[index].type === 'command' &&
this.tokens[index].value === command : false;
return index < this.tokens.length
? this.tokens[index].type === 'command' &&
this.tokens[index].value === command
: false;
}
hasInfixCommand() {
const index = this.index;
if (index < this.tokens.length &&
this.tokens[index].type === 'command') {
const info = Definitions.getInfo('\\' + this.tokens[index].value, this.parseMode, this.macros);
if (
index < this.tokens.length &&
this.tokens[index].type === 'command'
) {
const info = Definitions.getInfo(
'\\' + this.tokens[index].value,
this.parseMode,
this.macros
);
return info && info.infix;

@@ -171,12 +188,14 @@ }

const index = this.index;
return this.tabularMode && index < this.tokens.length ?
this.tokens[index].type === 'literal' &&
this.tokens[index].value === '&' : false;
return this.tabularMode && index < this.tokens.length
? this.tokens[index].type === 'literal' &&
this.tokens[index].value === '&'
: false;
}
hasRowSeparator() {
const index = this.index;
return this.tabularMode && index < this.tokens.length ?
this.tokens[index].type === 'command' &&
(this.tokens[index].value === '\\' ||
this.tokens[index].value === 'cr') : false;
return this.tabularMode && index < this.tokens.length
? this.tokens[index].type === 'command' &&
(this.tokens[index].value === '\\' ||
this.tokens[index].value === 'cr')
: false;
}

@@ -198,6 +217,16 @@ parseColumnSeparator() {

// use it.
return parseTokens(Lexer.tokenize(this.args['?']), this.parseMode, null, this.macros);
return parseTokens(
Lexer.tokenize(this.args['?']),
this.parseMode,
null,
this.macros
);
}
// U+2753 = BLACK QUESTION MARK ORNAMENT
const result = new MathAtom(this.parseMode, 'placeholder', '?', this.style);
const result = new MathAtom(
this.parseMode,
'placeholder',
'?',
this.style
);
result.captureSelection = true;

@@ -294,3 +323,5 @@ return [result];

}
done = this.end() || token.type !== 'literal' ||
done =
this.end() ||
token.type !== 'literal' ||
value.length >= keyword.length;

@@ -330,3 +361,3 @@ }

// \operatorname{lim~inf}. It's interpreted as a nbs
result += '\u00a0'; // NO-BREAK SPACE
result += '\u00a0'; // NO-BREAK SPACE
} else {

@@ -478,3 +509,7 @@ // TeX will give a 'Missing \endcsname inserted' error

const savedParsemode = this.swapParseMode('math');
result.push({ gap: this.scanImplicitGroup(token => token.type === '}') });
result.push({
gap: this.scanImplicitGroup(
token => token.type === '}'
),
});
this.swapParseMode(savedParsemode);

@@ -502,3 +537,5 @@ }

result.mathstyle = final === ')' ? 'textstyle' : 'displaystyle';
result.body = this.scanImplicitGroup(token => token.type === 'command' && token.value === final);
result.body = this.scanImplicitGroup(
token => token.type === 'command' && token.value === final
);
this.parseCommand(final);

@@ -590,3 +627,5 @@ this.swapParseMode(savedParsemode);

} else {
this.mathList = this.mathList.concat(this.scanImplicitGroup());
this.mathList = this.mathList.concat(
this.scanImplicitGroup()
);
}

@@ -599,3 +638,6 @@ }

// If we're in tabular mode, we should end up with an empty mathlist
console.assert(!this.tabularMode || newMathList.length === 0, 'Leftover atoms in tabular mode');
console.assert(
!this.tabularMode || newMathList.length === 0,
'Leftover atoms in tabular mode'
);
this.parseMode = savedMode;

@@ -605,7 +647,11 @@ this.tabularMode = savedTabularMode;

if (env.tabular && array.length === 0) return null;
const result = new MathAtom(this.parseMode, 'array', newMathList,
env.parser ? env.parser(envName, args, array) : {});
const result = new MathAtom(
this.parseMode,
'array',
newMathList,
env.parser ? env.parser(envName, args, array) : {}
);
result.array = array;
result.rowGaps = rowGaps;
result.env = {...env};
result.env = { ...env };
result.env.name = envName;

@@ -632,3 +678,4 @@ return result;

if (!done) {
done = token => token.type === '}' ||
done = token =>
token.type === '}' ||
(token.type === 'literal' && token.value === '&') ||

@@ -645,3 +692,10 @@ (token.type === 'command' && /^(end|cr|\\)$/.test(token.value));

while (!this.end() && !done(this.peek())) {
if (this.hasImplicitCommand(['displaystyle', 'textstyle', 'scriptstyle', 'scriptscriptstyle'])) {
if (
this.hasImplicitCommand([
'displaystyle',
'textstyle',
'scriptstyle',
'scriptscriptstyle',
])
) {
// Implicit math style commands such as \displaystyle, \textstyle...

@@ -671,9 +725,18 @@ // Note these commands switch to math mode and a specific size

// for the parseMode
const info = Definitions.getInfo('\\' + infix.value, 'math', this.macros);
const info = Definitions.getInfo(
'\\' + infix.value,
'math',
this.macros
);
if (info) {
result = [new MathAtom(this.parseMode,
info.type,
info.value || infix.value, // Functions don't have
info.parse ? info.parse('\\' + infix.value, [prefix, suffix]) :
null)];
result = [
new MathAtom(
this.parseMode,
info.type,
info.value || infix.value, // Functions don't have
info.parse
? info.parse('\\' + infix.value, [prefix, suffix])
: null
),
];
} else {

@@ -756,3 +819,7 @@ result = [new MathAtom(this.parseMode, 'mop', infix.value)];

// (when the closing delimiter is displayed greyed out)
if (/^(\?|\||<|>|\\vert|\\Vert|\\\||\\surd|\\uparrow|\\downarrow|\\Uparrow|\\Downarrow|\\updownarrow|\\Updownarrow|\\mid|\\mvert|\\mVert)$/.test(delim)) {
if (
/^(\?|\||<|>|\\vert|\\Vert|\\\||\\surd|\\uparrow|\\downarrow|\\Uparrow|\\Downarrow|\\updownarrow|\\Updownarrow|\\mid|\\mvert|\\mVert)$/.test(
delim
)
) {
return delim;

@@ -776,5 +843,3 @@ }

// We have an unbalanced left/right (there's a \right, but no \left)
const result = new MathAtom(this.parseMode, 'leftright');
result.rightDelim = this.scanDelim() || '.';
return result;
return null;
}

@@ -789,3 +854,5 @@

}
const leftDelim = this.scanDelim() || '.';
const leftDelim = this.scanDelim();
if (!leftDelim) return null;
const savedMathList = this.swapMathList([]);

@@ -801,2 +868,3 @@ while (!this.end() && !this.parseCommand(close)) {

const rightDelim = this.scanDelim();
const result = new MathAtom(this.parseMode, 'leftright');

@@ -825,3 +893,7 @@ result.leftDelim = leftDelim;

let result = false;
while (this.hasLiteral('^') || this.hasLiteral('_') || this.hasLiteral("'")) {
while (
this.hasLiteral('^') ||
this.hasLiteral('_') ||
this.hasLiteral("'")
) {
let supsub;

@@ -846,3 +918,5 @@ if (this.hasLiteral('^')) {

atom.superscript = atom.superscript || [];
atom.superscript.push(new MathAtom(atom.parseMode, 'mord', '\u2032'));
atom.superscript.push(
new MathAtom(atom.parseMode, 'mord', '\u2032')
);
result = true;

@@ -889,3 +963,4 @@ }

scanOptionalArg(parseMode) {
parseMode = (!parseMode || parseMode === 'auto') ? this.parseMode : parseMode;
parseMode =
!parseMode || parseMode === 'auto' ? this.parseMode : parseMode;
this.skipWhitespace();

@@ -917,3 +992,6 @@ if (!this.parseLiteral('[')) return null;

// ['x', 'rgb(a, b, c)']
const list = this.scanString().toLowerCase().trim().split(/,(?![^(]*\)(?:(?:[^(]*\)){2})*[^"]*$)/);
const list = this.scanString()
.toLowerCase()
.trim()
.split(/,(?![^(]*\)(?:(?:[^(]*\)){2})*[^"]*$)/);
for (const elem of list) {

@@ -939,4 +1017,11 @@ const color = Color.stringToColor(elem);

} else {
console.assert(parseMode === 'math', 'Unexpected parse mode: "' + parseMode + '"');
this.mathList = this.mathList.concat(this.scanImplicitGroup(token => token.type === 'literal' && token.value === ']'));
console.assert(
parseMode === 'math',
'Unexpected parse mode: "' + parseMode + '"'
);
this.mathList = this.mathList.concat(
this.scanImplicitGroup(
token => token.type === 'literal' && token.value === ']'
)
);
}

@@ -960,3 +1045,4 @@ }

scanArg(parseMode) {
parseMode = (!parseMode || parseMode === 'auto') ? this.parseMode : parseMode;
parseMode =
!parseMode || parseMode === 'auto' ? this.parseMode : parseMode;
this.parseFiller();

@@ -990,4 +1076,6 @@ let result;

if (this.args) {
if (this.args[paramToken.value] === undefined &&
this.args['?'] !== undefined) {
if (
this.args[paramToken.value] === undefined &&
this.args['?'] !== undefined
) {
return this.placeholder();

@@ -1024,3 +1112,6 @@ }

} else {
console.assert(/^(math|text)$/.test(parseMode), 'Unexpected parse mode: "' + parseMode + '"');
console.assert(
/^(math|text)$/.test(parseMode),
'Unexpected parse mode: "' + parseMode + '"'
);
do {

@@ -1054,5 +1145,9 @@ this.mathList = this.mathList.concat(this.scanImplicitGroup());

if (token.value === 'placeholder') {
result = new MathAtom(this.parseMode, 'placeholder', this.scanArg('string'), this.style);
result = new MathAtom(
this.parseMode,
'placeholder',
this.scanArg('string'),
this.style
);
result.captureSelection = true;
} else if (token.value === 'char') {

@@ -1062,11 +1157,20 @@ // \char has a special syntax and requires a non-braced integer

let codepoint = Math.floor(this.scanNumber(true));
if (!isFinite(codepoint) || codepoint < 0 || codepoint > 0x10FFFF) {
if (
!isFinite(codepoint) ||
codepoint < 0 ||
codepoint > 0x10ffff
) {
codepoint = 0x2753; // BLACK QUESTION MARK
}
result = new MathAtom(this.parseMode,
result = new MathAtom(
this.parseMode,
this.parseMode === 'math' ? 'mord' : '',
String.fromCodePoint(codepoint));
result.latex = '{\\char"' +
('000000' + codepoint.toString(16)).toUpperCase().substr(-6) + '}';
String.fromCodePoint(codepoint)
);
result.latex =
'{\\char"' +
('000000' + codepoint.toString(16))
.toUpperCase()
.substr(-6) +
'}';
} else if (token.value === 'hskip' || token.value === 'kern') {

@@ -1077,11 +1181,19 @@ // \hskip and \kern have a special syntax and requires a non-braced

if (isFinite(width)) {
result = new MathAtom(this.parseMode, 'spacing', null, this.style);
result = new MathAtom(
this.parseMode,
'spacing',
null,
this.style
);
result.width = width;
}
result .latex = '\\' + token.value;
result.latex = '\\' + token.value;
} else {
result = this.scanMacro(token.value);
if (!result) {
const info = Definitions.getInfo('\\' + token.value, this.parseMode, this.macros);
const info = Definitions.getInfo(
'\\' + token.value,
this.parseMode,
this.macros
);
const args = [];

@@ -1116,4 +1228,8 @@ let argString = '';

const arg = this.scanArg(param.type);
if (arg && arg.length === 1 &&
arg[0].type === 'placeholder' && param.placeholder) {
if (
arg &&
arg.length === 1 &&
arg[0].type === 'placeholder' &&
param.placeholder
) {
arg[0].value = param.placeholder;

@@ -1124,3 +1240,7 @@ }

} else if (param.placeholder) {
const placeholder = new MathAtom(this.parseMode, 'placeholder', param.placeholder);
const placeholder = new MathAtom(
this.parseMode,
'placeholder',
param.placeholder
);
placeholder.captureSelection = true;

@@ -1132,4 +1252,7 @@

}
if (param.type !== 'math' && typeof arg === 'string') {
argString += arg
if (
param.type !== 'math' &&
typeof arg === 'string'
) {
argString += arg;
}

@@ -1143,3 +1266,3 @@ }

// (second infix command in an implicit group) and should be ignored.
// Create the MathAtom.

@@ -1149,3 +1272,6 @@ // If a parse function is present, invoke it with the arguments,

if (info.parse) {
const attributes = info.parse('\\' + token.value, args);
const attributes = info.parse(
'\\' + token.value,
args
);
if (!attributes.type) {

@@ -1165,3 +1291,6 @@ // No type provided -> the parse function will modify

const saveStyle = this.style;
this.style = {...this.style, ...attributes};
this.style = {
...this.style,
...attributes,
};
result = this.scanArg(explicitGroup);

@@ -1171,19 +1300,28 @@ this.style = saveStyle;

// Merge the new style info with the current style
this.style = {...this.style, ...attributes};
this.style = {
...this.style,
...attributes,
};
}
this.parseMode = savedMode;
} else {
result = new MathAtom(this.parseMode,
result = new MathAtom(
this.parseMode,
info.type,
explicitGroup ? this.scanArg(explicitGroup) : null,
{...this.style, ...attributes});
explicitGroup
? this.scanArg(explicitGroup)
: null,
{ ...this.style, ...attributes }
);
}
} else {
const style = {...this.style};
if (info.baseFontFamily) style.baseFontFamily = info.baseFontFamily;
result = new MathAtom(this.parseMode,
const style = { ...this.style };
if (info.baseFontFamily)
style.baseFontFamily = info.baseFontFamily;
result = new MathAtom(
this.parseMode,
info.type || 'mop',
info.value || token.value,
style);
style
);

@@ -1194,6 +1332,9 @@ if (info.skipBoundary) {

}
if (result && !/^(llap|rlap|class|cssId)$/.test(token.value)) {
if (
result &&
!/^(llap|rlap|class|cssId)$/.test(token.value)
) {
result.latex = '\\' + token.value;
if (argString /*|| mandatoryParamsCount > 0*/) {
result.latex += '{' + argString + '}'
result.latex += '{' + argString + '}';
}

@@ -1213,6 +1354,8 @@ if (result.isFunction && this.smartFence) {

// An unknown command
result = new MathAtom(this.parseMode,
'error', '\\' + token.value);
result = new MathAtom(
this.parseMode,
'error',
'\\' + token.value
);
result.latex = '\\' + token.value;
}

@@ -1222,10 +1365,17 @@ }

} else if (token.type === 'literal') {
const info = Definitions.getInfo(token.value, this.parseMode, this.macros);
const info = Definitions.getInfo(
token.value,
this.parseMode,
this.macros
);
if (info) {
const style = {...this.style};
if (info.baseFontFamily) style.baseFontFamily = info.baseFontFamily;
result = new MathAtom(this.parseMode,
const style = { ...this.style };
if (info.baseFontFamily)
style.baseFontFamily = info.baseFontFamily;
result = new MathAtom(
this.parseMode,
info.type,
info.value || token.value,
style);
style
);
if (info.isFunction) {

@@ -1235,8 +1385,13 @@ result.isFunction = true;

} else {
result = new MathAtom(this.parseMode,
result = new MathAtom(
this.parseMode,
this.parseMode === 'math' ? 'mord' : '',
token.value, this.style);
token.value,
this.style
);
}
result.latex = Definitions.matchCodepoint(this.parseMode,
token.value.codePointAt(0));
result.latex = Definitions.matchCodepoint(
this.parseMode,
token.value.codePointAt(0)
);
if (info && info.isFunction && this.smartFence) {

@@ -1269,4 +1424,9 @@ // The atom was a function that may be followed by

} else {
console.warn('Unexpected token type "' + token.type +
'", value ="' + token.value + '"');
console.warn(
'Unexpected token type "' +
token.type +
'", value ="' +
token.value +
'"'
);
}

@@ -1298,3 +1458,3 @@ return result;

def = this.macros[macro].def;
argCount = (this.macros[macro].args || 0);
argCount = this.macros[macro].args || 0;
}

@@ -1311,3 +1471,7 @@ for (let i = 1; i <= argCount; i++) {

// unit
const atom = new MathAtom(this.parseMode, 'group', parseTokens(Lexer.tokenize(def), this.parseMode, args, this.macros));
const atom = new MathAtom(
this.parseMode,
'group',
parseTokens(Lexer.tokenize(def), this.parseMode, args, this.macros)
);
atom.captureSelection = true;

@@ -1335,3 +1499,4 @@ atom.latex = '\\' + macro;

parseAtom() {
let result = this.scanEnvironment() ||
let result =
this.scanEnvironment() ||
this.scanModeShift() ||

@@ -1355,7 +1520,2 @@ this.scanModeSet() ||

/**

@@ -1378,6 +1538,6 @@ * Given an array of tokens returned by the lexer, return a corresponding

const parser = new Parser(tokens, args, macros);
parser.parseMode = parseMode || 'math'; // other possible values: 'text', 'color', etc...
parser.parseMode = parseMode || 'math'; // other possible values: 'text', 'color', etc...
if (smartFence) parser.smartFence = true;
while(!parser.end()) {
while (!parser.end()) {
mathlist = mathlist.concat(parser.scanImplicitGroup());

@@ -1391,6 +1551,3 @@ }

Parser: Parser,
parseTokens: parseTokens
}
parseTokens: parseTokens,
};

@@ -34,3 +34,2 @@ /**

//----------------------------------------------------------------------------

@@ -108,3 +107,2 @@ // SPAN

selected(isSelected) {

@@ -183,8 +181,10 @@ if (isSelected && !/ML__selected/.test(this.classes)) {

if (style.fontShape) {
this.classes += ' ' + ({
'it': 'ML__it',
'sl': 'ML__shape_sl', // slanted
'sc': 'ML__shape_sc', // small caps
'ol': 'ML__shape_ol' // outline
}[style.fontShape] || '');
this.classes +=
' ' +
({
it: 'ML__it',
sl: 'ML__shape_sl', // slanted
sc: 'ML__shape_sc', // small caps
ol: 'ML__shape_ol', // outline
}[style.fontShape] || '');
}

@@ -194,24 +194,28 @@ if (style.fontSeries) {

if (m) {
this.classes += ' ' + ({
'ul': 'ML__series_ul',
'el': 'ML__series_el',
'l': 'ML__series_l',
'sl': 'ML__series_sl',
'm': '', // medium (default)
'sb': 'ML__series_sb',
'b': 'ML__bold',
'eb': 'ML__series_eb',
'ub': 'ML__series_ub',
}[m[1] || ''] || '');
this.classes += ' ' + ({
'uc': 'ML__series_uc',
'ec': 'ML__series_ec',
'c': 'ML__series_c',
'sc': 'ML__series_sc',
'n': '', // normal (default)
'sx': 'ML__series_sx',
'x': 'ML__series_x',
'ex': 'ML__series_ex',
'ux': 'ML__series_ux',
}[m[2] || ''] || '');
this.classes +=
' ' +
({
ul: 'ML__series_ul',
el: 'ML__series_el',
l: 'ML__series_l',
sl: 'ML__series_sl',
m: '', // medium (default)
sb: 'ML__series_sb',
b: 'ML__bold',
eb: 'ML__series_eb',
ub: 'ML__series_ub',
}[m[1] || ''] || '');
this.classes +=
' ' +
({
uc: 'ML__series_uc',
ec: 'ML__series_ec',
c: 'ML__series_c',
sc: 'ML__series_sc',
n: '', // normal (default)
sx: 'ML__series_sx',
x: 'ML__series_x',
ex: 'ML__series_ex',
ux: 'ML__series_ux',
}[m[2] || ''] || '');
}

@@ -233,18 +237,22 @@ }

this.depth = 0.0;
this.maxFontSize = {
size1: 0.5,
size2: 0.7,
size3: 0.8,
size4: 0.9,
size5: 1.0,
size6: 1.2,
size7: 1.44,
size8: 1.73,
size9: 2.07,
size10: 2.49,
}[style.fontSize] || 1.0;
this.maxFontSize =
{
size1: 0.5,
size2: 0.7,
size3: 0.8,
size4: 0.9,
size5: 1.0,
size6: 1.2,
size7: 1.44,
size8: 1.73,
size9: 2.07,
size10: 2.49,
}[style.fontSize] || 1.0;
this.skew = 0.0;
this.italic = 0.0;
for (let i = 0; i < this.body.length; i++) {
const metrics = FontMetrics.getCharacterMetrics(this.body.charAt(i), fontName);
const metrics = FontMetrics.getCharacterMetrics(
this.body.charAt(i),
fontName
);
// If we were able to get metrics info for this character, store it.

@@ -259,6 +267,4 @@ if (metrics) {

}
}
/**

@@ -291,7 +297,7 @@ * Set the value of a CSS property associated with this span.

/**
*
* @param {number} left
* @private
*/
/**
*
* @param {number} left
* @private
*/
setLeft(left) {

@@ -303,7 +309,7 @@ if (left && left !== 0) {

}
/**
*
* @param {number} right
* @private
*/
/**
*
* @param {number} right
* @private
*/
setRight(right) {

@@ -324,4 +330,8 @@ if (right && right !== 0) {

if (margin && margin !== 0) {
if (!this.style &&
!/qquad|quad|enspace|thickspace|mediumspace|thinspace|negativethinspace/.test(this.classes)) {
if (
!this.style &&
!/qquad|quad|enspace|thickspace|mediumspace|thinspace|negativethinspace/.test(
this.classes
)
) {
// Attempt to use a class instead of an explicit margin

@@ -335,3 +345,3 @@ const cls = {

'0.166667': 'thinspace',
'-0.166667': 'negativethinspace'
'-0.166667': 'negativethinspace',
}[margin.toString()];

@@ -345,3 +355,4 @@ if (cls) {

const currentMargin = parseFloat(this.style['margin-right'] || '0');
this.style['margin-right'] = toString(currentMargin + margin) + 'em';
this.style['margin-right'] =
toString(currentMargin + margin) + 'em';
}

@@ -375,5 +386,10 @@ }

if (child.isTight) {
spacing = (INTER_ATOM_TIGHT_SPACING[previousType + '+' + type] || 0);
spacing =
INTER_ATOM_TIGHT_SPACING[
previousType + '+' + type
] || 0;
} else {
spacing = (INTER_ATOM_SPACING[previousType + '+' + type] || 0);
spacing =
INTER_ATOM_SPACING[previousType + '+' + type] ||
0;
}

@@ -388,6 +404,7 @@ spacing = Math.floor(hscale * spacing);

// Collapse 'empty' spans
if ((body === '\u200b' || !body) &&
(!this.classes || this.classes === 'ML__selected')) {
if (
(body === '\u200b' || !body) &&
(!this.classes || this.classes === 'ML__selected')
) {
result = '';
} else {

@@ -399,3 +416,3 @@ // Note: We can't omit the tag, even if it has no class and no style,

if (this.cssId) {
result += ' id="' + this.cssId + '" '
result += ' id="' + this.cssId + '" ';
}

@@ -411,4 +428,14 @@

for (const attribute in this.attributes) {
if (Object.prototype.hasOwnProperty.call(this.attributes, attribute)) {
result += ' ' + attribute + '="' + this.attributes[attribute] + '"';
if (
Object.prototype.hasOwnProperty.call(
this.attributes,
attribute
)
) {
result +=
' ' +
attribute +
'="' +
this.attributes[attribute] +
'"';
}

@@ -423,7 +450,9 @@ }

if (/command|placeholder|error/.test(this.type)) {
classes.push({
'command': 'ML__command',
'placeholder': 'ML__placeholder',
'error': 'ML__error'
}[this.type]);
classes.push(
{
command: 'ML__command',
placeholder: 'ML__placeholder',
error: 'ML__error',
}[this.type]
);
}

@@ -435,9 +464,10 @@ if (this.caret && this.type === 'command') {

// Remove duplicate and empty classes
let classList = '';
if (classes.length > 1) {
classList = classes.filter(function (x, e, a) {
return x.length > 0 && a.indexOf(x) === e;
}).join(' ');
classList = classes
.filter(function(x, e, a) {
return x.length > 0 && a.indexOf(x) === e;
})
.join(' ');
} else {

@@ -456,3 +486,5 @@ classList = classes[0];

this.style['margin-left'] =
toString((parseFloat(this.style['margin-left']) + hskip / 18)) + 'em';
toString(
parseFloat(this.style['margin-left']) + hskip / 18
) + 'em';
} else {

@@ -475,7 +507,10 @@ // No margin yet. Can we encode it as a Unicode space?

for (const style in this.style) {
if (Object.prototype.hasOwnProperty.call(this.style, style)) {
if (
Object.prototype.hasOwnProperty.call(this.style, style)
) {
// Render the style property, except the background
// of selected spans
if (style !== 'background-color' || !isSelected) {
styleString += style + ':' + this.style[style] + ';';
styleString +=
style + ':' + this.style[style] + ';';
}

@@ -506,7 +541,14 @@ }

result += 'height:' + (this.height + this.depth) + 'em;';
result += 'transform:translateY(-' + Math.round(FontMetrics.toPx(this.depth, 'em') + FontMetrics.toPx(this.style.padding)) + 'px);';
result +=
'transform:translateY(-' +
Math.round(
FontMetrics.toPx(this.depth, 'em') +
FontMetrics.toPx(this.style.padding)
) +
'px);';
if (this.style && this.style.padding) {
result += 'top:' + this.style.padding + ';';
result += 'left:' + this.style.padding + ';';
result += 'width:calc(100% - 2 * ' + this.style.padding + ' );';
result +=
'width:calc(100% - 2 * ' + this.style.padding + ' );';
} else {

@@ -532,3 +574,2 @@ result += 'top:0;';

if (this.caret && this.type !== 'command') {

@@ -545,3 +586,2 @@ if (this.caret === 'text') {

/**

@@ -564,4 +604,8 @@ * Can this span be coalesced with 'span'?

// Don't coalesce consecutive errors or placeholders
if (this.type === 'error' || this.type === 'placeholder' ||
this.type === 'command') return false;
if (
this.type === 'error' ||
this.type === 'placeholder' ||
this.type === 'command'
)
return false;
// If this span or the candidate span have children, we can't

@@ -578,5 +622,9 @@ // coalesce them, but we'll try to coalesce their children

// any 'empty' classes (whitespace)
const classes = this.classes.trim().replace(/\s+/g, ' ')
const classes = this.classes
.trim()
.replace(/\s+/g, ' ')
.split(' ');
const spanClasses = span.classes.trim().replace(/\s+/g, ' ')
const spanClasses = span.classes
.trim()
.replace(/\s+/g, ' ')
.split(' ');

@@ -598,4 +646,6 @@ // If they have a different number of classes, can't coalesce

for (const style in this.style) {
if (Object.prototype.hasOwnProperty.call(this.style, style) &&
Object.prototype.hasOwnProperty.call(span.style, style)) {
if (
Object.prototype.hasOwnProperty.call(this.style, style) &&
Object.prototype.hasOwnProperty.call(span.style, style)
) {
if (this.style[style] !== span.style[style]) return false;

@@ -618,16 +668,2 @@ }

/**

@@ -644,58 +680,57 @@ * Return HTML markup representing this span, its style, classes and

const INTER_ATOM_SPACING = {
'mord+mop': 3,
'mord+mbin': 4,
'mord+mrel': 5,
'mord+minner': 3,
'mord+mop': 3,
'mord+mbin': 4,
'mord+mrel': 5,
'mord+minner': 3,
'mop+mord': 3,
'mop+mop': 3,
'mop+mbin': 5,
'mop+minner': 3,
'mop+mord': 3,
'mop+mop': 3,
'mop+mbin': 5,
'mop+minner': 3,
'mbin+mord': 4,
'mbin+mop': 4,
'mbin+mopen': 4,
'mbin+minner': 4,
'mbin+mord': 4,
'mbin+mop': 4,
'mbin+mopen': 4,
'mbin+minner': 4,
'mrel+mord': 5,
'mrel+mop': 5,
'mrel+mopen': 5,
'mrel+minner': 5,
'mrel+mord': 5,
'mrel+mop': 5,
'mrel+mopen': 5,
'mrel+minner': 5,
'mclose+mop': 3,
'mclose+mbin': 4,
'mclose+mrel': 5,
'mclose+minner': 3,
'mclose+mop': 3,
'mclose+mbin': 4,
'mclose+mrel': 5,
'mclose+minner': 3,
'mpunct+mord': 3,
'mpunct+mop': 3,
'mpunct+mbin': 4,
'mpunct+mrel': 5,
'mpunct+mopen': 3,
'mpunct+mpunct': 3,
'mpunct+minner': 3
}
'mpunct+mord': 3,
'mpunct+mop': 3,
'mpunct+mbin': 4,
'mpunct+mrel': 5,
'mpunct+mopen': 3,
'mpunct+mpunct': 3,
'mpunct+minner': 3,
};
// See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
// 6.1.4 Non-Marking Characters
const SPACING_CHARACTER = [
'\u200b', // 0/18 ZERO-WIDTH SPACE
'\u200a', // 1/18 HAIR SPACE
'\u200a\u200a', // 2/18
'\u2009', // 3/18 THIN SPACE
'\u205f', // 4/18 MEDIUM MATHEMATICAL SPACE
'\u205f\u200a', // 5/18 MEDIUM MATHEMATICAL SPACE + HAIR SPACE
'\u2004', // 6/18 THREE-PER-EM SPACE 1/3em
'\u200b', // 0/18 ZERO-WIDTH SPACE
'\u200a', // 1/18 HAIR SPACE
'\u200a\u200a', // 2/18
'\u2009', // 3/18 THIN SPACE
'\u205f', // 4/18 MEDIUM MATHEMATICAL SPACE
'\u205f\u200a', // 5/18 MEDIUM MATHEMATICAL SPACE + HAIR SPACE
'\u2004', // 6/18 THREE-PER-EM SPACE 1/3em
'',
'',
'\u2002' // 9/18 EN SPACE 1/2em = 9/18
'\u2002', // 9/18 EN SPACE 1/2em = 9/18
];
const NEGATIVE_SPACING_CHARACTER = [
'',
'\u200a\u2063', // -1/18
'\u200a\u2063', // -1/18
'',
'\u2009\u2063', // -3/18
'\u205f\u2063', // -4/18
'\u2005\u2063' // -5/18
'\u2009\u2063', // -3/18
'\u205f\u2063', // -4/18
'\u2005\u2063', // -5/18
];

@@ -709,8 +744,8 @@

const INTER_ATOM_TIGHT_SPACING = {
'mord+mop': 3,
'mop+mord': 3,
'mop+mop': 3,
'mclose+mop': 3,
'minner+mop': 3
}
'mord+mop': 3,
'mop+mord': 3,
'mop+mop': 3,
'mclose+mop': 3,
'minner+mop': 3,
};

@@ -724,5 +759,2 @@ function lastSpanType(span) {

/**

@@ -752,3 +784,2 @@ * Attempts to coalesce (merge) spans, for example consecutive text spans.

//----------------------------------------------------------------------------

@@ -774,3 +805,2 @@ // UTILITY FUNCTIONS

function skew(spans) {

@@ -796,3 +826,2 @@ if (!spans) return 0;

/**

@@ -818,3 +847,2 @@ * Make an element made of a sequence of children with classes

/**

@@ -842,3 +870,2 @@ *

/**

@@ -855,19 +882,25 @@ * Makes an element placed in each of the vlist elements to ensure that each

function makeFontSizer(context, fontSize) {
const fontSizeAdjustment = fontSize ? fontSize / context.mathstyle.sizeMultiplier : 0;
const fontSizeInner = new Span('\u200b'); // ZERO WIDTH SPACE
const fontSizeAdjustment = fontSize
? fontSize / context.mathstyle.sizeMultiplier
: 0;
const fontSizeInner = new Span('\u200b'); // ZERO WIDTH SPACE
if (fontSizeAdjustment !== 1) {
fontSizeInner.setStyle('font-size',
fontSizeInner.setStyle(
'font-size',
fontSizeAdjustment,
(fontSizeAdjustment > 0) ? 'em' : '');
fontSizeAdjustment > 0 ? 'em' : ''
);
fontSizeInner.attributes = {
"aria-hidden": true
}
'aria-hidden': true,
};
}
if (context.size !== 'size5') {
return new Span(fontSizeInner,
'fontsize-ensurer reset-' + context.size + ' size5');
return new Span(
fontSizeInner,
'fontsize-ensurer reset-' + context.size + ' size5'
);
}
return (fontSizeAdjustment !== 0) ? fontSizeInner : null;
return fontSizeAdjustment !== 0 ? fontSizeInner : null;
}

@@ -921,3 +954,2 @@

function makeStyleWrap(type, children, fromStyle, toStyle, classes) {

@@ -967,3 +999,3 @@ classes = classes || '';

// An array, with a single span, use the single span as the output
return spans[0]
return spans[0];
}

@@ -1052,8 +1084,10 @@ }

for (let i = 2; i < originalElements.length; i += 2) {
const diff = -originalElements[i + 1] - currPos -
originalElements[i].depth;
const diff =
-originalElements[i + 1] - currPos - originalElements[i].depth;
currPos = currPos + diff;
const kern = diff -
(originalElements[i - 2].height + originalElements[i - 2].depth);
const kern =
diff -
(originalElements[i - 2].height +
originalElements[i - 2].depth);

@@ -1129,4 +1163,2 @@ elements.push(kern);

//----------------------------------------------------------------------------

@@ -1138,30 +1170,27 @@ // FONTS

const FONT_NAME = {
'ams': 'AMS-Regular',
'bb': 'AMS-Regular',
'cal': 'Caligraphic-Regular',
'frak': 'Fraktur-Regular',
'scr': 'Script-Regular',
'cmr': 'Main-Regular',
'cmss': 'SansSerif-Regular',
'cmtt': 'Typewriter-Regular',
'math': 'Math-Regular',
'mainit': 'Main-Italic',
ams: 'AMS-Regular',
bb: 'AMS-Regular',
cal: 'Caligraphic-Regular',
frak: 'Fraktur-Regular',
scr: 'Script-Regular',
cmr: 'Main-Regular',
cmss: 'SansSerif-Regular',
cmtt: 'Typewriter-Regular',
math: 'Math-Regular',
mainit: 'Main-Italic',
};
const FONT_CLASS = {
'ams': 'ML__ams',
'bb': 'ML__bb',
'cal': 'ML__cal',
'frak': 'ML__frak',
'scr': 'ML__script',
'cmr': 'ML__mathrm',
'cmss': 'ML__sans',
'cmtt': 'ML__tt',
'math': 'ML__mathit',
'mainit': 'ML__mainit',
}
ams: 'ML__ams',
bb: 'ML__bb',
cal: 'ML__cal',
frak: 'ML__frak',
scr: 'ML__script',
cmr: 'ML__mathrm',
cmss: 'ML__sans',
cmtt: 'ML__tt',
math: 'ML__mathit',
mainit: 'ML__mainit',
};
/**

@@ -1179,5 +1208,7 @@ * Given a font family ('frak', 'math'...) return a corresponding

// If this is not a single char, just do a simple fontFamily -> fontName mapping
if (typeof symbol !== 'string' ||
if (
typeof symbol !== 'string' ||
symbol.length > 1 ||
symbol === '\u200b') {
symbol === '\u200b'
) {
return FONT_NAME[fontFamily];

@@ -1193,7 +1224,5 @@ }

if (!/^[A-Z ]$/.test(symbol)) return null;
} else if (fontFamily === 'cal') {
// Only supports uppercase latin and digits
if (!/^[0-9A-Z ]$/.test(symbol)) return null;
} else if (fontFamily === 'frak') {

@@ -1204,3 +1233,7 @@ if (!/^[0-9A-Za-z ]$|^[!"#$%&'()*+,\-./:;=?[]^’‘]$/.test(symbol)) {

} else if (fontFamily === 'cmtt' || fontFamily === 'cmss') {
if (!/^[0-9A-Za-z ]$|^[!"&'()*+,\-./:;=?@[]^_~\u0131\u0237\u0393\u0394\u0398\u039b\u039e\u03A0\u03A3\u03A5\u03A8\u03a9’‘]$/.test(symbol)) {
if (
!/^[0-9A-Za-z ]$|^[!"&'()*+,\-./:;=?@[]^_~\u0131\u0237\u0393\u0394\u0398\u039b\u039e\u03A0\u03A3\u03A5\u03A8\u03a9’‘]$/.test(
symbol
)
) {
return null;

@@ -1238,5 +1271,3 @@ }

skew,
italic
}
italic,
};

@@ -1,2 +0,1 @@

/**

@@ -13,85 +12,85 @@ * This modules handles low-level keyboard events and normalize them across

const INTL_KEY = {
'#': '#',
'|': '|',
'[': 'BracketLeft',
']': 'BracketRight',
'-': 'Minus',
'+': 'Plus',
'=': 'Equal',
'/': 'Slash',
'\\': 'Backslash',
}
'#': '#',
'|': '|',
'[': 'BracketLeft',
']': 'BracketRight',
'-': 'Minus',
'+': 'Plus',
'=': 'Equal',
'/': 'Slash',
'\\': 'Backslash',
};
const KEY_NAMES = {
'Space': 'Spacebar',
' ': 'Spacebar',
'Escape': 'Esc',
'ArrowLeft': 'Left',
'ArrowUp': 'Up',
'ArrowRight': 'Right',
'ArrowDown': 'Down',
'Delete': 'Del'
Space: 'Spacebar',
' ': 'Spacebar',
Escape: 'Esc',
ArrowLeft: 'Left',
ArrowUp: 'Up',
ArrowRight: 'Right',
ArrowDown: 'Down',
Delete: 'Del',
};
const VIRTUAL_KEY_NAMES = {
'q' : 'KeyQ',
'w' : 'KeyW',
'e' : 'KeyE',
'r' : 'KeyR',
't' : 'KeyT',
'y' : 'KeyY',
'u' : 'KeyU',
'i' : 'KeyI',
'o' : 'KeyO',
'p' : 'KeyP',
'a' : 'KeyA',
's' : 'KeyS',
'd' : 'KeyD',
'f' : 'KeyF',
'g' : 'KeyG',
'h' : 'KeyH',
'j' : 'KeyJ',
'k' : 'KeyK',
'l' : 'KeyL',
'z' : 'KeyZ',
'x' : 'KeyX',
'c' : 'KeyC',
'v' : 'KeyV',
'b' : 'KeyB',
'n' : 'KeyN',
'm' : 'KeyM',
const VIRTUAL_KEY_NAMES = {
q: 'KeyQ',
w: 'KeyW',
e: 'KeyE',
r: 'KeyR',
t: 'KeyT',
y: 'KeyY',
u: 'KeyU',
i: 'KeyI',
o: 'KeyO',
p: 'KeyP',
a: 'KeyA',
s: 'KeyS',
d: 'KeyD',
f: 'KeyF',
g: 'KeyG',
h: 'KeyH',
j: 'KeyJ',
k: 'KeyK',
l: 'KeyL',
z: 'KeyZ',
x: 'KeyX',
c: 'KeyC',
v: 'KeyV',
b: 'KeyB',
n: 'KeyN',
m: 'KeyM',
'1' : 'Digit1',
'2' : 'Digit2',
'3' : 'Digit3',
'4' : 'Digit4',
'5' : 'Digit5',
'6' : 'Digit6',
'7' : 'Digit7',
'8' : 'Digit8',
'9' : 'Digit9',
'0' : 'Digit0',
'1': 'Digit1',
'2': 'Digit2',
'3': 'Digit3',
'4': 'Digit4',
'5': 'Digit5',
'6': 'Digit6',
'7': 'Digit7',
'8': 'Digit8',
'9': 'Digit9',
'0': 'Digit0',
'!' : 'Shift-Digit1',
'@' : 'Shift-Digit2',
'#' : 'Shift-Digit3',
'$' : 'Shift-Digit4',
'%' : 'Shift-Digit5',
'^' : 'Shift-Digit6',
'&' : 'Shift-Digit7',
'*' : 'Shift-Digit8',
'(' : 'Shift-Digit9',
')' : 'Shift-Digit0',
'!': 'Shift-Digit1',
'@': 'Shift-Digit2',
'#': 'Shift-Digit3',
$: 'Shift-Digit4',
'%': 'Shift-Digit5',
'^': 'Shift-Digit6',
'&': 'Shift-Digit7',
'*': 'Shift-Digit8',
'(': 'Shift-Digit9',
')': 'Shift-Digit0',
'-' : 'Minus',
'_' : 'Shift-Minus',
'-': 'Minus',
_: 'Shift-Minus',
'/' : 'Slash',
'\\' : 'Backslash', // Some virtual keyboards (iOS) return '\' as the event.key
// with no evt.code
'|' : 'Shift-Backslash',
'?' : 'Shift-Slash',
'/': 'Slash',
'\\': 'Backslash', // Some virtual keyboards (iOS) return '\' as the event.key
// with no evt.code
'|': 'Shift-Backslash',
'?': 'Shift-Slash',
' ' : 'Spacebar'
};
' ': 'Spacebar',
};

@@ -137,3 +136,3 @@ /**

if (!keyname) {
keyname = VIRTUAL_KEY_NAMES[evt.key.toLowerCase()] || evt.key;
keyname = VIRTUAL_KEY_NAMES[evt.key.toLowerCase()];
}

@@ -159,5 +158,4 @@ }

return modifiers.join('-');
}
}
/**

@@ -225,6 +223,9 @@ * Setup to capture the keyboard events from a `TextArea` and redispatch them to

function onKeydown(e) {
const allowDeadKey = typeof handlers.allowDeadKey === 'function' &&
const allowDeadKey =
typeof handlers.allowDeadKey === 'function' &&
handlers.allowDeadKey();
if (!allowDeadKey &&
((e.key === 'Dead' || e.key === 'Unidentified') || e.keyCode === 229)) {
if (
!allowDeadKey &&
(e.key === 'Dead' || e.key === 'Unidentified' || e.keyCode === 229)
) {
deadKey = true;

@@ -245,5 +246,7 @@ compositionInProgress = false;

}
if (!compositionInProgress &&
if (
!compositionInProgress &&
e.code !== 'CapsLock' &&
!/(Control|Meta|Alt|Shift)(Right|Left)/.test(e.code)) {
!/(Control|Meta|Alt|Shift)(Right|Left)/.test(e.code)
) {
keydownEvent = e;

@@ -261,3 +264,6 @@ keypressEvent = null;

if (keydownEvent && keypressEvent) {
handlers.keystroke(keyboardEventToString(keydownEvent), keydownEvent);
handlers.keystroke(
keyboardEventToString(keydownEvent),
keydownEvent
);
}

@@ -271,3 +277,3 @@

function onKeyup() {
// If we've received a keydown, but no keypress, check what's in the
// If we've received a keydown, but no keypress, check what's in the
// textarea field.

@@ -317,6 +323,17 @@ if (!compositionInProgress && keydownEvent && !keypressEvent) {

target.addEventListener('focus', onFocus, true);
target.addEventListener('compositionstart',
() => { compositionInProgress = true }, true);
target.addEventListener('compositionend',
() => { compositionInProgress = false; defer(handleTypedText); }, true);
target.addEventListener(
'compositionstart',
() => {
compositionInProgress = true;
},
true
);
target.addEventListener(
'compositionend',
() => {
compositionInProgress = false;
defer(handleTypedText);
},
true
);

@@ -342,3 +359,2 @@ // The `input` handler gets called when the field is changed, for example

});
}

@@ -350,3 +366,2 @@

function eventToChar(evt) {

@@ -363,3 +378,7 @@ if (!evt) return '';

result = result || evt.key || evt.code;
if (/^(Return|Enter|Tab|Escape|Delete|PageUp|PageDown|Home|End|Help|ArrowLeft|ArrowRight|ArrowUp|ArrowDown)$/.test(result)) {
if (
/^(Return|Enter|Tab|Escape|Delete|PageUp|PageDown|Home|End|Help|ArrowLeft|ArrowRight|ArrowUp|ArrowDown)$/.test(
result
)
) {
result = '';

@@ -376,3 +395,3 @@ }

altKey: false,
shiftKey: false
shiftKey: false,
};

@@ -388,6 +407,3 @@

eventToChar,
charToEvent
charToEvent,
};

@@ -6,5 +6,2 @@ /**

/**

@@ -29,3 +26,2 @@ *

/**

@@ -40,3 +36,3 @@ *

// Reset the path
const result = {path: [], extent: 0};
const result = { path: [], extent: 0 };

@@ -56,3 +52,3 @@ // Parse the selection extent, if present

relation: m2[1],
offset: parseInt(m2[2])
offset: parseInt(m2[2]),
});

@@ -78,5 +74,7 @@ }

let i = 0;
while ( i <= maxIndex &&
p[i].relation === q[i].relation &&
p[i].offset === q[i].offset) {
while (
i <= maxIndex &&
p[i].relation === q[i].relation &&
p[i].offset === q[i].offset
) {
result.push(p[i]);

@@ -99,11 +97,11 @@ i += 1;

function pathDistance(p, q) {
let result = 0;
let i = -1;
let done = false;
while (!done) {
let result = 0;
let i = -1;
let done = false;
while (!done) {
i += 1;
done = i >= p.length || i >= q.length;
done = done ||
!(p[i].relation === q[i].relation &&
p[i].offset === q[i].offset);
done =
done ||
!(p[i].relation === q[i].relation && p[i].offset === q[i].offset);
}

@@ -113,4 +111,7 @@ if (i === p.length && i === q.length) {

result = 0;
} else if (i + 1 === p.length && i + 1 === q.length &&
p[i].relation === q[i].relation ) {
} else if (
i + 1 === p.length &&
i + 1 === q.length &&
p[i].relation === q[i].relation
) {
// They're siblings

@@ -122,7 +123,5 @@ result = 1;

return result;
return result;
}
function clone(path) {

@@ -137,7 +136,3 @@ return pathFromString(pathToString(path)).path;

pathCommonAncestor,
clone
}
clone,
};

@@ -1,3 +0,1 @@

import MathAtom from '../core/mathAtom.js';

@@ -10,108 +8,107 @@ import Lexer from '../core/lexer.js';

const SAMPLES = {
'\\mathrm': '\\mathrm{x=+3.14, x\\in A}',
'\\mathbf': '\\mathbf{x=+3.14, x\\in A}',
'\\bf': '\\bf{x=+3.14, x\\in A}',
'\\bm': '\\bm{x=+3.14, x\\in A}',
'\\bold': '\\bold{x=+3.14, x\\in A}',
'\\mathit': '\\mathbb{x=+3.14}',
'\\mathbb': '\\mathbb{ABCD}',
'\\Bbb': '\\mathbb{ABCD}',
'\\frak': '\\frak{ABCD}',
'\\mathfrak': '\\mathfrak{ABCD}',
'\\mathscr': '\\mathscr{ABCD}',
'\\mathsf': '\\mathsf{ABab01}',
'\\mathtt': '\\mathtt{x=+3.14, x\\in A}',
'\\mathcal': '\\mathcal{ABCD}',
'\\boldsymbol': '\\boldsymbol{ABab01+=}',
'\\mathrm': '\\mathrm{x=+3.14, x\\in A}',
'\\mathbf': '\\mathbf{x=+3.14, x\\in A}',
'\\bf': '\\bf{x=+3.14, x\\in A}',
'\\bm': '\\bm{x=+3.14, x\\in A}',
'\\bold': '\\bold{x=+3.14, x\\in A}',
'\\mathit': '\\mathbb{x=+3.14}',
'\\mathbb': '\\mathbb{ABCD}',
'\\Bbb': '\\mathbb{ABCD}',
'\\frak': '\\frak{ABCD}',
'\\mathfrak': '\\mathfrak{ABCD}',
'\\mathscr': '\\mathscr{ABCD}',
'\\mathsf': '\\mathsf{ABab01}',
'\\mathtt': '\\mathtt{x=+3.14, x\\in A}',
'\\mathcal': '\\mathcal{ABCD}',
'\\boldsymbol': '\\boldsymbol{ABab01+=}',
'\\text': '\\text{ABC abc}',
'\\textrm': '\\textrm{ABC abc}',
'\\textnormal': '\\textnormal{ABC abc}',
'\\textit': '\\textit{ABC abc}',
'\\textbf': '\\textbf{ABC abc}',
'\\texttt': '\\texttt{ABC abc}',
'\\textsf': '\\textsf{ABC abc}',
'\\textcolor': `{\\textcolor{m0}A}{\\textcolor{m1}B}{\\textcolor{m2}C }{\\textcolor{m3}a}{\\textcolor{m4}b}{\\textcolor{m5}c}{\\textcolor{m6}8}`,
'\\color': `{\\color{m0}A}{\\color{m1}B}{\\color{m2}C}{\\color{m3}a}{\\color{m4}b}{\\color{m5}c}{\\color{m6}8}`,
'\\text': '\\text{ABC abc}',
'\\textrm': '\\textrm{ABC abc}',
'\\textnormal': '\\textnormal{ABC abc}',
'\\textit': '\\textit{ABC abc}',
'\\textbf': '\\textbf{ABC abc}',
'\\texttt': '\\texttt{ABC abc}',
'\\textsf': '\\textsf{ABC abc}',
'\\textcolor': `{\\textcolor{m0}A}{\\textcolor{m1}B}{\\textcolor{m2}C }{\\textcolor{m3}a}{\\textcolor{m4}b}{\\textcolor{m5}c}{\\textcolor{m6}8}`,
'\\color': `{\\color{m0}A}{\\color{m1}B}{\\color{m2}C}{\\color{m3}a}{\\color{m4}b}{\\color{m5}c}{\\color{m6}8}`,
'\\underline': '\\underline{\\unicode{"2B1A}}',
'\\overline': '\\overline{\\unicode{"2B1A}}',
'\\underline': '\\underline{\\unicode{"2B1A}}',
'\\overline': '\\overline{\\unicode{"2B1A}}',
'\\vec': '\\vec{\\unicode{"25CC}}',
'\\check': '\\check{\\unicode{"25CC}}',
'\\acute': '\\acute{\\unicode{"25CC}}',
'\\breve': '\\breve{\\unicode{"25CC}}',
'\\tilde': '\\tilde{\\unicode{"25CC}}',
'\\hat': '\\hat{\\unicode{"25CC}}',
'\\ddot': '\\ddot{\\unicode{"25CC}}',
'\\dot': '\\dot{\\unicode{"25CC}}',
'\\bar': '\\bar{\\unicode{"25CC}}',
'\\vec': '\\vec{\\unicode{"25CC}}',
'\\check': '\\check{\\unicode{"25CC}}',
'\\acute': '\\acute{\\unicode{"25CC}}',
'\\breve': '\\breve{\\unicode{"25CC}}',
'\\tilde': '\\tilde{\\unicode{"25CC}}',
'\\hat': '\\hat{\\unicode{"25CC}}',
'\\ddot': '\\ddot{\\unicode{"25CC}}',
'\\dot': '\\dot{\\unicode{"25CC}}',
'\\bar': '\\bar{\\unicode{"25CC}}',
'\\!': '\\unicode{"203A}\\!\\unicode{"2039}',
'\\,': '\\unicode{"203A}\\,\\unicode{"2039}',
'\\:': '\\unicode{"203A}\\:\\unicode{"2039}',
'\\;': '\\unicode{"203A}\\;\\unicode{"2039}',
'\\quad': '\\unicode{"203A}\\quad\\unicode{"2039}',
'\\qquad': '\\unicode{"203A}\\qquad\\unicode{"2039}',
'\\enskip': '\\unicode{"203A}\\enskip\\unicode{"2039}',
'\\space': '\\unicode{"203A}\\space\\unicode{"2039}',
'\\!': '\\unicode{"203A}\\!\\unicode{"2039}',
'\\,': '\\unicode{"203A}\\,\\unicode{"2039}',
'\\:': '\\unicode{"203A}\\:\\unicode{"2039}',
'\\;': '\\unicode{"203A}\\;\\unicode{"2039}',
'\\quad': '\\unicode{"203A}\\quad\\unicode{"2039}',
'\\qquad': '\\unicode{"203A}\\qquad\\unicode{"2039}',
'\\enskip': '\\unicode{"203A}\\enskip\\unicode{"2039}',
'\\space': '\\unicode{"203A}\\space\\unicode{"2039}',
'\\frac': '\\frac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\dfrac': '\\dfrac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\cfrac': '\\cfrac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\tfrac': '\\tfrac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\dbinom': '\\dbinom{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\tbinom': '\\tbinom{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\binom': '\\binom{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\pdiff': '\\pdiff{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\frac': '\\frac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\dfrac': '\\dfrac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\cfrac': '\\cfrac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\tfrac': '\\tfrac{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\dbinom': '\\dbinom{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\tbinom': '\\tbinom{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\binom': '\\binom{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\pdiff': '\\pdiff{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\in': 'n\\in\\N',
'\\notin': 'n\\notin\\N',
'\\not': 'B \\not A',
'\\ni': 'N\\in n',
'\\owns': 'N\\owns n',
'\\subset': 'A\\subset B',
'\\supset': 'B\\supset A',
'\\subseteq': 'A\\subseteq B',
'\\supseteq': 'B\\supseteq A',
'\\nsubseteq': 'A\\nsubseteq B',
'\\nsupseteq': 'B\\nsupseteq A',
'\\subsetneq': 'A\\subsetneq B',
'\\supsetneq': 'B\\supsetneq A',
'\\varsubsetneq': 'A\\varsubsetneq B',
'\\varsupsetneq': 'B\\varsupsetneq A',
'\\nsubseteqq': 'A\\varsupsetneq B',
'\\subsetneqq': 'A\\subsetneqq B',
'\\varsubsetneqq': 'A\\varsubsetneqq B',
'\\nsubset': 'A\\nsubset B',
'\\nsupset': 'B\\nsupset A',
'\\complement': 'A^\\complement',
'\\in': 'n\\in\\N',
'\\notin': 'n\\notin\\N',
'\\not': 'B \\not A',
'\\ni': 'N\\in n',
'\\owns': 'N\\owns n',
'\\subset': 'A\\subset B',
'\\supset': 'B\\supset A',
'\\subseteq': 'A\\subseteq B',
'\\supseteq': 'B\\supseteq A',
'\\nsubseteq': 'A\\nsubseteq B',
'\\nsupseteq': 'B\\nsupseteq A',
'\\subsetneq': 'A\\subsetneq B',
'\\supsetneq': 'B\\supsetneq A',
'\\varsubsetneq': 'A\\varsubsetneq B',
'\\varsupsetneq': 'B\\varsupsetneq A',
'\\nsubseteqq': 'A\\varsupsetneq B',
'\\subsetneqq': 'A\\subsetneqq B',
'\\varsubsetneqq': 'A\\varsubsetneqq B',
'\\nsubset': 'A\\nsubset B',
'\\nsupset': 'B\\nsupset A',
'\\complement': 'A^\\complement',
'\\bigcup': '\\bigcup_{\\unicode{"2B1A}}',
'\\bigcap': '\\bigcap_{\\unicode{"2B1A}}',
'\\sqrt': '\\sqrt{\\unicode{"2B1A}}',
'\\prod': '\\prod_{\\unicode{"2B1A}}^{\\unicode{"2B1A}}',
'\\sum': '\\sum_{\\unicode{"2B1A}}^{\\unicode{"2B1A}}',
'\\int': '\\int_{\\unicode{"2B1A}}^{\\unicode{"2B1A}}',
'\\stackrel': '\\stackrel{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\stackbin': '\\stackbin{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\underset': '\\underset{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\overset': '\\overset{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\prime': '\\unicode{"2B1A}^{\\prime}',
'\\boxed': '\\boxed{\\unicode{"2B1A}}',
'\\colorbox': '\\colorbox{#fbc0bd}{\\unicode{"2B1A}}',
'\\bbox': '\\bbox[#ffd400, solid 2px #ffd400]{\\unicode{"2B1A}}',
'\\enclose':
'\\enclose{updiagonalstrike,roundedbox}[1px solid red, mathbackground="#fbc0bd"]{23+45}',
'\\fcolorbox': '\\fcolorbox{#cd0030}{#ffd400}{\\unicode{"2B1A}}',
'\\ ': '\\char"2423', // OPEN BOX
'\\bigcup': '\\bigcup_{\\unicode{"2B1A}}',
'\\bigcap': '\\bigcap_{\\unicode{"2B1A}}',
'\\sqrt': '\\sqrt{\\unicode{"2B1A}}',
'\\prod': '\\prod_{\\unicode{"2B1A}}^{\\unicode{"2B1A}}',
'\\sum': '\\sum_{\\unicode{"2B1A}}^{\\unicode{"2B1A}}',
'\\int': '\\int_{\\unicode{"2B1A}}^{\\unicode{"2B1A}}',
'\\stackrel': '\\stackrel{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\stackbin': '\\stackbin{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\underset': '\\underset{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\overset': '\\overset{\\unicode{"2B1A}}{\\unicode{"2B1A}}',
'\\prime': '\\unicode{"2B1A}^{\\prime}',
'\\top': '{\\color{red}P}\\top',
'\\bot': '{\\color{#0F0}P}\\bot',
'\\mid': 'P(p\\mid q)',
'\\boxed': '\\boxed{\\unicode{"2B1A}}',
'\\colorbox': '\\colorbox{#fbc0bd}{\\unicode{"2B1A}}',
'\\bbox': '\\bbox[#ffd400, solid 2px #ffd400]{\\unicode{"2B1A}}',
'\\enclose': '\\enclose{updiagonalstrike,roundedbox}[1px solid red, mathbackground="#fbc0bd"]{23+45}',
'\\fcolorbox': '\\fcolorbox{#cd0030}{#ffd400}{\\unicode{"2B1A}}',
'\\ ': '\\char"2423', // OPEN BOX
'\\top': '{\\color{red}P}\\top',
'\\bot': '{\\color{#0F0}P}\\bot',
'\\mid': 'P(p\\mid q)',
'\\rlap': '\\rlap{x}o',
'\\llap': 'o\\llap{/}',
'\\rlap': '\\rlap{x}o',
'\\llap': 'o\\llap{/}',
};

@@ -125,167 +122,187 @@

const NOTES = {
'\\text': 'roman text',
'\\textrm': 'roman text',
'\\text': 'roman text',
'\\textrm': 'roman text',
'\\textnormal': 'roman text',
'\\textit': 'italic text',
'\\textbf': 'bold text',
'\\texttt': 'monospaced text',
'\\textsf': 'sans-serif text',
'\\mathrm': ['roman', '(upright)'],
'\\mathbf': 'bold',
'\\bf': 'bold',
'\\bold': 'bold',
'\\mathit': 'italic',
'\\mathbb': 'blackboard',
'\\Bbb': 'blackboard',
'\\mathscr': 'script',
'\\mathtt': ['typewriter', '(monospaced)'],
'\\mathsf': 'sans-serif',
'\\mathcal': 'caligraphic',
'\\frak': ['fraktur', '(gothic)'],
'\\mathfrak': ['fraktur', '(gothic)'],
'\\textit': 'italic text',
'\\textbf': 'bold text',
'\\texttt': 'monospaced text',
'\\textsf': 'sans-serif text',
'\\mathrm': ['roman', '(upright)'],
'\\mathbf': 'bold',
'\\bf': 'bold',
'\\bold': 'bold',
'\\mathit': 'italic',
'\\mathbb': 'blackboard',
'\\Bbb': 'blackboard',
'\\mathscr': 'script',
'\\mathtt': ['typewriter', '(monospaced)'],
'\\mathsf': 'sans-serif',
'\\mathcal': 'caligraphic',
'\\frak': ['fraktur', '(gothic)'],
'\\mathfrak': ['fraktur', '(gothic)'],
'\\textcolor': 'text color',
'\\color': 'color',
'\\textcolor': 'text color',
'\\color': 'color',
'\\forall': 'for all',
'\\exists': 'there exists',
'\\nexists': 'there does not exist',
'\\frac': 'fraction',
'\\dfrac': 'display fraction',
'\\cfrac': 'continuous fraction',
'\\tfrac': 'text fraction',
'\\binom': 'binomial coefficient',
'\\dbinom': 'display binomial coefficient',
'\\tbinom': 'text binomial coefficient',
'\\pdiff': 'partial differential',
'\\forall': 'for all',
'\\exists': 'there exists',
'\\nexists': 'there does not exist',
'\\frac': 'fraction',
'\\dfrac': 'display fraction',
'\\cfrac': 'continuous fraction',
'\\tfrac': 'text fraction',
'\\binom': 'binomial coefficient',
'\\dbinom': 'display binomial coefficient',
'\\tbinom': 'text binomial coefficient',
'\\pdiff': 'partial differential',
'\\vec': 'vector',
'\\check': 'caron',
'\\acute': 'acute',
'\\breve': 'breve',
'\\tilde': 'tilde',
'\\dot': 'dot',
'\\hat': ['hat', 'circumflex'],
'\\ddot': 'double dot',
'\\bar': 'bar',
'\\vec': 'vector',
'\\check': 'caron',
'\\acute': 'acute',
'\\breve': 'breve',
'\\tilde': 'tilde',
'\\dot': 'dot',
'\\hat': ['hat', 'circumflex'],
'\\ddot': 'double dot',
'\\bar': 'bar',
'\\prime': 'prime',
'\\doubleprime':'double prime',
'\\prime': 'prime',
'\\doubleprime': 'double prime',
'\\varnothing': 'empty set',
'\\emptyset': 'empty set',
'\\subseteq': 'subset of or <br>equal to',
'\\supseteq': 'superset of or <br>equal to',
'\\supset': 'superset of',
'\\subset': 'subset of',
'\\partial': 'partial derivative',
'\\bigcup': 'union',
'\\bigcap': 'intersection',
'\\approx': 'approximately equal to',
'\\notin': 'not an element of',
'\\in': ['element of', 'included in'],
'\\infty': 'infinity',
'\\land': 'logical and',
'\\sqrt': 'square root',
'\\prod': 'product',
'\\sum': 'summation',
'\\amalg': ['amalgamation', 'coproduct', 'free product', 'disjoint union'],
'\\cup': 'union with',
'\\cap': 'intersection with',
'\\int': 'integral',
'\\iint': 'surface integral',
'\\oint': 'curve integral',
'\\iiint': 'volume integral',
'\\iff': 'if and only if',
'\\ln': 'natural logarithm',
'\\emptyset': 'empty set',
'\\subseteq': 'subset of or <br>equal to',
'\\supseteq': 'superset of or <br>equal to',
'\\supset': 'superset of',
'\\subset': 'subset of',
'\\partial': 'partial derivative',
'\\bigcup': 'union',
'\\bigcap': 'intersection',
'\\approx': 'approximately equal to',
'\\notin': 'not an element of',
'\\in': ['element of', 'included in'],
'\\infty': 'infinity',
'\\land': 'logical and',
'\\sqrt': 'square root',
'\\prod': 'product',
'\\sum': 'summation',
'\\amalg': ['amalgamation', 'coproduct', 'free product', 'disjoint union'],
'\\cup': 'union with',
'\\cap': 'intersection with',
'\\int': 'integral',
'\\iint': 'surface integral',
'\\oint': 'curve integral',
'\\iiint': 'volume integral',
'\\iff': 'if and only if',
'\\ln': 'natural logarithm',
'\\boldsymbol': 'bold',
'\\setminus': 'set subtraction',
'\\stackrel': 'relation with symbol above',
'\\stackbin': 'operator with symbol above',
'\\underset': 'symbol with annotation below',
'\\overset': 'symbol with annotation above',
'\\hslash': ['h-bar', 'Planck constant'],
'\\gtrsim': 'greater than or <br>similar to',
'\\propto': 'proportional to',
'\\equiv': 'equivalent to',
'\\setminus': 'set subtraction',
'\\stackrel': 'relation with symbol above',
'\\stackbin': 'operator with symbol above',
'\\underset': 'symbol with annotation below',
'\\overset': 'symbol with annotation above',
'\\hslash': ['h-bar', 'Planck constant'],
'\\gtrsim': 'greater than or <br>similar to',
'\\propto': 'proportional to',
'\\equiv': 'equivalent to',
'\\!': ['negative thin space', '(-3 mu)'],
'\\ ': ['space', '(6 mu)'],
'\\,': ['thin space', '(3 mu)'],
'\\:': ['medium space', '(4 mu)'],
'\\;': ['thick space', '(5 mu)'],
'\\quad': ['1 em space', '(18 mu)'],
'\\qquad': ['2 em space', '(36 mu)'],
'\\enskip': ['&#189; em space', '(9 mu)'],
'\\!': ['negative thin space', '(-3 mu)'],
'\\ ': ['space', '(6 mu)'],
'\\,': ['thin space', '(3 mu)'],
'\\:': ['medium space', '(4 mu)'],
'\\;': ['thick space', '(5 mu)'],
'\\quad': ['1 em space', '(18 mu)'],
'\\qquad': ['2 em space', '(36 mu)'],
'\\enskip': ['&#189; em space', '(9 mu)'],
'\\mp': 'minus or plus',
'\\pm': 'plus or minus',
'\\Im': 'Imaginary part of',
'\\Re': 'Real part of',
'\\mp': 'minus or plus',
'\\pm': 'plus or minus',
'\\Im': 'Imaginary part of',
'\\Re': 'Real part of',
'\\gothicCapitalR': 'Real part of',
'\\gothicCapitalI': 'Imaginary part part of',
'\\differentialD': 'differential d',
'\\aleph': ['aleph', 'infinite cardinal',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Cardinal_number">Wikipedia <big>&#x203A;</big></a>'
'\\differentialD': 'differential d',
'\\aleph': [
'aleph',
'infinite cardinal',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Cardinal_number">Wikipedia <big>&#x203A;</big></a>',
],
'\\beth': ['beth', 'beth number',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Beth_number">Wikipedia <big>&#x203A;</big></a>'
'\\beth': [
'beth',
'beth number',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Beth_number">Wikipedia <big>&#x203A;</big></a>',
],
'\\gimel': ['gimel', 'gimel function',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Gimel_function">Wikipedia <big>&#x203A;</big></a>'
'\\gimel': [
'gimel',
'gimel function',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Gimel_function">Wikipedia <big>&#x203A;</big></a>',
],
'\\O': 'empty set',
'\\N': 'set of <br>natural numbers',
'\\Z': 'set of <br>integers',
'\\Q': 'set of <br>rational numbers',
'\\C': 'set of <br>complex numbers',
'\\R': 'set of <br>real numbers',
'\\P': 'set of <br>prime numbers',
'\\O': 'empty set',
'\\N': 'set of <br>natural numbers',
'\\Z': 'set of <br>integers',
'\\Q': 'set of <br>rational numbers',
'\\C': 'set of <br>complex numbers',
'\\R': 'set of <br>real numbers',
'\\P': 'set of <br>prime numbers',
'\\lesseqqgtr': 'less than, equal to or<br> greater than',
'\\gnapprox': 'greater than and <br>not approximately',
'\\lnapprox': 'lesser than and <br>not approximately',
'\\lesseqqgtr': 'less than, equal to or<br> greater than',
'\\gnapprox': 'greater than and <br>not approximately',
'\\lnapprox': 'lesser than and <br>not approximately',
'\\j': 'dotless j',
'\\i': 'dotless i',
'\\cdot': 'centered dot',
'\\lmoustache': 'left moustache',
'\\rmoustache': 'right moustache',
'\\nabla': ['nabla', 'del', 'differential vector operator'],
'\\j': 'dotless j',
'\\i': 'dotless i',
'\\cdot': 'centered dot',
'\\lmoustache': 'left moustache',
'\\rmoustache': 'right moustache',
'\\nabla': ['nabla', 'del', 'differential vector operator'],
'\\square': ['square', 'd’Alembert operator',
'<a target="_blank" href="https://en.wikipedia.org/wiki/D%27Alembert_operator">Wikipedia <big>&#x203A;</big></a>'
'\\square': [
'square',
'd’Alembert operator',
'<a target="_blank" href="https://en.wikipedia.org/wiki/D%27Alembert_operator">Wikipedia <big>&#x203A;</big></a>',
],
'\\blacksquare': ['black square', 'end of proof', 'tombstone', 'Halmos symbol'],
'\\Box': 'end of proof',
'\\colon': ['such that', 'ratio'],
'\\coloneq': ['is defined by', 'is assigned'],
'\\Colon': ['is defined by', 'as'],
'\\_': ['underbar', 'underscore'],
'\\ll': 'much less than',
'\\gg': 'much greater than',
'\\doteq': 'approximately equal to',
'\\Doteq': 'approximately equal to',
'\\doteqdot': 'approximately equal to',
'\\cong': ['isomorphism of', '(for algebras, modules...)'],
'\\det': ['determinant of', '(of a matrix)'],
'\\dotplus': 'Cartesian product algebra',
'\\otimes': ['tensor product', '(of algebras)',
'Kronecker product', '(of matrices)'],
'\\oplus': ['direct sum', '(of modules)'],
'\\lb': 'base-2 logarithm',
'\\lg': 'base-10 logarithm',
'\\wp': ['Weierstrass P',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Weierstrass%27s_elliptic_functions">Wikipedia <big>&#x203A;</big></a>'
],
'\\wr': ['wreath product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Wreath_product">Wikipedia <big>&#x203A;</big></a>'
],
'\\top': ['tautology', 'Proposition P is universally true'],
'\\bot': ['contradiction', 'Proposition P is contradictory'],
'\\mid': ['probability', 'of event A given B'],
'\\mho': ['Siemens', 'electrical conductance in SI unit',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Siemens_(unit)">Wikipedia <big>&#x203A;</big></a>'
],
'\\blacksquare': [
'black square',
'end of proof',
'tombstone',
'Halmos symbol',
],
'\\Box': 'end of proof',
'\\colon': ['such that', 'ratio'],
'\\coloneq': ['is defined by', 'is assigned'],
'\\Colon': ['is defined by', 'as'],
'\\_': ['underbar', 'underscore'],
'\\ll': 'much less than',
'\\gg': 'much greater than',
'\\doteq': 'approximately equal to',
'\\Doteq': 'approximately equal to',
'\\doteqdot': 'approximately equal to',
'\\cong': ['isomorphism of', '(for algebras, modules...)'],
'\\det': ['determinant of', '(of a matrix)'],
'\\dotplus': 'Cartesian product algebra',
'\\otimes': [
'tensor product',
'(of algebras)',
'Kronecker product',
'(of matrices)',
],
'\\oplus': ['direct sum', '(of modules)'],
'\\lb': 'base-2 logarithm',
'\\lg': 'base-10 logarithm',
'\\wp': [
'Weierstrass P',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Weierstrass%27s_elliptic_functions">Wikipedia <big>&#x203A;</big></a>',
],
'\\wr': [
'wreath product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Wreath_product">Wikipedia <big>&#x203A;</big></a>',
],
'\\top': ['tautology', 'Proposition P is universally true'],
'\\bot': ['contradiction', 'Proposition P is contradictory'],
'\\mid': ['probability', 'of event A given B'],
'\\mho': [
'Siemens',
'electrical conductance in SI unit',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Siemens_(unit)">Wikipedia <big>&#x203A;</big></a>',
],

@@ -295,58 +312,57 @@ '\\Longrightarrow': 'implies',

'\\prec': 'precedes',
'\\preceq': 'precedes or is equal to',
'\\succ': 'succeedes',
'\\succeq': 'succeedes or is equal to',
'\\perp': ['is perpendicular to', 'is independent of'],
'\\prec': 'precedes',
'\\preceq': 'precedes or is equal to',
'\\succ': 'succeedes',
'\\succeq': 'succeedes or is equal to',
'\\perp': ['is perpendicular to', 'is independent of'],
'\\models': ['entails',
'double-turnstyle, models',
'is a semantic consequence of',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Double_turnstile">Wikipedia <big>&#x203A;</big></a>'
],
'\\vdash': ['satisfies',
'turnstyle, assertion sign',
'syntactic inference',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Turnstile_(symbol)">Wikipedia <big>&#x203A;</big></a>'
'\\models': [
'entails',
'double-turnstyle, models',
'is a semantic consequence of',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Double_turnstile">Wikipedia <big>&#x203A;</big></a>',
],
'\\vdash': [
'satisfies',
'turnstyle, assertion sign',
'syntactic inference',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Turnstile_(symbol)">Wikipedia <big>&#x203A;</big></a>',
],
'\\implies': ['implies', 'logical consequence'],
'\\impliedby': ['implied by', 'logical consequence'],
'\\implies': ['implies', 'logical consequence'],
'\\impliedby': ['implied by', 'logical consequence'],
'\\surd': ['surd', 'root of', 'checkmark'],
'\\ltimes': ['semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>'
],
'\\rtimes': ['semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>'
],
'\\leftthreetimes': ['semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>'
],
'\\rightthreetimes': ['semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>'
],
'\\divideontimes': ['divide on times'],
'\\curlywedge': 'nor',
'\\curlyvee': 'nand',
'\\surd': ['surd', 'root of', 'checkmark'],
'\\ltimes': [
'semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>',
],
'\\rtimes': [
'semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>',
],
'\\leftthreetimes': [
'semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>',
],
'\\rightthreetimes': [
'semi direct product',
'<a target="_blank" href="https://en.wikipedia.org/wiki/Semidirect_product">Wikipedia <big>&#x203A;</big></a>',
],
'\\divideontimes': ['divide on times'],
'\\curlywedge': 'nor',
'\\curlyvee': 'nand',
'\\simeq': 'is group isomorphic with',
'\\vartriangleleft': [
'is a normal subgroup of',
'is an ideal ring of'
],
'\\simeq': 'is group isomorphic with',
'\\vartriangleleft': ['is a normal subgroup of', 'is an ideal ring of'],
'\\circ': ['circle', 'ring', 'function composition'],
'\\circ': ['circle', 'ring', 'function composition'],
'\\rlap': ['overlap right',
'\\rlap{x}o'],
'\\llap': ['overlap left',
'o\\llap{/}'],
'\\colorbox': ['color box',
'\\colorbox{#fbc0bd}{...}'
],
'\\ast': ['asterisk', 'reflexive closure (as a superscript)'],
'\\bullet': 'bullet',
'\\rlap': ['overlap right', '\\rlap{x}o'],
'\\llap': ['overlap left', 'o\\llap{/}'],
'\\colorbox': ['color box', '\\colorbox{#fbc0bd}{...}'],
'\\ast': ['asterisk', 'reflexive closure (as a superscript)'],
'\\bullet': 'bullet',
'\\lim': 'limit',
'\\lim': 'limit',
};

@@ -363,12 +379,16 @@

function latexToMarkup(latex, mf) {
const parse = ParserModule.parseTokens(Lexer.tokenize(latex), 'math', null, mf.config.macros);
const parse = ParserModule.parseTokens(
Lexer.tokenize(latex),
'math',
null,
mf.config.macros
);
const spans = MathAtom.decompose(
{
mathstyle: 'displaystyle',
macros: mf.config.macros
macros: mf.config.macros,
},
parse);
parse
);

@@ -382,3 +402,6 @@ const base = Span.makeSpan(spans, 'ML__base');

bottomStrut.setStyle('vertical-align', -base.depth, 'em');
const wrapper = Span.makeSpan([topStrut, bottomStrut, base], 'ML__mathlive');
const wrapper = Span.makeSpan(
[topStrut, bottomStrut, base],
'ML__mathlive'
);

@@ -399,17 +422,21 @@ return wrapper.toMarkup();

let template = displayArrows ?
'<div class="ML__popover__prev-shortcut" role="button" aria-label="Previous suggestion"><span><span>&#x25B2;</span></span></div>' : '';
let template = displayArrows
? '<div class="ML__popover__prev-shortcut" role="button" aria-label="Previous suggestion"><span><span>&#x25B2;</span></span></div>'
: '';
template += '<span class="ML__popover__content" role="button">';
template += '<div class="ML__popover__command">' +
command_markup + '</div>';
template +=
'<div class="ML__popover__command">' + command_markup + '</div>';
if (command_note) {
template += '<div class="ML__popover__note">' +
command_note + '</div>';
template += '<div class="ML__popover__note">' + command_note + '</div>';
}
if (command_shortcuts) {
template += '<div class="ML__popover__shortcut">' +
command_shortcuts + '</div>';
template +=
'<div class="ML__popover__shortcut">' +
command_shortcuts +
'</div>';
}
template += '</span>';
template += displayArrows ? '<div class="ML__popover__next-shortcut" role="button" aria-label="Next suggestion"><span><span>&#x25BC;</span></span></div>' : '';
template += displayArrows
? '<div class="ML__popover__next-shortcut" role="button" aria-label="Next suggestion"><span><span>&#x25BC;</span></span></div>'
: '';
showPopover(mf, template);

@@ -419,6 +446,8 @@

if (el && el.length > 0) {
mf._attachButtonHandlers(el[0], ['complete', {acceptSuggestion:true}]);
mf._attachButtonHandlers(el[0], [
'complete',
{ acceptSuggestion: true },
]);
}
el = mf.popover.getElementsByClassName('ML__popover__prev-shortcut');

@@ -433,3 +462,2 @@ if (el && el.length > 0) {

}
}

@@ -450,3 +478,6 @@

} else {
if (!mf.mathlist.anchor() || mf.mathlist.anchor().type !== 'command') {
if (
!mf.mathlist.anchor() ||
mf.mathlist.anchor().type !== 'command'
) {
hidePopover(mf);

@@ -473,6 +504,8 @@ } else {

// get screen width & height (browser compatibility)
const screen_height = window.innerHeight ||
const screen_height =
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight;
const screen_width = window.innerWidth ||
const screen_width =
window.innerWidth ||
document.documentElement.clientWidth ||

@@ -482,29 +515,33 @@ document.body.clientWidth;

// get scrollbar size. This would be 0 in mobile device (also no needed).
const scrollbar_width = window.innerWidth -
document.documentElement.clientWidth;
const scrollbar_height = window.innerHeight -
document.documentElement.clientHeight;
const virtualkeyboard_height = mf.virtualKeyboardVisible ?
mf.virtualKeyboard.offsetHeight : 0;
const scrollbar_width =
window.innerWidth - document.documentElement.clientWidth;
const scrollbar_height =
window.innerHeight - document.documentElement.clientHeight;
const virtualkeyboard_height = mf.virtualKeyboardVisible
? mf.virtualKeyboard.offsetHeight
: 0;
// prevent screen overflow horizontal.
if (position.x + (mf.popover.offsetWidth / 2) > screen_width - scrollbar_width) {
if (
position.x + mf.popover.offsetWidth / 2 >
screen_width - scrollbar_width
) {
mf.popover.style.left =
(screen_width - mf.popover.offsetWidth - scrollbar_width) + 'px';
} else if (position.x - (mf.popover.offsetWidth / 2) < 0) {
screen_width - mf.popover.offsetWidth - scrollbar_width + 'px';
} else if (position.x - mf.popover.offsetWidth / 2 < 0) {
mf.popover.style.left = 0;
} else {
mf.popover.style.left =
(position.x - mf.popover.offsetWidth / 2) + 'px';
mf.popover.style.left = position.x - mf.popover.offsetWidth / 2 + 'px';
}
// and position the popover right below or above the caret
if (position.y + mf.popover.offsetHeight + 5 >
screen_height - scrollbar_height - virtualkeyboard_height) {
if (
position.y + mf.popover.offsetHeight + 5 >
screen_height - scrollbar_height - virtualkeyboard_height
) {
mf.popover.classList.add('reverse-direction');
mf.popover.style.top =
(position.y - position.height -
mf.popover.offsetHeight - 5) + 'px';
position.y - position.height - mf.popover.offsetHeight - 5 + 'px';
} else {
mf.popover.classList.remove('reverse-direction');
mf.popover.style.top = (position.y + 5) + 'px';
mf.popover.style.top = position.y + 5 + 'px';
}

@@ -517,4 +554,2 @@ }

export default {

@@ -527,6 +562,3 @@ getNote,

hidePopover,
updatePopoverPosition
}
updatePopoverPosition,
};

@@ -50,131 +50,133 @@ /**

const KEYBOARD_SHORTCUTS = {
'Left': 'moveToPreviousChar',
'Right': 'moveToNextChar',
'Up': 'moveUp',
'Down': 'moveDown',
Left: 'moveToPreviousChar',
Right: 'moveToNextChar',
Up: 'moveUp',
Down: 'moveDown',
'Shift-Left': 'extendToPreviousChar',
'Shift-Right': 'extendToNextChar',
'Shift-Up': 'extendUp',
'Shift-Down': 'extendDown',
'Shift-Left': 'extendToPreviousChar',
'Shift-Right': 'extendToNextChar',
'Shift-Up': 'extendUp',
'Shift-Down': 'extendDown',
'Backspace': 'deletePreviousChar',
'Alt-Del': 'deletePreviousChar',
Backspace: 'deletePreviousChar',
'Alt-Del': 'deletePreviousChar',
'Del': 'deleteNextChar',
'Alt-Backspace': 'deleteNextChar',
Del: 'deleteNextChar',
'Alt-Backspace': 'deleteNextChar',
'Alt-Left': 'moveToPreviousWord',
'Alt-Right': 'moveToNextWord',
'Alt-Left': 'moveToPreviousWord',
'Alt-Right': 'moveToNextWord',
'Alt-Shift-Left': 'extendToPreviousWord',
'Alt-Shift-Right': 'extendToNextWord',
'Alt-Shift-Left': 'extendToPreviousWord',
'Alt-Shift-Right': 'extendToNextWord',
'Ctrl-Left': 'moveToGroupStart',
'Ctrl-Right': 'moveToGroupEnd',
'Ctrl-Left': 'moveToGroupStart',
'Ctrl-Right': 'moveToGroupEnd',
'Ctrl-Shift-Left': 'extendToGroupStart',
'Ctrl-Shift-Right': 'extendToGroupEnd',
'Ctrl-Shift-Left': 'extendToGroupStart',
'Ctrl-Shift-Right': 'extendToGroupEnd',
'math:Spacebar': 'moveAfterParent',
'math:Shift-Spacebar': 'moveBeforeParent',
'math:Spacebar': 'moveAfterParent',
'math:Shift-Spacebar': 'moveBeforeParent',
'Home': 'moveToMathFieldStart',
'mac:Meta-Left': 'moveToMathFieldStart',
'Shift-Home': 'extendToMathFieldStart',
'mac:Meta-Shift-Left': 'extendToMathFieldStart',
Home: 'moveToMathFieldStart',
'mac:Meta-Left': 'moveToMathFieldStart',
'Shift-Home': 'extendToMathFieldStart',
'mac:Meta-Shift-Left': 'extendToMathFieldStart',
'End': 'moveToMathFieldEnd',
'mac:Meta-Right': 'moveToMathFieldEnd',
'Shift-End': 'extendToMathFieldEnd',
'mac:Meta-Shift-Right': 'extendToMathFieldEnd',
End: 'moveToMathFieldEnd',
'mac:Meta-Right': 'moveToMathFieldEnd',
'Shift-End': 'extendToMathFieldEnd',
'mac:Meta-Shift-Right': 'extendToMathFieldEnd',
'PageUp': 'moveToGroupStart',
'PageDown': 'moveToGroupEnd',
PageUp: 'moveToGroupStart',
PageDown: 'moveToGroupEnd',
'math:Tab': 'moveToNextPlaceholder',
'math:F8': 'moveToNextPlaceholder', // Visual Studio
'math:Shift-Tab': 'moveToPreviousPlaceholder',
'math:Shift-F8': 'moveToPreviousPlaceholder', // Visual Studio
'math:Tab': 'moveToNextPlaceholder',
'math:F8': 'moveToNextPlaceholder', // Visual Studio
'math:Shift-Tab': 'moveToPreviousPlaceholder',
'math:Shift-F8': 'moveToPreviousPlaceholder', // Visual Studio
'text:Tab': 'moveToNextPlaceholder',
'text:F8': 'moveToNextPlaceholder', // Visual Studio
'text:Shift-Tab': 'moveToPreviousPlaceholder',
'text:Shift-F8': 'moveToPreviousPlaceholder', // Visual Studio
'text:Tab': 'moveToNextPlaceholder',
'text:F8': 'moveToNextPlaceholder', // Visual Studio
'text:Shift-Tab': 'moveToPreviousPlaceholder',
'text:Shift-F8': 'moveToPreviousPlaceholder', // Visual Studio
'math:Esc': ['switch-mode', 'command'],
'math:Backslash': ['switch-mode', 'command'],
'math:IntlBackslash': ['switch-mode', 'command'],
'math:Esc': ['switch-mode', 'command'],
'math:Backslash': ['switch-mode', 'command'],
'math:IntlBackslash': ['switch-mode', 'command'],
'math:Alt-Equal': ['apply-style', {mode: 'text'}],
'text:Alt-Equal': ['apply-style', {mode: 'math'}],
'math:Alt-Equal': ['apply-style', { mode: 'text' }],
'text:Alt-Equal': ['apply-style', { mode: 'math' }],
'command:Esc': ['complete', {discard: true}], // discard the command, insert nothing
'command:Tab': ['complete', {acceptSuggestion: true}], // complete the suggestion
'command:Return': 'complete',
'command:Enter': 'complete',
'command:Shift-Esc': ['complete', {discard: true}], // Some keyboards can't generate
// this combination, for example in 60% keyboards it is mapped to ~
'command:Down': 'nextSuggestion',
'ios:command:Tab': 'nextSuggestion',
'command:Up': 'previousSuggestion',
'command:Esc': ['complete', { discard: true }], // discard the command, insert nothing
'command:Tab': ['complete', { acceptSuggestion: true }], // complete the suggestion
'command:Return': 'complete',
'command:Enter': 'complete',
'command:Shift-Esc': ['complete', { discard: true }], // Some keyboards can't generate
// this combination, for example in 60% keyboards it is mapped to ~
'command:Down': 'nextSuggestion',
'ios:command:Tab': 'nextSuggestion',
'command:Up': 'previousSuggestion',
'!mac:Ctrl-KeyA': 'selectAll',
'mac:Meta-KeyA': 'selectAll',
'!mac:Ctrl-KeyA': 'selectAll',
'mac:Meta-KeyA': 'selectAll',
// Rare keys on some extended keyboards
'Cut': 'cut',
'Copy': 'copy',
'Paste': 'paste',
'Clear': 'delete',
Cut: 'cut',
Copy: 'copy',
Paste: 'paste',
Clear: 'delete',
'!mac:Ctrl-KeyZ': 'undo',
'mac:Meta-KeyZ': 'undo',
'Undo': 'undo',
'!mac:Ctrl-KeyY': 'redo', // ARIA recommendation
'mac:Meta-Shift-KeyY': 'redo',
'!mac:Ctrl-Shift-KeyZ': 'redo',
'mac:Meta-Shift-KeyZ': 'redo',
'Redo': 'redo',
'!mac:Ctrl-KeyZ': 'undo',
'mac:Meta-KeyZ': 'undo',
Undo: 'undo',
'!mac:Ctrl-KeyY': 'redo', // ARIA recommendation
'mac:Meta-Shift-KeyY': 'redo',
'!mac:Ctrl-Shift-KeyZ': 'redo',
'mac:Meta-Shift-KeyZ': 'redo',
Redo: 'redo',
'EraseEof': 'deleteToGroupEnd',
EraseEof: 'deleteToGroupEnd',
// EMACS/MACOS BINDINGS
'mac:Ctrl-KeyB': 'moveToPreviousChar',
'mac:Ctrl-KeyF': 'moveToNextChar',
'mac:Ctrl-KeyP': 'moveUp',
'mac:Ctrl-KeyN': 'moveDown',
'mac:Ctrl-KeyA': 'moveToMathFieldStart',
'mac:Ctrl-KeyE': 'moveToMathFieldEnd',
'mac:Ctrl-KeyB': 'moveToPreviousChar',
'mac:Ctrl-KeyF': 'moveToNextChar',
'mac:Ctrl-KeyP': 'moveUp',
'mac:Ctrl-KeyN': 'moveDown',
'mac:Ctrl-KeyA': 'moveToMathFieldStart',
'mac:Ctrl-KeyE': 'moveToMathFieldEnd',
'mac:Ctrl-Shift-KeyB': 'extendToPreviousChar',
'mac:Ctrl-Shift-KeyF': 'extendToNextChar',
'mac:Ctrl-Shift-KeyP': 'extendUp',
'mac:Ctrl-Shift-KeyN': 'extendDown',
'mac:Ctrl-Shift-KeyA': 'extendToMathFieldStart',
'mac:Ctrl-Shift-KeyE': 'extendToMathFieldEnd',
'mac:Ctrl-Alt-KeyB': 'moveToPreviousWord',
'mac:Ctrl-Alt-KeyF': 'moveToNextWord',
'mac:Ctrl-Shift-Alt-KeyB': 'extendToPreviousWord',
'mac:Ctrl-Shift-Alt-KeyF': 'extendToNextWord',
'mac:Ctrl-Shift-KeyB': 'extendToPreviousChar',
'mac:Ctrl-Shift-KeyF': 'extendToNextChar',
'mac:Ctrl-Shift-KeyP': 'extendUp',
'mac:Ctrl-Shift-KeyN': 'extendDown',
'mac:Ctrl-Shift-KeyA': 'extendToMathFieldStart',
'mac:Ctrl-Shift-KeyE': 'extendToMathFieldEnd',
'mac:Ctrl-Alt-KeyB': 'moveToPreviousWord',
'mac:Ctrl-Alt-KeyF': 'moveToNextWord',
'mac:Ctrl-Shift-Alt-KeyB': 'extendToPreviousWord',
'mac:Ctrl-Shift-Alt-KeyF': 'extendToNextWord',
'mac:Ctrl-KeyH': 'deletePreviousChar',
'mac:Ctrl-KeyD': 'deleteNextChar',
'mac:Ctrl-KeyL': 'scrollIntoView',
'mac:Ctrl-KeyT': 'transpose',
'mac:Ctrl-KeyH': 'deletePreviousChar',
'mac:Ctrl-KeyD': 'deleteNextChar',
'mac:Ctrl-KeyL': 'scrollIntoView',
'mac:Ctrl-KeyT': 'transpose',
'math:Shift-Quote': ['switch-mode', 'text', '', '“'],
'text:Shift-Quote': ['switch-mode', 'math', '”', ''],
'math:Shift-Quote': ['switch-mode', 'text', '', '“'],
'text:Shift-Quote': ['switch-mode', 'math', '”', ''],
// WOLFRAM MATHEMATICA BINDINGS
'math:Ctrl-Digit2': ['insert', '\\sqrt{#0}'],
'math:Ctrl-Digit5': 'moveToOpposite',
'math:Ctrl-Digit6': 'moveToSuperscript',
'math:Ctrl-Minus': 'moveToSubscript',
'math:Alt-BracketLeft': ['insert', '\\left\\lbrack #0 \\right\\rbrack'],
'math:Alt-Shift-BracketLeft': ['insert', '\\left\\lbrace #0 \\right\\rbrace'],
'math:Return': 'addRowAfter',
'math:Enter': 'addRowAfter',
'math:Ctrl-Comma': 'addColumnAfter',
'math:Ctrl-Digit2': ['insert', '\\sqrt{#0}'],
'math:Ctrl-Digit5': 'moveToOpposite',
'math:Ctrl-Digit6': 'moveToSuperscript',
'math:Ctrl-Minus': 'moveToSubscript',
'math:Alt-BracketLeft': ['insert', '\\left\\lbrack #0 \\right\\rbrack'],
'math:Alt-Shift-BracketLeft': [
'insert',
'\\left\\lbrace #0 \\right\\rbrace',
],
'math:Return': 'addRowAfter',
'math:Enter': 'addRowAfter',
'math:Ctrl-Comma': 'addColumnAfter',
// Excel shortcuts:

@@ -186,35 +188,35 @@ // Shift-space: select entire row, ctrl+space: select an entire column

// MATHLIVE BINDINGS
'math:Alt-KeyQ': ['insert', '\\theta'],
'math:Alt-KeyP': ['insert', '\\pi'],
'math:Alt-KeyV': ['insert', '\\sqrt{#0}'],
'math:Alt-KeyW': ['insert', '\\sum_{i=#?}^{#?}'],
'math:Alt-KeyB': ['insert', '\\int_{#?}^{#?}'],
'math:Alt-KeyU': ['insert', '\\cup'],
'math:Alt-KeyN': ['insert', '\\cap'],
'math:Alt-KeyO': ['insert', '\\emptyset'],
'math:Alt-KeyD': ['insert', '\\differentialD'],
'math:Alt-Shift-KeyO': ['insert', '\\varnothing'],
'math:Alt-Shift-KeyD': ['insert', '\\partial'],
'math:Alt-Shift-KeyP': ['insert', '\\prod_{i=#?}^{#?}'],
'math:Alt-Shift-KeyU': ['insert', '\\bigcup'],
'math:Alt-Shift-KeyN': ['insert', '\\bigcap'],
'math:Alt-Shift-KeyA': ['insert', '\\forall'],
'math:Alt-Shift-KeyE': ['insert', '\\exists'],
'math:Alt-Digit5': ['insert', '\\infty'], // "%" key
'math:Alt-Digit6': ['insert', '\\wedge'], // "^" key
'math:Alt-Shift-Digit6': ['insert', '\\vee'], // "^" key
'math:Alt-Digit9': ['insert', '('], // "(" key, override smartFence
'math:Alt-Digit0': ['insert', ')'], // ")" key, override smartFence
'math:Alt-Shift-Backslash': ['insert', '|'], // "|" key, override smartFence
'math:Alt-Backslash': ['insert', '\\backslash'], // "|" key, override command mode
'math:Slash': ['insert', '\\frac{#@}{#?}'],
'math:Alt-Slash': ['insert', '\\frac{#?}{#@}'],
'math:NumpadDivide': ['insert', '\\frac{#@}{#?}'],
'math:Alt-NumpadDivide': ['insert', '\\frac{#?}{#@}'],
'math:Shift-Backquote': ['insert', '\\~'],
'math:Alt-Shift-Slash': ['insert', '\\/'],
'math:Alt-KeyQ': ['insert', '\\theta'],
'math:Alt-KeyP': ['insert', '\\pi'],
'math:Alt-KeyV': ['insert', '\\sqrt{#0}'],
'math:Alt-KeyW': ['insert', '\\sum_{i=#?}^{#?}'],
'math:Alt-KeyB': ['insert', '\\int_{#?}^{#?}'],
'math:Alt-KeyU': ['insert', '\\cup'],
'math:Alt-KeyN': ['insert', '\\cap'],
'math:Alt-KeyO': ['insert', '\\emptyset'],
'math:Alt-KeyD': ['insert', '\\differentialD'],
'math:Alt-Shift-KeyO': ['insert', '\\varnothing'],
'math:Alt-Shift-KeyD': ['insert', '\\partial'],
'math:Alt-Shift-KeyP': ['insert', '\\prod_{i=#?}^{#?}'],
'math:Alt-Shift-KeyU': ['insert', '\\bigcup'],
'math:Alt-Shift-KeyN': ['insert', '\\bigcap'],
'math:Alt-Shift-KeyA': ['insert', '\\forall'],
'math:Alt-Shift-KeyE': ['insert', '\\exists'],
'math:Alt-Digit5': ['insert', '\\infty'], // "%" key
'math:Alt-Digit6': ['insert', '\\wedge'], // "^" key
'math:Alt-Shift-Digit6': ['insert', '\\vee'], // "^" key
'math:Alt-Digit9': ['insert', '('], // "(" key, override smartFence
'math:Alt-Digit0': ['insert', ')'], // ")" key, override smartFence
'math:Alt-Shift-Backslash': ['insert', '|'], // "|" key, override smartFence
'math:Alt-Backslash': ['insert', '\\backslash'], // "|" key, override command mode
'math:Slash': ['insert', '\\frac{#@}{#?}'],
'math:Alt-Slash': ['insert', '\\frac{#?}{#@}'],
'math:NumpadDivide': ['insert', '\\frac{#@}{#?}'],
'math:Alt-NumpadDivide': ['insert', '\\frac{#?}{#@}'],
'math:Shift-Backquote': ['insert', '\\~'],
'math:Alt-Shift-Slash': ['insert', '\\/'],
// Accessibility
'Alt-Shift-KeyK': 'toggleKeystrokeCaption',
'Alt-Space': 'toggleVirtualKeyboard',
'Alt-Shift-KeyK': 'toggleKeystrokeCaption',
'Alt-Space': 'toggleVirtualKeyboard',

@@ -225,3 +227,3 @@ // Note: On Mac OS (as of 10.12), there is a bug/behavior that causes

// In ~/Library/KeyBindings/DefaultKeyBinding.dict add these entries:
/*
/*
{

@@ -233,23 +235,31 @@ "^@\UF701" = "noop:";

*/
'mac:Ctrl-Meta-Up': ['speak', 'parent', {withHighlighting: false}],
'!mac:Ctrl-Alt-Up': ['speak', 'parent', {withHighlighting: false}],
'mac:Ctrl-Meta-Down': ['speak', 'all', {withHighlighting: false}],
'!mac:Ctrl-Alt-Down': ['speak', 'all', {withHighlighting: false}],
'mac:Ctrl-Meta-Left': ['speak', 'left', {withHighlighting: false}],
'!mac:Ctrl-Alt-Left': ['speak', 'left', {withHighlighting: false}],
'mac:Ctrl-Meta-Right': ['speak', 'right', {withHighlighting: false}],
'!mac:Ctrl-Alt-Right': ['speak', 'right', {withHighlighting: false}],
'!mac:Ctrl-Alt-Period': ['speak', 'selection', {withHighlighting: false}],
'mac:Ctrl-Meta-Period': ['speak', 'selection', {withHighlighting: false}],
'mac:Ctrl-Meta-Shift-Up': ['speak', 'parent', {withHighlighting: true}],
'!mac:Ctrl-Alt-Shift-Up': ['speak', 'parent', {withHighlighting: true}],
'mac:Ctrl-Meta-Shift-Down': ['speak', 'all', {withHighlighting: true}],
'!mac:Ctrl-Alt-Shift-Down': ['speak', 'all', {withHighlighting: true}],
'mac:Ctrl-Meta-Shift-Left': ['speak', 'left', {withHighlighting: true}],
'!mac:Ctrl-Alt-Shift-Left': ['speak', 'left', {withHighlighting: true}],
'mac:Ctrl-Meta-Shift-Right': ['speak', 'right', {withHighlighting: true}],
'!mac:Ctrl-Alt-Shift-Right': ['speak', 'right', {withHighlighting: true}],
'!mac:Ctrl-Alt-Shift-Period': ['speak', 'selection', {withHighlighting: true}],
'mac:Ctrl-Meta-Shift-Period': ['speak', 'selection', {withHighlighting: true}],
'mac:Ctrl-Meta-Up': ['speak', 'parent', { withHighlighting: false }],
'!mac:Ctrl-Alt-Up': ['speak', 'parent', { withHighlighting: false }],
'mac:Ctrl-Meta-Down': ['speak', 'all', { withHighlighting: false }],
'!mac:Ctrl-Alt-Down': ['speak', 'all', { withHighlighting: false }],
'mac:Ctrl-Meta-Left': ['speak', 'left', { withHighlighting: false }],
'!mac:Ctrl-Alt-Left': ['speak', 'left', { withHighlighting: false }],
'mac:Ctrl-Meta-Right': ['speak', 'right', { withHighlighting: false }],
'!mac:Ctrl-Alt-Right': ['speak', 'right', { withHighlighting: false }],
'!mac:Ctrl-Alt-Period': ['speak', 'selection', { withHighlighting: false }],
'mac:Ctrl-Meta-Period': ['speak', 'selection', { withHighlighting: false }],
'mac:Ctrl-Meta-Shift-Up': ['speak', 'parent', { withHighlighting: true }],
'!mac:Ctrl-Alt-Shift-Up': ['speak', 'parent', { withHighlighting: true }],
'mac:Ctrl-Meta-Shift-Down': ['speak', 'all', { withHighlighting: true }],
'!mac:Ctrl-Alt-Shift-Down': ['speak', 'all', { withHighlighting: true }],
'mac:Ctrl-Meta-Shift-Left': ['speak', 'left', { withHighlighting: true }],
'!mac:Ctrl-Alt-Shift-Left': ['speak', 'left', { withHighlighting: true }],
'mac:Ctrl-Meta-Shift-Right': ['speak', 'right', { withHighlighting: true }],
'!mac:Ctrl-Alt-Shift-Right': ['speak', 'right', { withHighlighting: true }],
'!mac:Ctrl-Alt-Shift-Period': [
'speak',
'selection',
{ withHighlighting: true },
],
'mac:Ctrl-Meta-Shift-Period': [
'speak',
'selection',
{ withHighlighting: true },
],
// '!mac:Ctrl-Alt-Shift-Home': ['speak', 'start', {withHighlighting: true}],

@@ -259,3 +269,3 @@ // 'mac:Ctrl-Alt-Shift-Home': ['speak', 'start', {withHighlighting: true}],

// 'mac:Ctrl-Alt-Shift-End': ['speak', 'end', {withHighlighting: true}],
}
};

@@ -273,26 +283,25 @@ /**

const REVERSE_KEYBOARD_SHORTCUTS = {
'\\theta': 'Alt-KeyQ',
'\\sqrt': ['Alt-KeyV', 'Ctrl-Digit2'],
'\\pi': 'Alt-KeyP',
'\\prod': 'Alt-Shift-KeyP',
'\\sum': 'Alt-KeyW',
'\\int': 'Alt-KeyB',
'\\cup': 'Alt-KeyU',
'\\cap': 'Alt-KeyN',
'\\bigcup': 'Alt-Shift-KeyU',
'\\bigcap': 'Alt-Shift-KeyN',
'\\forall': 'Alt-Shift-KeyA',
'\\exists': 'Alt-Shift-KeyE',
'\\infty': 'Alt-Digit5',
'\\wedge': 'Alt-Digit5',
'\\vee': 'Alt-Shift-Digit6',
'\\differentialD': 'Alt-keyD',
'\\partial': 'Alt-Shift-KeyD',
'\\frac': 'Slash',
'\\emptyset': 'Alt-KeyO',
'\\varnothing': 'Alt-Shift-KeyO',
'\\~': '~'
'\\theta': 'Alt-KeyQ',
'\\sqrt': ['Alt-KeyV', 'Ctrl-Digit2'],
'\\pi': 'Alt-KeyP',
'\\prod': 'Alt-Shift-KeyP',
'\\sum': 'Alt-KeyW',
'\\int': 'Alt-KeyB',
'\\cup': 'Alt-KeyU',
'\\cap': 'Alt-KeyN',
'\\bigcup': 'Alt-Shift-KeyU',
'\\bigcap': 'Alt-Shift-KeyN',
'\\forall': 'Alt-Shift-KeyA',
'\\exists': 'Alt-Shift-KeyE',
'\\infty': 'Alt-Digit5',
'\\wedge': 'Alt-Digit5',
'\\vee': 'Alt-Shift-Digit6',
'\\differentialD': 'Alt-keyD',
'\\partial': 'Alt-Shift-KeyD',
'\\frac': 'Slash',
'\\emptyset': 'Alt-KeyO',
'\\varnothing': 'Alt-Shift-KeyO',
'\\~': '~',
};
}
/**

@@ -307,308 +316,343 @@ * These shortcut strings are replaced with the corresponding LaTeX expression

// Primes
"''": { mode: 'math', value: '^{\\doubleprime}'},
"''": { mode: 'math', value: '^{\\doubleprime}' },
// Greek letters
'alpha': '\\alpha',
'delta': '\\delta',
'Delta': '\\Delta',
'pi': { mode: 'math', value: '\\pi'},
'pi ': { mode: 'text', value: '\\pi '},
'Pi': { mode: 'math', value: '\\Pi'},
'theta': '\\theta',
'Theta': '\\Theta',
alpha: '\\alpha',
delta: '\\delta',
Delta: '\\Delta',
pi: { mode: 'math', value: '\\pi' },
'pi ': { mode: 'text', value: '\\pi ' },
Pi: { mode: 'math', value: '\\Pi' },
theta: '\\theta',
Theta: '\\Theta',
// Letter-like
'ii': { after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\imaginaryI' },
'jj': { after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\imaginaryJ' },
'ee': {
mode: 'math',
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\exponentialE',
},
ii: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\imaginaryI',
},
jj: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\imaginaryJ',
},
ee: {
mode: 'math',
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\exponentialE',
},
'nabla': { mode: 'math', value: '\\nabla'},
'grad': { mode: 'math', value: '\\nabla'},
'del': { mode: 'math', value: '\\partial'},
nabla: { mode: 'math', value: '\\nabla' },
grad: { mode: 'math', value: '\\nabla' },
del: { mode: 'math', value: '\\partial' },
'\u221e': '\\infty', // @TODO: doesn't work
'\u221e': '\\infty', // @TODO: doesn't work
// '&infin;': '\\infty',
// '&#8734;': '\\infty',
'oo': {
mode: 'math',
after: 'nothing+digit+frac+surd+binop+relop+punct+array+openfence+closefence+space',
value: '\\infty',
},
oo: {
mode: 'math',
after:
'nothing+digit+frac+surd+binop+relop+punct+array+openfence+closefence+space',
value: '\\infty',
},
// Big operators
'∑': { mode: 'math', value: '\\sum'},
'sum': { mode: 'math', value: '\\sum_{#?}^{#?}' },
'prod': { mode: 'math', value: '\\prod_{#?}^{#?}' },
'sqrt': { mode: 'math', value: '\\sqrt'},
'∑': { mode: 'math', value: '\\sum' },
sum: { mode: 'math', value: '\\sum_{#?}^{#?}' },
prod: { mode: 'math', value: '\\prod_{#?}^{#?}' },
sqrt: { mode: 'math', value: '\\sqrt' },
// '∫': '\\int', // There's a alt-B command for this
'∆': { mode: 'math', value: '\\differentialD'}, // @TODO: is \\diffD most common?
'∂': { mode: 'math', value: '\\differentialD'},
'∆': { mode: 'math', value: '\\differentialD' }, // @TODO: is \\diffD most common?
'∂': { mode: 'math', value: '\\differentialD' },
// Functions
'sin': { mode: 'math', value: '\\sin'},
'cos': { mode: 'math', value: '\\cos'},
'tan': { mode: 'math', value: '\\tan'},
'tanh': { mode: 'math', value: '\\tanh'},
'log': { mode: 'math', value: '\\log'},
'ln': { mode: 'math', value: '\\ln'},
'exp': { mode: 'math', value: '\\exp'},
'lim': { mode: 'math', value: '\\lim_{#?}'},
sin: { mode: 'math', value: '\\sin' },
cos: { mode: 'math', value: '\\cos' },
tan: { mode: 'math', value: '\\tan' },
tanh: { mode: 'math', value: '\\tanh' },
log: { mode: 'math', value: '\\log' },
ln: { mode: 'math', value: '\\ln' },
exp: { mode: 'math', value: '\\exp' },
lim: { mode: 'math', value: '\\lim_{#?}' },
// Differentials
// According to ISO31/XI (ISO 80000-2), differentials should be upright
'dx': '\\differentialD x',
'dy': '\\differentialD y',
'dt': '\\differentialD t',
dx: '\\differentialD x',
dy: '\\differentialD y',
dt: '\\differentialD t',
// Logic
'AA': { mode: 'math', value: '\\forall'},
'EE': { mode: 'math', value: '\\exists'},
'!EE': { mode: 'math', value: '\\nexists'},
'&&': { mode: 'math', value: '\\land'},
AA: { mode: 'math', value: '\\forall' },
EE: { mode: 'math', value: '\\exists' },
'!EE': { mode: 'math', value: '\\nexists' },
'&&': { mode: 'math', value: '\\land' },
// The shortcut for the greek letter "xi" is interfering with "x in"
'xin': {
mode: 'math',
after: 'nothing+text+relop+punct+openfence+space',
value: 'x \\in',
},
'in': {
mode: 'math',
after: 'nothing+letter+closefence',
value: '\\in',
},
'!in': { mode: 'math', value: '\\notin'},
xin: {
mode: 'math',
after: 'nothing+text+relop+punct+openfence+space',
value: 'x \\in',
},
in: {
mode: 'math',
after: 'nothing+letter+closefence',
value: '\\in',
},
'!in': { mode: 'math', value: '\\notin' },
// Sets
'NN': '\\N', // Natural numbers
'ZZ': '\\Z', // Integers
'QQ': '\\Q', // Rational numbers
'RR': '\\R', // Real numbers
'CC': '\\C', // Complex numbers
'PP': '\\P', // Prime numbers
NN: '\\N', // Natural numbers
ZZ: '\\Z', // Integers
QQ: '\\Q', // Rational numbers
RR: '\\R', // Real numbers
CC: '\\C', // Complex numbers
PP: '\\P', // Prime numbers
// Operators
'xx': '\\times',
'+-': '\\pm',
xx: '\\times',
'+-': '\\pm',
// Relational operators
'!=': '\\ne',
'>=': '\\ge',
'<=': '\\le',
'<<': '\\ll',
'>>': '\\gg',
'~~': '\\approx',
'!=': '\\ne',
'>=': '\\ge',
'<=': '\\le',
'<<': '\\ll',
'>>': '\\gg',
'~~': '\\approx',
// More operators
'≈': '\\approx',
'?=': '\\questeq',
'÷': '\\div',
'¬': '\\neg',
':=': '\\coloneq',
'::': '\\Colon',
'≈': '\\approx',
'?=': '\\questeq',
'÷': '\\div',
'¬': '\\neg',
':=': '\\coloneq',
'::': '\\Colon',
// Fences
'(:': '\\langle',
':)': '\\rangle',
'(:': '\\langle',
':)': '\\rangle',
// More Greek letters
'beta': '\\beta',
'chi': '\\chi',
'epsilon': '\\epsilon',
'varepsilon': '\\varepsilon',
'eta': {
mode: 'math',
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\eta'
},
'eta ': {
mode: 'text',
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\eta '
},
'gamma': '\\gamma',
'Gamma': '\\Gamma',
'iota': '\\iota',
'kappa': '\\kappa',
'lambda': '\\lambda',
'Lambda': '\\Lambda',
'mu': {
mode: 'math',
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\mu'
},
'mu ': {
mode: 'text',
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\mu '
},
'nu': {
mode: 'math',
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value:'\\nu'
},
'nu ': {
mode: 'text',
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value:'\\nu '
},
'µ': '\\mu', // @TODO: or micro?
'phi': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\phi'
},
'Phi': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value:'\\Phi'
},
'varphi': '\\varphi',
'psi': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\psi'
},
'Psi': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value:'\\Psi'
beta: '\\beta',
chi: '\\chi',
epsilon: '\\epsilon',
varepsilon: '\\varepsilon',
eta: {
mode: 'math',
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\eta',
},
'rho': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\rho'
'eta ': {
mode: 'text',
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\eta ',
},
'sigma': '\\sigma',
'Sigma': '\\Sigma',
'tau': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\tau'
gamma: '\\gamma',
Gamma: '\\Gamma',
iota: '\\iota',
kappa: '\\kappa',
lambda: '\\lambda',
Lambda: '\\Lambda',
mu: {
mode: 'math',
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\mu',
},
'vartheta': '\\vartheta',
'upsilon': '\\upsilon',
'xi': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value:'\\xi'},
'Xi': {
after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value:'\\Xi'},
'zeta': '\\zeta',
'omega': '\\omega',
'Omega': '\\Omega',
'Ω': '\\omega', // @TODO: or ohm?
'mu ': {
mode: 'text',
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\mu ',
},
nu: {
mode: 'math',
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\nu',
},
'nu ': {
mode: 'text',
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\nu ',
},
µ: '\\mu', // @TODO: or micro?
phi: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\phi',
},
Phi: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\Phi',
},
varphi: '\\varphi',
psi: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\psi',
},
Psi: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\Psi',
},
rho: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\rho',
},
sigma: '\\sigma',
Sigma: '\\Sigma',
tau: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\tau',
},
vartheta: '\\vartheta',
upsilon: '\\upsilon',
xi: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\xi',
},
Xi: {
after:
'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',
value: '\\Xi',
},
zeta: '\\zeta',
omega: '\\omega',
Omega: '\\Omega',
Ω: '\\omega', // @TODO: or ohm?
// More Logic
'forall': '\\forall',
'exists': {
mode: 'math',
value:'\\exists'
},
'!exists': {
mode: 'math',
value: '\\nexists'
},
':.': {
mode: 'math',
value:'\\therefore'
forall: '\\forall',
exists: {
mode: 'math',
value: '\\exists',
},
'!exists': {
mode: 'math',
value: '\\nexists',
},
':.': {
mode: 'math',
value: '\\therefore',
},
// MORE FUNCTIONS
// 'arg': '\\arg',
'liminf': '\\operatorname*{lim~inf}_{#?}',
'limsup': '\\operatorname*{lim~sup}_{#?}',
'argmin': '\\operatorname*{arg~min}_{#?}',
'argmax': '\\operatorname*{arg~max}_{#?}',
'det': '\\det',
'mod': {
mode: 'math',
value:'\\mod'},
'max': {
mode: 'math',
value:'\\max'},
'min': {
mode: 'math',
value:'\\min'},
'erf': '\\operatorname{erf}',
'erfc': '\\operatorname{erfc}',
'bessel': {
mode: 'math',
value:'\\operatorname{bessel}'},
'mean': {
mode: 'math',
value: '\\operatorname{mean}'
liminf: '\\operatorname*{lim~inf}_{#?}',
limsup: '\\operatorname*{lim~sup}_{#?}',
argmin: '\\operatorname*{arg~min}_{#?}',
argmax: '\\operatorname*{arg~max}_{#?}',
det: '\\det',
mod: {
mode: 'math',
value: '\\mod',
},
'median': {
mode: 'math',
value: '\\operatorname{median}'},
'fft': {
mode: 'math',
value:'\\operatorname{fft}'},
'lcm': {
mode: 'math',
value:'\\operatorname{lcm}'},
'gcd': {
mode: 'math',
value:'\\operatorname{gcd}'},
'randomReal': '\\operatorname{randomReal}',
'randomInteger': '\\operatorname{randomInteger}',
'Re': {
mode: 'math',
value:'\\operatorname{Re}'},
'Im': {
mode: 'math',
value:'\\operatorname{Im}'},
max: {
mode: 'math',
value: '\\max',
},
min: {
mode: 'math',
value: '\\min',
},
erf: '\\operatorname{erf}',
erfc: '\\operatorname{erfc}',
bessel: {
mode: 'math',
value: '\\operatorname{bessel}',
},
mean: {
mode: 'math',
value: '\\operatorname{mean}',
},
median: {
mode: 'math',
value: '\\operatorname{median}',
},
fft: {
mode: 'math',
value: '\\operatorname{fft}',
},
lcm: {
mode: 'math',
value: '\\operatorname{lcm}',
},
gcd: {
mode: 'math',
value: '\\operatorname{gcd}',
},
randomReal: '\\operatorname{randomReal}',
randomInteger: '\\operatorname{randomInteger}',
Re: {
mode: 'math',
value: '\\operatorname{Re}',
},
Im: {
mode: 'math',
value: '\\operatorname{Im}',
},
// UNITS
'mm': { mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{mm}', // millimeter
},
'cm': { mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{cm}', // centimeter
},
'km': { mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{km}', // kilometer
},
'kg': { mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{kg}', // kilogram
},
mm: {
mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{mm}', // millimeter
},
cm: {
mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{cm}', // centimeter
},
km: {
mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{km}', // kilometer
},
kg: {
mode: 'math',
after: 'nothing+digit',
value: '\\operatorname{kg}', // kilogram
},
// '||': '\\lor',
'...': '\\ldots', // In general, use \ldots
'+...': '+\\cdots', // ... but use \cdots after + ...
'-...': '-\\cdots', // ... - and ...
'->...': '\\to\\cdots', // ->
'...': '\\ldots', // In general, use \ldots
'+...': '+\\cdots', // ... but use \cdots after + ...
'-...': '-\\cdots', // ... - and ...
'->...': '\\to\\cdots', // ->
'->': '\\to',
'|->': '\\mapsto',
'-->': '\\longrightarrow',
// '<-': '\\leftarrow',
'<--': '\\longleftarrow',
'=>': '\\Rightarrow',
'==>': '\\Longrightarrow',
// '<=': '\\Leftarrow', // CONFLICTS WITH LESS THAN OR EQUAL
'<=>': '\\Leftrightarrow',
'<->': '\\leftrightarrow',
'->': '\\to',
'|->': '\\mapsto',
'-->': '\\longrightarrow',
// '<-': '\\leftarrow',
'<--': '\\longleftarrow',
'=>': '\\Rightarrow',
'==>': '\\Longrightarrow',
// '<=': '\\Leftarrow', // CONFLICTS WITH LESS THAN OR EQUAL
'<=>': '\\Leftrightarrow',
'<->': '\\leftrightarrow',
'(.)': '\\odot',
'(+)': '\\oplus',
'(/)': '\\oslash',
'(*)': '\\otimes',
'(-)': '\\ominus',
'(.)': '\\odot',
'(+)': '\\oplus',
'(/)': '\\oslash',
'(*)': '\\otimes',
'(-)': '\\ominus',
// '(-)': '\\circleddash',
'||': '\\Vert',
'{': '\\{',
'}': '\\}',
'*': '\\cdot',
'||': '\\Vert',
'{': '\\{',
'}': '\\}',
'*': '\\cdot',
/*
/*
//

@@ -695,3 +739,2 @@ // ASCIIIMath

/**

@@ -709,3 +752,4 @@ * Return an array of potential shortcuts

const s2 = s.substring(i);
const skipDefaultShortcuts = config && config.overrideDefaultInlineShortcuts;
const skipDefaultShortcuts =
config && config.overrideDefaultInlineShortcuts;
if (!skipDefaultShortcuts) {

@@ -719,4 +763,4 @@ Object.keys(INLINE_SHORTCUTS).forEach(key => {

const customInlineShortcuts = config && config.inlineShortcuts ?
config.inlineShortcuts : null;
const customInlineShortcuts =
config && config.inlineShortcuts ? config.inlineShortcuts : null;
if (customInlineShortcuts) {

@@ -733,3 +777,2 @@ Object.keys(customInlineShortcuts).forEach(key => {

/**

@@ -743,11 +786,12 @@ *

function validateShortcut(mode, siblings, shortcut) {
if (!shortcut) return shortcut
if (!shortcut) return shortcut;
// If it's a simple shortcut (no conditional), it's valid
if (typeof shortcut === 'string') return shortcut
if (typeof shortcut === 'string') return shortcut;
if (typeof shortcut.mode === 'string' && shortcut.mode !== mode) return null;
if (typeof shortcut.mode === 'string' && shortcut.mode !== mode)
return null;
// If we have no context, we assume all the shortcuts are valid
if (!siblings) return shortcut ? shortcut.value : undefined;
let nothing = false;

@@ -773,7 +817,11 @@ let letter = false;

}
nothing = !sibling || sibling.type === 'first'; // start of a group
nothing = !sibling || sibling.type === 'first'; // start of a group
if (sibling) {
text = sibling.mode === 'text';
letter = !text && sibling.type === 'mord' && Definitions.LETTER.test(sibling.body);
digit = !text && sibling.type === 'mord' && /[0-9]+$/.test(sibling.body);
letter =
!text &&
sibling.type === 'mord' &&
Definitions.LETTER.test(sibling.body);
digit =
!text && sibling.type === 'mord' && /[0-9]+$/.test(sibling.body);
isFunction = !text && sibling.isFunction;

@@ -793,16 +841,18 @@ frac = sibling.type === 'genfrac';

// If this is a conditional shortcut, consider the conditions now
if ( (/nothing/.test(shortcut.after) && nothing) ||
(/letter/.test(shortcut.after) && letter) ||
(/digit/.test(shortcut.after) && digit) ||
(/function/.test(shortcut.after) && isFunction) ||
(/frac/.test(shortcut.after) && frac) ||
(/surd/.test(shortcut.after) && surd) ||
(/binop/.test(shortcut.after) && binop) ||
(/relop/.test(shortcut.after) && relop) ||
(/punct/.test(shortcut.after) && punct) ||
(/array/.test(shortcut.after) && array) ||
(/openfence/.test(shortcut.after) && openfence) ||
(/closefence/.test(shortcut.after) && closefence) ||
(/text/.test(shortcut.after) && text) ||
(/space/.test(shortcut.after) && space)){
if (
(/nothing/.test(shortcut.after) && nothing) ||
(/letter/.test(shortcut.after) && letter) ||
(/digit/.test(shortcut.after) && digit) ||
(/function/.test(shortcut.after) && isFunction) ||
(/frac/.test(shortcut.after) && frac) ||
(/surd/.test(shortcut.after) && surd) ||
(/binop/.test(shortcut.after) && binop) ||
(/relop/.test(shortcut.after) && relop) ||
(/punct/.test(shortcut.after) && punct) ||
(/array/.test(shortcut.after) && array) ||
(/openfence/.test(shortcut.after) && openfence) ||
(/closefence/.test(shortcut.after) && closefence) ||
(/text/.test(shortcut.after) && text) ||
(/space/.test(shortcut.after) && space)
) {
return shortcut.value;

@@ -832,3 +882,4 @@ }

const skipDefaultShortcuts = config && config.overrideDefaultInlineShortcuts;
const skipDefaultShortcuts =
config && config.overrideDefaultInlineShortcuts;
if (!skipDefaultShortcuts) {

@@ -838,9 +889,13 @@ result = validateShortcut(mode, context, INLINE_SHORTCUTS[s]);

const customInlineShortcuts = config && config.inlineShortcuts ?
config.inlineShortcuts : null;
const customInlineShortcuts =
config && config.inlineShortcuts ? config.inlineShortcuts : null;
let customResult;
if (customInlineShortcuts) {
customResult = validateShortcut(mode, context, customInlineShortcuts[s]);
customResult = validateShortcut(
mode,
context,
customInlineShortcuts[s]
);
}
return customResult || result;

@@ -875,5 +930,7 @@ }

result = 'android';
} else if (/(iphone)/i.test(navigator.userAgent) ||
/(ipod)/i.test(navigator.userAgent) ||
/(ipad)/i.test(navigator.userAgent)) {
} else if (
/(iphone)/i.test(navigator.userAgent) ||
/(ipod)/i.test(navigator.userAgent) ||
/(ipad)/i.test(navigator.userAgent)
) {
result = 'ios';

@@ -950,16 +1007,18 @@ } else if (/\bCrOS\b/i.test(navigator.userAgent)) {

const regex = new RegExp('^' +
command.replace('\\','\\\\').
replace('|', '\\|').
replace('*', '\\*').
replace('$', '\\$').
replace('^', '\\^')
+ '([^*a-zA-Z]|$)');
Object.keys(KEYBOARD_SHORTCUTS).forEach(shortcut => {
if (regex.test(commandToString(KEYBOARD_SHORTCUTS[shortcut]))) {
const m = shortcut.match(/:([^:]*)$/);
if (m) result.push(m[1]);
}
const regex = new RegExp(
'^' +
command
.replace('\\', '\\\\')
.replace('|', '\\|')
.replace('*', '\\*')
.replace('$', '\\$')
.replace('^', '\\^') +
'([^*a-zA-Z]|$)'
);
Object.keys(KEYBOARD_SHORTCUTS).forEach(shortcut => {
if (regex.test(commandToString(KEYBOARD_SHORTCUTS[shortcut]))) {
const m = shortcut.match(/:([^:]*)$/);
if (m) result.push(m[1]);
}
);
});

@@ -984,3 +1043,4 @@ return stringify(result);

if (plat === platform('mac') ||
if (
plat === platform('mac') ||
plat === platform('win') ||

@@ -990,8 +1050,22 @@ plat === platform('ios') ||

plat === platform('chromeos') ||
plat === platform('other')) {
plat === platform('other')
) {
const m = shortcut.match(/:([^:]*)$/);
keyboardShortcut = m ? m[1] : shortcut;
} else if (!['mac', '!mac', 'win', '!win', 'ios', '!ios', 'android',
'!android', 'chromeos', '!chromeos', 'other', '!other'].includes(plat)) {
} else if (
![
'mac',
'!mac',
'win',
'!win',
'ios',
'!ios',
'android',
'!android',
'chromeos',
'!chromeos',
'other',
'!other',
].includes(plat)
) {
const m = shortcut.match(/:([^:]*)$/);

@@ -1001,11 +1075,13 @@ keyboardShortcut = m ? m[1] : shortcut;

if (keyboardShortcut) {
const useSymbol = platform('mac') === 'mac' ||
platform('ios') === 'ios';
const modifiers = keyboardShortcut.length > 1 ?
keyboardShortcut.split('-') : [keyboardShortcut];
const useSymbol =
platform('mac') === 'mac' || platform('ios') === 'ios';
const modifiers =
keyboardShortcut.length > 1
? keyboardShortcut.split('-')
: [keyboardShortcut];
let shortcutString = '';
for (const modifier of modifiers) {
if (!useSymbol && shortcutString.length > 0) {
shortcutString += '<span class="ML__shortcut-join">+</span>';
shortcutString +=
'<span class="ML__shortcut-join">+</span>';
}

@@ -1017,45 +1093,46 @@ if (modifier.substr(0, 3) === 'Key') {

} else {
shortcutString += {
'Meta': useSymbol ? '\u2318' : 'command',
'Shift': useSymbol ? '\u21e7' : 'shift',
'Alt': useSymbol ? '\u2325' : 'alt',
'Ctrl': useSymbol ? '\u2303' : 'control',
'\n': useSymbol ? '\u23ce' : 'return',
'Return': useSymbol ? '\u23ce' : 'return',
'Enter': useSymbol ? '\u2324' : 'enter',
'Tab': useSymbol ? '\u21e5' : 'tab',
// 'Esc': useSymbol ? '\u238b' : 'esc',
'Esc': 'esc',
shortcutString +=
{
Meta: useSymbol ? '\u2318' : 'command',
Shift: useSymbol ? '\u21e7' : 'shift',
Alt: useSymbol ? '\u2325' : 'alt',
Ctrl: useSymbol ? '\u2303' : 'control',
'\n': useSymbol ? '\u23ce' : 'return',
Return: useSymbol ? '\u23ce' : 'return',
Enter: useSymbol ? '\u2324' : 'enter',
Tab: useSymbol ? '\u21e5' : 'tab',
// 'Esc': useSymbol ? '\u238b' : 'esc',
Esc: 'esc',
'Backspace': useSymbol ? '\u232b' : 'backspace',
'Del': useSymbol ? '\u2326' : 'del',
'PageUp': useSymbol ? '\u21de' : 'page up',
'PageDown': useSymbol ? '\u21df' : 'page down',
'Home': useSymbol ? '\u2912' : 'home',
'End': useSymbol ? '\u2913' : 'end',
'Spacebar': 'space',
'Semicolon': ';',
'Period': '.',
'Comma': ',',
'Minus': '-',
'Equal': '=',
'Quote': '\'',
'BracketLeft': '[',
'BracketRight': ']',
'Backslash': '\\',
'IntlBackslash': '\\',
'Backquote': '`',
'Slash': '/',
'NumpadMultiply': '* &#128290;',
'NumpadDivide': '/ &#128290;', // Numeric keypad
'NumpadSubtract': '- &#128290;',
'NumpadAdd': '+ &#128290;',
'NumpadDecimal': '. &#128290;',
'NumpadComma': ', &#128290;',
'Help': 'help',
'Left': '\u21E0',
'Up': '\u21E1',
'Right': '\u21E2',
'Down': '\u21E3',
}[modifier] || modifier;
Backspace: useSymbol ? '\u232b' : 'backspace',
Del: useSymbol ? '\u2326' : 'del',
PageUp: useSymbol ? '\u21de' : 'page up',
PageDown: useSymbol ? '\u21df' : 'page down',
Home: useSymbol ? '\u2912' : 'home',
End: useSymbol ? '\u2913' : 'end',
Spacebar: 'space',
Semicolon: ';',
Period: '.',
Comma: ',',
Minus: '-',
Equal: '=',
Quote: "'",
BracketLeft: '[',
BracketRight: ']',
Backslash: '\\',
IntlBackslash: '\\',
Backquote: '`',
Slash: '/',
NumpadMultiply: '* &#128290;',
NumpadDivide: '/ &#128290;', // Numeric keypad
NumpadSubtract: '- &#128290;',
NumpadAdd: '+ &#128290;',
NumpadDecimal: '. &#128290;',
NumpadComma: ', &#128290;',
Help: 'help',
Left: '\u21E0',
Up: '\u21E1',
Right: '\u21E2',
Down: '\u21E3',
}[modifier] || modifier;
}

@@ -1073,3 +1150,2 @@ }

result += shortcutString;
}

@@ -1087,6 +1163,3 @@ }

selectorForKeystroke,
forCommand
}
forCommand,
};

@@ -54,3 +54,6 @@ /**

if (this.canUndo()) {
if (options && typeof options.onUndoStateWillChange === 'function') {
if (
options &&
typeof options.onUndoStateWillChange === 'function'
) {
options.onUndoStateWillChange(this.mathlist.target, 'undo');

@@ -115,3 +118,3 @@ }

latex: this.mathlist.root.toLatex(),
selection: this.mathlist.toString()
selection: this.mathlist.toString(),
});

@@ -151,7 +154,7 @@

* @private
*/
*/
save() {
return {
latex: this.mathlist.root.toLatex(),
selection: this.mathlist.toString()
selection: this.mathlist.toString(),
};

@@ -166,9 +169,10 @@ }

* @private
*/
*/
restore(state, options) {
const wasSuppressing = this.mathlist.suppressChangeNotifications;
if (options.suppressChangeNotifications !== undefined) {
this.mathlist.suppressChangeNotifications = options.suppressChangeNotifications;
this.mathlist.suppressChangeNotifications =
options.suppressChangeNotifications;
}
// Restore the content

@@ -180,7 +184,9 @@ this.mathlist.insert(state ? state.latex : '', {

format: 'latex',
...options
...options,
});
// Restore the selection
this.mathlist.setPath(state ? state.selection : [{relation: 'body', offset: 0}]);
this.mathlist.setPath(
state ? state.selection : [{ relation: 'body', offset: 0 }]
);

@@ -192,6 +198,3 @@ this.mathlist.suppressChangeNotifications = wasSuppressing;

export default {
UndoManager
}
UndoManager,
};

@@ -1,6 +0,2 @@

export function l10n(s) {
const language = l10n.locale.substring(0, 2);

@@ -20,6 +16,4 @@

return result;
}
l10n.plural = function(value, s, options) {

@@ -30,6 +24,6 @@ options = options || {};

const rules = options.type === 'ordinal' ? l10n.ordinal : l10n.cardinal;
let rule = options.type === 'ordinal' ?
l10n._ordinalPluralCategories.indexOf(rules.select(value)) :
l10n._cardinalPluralCategories.indexOf(rules.select(value));
let rule =
options.type === 'ordinal'
? l10n._ordinalPluralCategories.indexOf(rules.select(value))
: l10n._cardinalPluralCategories.indexOf(rules.select(value));

@@ -43,12 +37,14 @@ let result;

if (options.type === 'ordinal') {
rule = l10n._ordinalPluralCategories.indexOf(l10n._ordinalEnglish.select(value));
rule = l10n._ordinalPluralCategories.indexOf(
l10n._ordinalEnglish.select(value)
);
} else {
rule = l10n._cardinalPluralCategories.indexOf(l10n._cardinalEnglish.select(value));
rule = l10n._cardinalPluralCategories.indexOf(
l10n._cardinalEnglish.select(value)
);
}
}
return result.split(';')[rule] || result.split(';')[0]
}
return result.split(';')[rule] || result.split(';')[0];
};
/*

@@ -65,5 +61,5 @@ * Two forms for this function:

const savedLocale = l10n._locale;
l10n.locale = locale; // Load the necessary json file
l10n.locale = locale; // Load the necessary json file
l10n.strings[locale] = {...l10n.strings[locale], ...strings };
l10n.strings[locale] = { ...l10n.strings[locale], ...strings };
l10n.locale = savedLocale;

@@ -74,5 +70,4 @@ } else if (locale && !strings) {

}
}
};
// Add getter and setter for the _locale property of l10n

@@ -90,7 +85,9 @@ Object.defineProperty(l10n, 'locale', {

// Use the setter, which will load the necessary .json files.
l10n._locale = typeof navigator === 'undefined' ? 'en' :
navigator.language.slice(0, 5);
l10n._locale =
typeof navigator === 'undefined'
? 'en'
: navigator.language.slice(0, 5);
}
return l10n._locale
}
return l10n._locale;
},
});

@@ -101,5 +98,9 @@

if (!l10n._ordinal) {
l10n._ordinalEnglish = new Intl.PluralRules('en', {type: 'ordinal'});
l10n._ordinalEnglish = new Intl.PluralRules('en', {
type: 'ordinal',
});
l10n._ordinalEnglishPluralCategories = l10n._ordinalEnglish.resolvedOptions().pluralCategories;
l10n._ordinal = new Intl.PluralRules(l10n.locale, {type: 'ordinal'});
l10n._ordinal = new Intl.PluralRules(l10n.locale, {
type: 'ordinal',
});
l10n._ordinalPluralCategories = l10n._ordinal.resolvedOptions().pluralCategories;

@@ -109,3 +110,3 @@ // "zero", "one", "two", "few", "many" and "other"

return l10n._ordinal;
}
},
});

@@ -116,139 +117,143 @@

if (!l10n._cardinal) {
l10n._cardinalEnglish = new Intl.PluralRules('en', {type: 'cardinal'});
l10n._cardinalEnglish = new Intl.PluralRules('en', {
type: 'cardinal',
});
l10n._cardinalEnglishPluralCategories = l10n._cardinalEnglish.resolvedOptions().pluralCategories;
l10n._cardinal = new Intl.PluralRules(l10n.locale, {type: 'cardinal'});
l10n._cardinal = new Intl.PluralRules(l10n.locale, {
type: 'cardinal',
});
l10n._cardinaPluralCategories = l10n._ordinal.resolvedOptions().pluralCategories;
}
return l10n._cardinal;
}
},
});
l10n.strings = {
"en": {
"keyboard.tooltip.functions": "Functions",
"keyboard.tooltip.greek": "Greek Letters",
"keyboard.tooltip.command": "LaTeX Command Mode",
"keyboard.tooltip.numeric": "Numeric",
"keyboard.tooltip.roman": "Symbols and Roman Letters",
"tooltip.copy to clipboard": "Copy to Clipboard",
"tooltip.redo": "Redo",
"tooltip.toggle virtual keyboard": "Toggle Virtual Keyboard",
"tooltip.undo": "Undo"
en: {
'keyboard.tooltip.functions': 'Functions',
'keyboard.tooltip.greek': 'Greek Letters',
'keyboard.tooltip.command': 'LaTeX Command Mode',
'keyboard.tooltip.numeric': 'Numeric',
'keyboard.tooltip.roman': 'Symbols and Roman Letters',
'tooltip.copy to clipboard': 'Copy to Clipboard',
'tooltip.redo': 'Redo',
'tooltip.toggle virtual keyboard': 'Toggle Virtual Keyboard',
'tooltip.undo': 'Undo',
},
"ar": {
"keyboard.tooltip.functions": "مهام",
"keyboard.tooltip.greek": "حروف يونانية",
"keyboard.tooltip.command": "حالة تلقي الأوامر اللاتك",
"keyboard.tooltip.numeric": "الرقمية",
"keyboard.tooltip.roman": "رموز الاحرف الرومانية",
"tooltip.copy to clipboard": "نسخ إلى الحافظة",
"tooltip.redo": "الإعادة",
"tooltip.toggle virtual keyboard": "تبديل لوحة المفاتيح الإفتراضية",
"tooltip.undo": "إلغاء"
ar: {
'keyboard.tooltip.functions': 'مهام',
'keyboard.tooltip.greek': 'حروف يونانية',
'keyboard.tooltip.command': 'حالة تلقي الأوامر اللاتك',
'keyboard.tooltip.numeric': 'الرقمية',
'keyboard.tooltip.roman': 'رموز الاحرف الرومانية',
'tooltip.copy to clipboard': 'نسخ إلى الحافظة',
'tooltip.redo': 'الإعادة',
'tooltip.toggle virtual keyboard': 'تبديل لوحة المفاتيح الإفتراضية',
'tooltip.undo': 'إلغاء',
},
"de": {
"keyboard.tooltip.functions": "Funktionen",
"keyboard.tooltip.greek": "Griechische Buchstaben",
"keyboard.tooltip.command": "LaTeX-Befehlsmodus",
"keyboard.tooltip.numeric": "Numerisch",
"keyboard.tooltip.roman": "Symbole und römische Buchstaben",
"tooltip.copy to clipboard": "In die Zwischenablage kopieren",
"tooltip.redo": "Wiederholen",
"tooltip.toggle virtual keyboard": "Virtuelle Tastatur umschalten",
"tooltip.undo": "Widerrufen"
de: {
'keyboard.tooltip.functions': 'Funktionen',
'keyboard.tooltip.greek': 'Griechische Buchstaben',
'keyboard.tooltip.command': 'LaTeX-Befehlsmodus',
'keyboard.tooltip.numeric': 'Numerisch',
'keyboard.tooltip.roman': 'Symbole und römische Buchstaben',
'tooltip.copy to clipboard': 'In die Zwischenablage kopieren',
'tooltip.redo': 'Wiederholen',
'tooltip.toggle virtual keyboard': 'Virtuelle Tastatur umschalten',
'tooltip.undo': 'Widerrufen',
},
"el": {
"keyboard.tooltip.functions": "συναρτήσεις",
"keyboard.tooltip.greek": "ελληνικά γράμματα",
"keyboard.tooltip.command": "Λειτουργία εντολών LaTeX",
"keyboard.tooltip.numeric": "Αριθμητικός",
"keyboard.tooltip.roman": "Σύμβολα και ρωμαϊκά γράμματα",
"tooltip.copy to clipboard": "Αντιγραφή στο πρόχειρο",
"tooltip.redo": "Ξανακάνω",
"tooltip.toggle virtual keyboard": "Εναλλαγή εικονικού πληκτρολογίου",
"tooltip.undo": "Ξεκάνω"
el: {
'keyboard.tooltip.functions': 'συναρτήσεις',
'keyboard.tooltip.greek': 'ελληνικά γράμματα',
'keyboard.tooltip.command': 'Λειτουργία εντολών LaTeX',
'keyboard.tooltip.numeric': 'Αριθμητικός',
'keyboard.tooltip.roman': 'Σύμβολα και ρωμαϊκά γράμματα',
'tooltip.copy to clipboard': 'Αντιγραφή στο πρόχειρο',
'tooltip.redo': 'Ξανακάνω',
'tooltip.toggle virtual keyboard': 'Εναλλαγή εικονικού πληκτρολογίου',
'tooltip.undo': 'Ξεκάνω',
},
"es": {
"keyboard.tooltip.functions": "Funciones",
"keyboard.tooltip.greek": "Letras griegas",
"keyboard.tooltip.command": "Modo Comando LaTeX",
"keyboard.tooltip.numeric": "Numérico",
"keyboard.tooltip.roman": "Símbolos y letras romanas",
"tooltip.copy to clipboard": "Copiar al portapapeles",
"tooltip.redo": "Rehacer",
"tooltip.toggle virtual keyboard": "Alternar teclado virtual",
"tooltip.undo": "Deshacer"
es: {
'keyboard.tooltip.functions': 'Funciones',
'keyboard.tooltip.greek': 'Letras griegas',
'keyboard.tooltip.command': 'Modo Comando LaTeX',
'keyboard.tooltip.numeric': 'Numérico',
'keyboard.tooltip.roman': 'Símbolos y letras romanas',
'tooltip.copy to clipboard': 'Copiar al portapapeles',
'tooltip.redo': 'Rehacer',
'tooltip.toggle virtual keyboard': 'Alternar teclado virtual',
'tooltip.undo': 'Deshacer',
},
"fa": {
"keyboard.tooltip.functions": "توابع",
"keyboard.tooltip.greek": "حروف یونانی",
"keyboard.tooltip.command": "حالت دستور لاتک",
"keyboard.tooltip.numeric": "عددی",
"keyboard.tooltip.roman": "علائم و حروف لاتین",
"tooltip.copy to clipboard": "کپی به کلیپبورد",
"tooltip.redo": "بازگشت به بعد",
"tooltip.toggle virtual keyboard": "نمایش/نهفتن کیبورد مجازی",
"tooltip.undo": "بازگشت به قبل"
fa: {
'keyboard.tooltip.functions': 'توابع',
'keyboard.tooltip.greek': 'حروف یونانی',
'keyboard.tooltip.command': 'حالت دستور لاتک',
'keyboard.tooltip.numeric': 'عددی',
'keyboard.tooltip.roman': 'علائم و حروف لاتین',
'tooltip.copy to clipboard': 'کپی به کلیپبورد',
'tooltip.redo': 'بازگشت به بعد',
'tooltip.toggle virtual keyboard': 'نمایش/نهفتن کیبورد مجازی',
'tooltip.undo': 'بازگشت به قبل',
},
"fr": {
"keyboard.tooltip.functions": "Fonctions",
"keyboard.tooltip.greek": "Lettres grecques",
"keyboard.tooltip.command": "Mode de commandes LaTeX",
"keyboard.tooltip.numeric": "Numérique",
"keyboard.tooltip.roman": "Lettres et symboles romains",
"tooltip.copy to clipboard": "Copier dans le presse-papiers",
"tooltip.redo": "Rétablir",
"tooltip.toggle virtual keyboard": "Afficher/Masquer le clavier virtuel",
"tooltip.undo": "Annuler"
fr: {
'keyboard.tooltip.functions': 'Fonctions',
'keyboard.tooltip.greek': 'Lettres grecques',
'keyboard.tooltip.command': 'Mode de commandes LaTeX',
'keyboard.tooltip.numeric': 'Numérique',
'keyboard.tooltip.roman': 'Lettres et symboles romains',
'tooltip.copy to clipboard': 'Copier dans le presse-papiers',
'tooltip.redo': 'Rétablir',
'tooltip.toggle virtual keyboard':
'Afficher/Masquer le clavier virtuel',
'tooltip.undo': 'Annuler',
},
"it": {
"keyboard.tooltip.functions": "Funzioni",
"keyboard.tooltip.greek": "Lettere greche",
"keyboard.tooltip.command": "Modalità di comando LaTeX",
"keyboard.tooltip.numeric": "Numerico",
"keyboard.tooltip.roman": "Simboli e lettere romane",
"tooltip.copy to clipboard": "Copia negli appunti",
"tooltip.redo": "Rifare",
"tooltip.toggle virtual keyboard": "Attiva / disattiva la tastiera virtuale",
"tooltip.undo": "Disfare"
it: {
'keyboard.tooltip.functions': 'Funzioni',
'keyboard.tooltip.greek': 'Lettere greche',
'keyboard.tooltip.command': 'Modalità di comando LaTeX',
'keyboard.tooltip.numeric': 'Numerico',
'keyboard.tooltip.roman': 'Simboli e lettere romane',
'tooltip.copy to clipboard': 'Copia negli appunti',
'tooltip.redo': 'Rifare',
'tooltip.toggle virtual keyboard':
'Attiva / disattiva la tastiera virtuale',
'tooltip.undo': 'Disfare',
},
"ja": {
"keyboard.tooltip.functions": "関数",
"keyboard.tooltip.greek": "ギリシャ文字",
"keyboard.tooltip.command": "LaTeXコマンドモード",
"keyboard.tooltip.numeric": "数値",
"keyboard.tooltip.roman": "記号とローマ字",
"tooltip.copy to clipboard": "クリップボードにコピー",
"tooltip.redo": "やり直し",
"tooltip.toggle virtual keyboard": "仮想キーボードの切り替え",
"tooltip.undo": "元に戻す"
ja: {
'keyboard.tooltip.functions': '関数',
'keyboard.tooltip.greek': 'ギリシャ文字',
'keyboard.tooltip.command': 'LaTeXコマンドモード',
'keyboard.tooltip.numeric': '数値',
'keyboard.tooltip.roman': '記号とローマ字',
'tooltip.copy to clipboard': 'クリップボードにコピー',
'tooltip.redo': 'やり直し',
'tooltip.toggle virtual keyboard': '仮想キーボードの切り替え',
'tooltip.undo': '元に戻す',
},
"pl": {
"keyboard.tooltip.functions": "Funkcje",
"keyboard.tooltip.greek": "Litery greckie",
"keyboard.tooltip.command": "Tryb poleceń LaTeX",
"keyboard.tooltip.numeric": "Numeryczne",
"keyboard.tooltip.roman": "Symbole i litery rzymskie",
"tooltip.copy to clipboard": "Kopiuj do Schowka",
"tooltip.redo": "Przywróć",
"tooltip.toggle virtual keyboard": "Przełącz wirtualną klawiaturę",
"tooltip.undo": "Cofnij"
pl: {
'keyboard.tooltip.functions': 'Funkcje',
'keyboard.tooltip.greek': 'Litery greckie',
'keyboard.tooltip.command': 'Tryb poleceń LaTeX',
'keyboard.tooltip.numeric': 'Numeryczne',
'keyboard.tooltip.roman': 'Symbole i litery rzymskie',
'tooltip.copy to clipboard': 'Kopiuj do Schowka',
'tooltip.redo': 'Przywróć',
'tooltip.toggle virtual keyboard': 'Przełącz wirtualną klawiaturę',
'tooltip.undo': 'Cofnij',
},
"ru": {
"keyboard.tooltip.functions": "Функции",
"keyboard.tooltip.greek": "Греческие буквы",
"keyboard.tooltip.command": "Режим командной строки LaTeX",
"keyboard.tooltip.numeric": "числовой",
"keyboard.tooltip.roman": "Символы и римские буквы",
"tooltip.copy to clipboard": "Скопировать в буфер обмена",
"tooltip.redo": "переделывать",
"tooltip.toggle virtual keyboard": "Переключить виртуальную клавиатуру",
"tooltip.undo": "расстегивать"
}
ru: {
'keyboard.tooltip.functions': 'Функции',
'keyboard.tooltip.greek': 'Греческие буквы',
'keyboard.tooltip.command': 'Режим командной строки LaTeX',
'keyboard.tooltip.numeric': 'числовой',
'keyboard.tooltip.roman': 'Символы и римские буквы',
'tooltip.copy to clipboard': 'Скопировать в буфер обмена',
'tooltip.redo': 'переделывать',
'tooltip.toggle virtual keyboard': 'Переключить виртуальную клавиатуру',
'tooltip.undo': 'расстегивать',
},
};
export default {
l10n
}
l10n,
};
const SPECIAL_IDENTIFIERS = {
'\u2212': '-', // MINUS SIGN
'-': '-',
'\\alpha': 'alpha',
'\\beta': 'beta',
'\\gamma': 'gamma',
'\\delta': 'delta',
'\\epsilon': 'epsilon',
'\u2212': '-', // MINUS SIGN
'-': '-',
'\\alpha': 'alpha',
'\\beta': 'beta',
'\\gamma': 'gamma',
'\\delta': 'delta',
'\\epsilon': 'epsilon',
'\\varepsilon': 'varepsilon',
'\\zeta': 'zeta',
'\\eta': 'eta',
'\\theta': 'theta',
'\\vartheta': 'vartheta',
'\\iota': 'iota',
'\\kappa': 'kappa',
'\\lambda': 'lambda',
'\\mu': 'mu',
'\\nu': 'nu',
'\\xi': 'xi',
'\\pi': 'pi',
'\\rho': 'rho',
'\\sigma': 'sigma',
'\\tau': 'tau',
'\\upsilon': 'upsilon',
'\\phi': 'phi',
'\\varphi': 'varphi',
'\\chi': 'chi',
'\\psi': 'psi',
'\\omega': 'omega',
'\\Gamma': 'Gamma',
'\\Delta': 'Delta',
'\\Theta': 'Theta',
'\\Lambda': 'Lambda',
'\\Xi': 'Xi',
'\\Pi': 'Pi',
'\\Sigma': 'Sigma',
'\\Phi': 'Phi',
'\\Psi': 'Psi',
'\\Omega': 'Omega',
'\\zeta': 'zeta',
'\\eta': 'eta',
'\\theta': 'theta',
'\\vartheta': 'vartheta',
'\\iota': 'iota',
'\\kappa': 'kappa',
'\\lambda': 'lambda',
'\\mu': 'mu',
'\\nu': 'nu',
'\\xi': 'xi',
'\\pi': 'pi',
'\\rho': 'rho',
'\\sigma': 'sigma',
'\\tau': 'tau',
'\\upsilon': 'upsilon',
'\\phi': 'phi',
'\\varphi': 'varphi',
'\\chi': 'chi',
'\\psi': 'psi',
'\\omega': 'omega',
'\\Gamma': 'Gamma',
'\\Delta': 'Delta',
'\\Theta': 'Theta',
'\\Lambda': 'Lambda',
'\\Xi': 'Xi',
'\\Pi': 'Pi',
'\\Sigma': 'Sigma',
'\\Phi': 'Phi',
'\\Psi': 'Psi',
'\\Omega': 'Omega',
};

@@ -70,3 +70,3 @@

export function toASCIIMath(atom, options){
export function toASCIIMath(atom, options) {
if (!atom) return '';

@@ -97,2 +97,6 @@ if (Array.isArray(atom)) {

if (atom.mode === 'text') {
return '"' + atom.body + '"'; // text -- add in (ASCII) quotes
}
let result = '';

@@ -102,3 +106,3 @@ const command = atom.latex ? atom.latex.trim() : null;

switch(atom.type) {
switch (atom.type) {
case 'group':

@@ -114,3 +118,6 @@ case 'root':

if (atom.leftDelim || atom.rightDelim) {
result += (atom.leftDelim === '.' || !atom.leftDelim) ? '{:' : atom.leftDelim;
result +=
atom.leftDelim === '.' || !atom.leftDelim
? '{:'
: atom.leftDelim;
}

@@ -129,10 +136,17 @@ if (atom.hasBarLine) {

if (atom.leftDelim || atom.rightDelim) {
result += (atom.rightDelim === '.' || !atom.rightDelim) ? '{:' : atom.rightDelim;
result +=
atom.rightDelim === '.' || !atom.rightDelim
? '{:'
: atom.rightDelim;
}
break;
break;
case 'surd':
if (atom.index) {
result += 'root(' + toASCIIMath(atom.index, options) + ')(' +
toASCIIMath(atom.body, options) + ')';
result +=
'root(' +
toASCIIMath(atom.index, options) +
')(' +
toASCIIMath(atom.body, options) +
')';
} else {

@@ -144,5 +158,11 @@ result += 'sqrt(' + toASCIIMath(atom.body, options) + ')';

case 'leftright':
result += (atom.leftDelim === '.' || !atom.leftDelim) ? '{:' : atom.leftDelim;
result +=
atom.leftDelim === '.' || !atom.leftDelim
? '{:'
: atom.leftDelim;
result += toASCIIMath(atom.body, options);
result += (atom.rightDelim === '.' || !atom.rightDelim) ? '{:' : atom.rightDelim;
result +=
atom.rightDelim === '.' || !atom.rightDelim
? '{:'
: atom.rightDelim;
break;

@@ -155,3 +175,2 @@

case 'accent':

@@ -165,3 +184,2 @@ break;

case 'overunder':
break;

@@ -171,9 +189,13 @@

// @todo, deal with some special identifiers: \alpha, etc...
result = SPECIAL_IDENTIFIERS[command] || command ||
result =
SPECIAL_IDENTIFIERS[command] ||
command ||
(typeof atom.body === 'string' ? atom.body : '');
if (result[0] === '\\') result += '';
m = command ? command.match(/[{]?\\char"([0-9abcdefABCDEF]*)[}]?/) : null;
m = command
? command.match(/[{]?\\char"([0-9abcdefABCDEF]*)[}]?/)
: null;
if (m) {
// It's a \char command
result = String.fromCharCode(parseInt('0x' + m[1]))
result = String.fromCharCode(parseInt('0x' + m[1]));
} else if (result.length > 0 && result.charAt(0) === '\\') {

@@ -219,3 +241,3 @@ // atom is an identifier with no special handling. Use the

if (command === '\\operatorname') {
result += atom.body;
result += toASCIIMath(atom.body, options);
} else {

@@ -241,5 +263,4 @@ result += atom.body || command;

case 'space':
result = ' '
result = ' ';
break;
}

@@ -251,3 +272,3 @@ // Subscripts before superscripts (according to the ASCIIMath spec)

if (arg.length > 1 && !/^(-)?\d+(\.\d*)?$/.test(arg)) {
result += '(' + arg + ')'
result += '(' + arg + ')';
} else {

@@ -262,3 +283,3 @@ result += arg;

if (arg.length > 1 && !/^(-)?\d+(\.\d*)?$/.test(arg)) {
result += '(' + arg + ')'
result += '(' + arg + ')';
} else {

@@ -273,3 +294,3 @@ result += arg;

export default {
toASCIIMath
}
toASCIIMath,
};

@@ -1,2 +0,1 @@

/**

@@ -57,4 +56,7 @@ *

console.assert(/displaystyle|textstyle|scriptstyle|scriptscriptstyle/.test(mathstyle),
"Invalid style:", mathstyle);
console.assert(
/displaystyle|textstyle|scriptstyle|scriptscriptstyle/.test(mathstyle),
'Invalid style:',
mathstyle
);

@@ -76,4 +78,2 @@ //

//

@@ -83,5 +83,4 @@ // 3. Transform the math atoms into elementary spans

//
let spans = MathAtom.decompose({mathstyle: mathstyle}, mathlist);
let spans = MathAtom.decompose({ mathstyle: mathstyle }, mathlist);
//

@@ -101,3 +100,3 @@ // 4. Simplify by coalescing adjacent nodes

const topStrut = Span.makeSpan('', 'ML__strut')
const topStrut = Span.makeSpan('', 'ML__strut');
topStrut.setStyle('height', base.height, 'em');

@@ -114,3 +113,2 @@ const struts = [topStrut];

//

@@ -123,4 +121,2 @@ // 6. Generate markup

/**

@@ -185,4 +181,8 @@ * Convert a DOM element into an editable mathfield.

const mathlist = ParserModule.parseTokens(Lexer.tokenize(latex),
'math', null, options.macros);
const mathlist = ParserModule.parseTokens(
Lexer.tokenize(latex),
'math',
null,
options.macros
);

@@ -215,4 +215,8 @@ return MathAtom.toMathML(mathlist, options);

const mathlist = ParserModule.parseTokens(Lexer.tokenize(latex),
'math', null, options.macros);
const mathlist = ParserModule.parseTokens(
Lexer.tokenize(latex),
'math',
null,
options.macros
);

@@ -222,3 +226,2 @@ return MathAtom.toAST(mathlist, options);

/**

@@ -247,3 +250,3 @@ * Converts an Abstract Syntax Tree (MathJSON) to a LaTeX string.

* used at the end of repeating digits. **Default** = `"}"`
*
*
* @return {string} The LaTeX representation of the Abstract Syntax Tree, if valid.

@@ -257,3 +260,2 @@ * @category Converting

/**

@@ -300,3 +302,3 @@ * Converts a LaTeX string to a textual representation ready to be spoken

console.warn('The outputSpokenText module is not loaded.');
return "";
return '';
}

@@ -307,4 +309,8 @@ options = options || {};

const mathlist = ParserModule.parseTokens(Lexer.tokenize(latex),
'math', null, options.macros);
const mathlist = ParserModule.parseTokens(
Lexer.tokenize(latex),
'math',
null,
options.macros
);

@@ -314,3 +320,2 @@ return MathAtom.toSpeakableText(mathlist, options);

function removeHighlight(node) {

@@ -369,5 +374,7 @@ node.classList.remove('highlight');

if (!window || !window.AWS) {
console.warn('AWS SDK not loaded. See https://www.npmjs.com/package/aws-sdk');
console.warn(
'AWS SDK not loaded. See https://www.npmjs.com/package/aws-sdk'
);
} else {
const polly = new window.AWS.Polly({apiVersion: '2016-06-10'});
const polly = new window.AWS.Polly({ apiVersion: '2016-06-10' });
const params = {

@@ -383,7 +390,13 @@ OutputFormat: 'mp3',

if (err) {
console.warn('polly.synthesizeSpeech() error:', err, err.stack);
console.warn(
'polly.synthesizeSpeech() error:',
err,
err.stack
);
} else {
if (data && data.AudioStream) {
const uInt8Array = new Uint8Array(data.AudioStream);
const blob = new Blob([uInt8Array.buffer], {type: 'audio/mpeg'});
const blob = new Blob([uInt8Array.buffer], {
type: 'audio/mpeg',
});
const url = URL.createObjectURL(blob);

@@ -402,3 +415,5 @@

} else if (config.speechEngine === 'google') {
console.warn('The Google speech engine is not supported yet. Please come again.');
console.warn(
'The Google speech engine is not supported yet. Please come again.'
);
// @todo: implement support for Google Text-to-Speech API,

@@ -408,19 +423,19 @@ // using config.speechEngineToken, config.speechEngineVoice and

// curl -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
// -H "Content-Type: application/json; charset=utf-8" \
// --data "{
// 'input':{
// 'text':'Android is a mobile operating system developed by Google,
// based on the Linux kernel and designed primarily for
// touchscreen mobile devices such as smartphones and tablets.'
// },
// 'voice':{
// 'languageCode':'en-gb',
// 'name':'en-GB-Standard-A',
// 'ssmlGender':'FEMALE'
// },
// 'audioConfig':{
// 'audioEncoding':'MP3'
// }
// }" "https://texttospeech.googleapis.com/v1beta1/text:synthesize" > synthesize-text.txt
// curl -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
// -H "Content-Type: application/json; charset=utf-8" \
// --data "{
// 'input':{
// 'text':'Android is a mobile operating system developed by Google,
// based on the Linux kernel and designed primarily for
// touchscreen mobile devices such as smartphones and tablets.'
// },
// 'voice':{
// 'languageCode':'en-gb',
// 'name':'en-GB-Standard-A',
// 'ssmlGender':'FEMALE'
// },
// 'audioConfig':{
// 'audioEncoding':'MP3'
// }
// }" "https://texttospeech.googleapis.com/v1beta1/text:synthesize" > synthesize-text.txt
}

@@ -454,6 +469,8 @@ }

if (!window.AWS) {
console.warn('AWS SDK not loaded. See https://www.npmjs.com/package/aws-sdk');
console.warn(
'AWS SDK not loaded. See https://www.npmjs.com/package/aws-sdk'
);
return;
}
const polly = new window.AWS.Polly({apiVersion: '2016-06-10'});
const polly = new window.AWS.Polly({ apiVersion: '2016-06-10' });

@@ -465,3 +482,3 @@ const params = {

TextType: 'ssml',
SpeechMarkTypes: ['ssml']
SpeechMarkTypes: ['ssml'],
};

@@ -472,3 +489,4 @@

const status = config.onReadAloudStatus || window.mathlive.onReadAloudStatus;
const status =
config.onReadAloudStatus || window.mathlive.onReadAloudStatus;

@@ -481,4 +499,8 @@ // Request the mark points

if (data && data.AudioStream) {
const response = new TextDecoder('utf-8').decode(new Uint8Array(data.AudioStream));
window.mathlive.readAloudMarks = response.split('\n').map(x => x ? JSON.parse(x) : {});
const response = new TextDecoder('utf-8').decode(
new Uint8Array(data.AudioStream)
);
window.mathlive.readAloudMarks = response
.split('\n')
.map(x => (x ? JSON.parse(x) : {}));
window.mathlive.readAloudTokens = [];

@@ -497,7 +519,15 @@ for (const mark of window.mathlive.readAloudMarks) {

if (err) {
console.warn('polly.synthesizeSpeech(', text , ') error:', err, err.stack);
console.warn(
'polly.synthesizeSpeech(',
text,
') error:',
err,
err.stack
);
} else {
if (data && data.AudioStream) {
const uInt8Array = new Uint8Array(data.AudioStream);
const blob = new Blob([uInt8Array.buffer], {type: 'audio/mpeg'});
const blob = new Blob([uInt8Array.buffer], {
type: 'audio/mpeg',
});
const url = URL.createObjectURL(blob);

@@ -507,38 +537,72 @@

window.mathlive.readAloudAudio = new Audio();
window.mathlive.readAloudAudio.addEventListener('ended', () => {
if (status) status(window.mathlive.readAloudMathField, 'ended');
if (window.mathlive.readAloudMathField) {
window.mathlive.readAloudMathField._render();
window.mathlive.readAloudElement = null;
window.mathlive.readAloudMathField = null;
window.mathlive.readAloudTokens = [];
window.mathlive.readAloudMarks = [];
window.mathlive.readAloudCurrentMark = '';
} else {
removeHighlight(window.mathlive.readAloudElement);
window.mathlive.readAloudAudio.addEventListener(
'ended',
() => {
if (status)
status(
window.mathlive
.readAloudMathField,
'ended'
);
if (
window.mathlive.readAloudMathField
) {
window.mathlive.readAloudMathField._render();
window.mathlive.readAloudElement = null;
window.mathlive.readAloudMathField = null;
window.mathlive.readAloudTokens = [];
window.mathlive.readAloudMarks = [];
window.mathlive.readAloudCurrentMark =
'';
} else {
removeHighlight(
window.mathlive.readAloudElement
);
}
}
});
window.mathlive.readAloudAudio.addEventListener('timeupdate', () => {
let value = '';
// The target, the atom we're looking for, is the one matching the current audio
// plus 100 ms. By anticipating it a little bit, it feels more natural, otherwise it
// feels like the highlighting is trailing the audio.
const target = window.mathlive.readAloudAudio.currentTime * 1000 + 100;
);
window.mathlive.readAloudAudio.addEventListener(
'timeupdate',
() => {
let value = '';
// The target, the atom we're looking for, is the one matching the current audio
// plus 100 ms. By anticipating it a little bit, it feels more natural, otherwise it
// feels like the highlighting is trailing the audio.
const target =
window.mathlive.readAloudAudio
.currentTime *
1000 +
100;
// Find the smallest element which is bigger than the target time
for (const mark of window.mathlive.readAloudMarks) {
if (mark.time < target) {
value = mark.value;
// Find the smallest element which is bigger than the target time
for (const mark of window.mathlive
.readAloudMarks) {
if (mark.time < target) {
value = mark.value;
}
}
}
if (window.mathlive.readAloudCurrentMark !== value) {
window.mathlive.readAloudCurrentToken = value;
if (value && value === window.mathlive.readAloudFinalToken) {
window.mathlive.readAloudAudio.pause();
} else {
window.mathlive.readAloudCurrentMark = value;
highlightAtomID(window.mathlive.readAloudElement, window.mathlive.readAloudCurrentMark);
if (
window.mathlive
.readAloudCurrentMark !== value
) {
window.mathlive.readAloudCurrentToken = value;
if (
value &&
value ===
window.mathlive
.readAloudFinalToken
) {
window.mathlive.readAloudAudio.pause();
} else {
window.mathlive.readAloudCurrentMark = value;
highlightAtomID(
window.mathlive
.readAloudElement,
window.mathlive
.readAloudCurrentMark
);
}
}
}
});
);
} else {

@@ -550,3 +614,6 @@ window.mathlive.readAloudAudio.pause();

if (status) {
status(window.mathlive.readAloudMathField, 'playing');
status(
window.mathlive.readAloudMathField,
'playing'
);
}

@@ -604,3 +671,6 @@ window.mathlive.readAloudAudio.play();

if (window.mathlive.onReadAloudStatus) {
window.mathlive.onReadAloudStatus(window.mathlive.readAloudMathField, 'paused');
window.mathlive.onReadAloudStatus(
window.mathlive.readAloudMathField,
'paused'
);
}

@@ -623,3 +693,6 @@ window.mathlive.readAloudAudio.pause();

if (window.mathlive.onReadAloudStatus) {
window.mathlive.onReadAloudStatus(window.mathlive.readAloudMathField, 'playing');
window.mathlive.onReadAloudStatus(
window.mathlive.readAloudMathField,
'playing'
);
}

@@ -647,3 +720,4 @@ window.mathlive.readAloudAudio.play();

if (token) {
window.mathlive.readAloudMarks = window.mathlive.readAloudMarks || [];
window.mathlive.readAloudMarks =
window.mathlive.readAloudMarks || [];
for (const mark of window.mathlive.readAloudMarks) {

@@ -664,3 +738,6 @@ if (mark.value === token) {

if (window.mathlive.onReadAloudStatus) {
window.mathlive.onReadAloudStatus(window.mathlive.readAloudMathField, 'playing');
window.mathlive.onReadAloudStatus(
window.mathlive.readAloudMathField,
'playing'
);
}

@@ -671,3 +748,2 @@ window.mathlive.readAloudAudio.play();

/**

@@ -794,3 +870,4 @@ * Transform all the elements in the document body that contain LaTeX code

options.renderToMathML = options.renderToMathML || toMathML;
options.renderToSpeakableText = options.renderToSpeakableText || latexToSpeakableText;
options.renderToSpeakableText =
options.renderToSpeakableText || latexToSpeakableText;
options.macros = options.macros || Definitions.MACROS;

@@ -800,11 +877,11 @@ AutoRender.renderMathInElement(getElement(element), options);

function validateNamespace(options) {
if (options.namespace) {
if (!/^[a-z]+[-]?$/.test(options.namespace)) {
throw Error('options.namespace must be a string of lowercase characters only');
throw Error(
'options.namespace must be a string of lowercase characters only'
);
}
if (!/-$/.test(options.namespace)) {
options.namespace += '-';
options.namespace += '-';
}

@@ -834,9 +911,8 @@ }

validateNamespace(options);
element.innerHTML = element.getAttribute('data-' +
(options.namespace || '') + 'original-content');
element.innerHTML = element.getAttribute(
'data-' + (options.namespace || '') + 'original-content'
);
}
}
/**

@@ -881,4 +957,5 @@ * After calling {@linkcode module:mathlive#renderMathInElement renderMathInElement}

validateNamespace(options);
return element.getAttribute('data-' +
(options.namespace || '') + 'original-content');
return element.getAttribute(
'data-' + (options.namespace || '') + 'original-content'
);
}

@@ -901,8 +978,5 @@

resumeReadAloud,
playReadAloud
playReadAloud,
};
export default MathLive;
export default {
name: 'mathlive-mathfield',
template: '<div class="mathfield" :id="id"><slot></slot></div>',
props:
{
props: {
id: {
type: String,
default: ''
default: '',
},
value: {
type: String,
default: ''
default: '',
},
config: {
type: Object,
default: () => ({})
default: () => ({}),
},
onKeystroke: {
type: Function,
default: function(_keystroke, _ev) { return true; }
default: function(_keystroke, _ev) {
return true;
},
},
onMoveOutOf: {
type: Function,
default: function(_direction) { return true; }
default: function(_direction) {
return true;
},
},
onTabOutOf: {
type: Function,
default: function(_direction) { return true; }
}
default: function(_direction) {
return true;
},
},
},

@@ -63,3 +68,3 @@ /*

this.$el.mathfield.$text(newValue, {
suppressChangeNotifications: true
suppressChangeNotifications: true,
});

@@ -71,11 +76,11 @@ }

handler: function(config) {
this.$el.mathfield.$setConfig(config)
}
this.$el.mathfield.$setConfig(config);
},
},
},
mounted: function () {
mounted: function() {
// A new instance is being created
const vm = this; // Keep a reference to the ViewModel
const vm = this; // Keep a reference to the ViewModel
// Wait until the DOM has been constructed...
this.$nextTick(function () {
this.$nextTick(function() {
// ... then make the MathField

@@ -93,17 +98,42 @@ vm.$mathlive.makeMathField(vm.$el, {

// Those asynchronous notification handlers are translated to events
onFocus: _ => { vm.$emit('focus'); },
onBlur: _ => { vm.$emit('blur'); },
onContentWillChange: _ => { vm.$emit('content-will-change'); },
onSelectionWillChange: _ => { vm.$emit('selection-will-change'); },
onUndoStateWillChange: (_, command) => { vm.$emit('undo-state-will-change', command); },
onUndoStateDidChange: (_, command) => { vm.$emit('undo-state-did-change', command); },
onVirtualKeyboardToggle: (_, visible, keyboardElement) => { vm.$emit('virtual-keyboard-toggle', visible, keyboardElement); },
onReadAloudStatus: (_, status) => { vm.$emit('read-aloud-status', status); },
onFocus: _ => {
vm.$emit('focus');
},
onBlur: _ => {
vm.$emit('blur');
},
onContentWillChange: _ => {
vm.$emit('content-will-change');
},
onSelectionWillChange: _ => {
vm.$emit('selection-will-change');
},
onUndoStateWillChange: (_, command) => {
vm.$emit('undo-state-will-change', command);
},
onUndoStateDidChange: (_, command) => {
vm.$emit('undo-state-did-change', command);
},
onVirtualKeyboardToggle: (_, visible, keyboardElement) => {
vm.$emit(
'virtual-keyboard-toggle',
visible,
keyboardElement
);
},
onReadAloudStatus: (_, status) => {
vm.$emit('read-aloud-status', status);
},
// Those notification handlers expect an answer back, so translate
// them to callbacks via props
onKeystroke: function(_, keystroke, ev) { return vm.onKeystroke(keystroke, ev); },
onMoveOutOf: (_, direction) => { return vm.onMoveOutOf(direction); },
onTabOutOf: (_, direction) => { return vm.onTabOutOf(direction); },
onKeystroke: function(_, keystroke, ev) {
return vm.onKeystroke(keystroke, ev);
},
onMoveOutOf: (_, direction) => {
return vm.onMoveOutOf(direction);
},
onTabOutOf: (_, direction) => {
return vm.onTabOutOf(direction);
},
});

@@ -164,4 +194,4 @@ });

this.$el.mathfield.$clearSelection();
}
}
};
},
},
};
{
"name": "mathlive",
"version": "0.33.2",
"version": "0.34.0",
"description": "Render and edit beautifully typeset math",

@@ -42,6 +42,5 @@ "license": "MIT",

"watch": "npm-run-all -p watch-*",
"http-server": "http-server . -c-1 --cors='*' -o http://localhost:8080/examples/index.html",
"http-server": "http-server . -c-1 --cors='*' -o examples/index.html",
"start": "npm-run-all -p watch-js watch-css http-server",
"lint": "eslint src/ -c .eslintrc.json",
"lint:fix": "eslint src/ -c .eslintrc.json --fix",
"lint": "prettier --ignore-path ./.prettierignore --write \"**/*.{ts,js,css,md,yml,json}\" \"!dist/**\" \"!docs/**\" \"!examples/**\"",
"test": "tape -r @babel/register test/* | tap-spec",

@@ -58,2 +57,3 @@ "watch-test": "chokidar \"src/*.js\" -c \"npm run test -s\" ",

},
"prettier": "@cortex-js/prettier-config",
"husky": {

@@ -68,2 +68,6 @@ "hooks": {

"git add"
],
"*.{js,css,json,md}": [
"prettier --write",
"git add"
]

@@ -101,26 +105,30 @@ },

"devDependencies": {
"@babel/cli": "^7.7.5",
"@babel/core": "^7.7.5",
"@babel/preset-env": "^7.7.6",
"@babel/register": "^7.7.4",
"autoprefixer": "^9.7.3",
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"@babel/register": "^7.8.3",
"@cortex-js/prettier-config": "^1.0.0",
"autoprefixer": "^9.7.4",
"chokidar-cli": "^2.1.0",
"cssnano": "^4.1.10",
"eslint": "^6.7.2",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-prettier": "^3.1.2",
"eslint-watch": "^6.0.1",
"http-server": "^0.12.0",
"husky": "^3.1.0",
"http-server": "^0.12.1",
"husky": "^4.2.1",
"jsdoc": "^3.6.3",
"less": "^3.10.3",
"lint-staged": "^9.5.0",
"lint-staged": "^10.0.7",
"npm-run-all": "^4.1.5",
"nyc": "^14.1.1",
"postcss-cli": "^6.1.3",
"rimraf": "^3.0.0",
"rollup": "^1.27.12",
"rollup-plugin-copy": "^3.1.0",
"rollup-plugin-terser": "^5.1.3",
"nyc": "^15.0.0",
"postcss-cli": "^7.1.0",
"prettier": "^1.19.1",
"rimraf": "^3.0.1",
"rollup": "^1.31.0",
"rollup-plugin-copy": "^3.3.0",
"rollup-plugin-terser": "^5.2.0",
"sutro-jsdoc-theme": "^1.0",
"tap-spec": "^5.0.0",
"tape": "^4.11.0",
"tape": "^4.13.0",
"tsd-jsdoc": "^2.4.0"

@@ -127,0 +135,0 @@ },

<img alt="math live" src="assets/logo.png?raw=true">
[![Maintenance](https://img.shields.io/maintenance/yes/2019.svg)]()
[![Maintenance](https://img.shields.io/maintenance/yes/2020.svg)]()
[![GitHub license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://raw.githubusercontent.com/arnog/mathlive/master/LICENSE.txt)

@@ -11,16 +9,15 @@

<img alt="Screenshot" src="assets/screenshots/screenshot.jpg">
MathLive: Math Input Made Easy
MathLive is a JavaScript library to render and edit math.
- [x] JavaScript library easy to integrate in your project
- [x] Beautiful, TeX-quality typesetting
- [x] Easy to use interface for formula editing
- [x] Designed for mobile devices with an extensive set of virtual keyboards
- [x] Accessility support: screen reader compatible, and includes custom
math-to-speech support
- [x] Outputs **LaTeX**, **MathML** and **MathJSON** (Abstract Syntax Tree)
- [x] And it is easy to customize to your needs!
- [x] TeX-quality typesetting
- [x] Easy to use interface for math editing
- [x] Fast and small
- [x] Works great on desktop and on mobile devices thanks to an extensive set of virtual keyboards
- [x] Outputs **LaTeX**, **MathML** and **MathJSON** (Abstract Syntax Tree)
- [x] And it is easy to customize to your needs!
Try it at [mathlive.io](https://mathlive.io)

@@ -50,32 +47,38 @@

## How To Use MathLive
### Displaying Math
Render math equations by
[adding a few lines to your web page](tutorials/USAGE_GUIDE.md).
Render math equations by
[adding a few lines to your web page](tutorials/USAGE_GUIDE.md).
```html
<!doctype html><html lang="en-US">
<head>
...
<link href="https://unpkg.com/mathlive/dist/mathlive.core.css" rel="stylesheet" >
<link href="https://unpkg.com/mathlive/dist/mathlive.css" rel="stylesheet" >
</head>
<body>
<h1>Euler's Identity</h1>
<p>$$e^{i\pi} + 1 = 0$$</p>
<!DOCTYPE html>
<html lang="en-US">
<head>
...
<link
href="https://unpkg.com/mathlive/dist/mathlive.core.css"
rel="stylesheet"
/>
<link
href="https://unpkg.com/mathlive/dist/mathlive.css"
rel="stylesheet"
/>
</head>
<body>
<h1>Euler's Identity</h1>
<p>$$e^{i\pi} + 1 = 0$$</p>
<script type='module'>
import MathLive from 'https://unpkg.com/mathlive/dist/mathlive.mjs';
MathLive.renderMathInDocument();
</script>
</body>
<script type="module">
import MathLive from 'https://unpkg.com/mathlive/dist/mathlive.mjs';
MathLive.renderMathInDocument();
</script>
</body>
</html>
```
### Editing Math
### Editing Math
You can also incorporate a “mathfield” to edit math just like you would edit
You can also incorporate a “mathfield” to edit math just like you would edit
text. The MathLive APIs allow you to interact with the mathfield,

@@ -85,16 +88,23 @@ including extracting its content, inserting placeholders and more.

```html
<!doctype html><html lang="en-US">
<head>
...
<link rel="stylesheet" href="https://unpkg.com/mathlive/dist/mathlive.core.css">
<link rel="stylesheet" href="https://unpkg.com/mathlive/dist/mathlive.css">
</head>
<body>
<div id='mathfield'>f(x)=</div>
<!DOCTYPE html>
<html lang="en-US">
<head>
...
<link
rel="stylesheet"
href="https://unpkg.com/mathlive/dist/mathlive.core.css"
/>
<link
rel="stylesheet"
href="https://unpkg.com/mathlive/dist/mathlive.css"
/>
</head>
<body>
<div id="mathfield">f(x)=</div>
<script type='module'>
import MathLive from 'https://unpkg.com/mathlive/dist/mathlive.mjs';
MathLive.makeMathField('mathfield');
</script>
</body>
<script type="module">
import MathLive from 'https://unpkg.com/mathlive/dist/mathlive.mjs';
MathLive.makeMathField('mathfield');
</script>
</body>
</html>

@@ -107,3 +117,2 @@ ```

### Installing MathLive

@@ -113,8 +122,10 @@

However, if you:
- want to contribute to MathLive
- use your own CDN
- make some other changes to MathLive
you can also install it locally in your project.
- want to contribute to MathLive
- use your own CDN
- make some other changes to MathLive
you can also install it locally in your project.
To do so:
```bash

@@ -124,2 +135,3 @@ $ npm install -s mathlive

```
This will make a local build of MathLive, run a local HTTP server and open a page with the examples in your browser.

@@ -129,18 +141,18 @@

* Using MathLive in your project? Want to support the project ongoing maintenance?
Consider becoming a patron on [Patreon](https://patreon.com/arnog) or making a
donation with [PayPal](https://www.paypal.me/arnogourdol)
* Something wrong? Got ideas for new features? Write up an issue. Read about
[Contributing](CONTRIBUTING.md) and follow our [Code of Conduct](CODE_OF_CONDUCT.md)
* Want to use MathLive in your web page? The [Usage Guide](tutorials/USAGE_GUIDE.md)
has all the details.
* Want to contribute some code for an issue or a feature? Read the
[Contributor Guide](tutorials/CONTRIBUTOR_GUIDE.md) and the
[docs](http://docs.mathlive.io). Looking for inspiration? Pick one of
the [good first issues](https://github.com/arnog/mathlive/labels/good%20first%20issue)
- Using MathLive in your project? Want to support the project ongoing maintenance?
Consider becoming a patron on [Patreon](https://patreon.com/arnog) or making a
donation with [PayPal](https://www.paypal.me/arnogourdol)
- Something wrong? Got ideas for new features? Write up an issue. Read about
[Contributing](CONTRIBUTING.md) and follow our [Code of Conduct](CODE_OF_CONDUCT.md)
- Want to use MathLive in your web page? The [Usage Guide](tutorials/USAGE_GUIDE.md)
has all the details.
- Want to contribute some code for an issue or a feature? Read the
[Contributor Guide](tutorials/CONTRIBUTOR_GUIDE.md) and the
[docs](http://docs.mathlive.io). Looking for inspiration? Pick one of
the [good first issues](https://github.com/arnog/mathlive/labels/good%20first%20issue)
## More Questions?
* Join our Slack channel at https://mathlive.slack.com.
* Drop a line to arno@arno.org or [/u/real_arnog](https://www.reddit.com/user/real_arnog)
- Join our Slack channel at https://mathlive.slack.com.
- Drop a line to arno@arno.org or [/u/real_arnog](https://www.reddit.com/user/real_arnog)

@@ -147,0 +159,0 @@ ## License

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc