add initial marp implementation with sample content and build configuration
This commit is contained in:
134
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsConfiguration.ts
generated
vendored
Normal file
134
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsConfiguration.ts
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/*************************************************************
|
||||
* Copyright (c) 2020-2022 MathJax Consortium
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Configuration file for the mathtools package.
|
||||
*
|
||||
* @author v.sorge@mathjax.org (Volker Sorge)
|
||||
* @author dpvc@mathjax.org (Davide P. Cervone)
|
||||
*/
|
||||
|
||||
import {Configuration} from '../Configuration.js';
|
||||
import {CommandMap} from '../SymbolMap.js';
|
||||
import NodeUtil from '../NodeUtil.js';
|
||||
import {expandable} from '../../../util/Options.js';
|
||||
import {ParserConfiguration} from '../Configuration.js';
|
||||
import {TeX} from '../../tex.js';
|
||||
import ParseOptions from '../ParseOptions.js';
|
||||
|
||||
import './MathtoolsMappings.js';
|
||||
import {MathtoolsUtil} from './MathtoolsUtil.js';
|
||||
import {MathtoolsTagFormat} from './MathtoolsTags.js';
|
||||
import {MultlinedItem} from './MathtoolsItems.js';
|
||||
|
||||
/**
|
||||
* The name of the paried-delimiters command map.
|
||||
*/
|
||||
export const PAIREDDELIMS = 'mathtools-paired-delims';
|
||||
|
||||
/**
|
||||
* Create the paired-delimiters command map, and link it into the configuration.
|
||||
* @param {ParserConfiguration} config The current configuration.
|
||||
*/
|
||||
function initMathtools(config: ParserConfiguration) {
|
||||
new CommandMap(PAIREDDELIMS, {}, {});
|
||||
config.append(Configuration.local({handler: {macro: [PAIREDDELIMS]}, priority: -5}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any pre-defined paired delimiters, and subclass the configured tag format.
|
||||
* @param {ParserConfiguration} config The current configuration.
|
||||
* @param {TeX} jac The TeX input jax
|
||||
*/
|
||||
function configMathtools(config: ParserConfiguration, jax: TeX<any, any, any>) {
|
||||
const parser = jax.parseOptions;
|
||||
const pairedDelims = parser.options.mathtools.pairedDelimiters;
|
||||
for (const cs of Object.keys(pairedDelims)) {
|
||||
MathtoolsUtil.addPairedDelims(parser, cs, pairedDelims[cs]);
|
||||
}
|
||||
MathtoolsTagFormat(config, jax);
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter to fix up mmultiscripts elements.
|
||||
* @param {ParseOptions} data The parse options.
|
||||
*/
|
||||
export function fixPrescripts({data}: {data: ParseOptions}) {
|
||||
for (const node of data.getList('mmultiscripts')) {
|
||||
if (!node.getProperty('fixPrescript')) continue;
|
||||
const childNodes = NodeUtil.getChildren(node);
|
||||
let n = 0;
|
||||
for (const i of [1, 2]) {
|
||||
if (!childNodes[i]) {
|
||||
NodeUtil.setChild(node, i, data.nodeFactory.create('node', 'none'));
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for (const i of [4, 5]) {
|
||||
if (NodeUtil.isType(childNodes[i], 'mrow') && NodeUtil.getChildren(childNodes[i]).length === 0) {
|
||||
NodeUtil.setChild(node, i, data.nodeFactory.create('node', 'none'));
|
||||
}
|
||||
}
|
||||
if (n === 2) {
|
||||
childNodes.splice(1, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The configuration for the mathtools package
|
||||
*/
|
||||
export const MathtoolsConfiguration = Configuration.create(
|
||||
'mathtools', {
|
||||
handler: {
|
||||
macro: ['mathtools-macros', 'mathtools-delimiters'],
|
||||
environment: ['mathtools-environments'],
|
||||
delimiter: ['mathtools-delimiters'],
|
||||
character: ['mathtools-characters']
|
||||
},
|
||||
items: {
|
||||
[MultlinedItem.prototype.kind]: MultlinedItem
|
||||
},
|
||||
init: initMathtools,
|
||||
config: configMathtools,
|
||||
postprocessors: [[fixPrescripts, -6]],
|
||||
options: {
|
||||
mathtools: {
|
||||
'multlinegap': '1em', // horizontal space for multlined environments
|
||||
'multlined-pos': 'c', // default alignment for multlined environments
|
||||
'firstline-afterskip': '', // space for first line of multlined (overrides multlinegap)
|
||||
'lastline-preskip': '', // space for last line of multlined (overrides multlinegap)
|
||||
'smallmatrix-align': 'c', // default alignment for smallmatrix environments
|
||||
'shortvdotsadjustabove': '.2em', // space to remove above \shortvdots
|
||||
'shortvdotsadjustbelow': '.2em', // space to remove below \shortvdots
|
||||
'centercolon': false, // true to have colon automatically centered
|
||||
'centercolon-offset': '.04em', // vertical adjustment for centered colons
|
||||
'thincolon-dx': '-.04em', // horizontal adjustment for thin colons (e.g., \coloneqq)
|
||||
'thincolon-dw': '-.08em', // width adjustment for thin colons
|
||||
'use-unicode': false, // true to use unicode characters rather than multi-character
|
||||
// version for \coloneqq, etc., when possible
|
||||
'prescript-sub-format': '', // format for \prescript subscript
|
||||
'prescript-sup-format': '', // format for \prescript superscript
|
||||
'prescript-arg-format': '', // format for \prescript base
|
||||
'allow-mathtoolsset': true, // true to allow \mathtoolsset to change settings
|
||||
pairedDelimiters: expandable({}), // predefined paired delimiters
|
||||
// name: [left, right, body, argcount, pre, post]
|
||||
tagforms: expandable({}), // tag form definitions
|
||||
// name: [left, right, format]
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
70
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsItems.ts
generated
vendored
Normal file
70
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsItems.ts
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*************************************************************
|
||||
* Copyright (c) 2020-2022 MathJax Consortium
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Implementation of items for the mathtools package.
|
||||
*
|
||||
* @author v.sorge@mathjax.org (Volker Sorge)
|
||||
* @author dpvc@mathjax.org (Davide P. Cervone)
|
||||
*/
|
||||
|
||||
import {MultlineItem} from '../ams/AmsItems.js';
|
||||
import NodeUtil from '../NodeUtil.js';
|
||||
import {TexConstant} from '../TexConstants.js';
|
||||
|
||||
|
||||
/**
|
||||
* The StackItem for the multlined environment
|
||||
*/
|
||||
export class MultlinedItem extends MultlineItem {
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
get kind() {
|
||||
return 'multlined';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public EndTable() {
|
||||
if (this.Size() || this.row.length) {
|
||||
this.EndEntry();
|
||||
this.EndRow();
|
||||
}
|
||||
if (this.table.length > 1) {
|
||||
const options = this.factory.configuration.options.mathtools;
|
||||
const gap = options.multlinegap;
|
||||
const firstskip = options['firstline-afterskip'] || gap;
|
||||
const lastskip = options['lastline-preskip'] || gap;
|
||||
const first = NodeUtil.getChildren(this.table[0])[0];
|
||||
if (NodeUtil.getAttribute(first, 'columnalign') !== TexConstant.Align.RIGHT) {
|
||||
first.appendChild(this.create('node', 'mspace', [], {width: firstskip}));
|
||||
}
|
||||
const last = NodeUtil.getChildren(this.table[this.table.length - 1])[0];
|
||||
if (NodeUtil.getAttribute(last, 'columnalign') !== TexConstant.Align.LEFT) {
|
||||
const top = NodeUtil.getChildren(last)[0];
|
||||
top.childNodes.unshift(null);
|
||||
const space = this.create('node', 'mspace', [], {width: lastskip});
|
||||
NodeUtil.setChild(top, 0, space);
|
||||
}
|
||||
}
|
||||
super.EndTable.call(this);
|
||||
}
|
||||
|
||||
}
|
||||
206
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsMappings.ts
generated
vendored
Normal file
206
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsMappings.ts
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/*************************************************************
|
||||
* Copyright (c) 2020-2022 MathJax Consortium
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Macro and environment mappings for the mathtools package.
|
||||
*
|
||||
* @author v.sorge@mathjax.org (Volker Sorge)
|
||||
* @author dpvc@mathjax.org (Davide P. Cervone)
|
||||
*/
|
||||
|
||||
import ParseMethods from '../ParseMethods.js';
|
||||
import {CommandMap, EnvironmentMap, DelimiterMap} from '../SymbolMap.js';
|
||||
import {TexConstant} from '../TexConstants.js';
|
||||
|
||||
import {MathtoolsMethods} from './MathtoolsMethods.js';
|
||||
|
||||
//
|
||||
// Mathtools macros that are not implemented:
|
||||
//
|
||||
// \smashoperator[〈pos〉]{〈operator with limits〉}
|
||||
// \SwapAboveDisplaySkip
|
||||
// \noeqref{〈label,label,. . . 〉}
|
||||
// \intertext{〈text 〉}
|
||||
// \shortintertext{〈text 〉}
|
||||
// \reDeclarePairedDelimiterInnerWrapper{〈macro name〉}{〈star or nostarnonscaled or nostarscaled〉}{〈code〉}
|
||||
// \DeclareMathSizes{〈dimen〉}{〈dimen〉}{〈dimen〉}{〈dimen〉}
|
||||
// \newgathered{〈name〉}{〈pre_line〉}{〈post_line〉}{〈after〉}
|
||||
// \renewgathered{〈name〉}{〈pre_line〉}{〈post_line〉}{〈after〉}
|
||||
//
|
||||
|
||||
/**
|
||||
* The macros for this package.
|
||||
*/
|
||||
new CommandMap('mathtools-macros', {
|
||||
|
||||
shoveleft: ['HandleShove', TexConstant.Align.LEFT], // override AMS version
|
||||
shoveright: ['HandleShove', TexConstant.Align.RIGHT], // override AMS version
|
||||
|
||||
xleftrightarrow: ['xArrow', 0x2194, 10, 10],
|
||||
xLeftarrow: ['xArrow', 0x21D0, 12, 7],
|
||||
xRightarrow: ['xArrow', 0x21D2, 7, 12],
|
||||
xLeftrightarrow: ['xArrow', 0x21D4, 12, 12],
|
||||
xhookleftarrow: ['xArrow', 0x21A9, 10, 5],
|
||||
xhookrightarrow: ['xArrow', 0x21AA, 5, 10],
|
||||
xmapsto: ['xArrow', 0x21A6, 10, 10],
|
||||
xrightharpoondown: ['xArrow', 0x21C1, 5, 10],
|
||||
xleftharpoondown: ['xArrow', 0x21BD, 10, 5],
|
||||
xrightleftharpoons: ['xArrow', 0x21CC, 10, 10],
|
||||
xrightharpoonup: ['xArrow', 0x21C0, 5, 10],
|
||||
xleftharpoonup: ['xArrow', 0x21BC, 10, 5],
|
||||
xleftrightharpoons: ['xArrow', 0x21CB, 10, 10],
|
||||
|
||||
mathllap: ['MathLap', 'l', false],
|
||||
mathrlap: ['MathLap', 'r', false],
|
||||
mathclap: ['MathLap', 'c', false],
|
||||
clap: ['MtLap', 'c'],
|
||||
textllap: ['MtLap', 'l'],
|
||||
textrlap: ['MtLap', 'r'],
|
||||
textclap: ['MtLap', 'c'],
|
||||
|
||||
cramped: 'Cramped',
|
||||
crampedllap: ['MathLap', 'l', true],
|
||||
crampedrlap: ['MathLap', 'r', true],
|
||||
crampedclap: ['MathLap', 'c', true],
|
||||
crampedsubstack: ['Macro', '\\begin{crampedsubarray}{c}#1\\end{crampedsubarray}', 1],
|
||||
|
||||
mathmbox: 'MathMBox',
|
||||
mathmakebox: 'MathMakeBox',
|
||||
|
||||
overbracket: 'UnderOverBracket',
|
||||
underbracket: 'UnderOverBracket',
|
||||
|
||||
refeq: 'HandleRef',
|
||||
|
||||
MoveEqLeft: ['Macro', '\\hspace{#1em}&\\hspace{-#1em}', 1, '2'],
|
||||
Aboxed: 'Aboxed',
|
||||
|
||||
ArrowBetweenLines: 'ArrowBetweenLines',
|
||||
vdotswithin: 'VDotsWithin',
|
||||
shortvdotswithin: 'ShortVDotsWithin',
|
||||
MTFlushSpaceAbove: 'FlushSpaceAbove',
|
||||
MTFlushSpaceBelow: 'FlushSpaceBelow',
|
||||
|
||||
DeclarePairedDelimiter: 'DeclarePairedDelimiter',
|
||||
DeclarePairedDelimiterX: 'DeclarePairedDelimiterX',
|
||||
DeclarePairedDelimiterXPP: 'DeclarePairedDelimiterXPP',
|
||||
|
||||
//
|
||||
// Typos from initial release -- kept for backward compatibility for now
|
||||
//
|
||||
DeclarePairedDelimiters: 'DeclarePairedDelimiter',
|
||||
DeclarePairedDelimitersX: 'DeclarePairedDelimiterX',
|
||||
DeclarePairedDelimitersXPP: 'DeclarePairedDelimiterXPP',
|
||||
|
||||
centercolon: ['CenterColon', true, true],
|
||||
ordinarycolon: ['CenterColon', false],
|
||||
MTThinColon: ['CenterColon', true, true, true],
|
||||
|
||||
coloneqq: ['Relation', ':=', '\u2254'],
|
||||
Coloneqq: ['Relation', '::=', '\u2A74'],
|
||||
coloneq: ['Relation', ':-'],
|
||||
Coloneq: ['Relation', '::-'],
|
||||
eqqcolon: ['Relation', '=:', '\u2255'],
|
||||
Eqqcolon: ['Relation', '=::'],
|
||||
eqcolon: ['Relation', '-:', '\u2239'],
|
||||
Eqcolon: ['Relation', '-::'],
|
||||
colonapprox: ['Relation', ':\\approx'],
|
||||
Colonapprox: ['Relation', '::\\approx'],
|
||||
colonsim: ['Relation', ':\\sim'],
|
||||
Colonsim: ['Relation', '::\\sim'],
|
||||
dblcolon: ['Relation', '::', '\u2237'],
|
||||
|
||||
nuparrow: ['NArrow', '\u2191', '.06em'],
|
||||
ndownarrow: ['NArrow', '\u2193', '.25em'],
|
||||
bigtimes: ['Macro', '\\mathop{\\Large\\kern-.1em\\boldsymbol{\\times}\\kern-.1em}'],
|
||||
|
||||
splitfrac: ['SplitFrac', false],
|
||||
splitdfrac: ['SplitFrac', true],
|
||||
|
||||
xmathstrut: 'XMathStrut',
|
||||
|
||||
prescript: 'Prescript',
|
||||
|
||||
newtagform: ['NewTagForm', false],
|
||||
renewtagform: ['NewTagForm', true],
|
||||
usetagform: 'UseTagForm',
|
||||
|
||||
adjustlimits: [
|
||||
'MacroWithTemplate',
|
||||
'\\mathop{{#1}\\vphantom{{#3}}}_{{#2}\\vphantom{{#4}}}\\mathop{{#3}\\vphantom{{#1}}}_{{#4}\\vphantom{{#2}}}',
|
||||
4, , '_', , '_'
|
||||
],
|
||||
|
||||
mathtoolsset: 'SetOptions'
|
||||
|
||||
}, MathtoolsMethods);
|
||||
|
||||
/**
|
||||
* The environments for this package.
|
||||
*/
|
||||
new EnvironmentMap('mathtools-environments', ParseMethods.environment, {
|
||||
dcases: ['Array', null, '\\{', '', 'll', null, '.2em', 'D'],
|
||||
rcases: ['Array', null, '', '\\}', 'll', null, '.2em'],
|
||||
drcases: ['Array', null, '', '\\}', 'll', null, '.2em', 'D'],
|
||||
'dcases*': ['Cases', null, '{', '', 'D'],
|
||||
'rcases*': ['Cases', null, '', '}'],
|
||||
'drcases*': ['Cases', null, '', '}', 'D'],
|
||||
'cases*': ['Cases', null, '{', ''],
|
||||
|
||||
'matrix*': ['MtMatrix', null, null, null],
|
||||
'pmatrix*': ['MtMatrix', null, '(', ')'],
|
||||
'bmatrix*': ['MtMatrix', null, '[', ']'],
|
||||
'Bmatrix*': ['MtMatrix', null, '\\{', '\\}'],
|
||||
'vmatrix*': ['MtMatrix', null, '\\vert', '\\vert'],
|
||||
'Vmatrix*': ['MtMatrix', null, '\\Vert', '\\Vert'],
|
||||
|
||||
'smallmatrix*': ['MtSmallMatrix', null, null, null],
|
||||
psmallmatrix: ['MtSmallMatrix', null, '(', ')', 'c'],
|
||||
'psmallmatrix*': ['MtSmallMatrix', null, '(', ')'],
|
||||
bsmallmatrix: ['MtSmallMatrix', null, '[', ']', 'c'],
|
||||
'bsmallmatrix*': ['MtSmallMatrix', null, '[', ']'],
|
||||
Bsmallmatrix: ['MtSmallMatrix', null, '\\{', '\\}', 'c'],
|
||||
'Bsmallmatrix*': ['MtSmallMatrix', null, '\\{', '\\}'],
|
||||
vsmallmatrix: ['MtSmallMatrix', null, '\\vert', '\\vert', 'c'],
|
||||
'vsmallmatrix*': ['MtSmallMatrix', null, '\\vert', '\\vert'],
|
||||
Vsmallmatrix: ['MtSmallMatrix', null, '\\Vert', '\\Vert', 'c'],
|
||||
'Vsmallmatrix*': ['MtSmallMatrix', null, '\\Vert', '\\Vert'],
|
||||
|
||||
crampedsubarray: ['Array', null, null, null, null, '0em', '0.1em', 'S\'', 1],
|
||||
|
||||
multlined: 'MtMultlined',
|
||||
|
||||
spreadlines: ['SpreadLines', true],
|
||||
|
||||
lgathered: ['AmsEqnArray', null, null, null, 'l', null, '.5em', 'D'],
|
||||
rgathered: ['AmsEqnArray', null, null, null, 'r', null, '.5em', 'D'],
|
||||
|
||||
}, MathtoolsMethods);
|
||||
|
||||
/**
|
||||
* The delimiters for this package.
|
||||
*/
|
||||
new DelimiterMap('mathtools-delimiters', ParseMethods.delimiter, {
|
||||
'\\lparen': '(',
|
||||
'\\rparen': ')'
|
||||
});
|
||||
|
||||
/**
|
||||
* The special characters for this package.
|
||||
*/
|
||||
new CommandMap('mathtools-characters', {
|
||||
':' : ['CenterColon', true]
|
||||
}, MathtoolsMethods);
|
||||
747
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsMethods.ts
generated
vendored
Normal file
747
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsMethods.ts
generated
vendored
Normal file
@@ -0,0 +1,747 @@
|
||||
/*************************************************************
|
||||
* Copyright (c) 2020-2022 MathJax Consortium
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Macro and environment implementations for the mathtools package.
|
||||
*
|
||||
* @author v.sorge@mathjax.org (Volker Sorge)
|
||||
* @author dpvc@mathjax.org (Davide P. Cervone)
|
||||
*/
|
||||
|
||||
|
||||
import {ArrayItem, EqnArrayItem} from '../base/BaseItems.js';
|
||||
import {StackItem} from '../StackItem.js';
|
||||
import ParseUtil from '../ParseUtil.js';
|
||||
import {ParseMethod, ParseResult} from '../Types.js';
|
||||
import {AmsMethods} from '../ams/AmsMethods.js';
|
||||
import BaseMethods from '../base/BaseMethods.js';
|
||||
import TexParser from '../TexParser.js';
|
||||
import TexError from '../TexError.js';
|
||||
import NodeUtil from '../NodeUtil.js';
|
||||
import {TEXCLASS} from '../../../core/MmlTree/MmlNode.js';
|
||||
import {length2em, em} from '../../../util/lengths.js';
|
||||
import {lookup} from '../../../util/Options.js';
|
||||
import NewcommandUtil from '../newcommand/NewcommandUtil.js';
|
||||
import NewcommandMethods from '../newcommand/NewcommandMethods.js';
|
||||
|
||||
import {MathtoolsTags} from './MathtoolsTags.js';
|
||||
import {MathtoolsUtil} from './MathtoolsUtil.js';
|
||||
|
||||
/**
|
||||
* The implementations for the macros and environments for the mathtools package.
|
||||
*/
|
||||
export const MathtoolsMethods: Record<string, ParseMethod> = {
|
||||
|
||||
/**
|
||||
* Handle a mathtools matrix environment, with optional alignment.
|
||||
*
|
||||
* @param {TexParser} parser The active tex parser.
|
||||
* @param {StackItem} begin The BeginItem for the environment.
|
||||
* @param {string} open The open delimiter for the matrix.
|
||||
* @param {string} close The close delimiter for the matrix.
|
||||
* @return {ParserResult} The ArrayItem for the matrix.
|
||||
*/
|
||||
MtMatrix(parser: TexParser, begin: StackItem, open: string, close: string): ParseResult {
|
||||
const align = parser.GetBrackets(`\\begin{${begin.getName()}}`, 'c');
|
||||
return MathtoolsMethods.Array(parser, begin, open, close, align);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a smallmatrix with given delimiters, and with optional alignment (and settable default)
|
||||
*
|
||||
* @param {TexParser} parser The active tex parser.
|
||||
* @param {StackItem} begin The BeginItem for the environment.
|
||||
* @param {string} open The open delimiter for the matrix.
|
||||
* @param {string} close The close delimiter for the matrix.
|
||||
* @param {string} align The (optional) alignment. If not given, use a bracket argument for it.
|
||||
* @return {ParseResult} The ArrayItem for the matrix.
|
||||
*/
|
||||
MtSmallMatrix(parser: TexParser, begin: StackItem, open: string, close: string, align?: string): ParseResult {
|
||||
if (!align) {
|
||||
align = parser.GetBrackets(`\\begin{${begin.getName()}}`, parser.options.mathtools['smallmatrix-align']);
|
||||
}
|
||||
return MathtoolsMethods.Array(
|
||||
parser, begin, open, close, align, ParseUtil.Em(1 / 3), '.2em', 'S', 1
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the multlined StackItem.
|
||||
*
|
||||
* @param {TexParser} parser The active tex parser.
|
||||
* @param {StackItem} begin The BeginItem for the environment.
|
||||
* @return {ParseResult} The MultlinedItem.
|
||||
*/
|
||||
MtMultlined(parser: TexParser, begin: StackItem): ParseResult {
|
||||
const name = `\\begin{${begin.getName()}}`;
|
||||
let pos = parser.GetBrackets(name, parser.options.mathtools['multlined-pos'] || 'c');
|
||||
let width = pos ? parser.GetBrackets(name, '') : '';
|
||||
if (pos && !pos.match(/^[cbt]$/)) {
|
||||
[width, pos] = [pos, width];
|
||||
}
|
||||
parser.Push(begin);
|
||||
const item = parser.itemFactory.create('multlined', parser, begin) as ArrayItem;
|
||||
item.arraydef = {
|
||||
displaystyle: true,
|
||||
rowspacing: '.5em',
|
||||
width: width || 'auto',
|
||||
columnwidth: '100%',
|
||||
};
|
||||
return ParseUtil.setArrayAlign(item as ArrayItem, pos || 'c');
|
||||
},
|
||||
|
||||
/**
|
||||
* Replacement for the AMS HandleShove that includes optional spacing values
|
||||
*
|
||||
* @param {TexParser} parser The active tex parser.
|
||||
* @param {string} name The name of the calling macro.
|
||||
* @param {string} shove Which way to shove the result.
|
||||
*/
|
||||
HandleShove(parser: TexParser, name: string, shove: string) {
|
||||
let top = parser.stack.Top();
|
||||
if (top.kind !== 'multline' && top.kind !== 'multlined') {
|
||||
throw new TexError(
|
||||
'CommandInMultlined',
|
||||
'%1 can only appear within the multline or multlined environments',
|
||||
name);
|
||||
}
|
||||
if (top.Size()) {
|
||||
throw new TexError(
|
||||
'CommandAtTheBeginingOfLine',
|
||||
'%1 must come at the beginning of the line',
|
||||
name);
|
||||
}
|
||||
top.setProperty('shove', shove);
|
||||
let shift = parser.GetBrackets(name);
|
||||
let mml = parser.ParseArg(name);
|
||||
if (shift) {
|
||||
let mrow = parser.create('node', 'mrow', []);
|
||||
let mspace = parser.create('node', 'mspace', [], {width: shift});
|
||||
if (shove === 'left') {
|
||||
mrow.appendChild(mspace);
|
||||
mrow.appendChild(mml);
|
||||
} else {
|
||||
mrow.appendChild(mml);
|
||||
mrow.appendChild(mspace);
|
||||
}
|
||||
mml = mrow;
|
||||
}
|
||||
parser.Push(mml);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle the spreadlines environment.
|
||||
*
|
||||
* @param {TexParser} parser The active tex parser.
|
||||
* @param {StackItem} begin The BeginItem for the environment.
|
||||
*/
|
||||
SpreadLines(parser: TexParser, begin: StackItem) {
|
||||
if (parser.stack.env.closing === begin.getName()) {
|
||||
//
|
||||
// When the environment ends, look through the contents and
|
||||
// adjust the spacing in any tables, then push the results.
|
||||
//
|
||||
delete parser.stack.env.closing;
|
||||
const top = parser.stack.Pop();
|
||||
const mml = top.toMml();
|
||||
const spread = top.getProperty('spread') as string;
|
||||
if (mml.isInferred) {
|
||||
for (const child of NodeUtil.getChildren(mml)) {
|
||||
MathtoolsUtil.spreadLines(child, spread);
|
||||
}
|
||||
} else {
|
||||
MathtoolsUtil.spreadLines(mml, spread);
|
||||
}
|
||||
parser.Push(mml);
|
||||
} else {
|
||||
//
|
||||
// Read the spread dimension and save it, then begin the environment.
|
||||
//
|
||||
const spread = parser.GetDimen(`\\begin{${begin.getName()}}`);
|
||||
begin.setProperty('spread', spread);
|
||||
parser.Push(begin);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements the various cases environments.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {StackItem} begin The BeginItem for the environment.
|
||||
* @param {string} open The open delimiter for the matrix.
|
||||
* @param {string} close The close delimiter for the matrix.
|
||||
* @param {string} style The style (D, T, S, SS) for the contents of the array
|
||||
* @return {ArrayItem} The ArrayItem for the environment
|
||||
*/
|
||||
Cases(parser: TexParser, begin: StackItem, open: string, close: string, style: string): ArrayItem {
|
||||
const array = parser.itemFactory.create('array').setProperty('casesEnv', begin.getName()) as ArrayItem;
|
||||
array.arraydef = {
|
||||
rowspacing: '.2em',
|
||||
columnspacing: '1em',
|
||||
columnalign: 'left'
|
||||
};
|
||||
if (style === 'D') {
|
||||
array.arraydef.displaystyle = true;
|
||||
}
|
||||
array.setProperties({open, close});
|
||||
parser.Push(begin);
|
||||
return array;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle \mathrlap, \mathllap, \mathclap, and their cramped versions.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {string} pos The position (l, c, r) of the lapped content
|
||||
* @param {boolean} cramped True if the style should be cramped
|
||||
*/
|
||||
MathLap(parser: TexParser, name: string, pos: string, cramped: boolean) {
|
||||
const style = parser.GetBrackets(name, '').trim();
|
||||
let mml = parser.create('node', 'mstyle', [
|
||||
parser.create('node', 'mpadded', [parser.ParseArg(name)], {
|
||||
width: 0, ...(pos === 'r' ? {} : {lspace: (pos === 'l' ? '-1width' : '-.5width')})
|
||||
})
|
||||
], {'data-cramped': cramped});
|
||||
MathtoolsUtil.setDisplayLevel(mml, style);
|
||||
parser.Push(parser.create('node', 'TeXAtom', [mml]));
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \cramped.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
Cramped(parser: TexParser, name: string) {
|
||||
const style = parser.GetBrackets(name, '').trim();
|
||||
const arg = parser.ParseArg(name);
|
||||
const mml = parser.create('node', 'mstyle', [arg], {'data-cramped': true});
|
||||
MathtoolsUtil.setDisplayLevel(mml, style);
|
||||
parser.Push(mml);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \clap (and could do \llap and \rlap, where the contents are text mode).
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {string} pos The position (l, c, r) of the lapped content
|
||||
*/
|
||||
MtLap(parser: TexParser, name: string, pos: string) {
|
||||
const content = ParseUtil.internalMath(parser, parser.GetArgument(name), 0);
|
||||
let mml = parser.create('node', 'mpadded', content, {width: 0});
|
||||
if (pos !== 'r') {
|
||||
NodeUtil.setAttribute(mml, 'lspace', pos === 'l' ? '-1width' : '-.5width');
|
||||
}
|
||||
parser.Push(mml);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \mathmakebox.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
MathMakeBox(parser: TexParser, name: string) {
|
||||
const width = parser.GetBrackets(name);
|
||||
const pos = parser.GetBrackets(name, 'c');
|
||||
const mml = parser.create('node', 'mpadded', [parser.ParseArg(name)]);
|
||||
if (width) {
|
||||
NodeUtil.setAttribute(mml, 'width', width);
|
||||
}
|
||||
const align = lookup(pos, {c: 'center', r: 'right'}, '');
|
||||
if (align) {
|
||||
NodeUtil.setAttribute(mml, 'data-align', align);
|
||||
}
|
||||
parser.Push(mml);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \mathmbox.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
MathMBox(parser: TexParser, name: string) {
|
||||
parser.Push(parser.create('node', 'mrow', [parser.ParseArg(name)]));
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \underbacket and \overbracket.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
UnderOverBracket(parser: TexParser, name: string) {
|
||||
const thickness = length2em(parser.GetBrackets(name, '.1em'), .1);
|
||||
const height = parser.GetBrackets(name, '.2em');
|
||||
const arg = parser.GetArgument(name);
|
||||
const [pos, accent, border] = (
|
||||
name.charAt(1) === 'o' ?
|
||||
['over', 'accent', 'bottom'] :
|
||||
['under', 'accentunder', 'top']
|
||||
);
|
||||
const t = em(thickness);
|
||||
const base = new TexParser(arg, parser.stack.env, parser.configuration).mml();
|
||||
const copy = new TexParser(arg, parser.stack.env, parser.configuration).mml();
|
||||
const script = parser.create('node', 'mpadded', [
|
||||
parser.create('node', 'mphantom', [copy])
|
||||
], {
|
||||
style: `border: ${t} solid; border-${border}: none`,
|
||||
height: height,
|
||||
depth: 0
|
||||
});
|
||||
const node = ParseUtil.underOver(parser, base, script, pos, true);
|
||||
const munderover = NodeUtil.getChildAt(NodeUtil.getChildAt(node, 0), 0); // TeXAtom.inferredMrow child 0
|
||||
NodeUtil.setAttribute(munderover, accent, true);
|
||||
parser.Push(node);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \Aboxed.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
Aboxed(parser: TexParser, name: string) {
|
||||
//
|
||||
// Check that the top item is an alignment, and that we are on an even number of cells
|
||||
// (othewise add one to make it even).
|
||||
//
|
||||
const top = MathtoolsUtil.checkAlignment(parser, name);
|
||||
if (top.row.length % 2 === 1) {
|
||||
top.row.push(parser.create('node', 'mtd', []));
|
||||
}
|
||||
//
|
||||
// Get the argument and the rest of the TeX string.
|
||||
//
|
||||
const arg = parser.GetArgument(name);
|
||||
const rest = parser.string.substr(parser.i);
|
||||
//
|
||||
// Put the argument back, followed by "&&", and a marker that we look for below.
|
||||
//
|
||||
parser.string = arg + '&&\\endAboxed';
|
||||
parser.i = 0;
|
||||
//
|
||||
// Get the two parts separated by ampersands, and ignore the rest.
|
||||
//
|
||||
const left = parser.GetUpTo(name, '&');
|
||||
const right = parser.GetUpTo(name, '&');
|
||||
parser.GetUpTo(name, '\\endAboxed');
|
||||
//
|
||||
// Insert the TeX needed for the boxed content
|
||||
//
|
||||
const tex = ParseUtil.substituteArgs(
|
||||
parser, [left, right], '\\rlap{\\boxed{#1{}#2}}\\kern.267em\\phantom{#1}&\\phantom{{}#2}\\kern.267em'
|
||||
);
|
||||
parser.string = tex + rest;
|
||||
parser.i = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \ArrowBetweenLines.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
ArrowBetweenLines(parser: TexParser, name: string) {
|
||||
const top = MathtoolsUtil.checkAlignment(parser, name);
|
||||
if (top.Size() || top.row.length) {
|
||||
throw new TexError('BetweenLines', '%1 must be on a row by itself', name);
|
||||
}
|
||||
const star = parser.GetStar();
|
||||
const symbol = parser.GetBrackets(name, '\\Updownarrow');
|
||||
if (star) {
|
||||
top.EndEntry();
|
||||
top.EndEntry();
|
||||
}
|
||||
const tex = (star ? '\\quad' + symbol : symbol + '\\quad');
|
||||
const mml = new TexParser(tex, parser.stack.env, parser.configuration).mml();
|
||||
parser.Push(mml);
|
||||
top.EndEntry();
|
||||
top.EndRow();
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \vdotswithin.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
VDotsWithin(parser: TexParser, name: string) {
|
||||
const top = parser.stack.Top() as EqnArrayItem;
|
||||
const isFlush = (top.getProperty('flushspaceabove') === top.table.length);
|
||||
const arg = '\\mmlToken{mi}{}' + parser.GetArgument(name) + '\\mmlToken{mi}{}';
|
||||
const base = new TexParser(arg, parser.stack.env, parser.configuration).mml();
|
||||
let mml = parser.create('node', 'mpadded', [
|
||||
parser.create('node', 'mpadded', [
|
||||
parser.create('node', 'mo', [
|
||||
parser.create('text', '\u22EE')
|
||||
])
|
||||
], {
|
||||
width: 0,
|
||||
lspace: '-.5width', ...(isFlush ? {height: '-.6em', voffset: '-.18em'} : {})
|
||||
}),
|
||||
parser.create('node', 'mphantom', [base])
|
||||
], {
|
||||
lspace: '.5width'
|
||||
});
|
||||
parser.Push(mml);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \shortvdotswithin.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
ShortVDotsWithin(parser: TexParser, _name: string) {
|
||||
const top = parser.stack.Top() as EqnArrayItem;
|
||||
const star = parser.GetStar();
|
||||
MathtoolsMethods.FlushSpaceAbove(parser, '\\MTFlushSpaceAbove');
|
||||
!star && top.EndEntry();
|
||||
MathtoolsMethods.VDotsWithin(parser, '\\vdotswithin');
|
||||
star && top.EndEntry();
|
||||
MathtoolsMethods.FlushSpaceBelow(parser, '\\MTFlushSpaceBelow');
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \MTFlushSpaceAbove.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
FlushSpaceAbove(parser: TexParser, name: string) {
|
||||
const top = MathtoolsUtil.checkAlignment(parser, name);
|
||||
top.setProperty('flushspaceabove', top.table.length); // marker so \vdotswithin can shorten its height
|
||||
top.addRowSpacing('-' + parser.options.mathtools['shortvdotsadjustabove']);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \MTFlushSpaceBelow.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
FlushSpaceBelow(parser: TexParser, name: string) {
|
||||
const top = MathtoolsUtil.checkAlignment(parser, name);
|
||||
top.Size() && top.EndEntry();
|
||||
top.EndRow();
|
||||
top.addRowSpacing('-' + parser.options.mathtools['shortvdotsadjustbelow']);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements a paired delimiter (e.g., from \DeclarePairedDelimiter).
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {string} open The open delimiter.
|
||||
* @param {string} close The close delimiter.
|
||||
* @param {string?} body The body betweeen the delimiters.
|
||||
* @param {number?} n The number of arguments to use for the body.
|
||||
* @param {string?} pre The TeX to go before the open delimiter.
|
||||
* @param {string?} post The TeX to go after the close delimiter.
|
||||
*/
|
||||
PairedDelimiters(parser: TexParser, name: string,
|
||||
open: string, close: string,
|
||||
body: string = '#1', n: number = 1,
|
||||
pre: string = '', post: string = '') {
|
||||
const star = parser.GetStar();
|
||||
const size = (star ? '' : parser.GetBrackets(name));
|
||||
const [left, right] = (star ? ['\\left', '\\right'] : size ? [size + 'l' , size + 'r'] : ['', '']);
|
||||
const delim = (star ? '\\middle' : size || '');
|
||||
if (n) {
|
||||
const args: string[] = [];
|
||||
for (let i = args.length; i < n; i++) {
|
||||
args.push(parser.GetArgument(name));
|
||||
}
|
||||
pre = ParseUtil.substituteArgs(parser, args, pre);
|
||||
body = ParseUtil.substituteArgs(parser, args, body);
|
||||
post = ParseUtil.substituteArgs(parser, args, post);
|
||||
}
|
||||
body = body.replace(/\\delimsize/g, delim);
|
||||
parser.string = [pre, left, open, body, right, close, post, parser.string.substr(parser.i)]
|
||||
.reduce((s, part) => ParseUtil.addArgs(parser, s, part), '');
|
||||
parser.i = 0;
|
||||
ParseUtil.checkMaxMacros(parser);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \DeclarePairedDelimiter.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
DeclarePairedDelimiter(parser: TexParser, name: string) {
|
||||
const cs = NewcommandUtil.GetCsNameArgument(parser, name);
|
||||
const open = parser.GetArgument(name);
|
||||
const close = parser.GetArgument(name);
|
||||
MathtoolsUtil.addPairedDelims(parser.configuration, cs, [open, close]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \DeclarePairedDelimiterX.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
DeclarePairedDelimiterX(parser: TexParser, name: string) {
|
||||
const cs = NewcommandUtil.GetCsNameArgument(parser, name);
|
||||
const n = NewcommandUtil.GetArgCount(parser, name);
|
||||
const open = parser.GetArgument(name);
|
||||
const close = parser.GetArgument(name);
|
||||
const body = parser.GetArgument(name);
|
||||
MathtoolsUtil.addPairedDelims(parser.configuration, cs, [open, close, body, n]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \DeclarePairedDelimiterXPP.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
DeclarePairedDelimiterXPP(parser: TexParser, name: string) {
|
||||
const cs = NewcommandUtil.GetCsNameArgument(parser, name);
|
||||
const n = NewcommandUtil.GetArgCount(parser, name);
|
||||
const pre = parser.GetArgument(name);
|
||||
const open = parser.GetArgument(name);
|
||||
const close = parser.GetArgument(name);
|
||||
const post = parser.GetArgument(name);
|
||||
const body = parser.GetArgument(name);
|
||||
MathtoolsUtil.addPairedDelims(parser.configuration, cs, [open, close, body, n, pre, post]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \centeredcolon, \ordinarycolon, \MTThinColon.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {boolean} center True if colon should be centered
|
||||
* @param {boolean} force True menas always center (don't use centercolon option).
|
||||
* @param {boolean} thin True if this is a thin color (for \coloneqq, etc).
|
||||
*/
|
||||
CenterColon(parser: TexParser, _name: string, center: boolean, force: boolean = false, thin: boolean = false) {
|
||||
const options = parser.options.mathtools;
|
||||
let mml = parser.create('token', 'mo', {}, ':');
|
||||
if (center && (options['centercolon'] || force)) {
|
||||
const dy = options['centercolon-offset'];
|
||||
mml = parser.create('node', 'mpadded', [mml], {
|
||||
voffset: dy, height: `+${dy}`, depth: `-${dy}`,
|
||||
...(thin ? {width: options['thincolon-dw'], lspace: options['thincolon-dx']} : {})
|
||||
});
|
||||
}
|
||||
parser.Push(mml);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \coloneqq and related macros.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {string} tex The tex string to use (if not using unicode versions or if there isn't one).
|
||||
* @param {string} unicode The unicode character (if there is one).
|
||||
*/
|
||||
Relation(parser: TexParser, _name: string, tex: string, unicode?: string) {
|
||||
const options = parser.options.mathtools;
|
||||
if (options['use-unicode'] && unicode) {
|
||||
parser.Push(parser.create('token', 'mo', {texClass: TEXCLASS.REL}, unicode));
|
||||
} else {
|
||||
tex = '\\mathrel{' + tex.replace(/:/g, '\\MTThinColon').replace(/-/g, '\\mathrel{-}') + '}';
|
||||
parser.string = ParseUtil.addArgs(parser, tex, parser.string.substr(parser.i));
|
||||
parser.i = 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \ndownarrow and \nuparrow via a terrible hack (visual only, no chance of this working with SRE).
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {string} c The base arrow for the slashed version
|
||||
* @param {string} dy A vertical offset for the slash
|
||||
*/
|
||||
NArrow(parser: TexParser, _name: string, c: string, dy: string) {
|
||||
parser.Push(
|
||||
parser.create('node', 'TeXAtom', [
|
||||
parser.create('token', 'mtext', {}, c),
|
||||
parser.create('node', 'mpadded', [
|
||||
parser.create('node', 'mpadded', [
|
||||
parser.create('node', 'menclose', [
|
||||
parser.create('node', 'mspace', [], {height: '.2em', depth: 0, width: '.4em'})
|
||||
], {notation: 'updiagonalstrike', 'data-thickness': '.05em', 'data-padding': 0})
|
||||
], {width: 0, lspace: '-.5width', voffset: dy}),
|
||||
parser.create('node', 'mphantom', [
|
||||
parser.create('token', 'mtext', {}, c)
|
||||
])
|
||||
], {width: 0, lspace: '-.5width'})
|
||||
], {texClass: TEXCLASS.REL})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \splitfrac and \splitdfrac.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {boolean} display True if \splitdfrac.
|
||||
*/
|
||||
SplitFrac(parser: TexParser, name: string, display: boolean) {
|
||||
const num = parser.ParseArg(name);
|
||||
const den = parser.ParseArg(name);
|
||||
parser.Push(
|
||||
parser.create('node', 'mstyle', [
|
||||
parser.create('node', 'mfrac', [
|
||||
parser.create('node', 'mstyle', [
|
||||
num,
|
||||
parser.create('token', 'mi'),
|
||||
parser.create('token', 'mspace', {width: '1em'}) // no parameter for this in mathtools. Should we add one?
|
||||
], {scriptlevel: 0}),
|
||||
parser.create('node', 'mstyle', [
|
||||
parser.create('token', 'mspace', {width: '1em'}),
|
||||
parser.create('token', 'mi'),
|
||||
den
|
||||
], {scriptlevel: 0})
|
||||
], {linethickness: 0, numalign: 'left', denomalign: 'right'})
|
||||
], {displaystyle: display, scriptlevel: 0})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \xmathstrut.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
XMathStrut(parser: TexParser, name: string) {
|
||||
let dd = parser.GetBrackets(name);
|
||||
let dh = parser.GetArgument(name);
|
||||
dh = MathtoolsUtil.plusOrMinus(name, dh);
|
||||
dd = MathtoolsUtil.plusOrMinus(name, dd || dh);
|
||||
parser.Push(
|
||||
parser.create('node', 'TeXAtom', [
|
||||
parser.create('node', 'mpadded', [
|
||||
parser.create('node', 'mphantom', [
|
||||
parser.create('token', 'mo', {stretchy: false}, '(')
|
||||
])
|
||||
], {width: 0, height: dh + 'height', depth: dd + 'depth'})
|
||||
], {texClass: TEXCLASS.ORD})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \prescript.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
Prescript(parser: TexParser, name: string) {
|
||||
const sup = MathtoolsUtil.getScript(parser, name, 'sup');
|
||||
const sub = MathtoolsUtil.getScript(parser, name, 'sub');
|
||||
const base = MathtoolsUtil.getScript(parser, name, 'arg');
|
||||
if (NodeUtil.isType(sup, 'none') && NodeUtil.isType(sub, 'none')) {
|
||||
parser.Push(base);
|
||||
return;
|
||||
}
|
||||
const mml = parser.create('node', 'mmultiscripts', [base]);
|
||||
NodeUtil.getChildren(mml).push(null, null);
|
||||
NodeUtil.appendChildren(mml, [parser.create('node', 'mprescripts'), sub, sup]);
|
||||
mml.setProperty('fixPrescript', true);
|
||||
parser.Push(mml);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \newtagform and \renewtagform.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
* @param {boolean=} renew True if \renewtagform.
|
||||
*/
|
||||
NewTagForm(parser: TexParser, name: string, renew: boolean = false) {
|
||||
const tags = parser.tags as MathtoolsTags;
|
||||
if (!('mtFormats' in tags)) {
|
||||
throw new TexError('TagsNotMT', '%1 can only be used with ams or mathtools tags', name);
|
||||
}
|
||||
const id = parser.GetArgument(name).trim();
|
||||
if (!id) {
|
||||
throw new TexError('InvalidTagFormID', 'Tag form name can\'t be empty');
|
||||
}
|
||||
const format = parser.GetBrackets(name, '');
|
||||
const left = parser.GetArgument(name);
|
||||
const right = parser.GetArgument(name);
|
||||
if (!renew && tags.mtFormats.has(id)) {
|
||||
throw new TexError('DuplicateTagForm', 'Duplicate tag form: %1', id);
|
||||
}
|
||||
tags.mtFormats.set(id, [left, right, format]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \usetagform.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
UseTagForm(parser: TexParser, name: string) {
|
||||
const tags = parser.tags as MathtoolsTags;
|
||||
if (!('mtFormats' in tags)) {
|
||||
throw new TexError('TagsNotMT', '%1 can only be used with ams or mathtools tags', name);
|
||||
}
|
||||
const id = parser.GetArgument(name).trim();
|
||||
if (!id) {
|
||||
tags.mtCurrent = null;
|
||||
return;
|
||||
}
|
||||
if (!tags.mtFormats.has(id)) {
|
||||
throw new TexError('UndefinedTagForm', 'Undefined tag form: %1', id);
|
||||
}
|
||||
tags.mtCurrent = tags.mtFormats.get(id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Implements \mathtoolsset.
|
||||
*
|
||||
* @param {TexParser} parser The calling parser.
|
||||
* @param {string} name The macro name.
|
||||
*/
|
||||
SetOptions(parser: TexParser, name: string) {
|
||||
const options = parser.options.mathtools;
|
||||
if (!options['allow-mathtoolsset']) {
|
||||
throw new TexError('ForbiddenMathtoolsSet', '%1 is disabled', name);
|
||||
}
|
||||
const allowed = {} as {[id: string]: number};
|
||||
Object.keys(options).forEach(id => {
|
||||
if (id !== 'pariedDelimiters' && id !== 'tagforms' && id !== 'allow-mathtoolsset') {
|
||||
allowed[id] = 1;
|
||||
}
|
||||
});
|
||||
const args = parser.GetArgument(name);
|
||||
const keys = ParseUtil.keyvalOptions(args, allowed, true);
|
||||
for (const id of Object.keys(keys)) {
|
||||
options[id] = keys[id];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Use the Base or AMS methods for these
|
||||
*/
|
||||
Array: BaseMethods.Array,
|
||||
Macro: BaseMethods.Macro,
|
||||
xArrow: AmsMethods.xArrow,
|
||||
HandleRef: AmsMethods.HandleRef,
|
||||
AmsEqnArray: AmsMethods.AmsEqnArray,
|
||||
MacroWithTemplate: NewcommandMethods.MacroWithTemplate,
|
||||
|
||||
};
|
||||
116
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsTags.ts
generated
vendored
Normal file
116
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsTags.ts
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*************************************************************
|
||||
* Copyright (c) 2021-2022 MathJax Consortium
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Tags implementation for the mathtools package.
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide P. Cervone)
|
||||
*/
|
||||
|
||||
import TexError from '../TexError.js';
|
||||
import {ParserConfiguration} from '../Configuration.js';
|
||||
import {TeX} from '../../tex.js';
|
||||
import {AbstractTags, TagsFactory} from '../Tags.js';
|
||||
|
||||
|
||||
/**
|
||||
* The type for the Mathtools tags (including their data).
|
||||
*/
|
||||
export type MathtoolsTags = AbstractTags & {
|
||||
mtFormats: Map<string, [string, string, string]>; // name -> [left, right, format]
|
||||
mtCurrent: [string, string, string]; // [left, right, format]
|
||||
};
|
||||
|
||||
/**
|
||||
* The ID number for the current tag class
|
||||
*/
|
||||
let tagID = 0;
|
||||
|
||||
/**
|
||||
* Creates and registers a subclass of the currently configured tag class
|
||||
* that handles the formats created by the \newtagform macro.
|
||||
*/
|
||||
export function MathtoolsTagFormat(config: ParserConfiguration, jax: TeX<any, any, any>) {
|
||||
/**
|
||||
* If the tag format is being added by one of the other extensions,
|
||||
* as is done for the 'ams' tags, make sure it is defined so we can create it.
|
||||
*/
|
||||
const tags = jax.parseOptions.options.tags;
|
||||
if (tags !== 'base' && config.tags.hasOwnProperty(tags)) {
|
||||
TagsFactory.add(tags, config.tags[tags]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The original tag class to be extended (none, ams, or all)
|
||||
*/
|
||||
const TagClass = TagsFactory.create(jax.parseOptions.options.tags).constructor as typeof AbstractTags;
|
||||
|
||||
/**
|
||||
* A Tags object that uses \newtagform to define the formatting
|
||||
*/
|
||||
class TagFormat extends TagClass {
|
||||
|
||||
/**
|
||||
* The defined tag formats
|
||||
*/
|
||||
public mtFormats: Map<string, [string, string, string]> = new Map();
|
||||
|
||||
/**
|
||||
* The format currently in use ([left, right, format]), or null for using the default
|
||||
*/
|
||||
public mtCurrent: [string, string, string] = null;
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
const forms = jax.parseOptions.options.mathtools.tagforms;
|
||||
for (const form of Object.keys(forms)) {
|
||||
if (!Array.isArray(forms[form]) || forms[form].length !== 3) {
|
||||
throw new TexError('InvalidTagFormDef',
|
||||
'The tag form definition for "%1" should be an array fo three strings', form);
|
||||
}
|
||||
this.mtFormats.set(form, forms[form]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public formatTag(tag: string) {
|
||||
if (this.mtCurrent) {
|
||||
const [left, right, format] = this.mtCurrent;
|
||||
return (format ? `${left}${format}{${tag}}${right}` : `${left}${tag}${right}`);
|
||||
}
|
||||
return super.formatTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get a unique name for the tag class (since it is tied to the input jax)
|
||||
// Note: These never get freed, so they will accumulate if you create many
|
||||
// TeX input jax instances with this extension.
|
||||
//
|
||||
tagID++;
|
||||
const tagName = 'MathtoolsTags-' + tagID;
|
||||
//
|
||||
// Register the tag class
|
||||
//
|
||||
TagsFactory.add(tagName, TagFormat);
|
||||
jax.parseOptions.options.tags = tagName;
|
||||
}
|
||||
145
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsUtil.ts
generated
vendored
Normal file
145
node_modules/mathjax-full/ts/input/tex/mathtools/MathtoolsUtil.ts
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
/*************************************************************
|
||||
* Copyright (c) 2021-2022 MathJax Consortium
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Utility functions for the mathtools package.
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide P. Cervone)
|
||||
*/
|
||||
|
||||
import {EqnArrayItem} from '../base/BaseItems.js';
|
||||
import ParseUtil from '../ParseUtil.js';
|
||||
import TexParser from '../TexParser.js';
|
||||
import TexError from '../TexError.js';
|
||||
import {CommandMap} from '../SymbolMap.js';
|
||||
import {Macro} from '../Symbol.js';
|
||||
import ParseOptions from '../ParseOptions.js';
|
||||
import {lookup} from '../../../util/Options.js';
|
||||
import {MmlNode} from '../../../core/MmlTree/MmlNode.js';
|
||||
|
||||
import {MathtoolsMethods} from './MathtoolsMethods.js';
|
||||
import {PAIREDDELIMS} from './MathtoolsConfiguration.js';
|
||||
|
||||
/**
|
||||
* Utility functions for the Mathtools package.
|
||||
*/
|
||||
export const MathtoolsUtil = {
|
||||
|
||||
/**
|
||||
* Set the displaystyle and scriptlevel attributes of an mstyle element
|
||||
*
|
||||
* @param {MmlNode} mml The mstyle node to modify.
|
||||
* @param {string} style The TeX style macro to apply.
|
||||
*/
|
||||
setDisplayLevel(mml: MmlNode, style: string) {
|
||||
if (!style) return;
|
||||
const [display, script] = lookup(style, {
|
||||
'\\displaystyle': [true, 0],
|
||||
'\\textstyle': [false, 0],
|
||||
'\\scriptstyle': [false, 1],
|
||||
'\\scriptscriptstyle': [false, 2]
|
||||
}, [null, null]);
|
||||
if (display !== null) {
|
||||
mml.attributes.set('displaystyle', display);
|
||||
mml.attributes.set('scriptlevel', script);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check that the top stack item is an alignment table.
|
||||
*
|
||||
* @param {TexParser} parser The current TeX parser.
|
||||
* @param {string} name The name of the macro doing the checking.
|
||||
* @return {EqnArrayItem} The top item (an EqnArrayItem).
|
||||
*/
|
||||
checkAlignment(parser: TexParser, name: string): EqnArrayItem {
|
||||
const top = parser.stack.Top() as EqnArrayItem;
|
||||
if (top.kind !== EqnArrayItem.prototype.kind) {
|
||||
throw new TexError('NotInAlignment', '%1 can only be used in aligment environments', name);
|
||||
}
|
||||
return top;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a paired delimiter to the list of them.
|
||||
*
|
||||
* @param {ParseOptions} config The parse options to modify.
|
||||
* @param {string} cs The control sequence for the paired delimiters.
|
||||
* @param {string[]} args The definition for the paired delimiters. One of:
|
||||
* [left, right]
|
||||
* [left, right, body, argcount]
|
||||
* [left, right, body, argcount, pre, post]
|
||||
*/
|
||||
addPairedDelims(config: ParseOptions, cs: string, args: string[]) {
|
||||
const delims = config.handlers.retrieve(PAIREDDELIMS) as CommandMap;
|
||||
delims.add(cs, new Macro(cs, MathtoolsMethods.PairedDelimiters, args));
|
||||
},
|
||||
|
||||
/**
|
||||
* Adjust the line spacing for a table.
|
||||
*
|
||||
* @param {MmlNode} mtable The mtable node to adjust (if it is a table).
|
||||
* @param {string} spread The dimension to change by (number-with-units).
|
||||
*/
|
||||
spreadLines(mtable: MmlNode, spread: string) {
|
||||
if (!mtable.isKind('mtable')) return;
|
||||
let rowspacing = mtable.attributes.get('rowspacing') as string;
|
||||
if (rowspacing) {
|
||||
const add = ParseUtil.dimen2em(spread);
|
||||
rowspacing = rowspacing
|
||||
.split(/ /)
|
||||
.map(s => ParseUtil.Em(Math.max(0, ParseUtil.dimen2em(s) + add)))
|
||||
.join(' ');
|
||||
} else {
|
||||
rowspacing = spread;
|
||||
}
|
||||
mtable.attributes.set('rowspacing', rowspacing);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if a string is a number and return it with an explicit plus if there isn't one.
|
||||
*
|
||||
* @param {string} name The name of the macro doing the checking.
|
||||
* @param {string} n The string to test as a number.
|
||||
* @return {srtring} The number with an explicit sign.
|
||||
*/
|
||||
plusOrMinus(name: string, n: string): string {
|
||||
n = n.trim();
|
||||
if (!n.match(/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)$/)) {
|
||||
throw new TexError('NotANumber', 'Argument to %1 is not a number', name);
|
||||
}
|
||||
return (n.match(/^[-+]/) ? n : '+' + n);
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse a \prescript argument, with its associated format, if any.
|
||||
*
|
||||
* @param {TexParser} parser The active tex parser.
|
||||
* @param {string} name The name of the calling macro (\prescript).
|
||||
* @param {string} pos The position for the argument (sub, sup, arg).
|
||||
* @return {MmlNode} The parsed MML version of the argument.
|
||||
*/
|
||||
getScript(parser: TexParser, name: string, pos: string): MmlNode {
|
||||
let arg = ParseUtil.trimSpaces(parser.GetArgument(name));
|
||||
if (arg === '') {
|
||||
return parser.create('node', 'none');
|
||||
}
|
||||
const format = parser.options.mathtools[`prescript-${pos}-format`];
|
||||
format && (arg = `${format}{${arg}}`);
|
||||
return new TexParser(arg, parser.stack.env, parser.configuration).mml();
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user