1
0

add initial marp implementation with sample content and build configuration

This commit is contained in:
2025-09-13 18:13:22 +02:00
parent dcacc9b409
commit e5f219507f
10319 changed files with 1402023 additions and 0 deletions

668
node_modules/mathjax-full/ts/core/DOMAdaptor.ts generated vendored Normal file
View File

@@ -0,0 +1,668 @@
/*************************************************************
*
* Copyright (c) 2018-2022 The 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 The DOMAdaptor interface and abstract class
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {OptionList} from '../util/Options.js';
/**
* The data for an attribute
*/
export type AttributeData = {
name: string,
value: string
};
/**
* The data for an elements page-based bounding box
*/
export type PageBBox = {
left: number,
right: number,
top: number,
bottom: number
};
/*****************************************************************/
/**
* The interface for the DOMAdaptor
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface DOMAdaptor<N, T, D> {
/**
* Document in which the nodes are to be created
*/
document: D;
/**
* @param {string} text The serialized document to be parsed
* @param {string} format The format (e.g., 'text/html' or 'text/xhtml')
* @return {D} The parsed document
*/
parse(text: string, format?: string): D;
/**
* @param {string} kind The tag name of the HTML node to be created
* @param {OptionList} def The properties to set for the created node
* @param {(N|T)[]} children The child nodes for the created HTML node
* @param {string} ns The namespace in which to create the node
* @return {N} The generated HTML tree
*/
node(kind: string, def?: OptionList, children?: (N | T)[], ns?: string): N;
/**
* @param {string} text The text from which to create an HTML text node
* @return {T} The generated text node with the given text
*/
text(text: string): T;
/**
* @param {D} doc The document whose head is to be obtained
* @return {N} The document.head element
*/
head(doc: D): N;
/**
* @param {D} doc The document whose body is to be obtained
* @return {N} The document.body element
*/
body(doc: D): N;
/**
* @param {D} doc The document whose documentElement is to be obtained
* @return {N} The documentElement
*/
root(doc: D): N;
/**
* @param {D} doc The document whose doctype is to be obtained
* @return {string} The DOCTYPE comment
*/
doctype(doc: D): string;
/**
* @param {N} node The node to search for tags
* @param {string} name The name of the tag to search for
* @param {string} ns The namespace to search in (or null for no namespace)
* @return {N[]} The list of tags found
*/
tags(node: N, name: string, ns?: string): N[];
/**
* Get a list of containers (to be searched for math). These can be
* specified by CSS selector, or as actual DOM elements or arrays of such.
*
* @param {(string | N | N[])[]} nodes The array of items to make into a container list
* @param {D} document The document in which to search
* @return {N[]} The array of containers to search
*/
getElements(nodes: (string | N | N[])[], document: D): N[];
/**
* Determine if a container node contains a given node somewhere in its DOM tree
*
* @param {N} container The container to search
* @param {N|T} node The node to look for
* @return {boolean} True if the node is in the container's DOM tree
*/
contains(container: N, node: N | T): boolean;
/**
* @param {N|T} node The HTML node whose parent is to be obtained
* @return {N} The parent node of the given one
*/
parent(node: N | T): N;
/**
* @param {N} node The HTML node to be appended to
* @param {N|T} child The node or text to be appended
* @return {N|T} The appended node
*/
append(node: N, child: N | T): N | T;
/**
* @param {N|T} nchild The node or text to be inserted
* @param {N|T} ochild The node or text where the new child is to be added before it
*/
insert(nchild: N | T, ochild: N | T): void;
/**
* @param {N|T} child The node or text to be removed from its parent
* @return {N|T} The removed node
*/
remove(child: N | T): N | T;
/**
* @param {N|T} nnode The node to replace with
* @param {N|T} onode The child to be replaced
* @return {N|T} The removed node
*/
replace(nnode: N | T, onode: N | T): N | T;
/**
* @param {N} node The HTML node to be cloned
* @return {N} The copied node
*/
clone(node: N): N;
/**
* @param {T} node The HTML text node to be split
* @param {number} n The index of the character where the split will occur
*/
split(node: T, n: number): T;
/**
* @param {N|T} node The HTML node whose sibling is to be obtained
* @return {N|T} The node following the given one (or null)
*/
next(node: N | T): N | T;
/**
* @param {N|T} node The HTML node whose sibling is to be obtained
* @return {N|T} The node preceding the given one (or null)
*/
previous(node: N | T): N | T;
/**
* @param {N} node The HTML node whose child is to be obtained
* @return {N|T} The first child of the given node (or null)
*/
firstChild(node: N): N | T;
/**
* @param {N} node The HTML node whose child is to be obtained
* @return {N} The last child of the given node (or null)
*/
lastChild(node: N): N | T;
/**
* @param {N} node The HTML node whose children are to be obtained
* @return {(N|T)[]} Array of children for the given node (not a live list)
*/
childNodes(node: N): (N | T)[];
/**
* @param {N} node The HTML node whose child is to be obtained
* @param {number} i The index of the child to return
* @return {N|T} The i-th child node of the given node (or null)
*/
childNode(node: N, i: number): N | T;
/**
* @param {N | T} node The HTML node whose tag or node name is to be obtained
* @return {string} The tag or node name of the given node
*/
kind(node: N | T): string;
/**
* @param {N|T} node The HTML node whose value is to be obtained
* @return {string} The value of the given node
*/
value(node: N | T): string;
/**
* @param {N} node The HTML node whose text content is to be obtained
* @return {string} The text content of the given node
*/
textContent(node: N): string;
/**
* @param {N} node The HTML node whose inner HTML string is to be obtained
* @return {string} The serialized content of the node
*/
innerHTML(node: N): string;
/**
* @param {N} node The HTML node whose outer HTML string is to be obtained
* @return {string} The serialized node and its content
*/
outerHTML(node: N): string;
/**
* @param {N} node The HTML node whose serialized string is to be obtained
* @return {string} The serialized node and its content
*/
serializeXML(node: N): string;
/**
* @param {N} node The HTML node whose attribute is to be set
* @param {string|number} name The name of the attribute to set
* @param {string} value The new value of the attribute
* @param {string=} ns The namespace to use for the attribute
*/
setAttribute(node: N, name: string, value: string | number, ns?: string): void;
/**
* @param {N} node The HTML element whose attributes are to be set
* @param {OptionList} def The attributes to set on that node
*/
setAttributes(node: N, def: OptionList): void;
/**
* @param {N} node The HTML node whose attribute is to be obtained
* @param {string} name The name of the attribute to get
* @return {string} The value of the given attribute of the given node
*/
getAttribute(node: N, name: string): string;
/**
* @param {N} node The HTML node whose attribute is to be removed
* @param {string} name The name of the attribute to remove
*/
removeAttribute(node: N, name: string): void;
/**
* @param {N} node The HTML node whose attribute is to be tested
* @param {string} name The name of the attribute to test
* @return {boolean} True of the node has the given attribute defined
*/
hasAttribute(node: N, name: string): boolean;
/**
* @param {N} node The HTML node whose attributes are to be returned
* @return {AttributeData[]} The list of attributes
*/
allAttributes(node: N): AttributeData[];
/**
* @param {N} node The HTML node whose class is to be augmented
* @param {string} name The class to be added
*/
addClass(node: N, name: string): void;
/**
* @param {N} node The HTML node whose class is to be changed
* @param {string} name The class to be removed
*/
removeClass(node: N, name: string): void;
/**
* @param {N} node The HTML node whose class is to be tested
* @param {string} name The class to test
* @return {boolean} True if the node has the given class
*/
hasClass(node: N, name: string): boolean;
/**
* @param {N} node The HTML node whose class list is needed
* @return {string[]} An array of the class names for this node
*/
allClasses(node: N): string[];
/**
* @param {N} node The HTML node whose style is to be changed
* @param {string} name The style to be set
* @param {string} value The new value of the style
*/
setStyle(node: N, name: string, value: string): void;
/**
* @param {N} node The HTML node whose style is to be obtained
* @param {string} name The style to be obtained
* @return {string} The value of the style
*/
getStyle(node: N, name: string): string;
/**
* @param {N} node The HTML node whose styles are to be returned
* @return {string} The cssText for the styles
*/
allStyles(node: N): string;
/**
* @param {N} node The stylesheet node where the rule will be added
* @param {string[]} rules The rule to add at the beginning of the stylesheet
*/
insertRules(node: N, rules: string[]): void;
/**
* @param {N} node The HTML node whose font size is to be determined
* @return {number} The font size (in pixels) of the node
*/
fontSize(node: N): number;
/**
* @param {N} node The HTML node whose font family is to be determined
* @return {string} The font family
*/
fontFamily(node: N): string;
/**
* @param {N} node The HTML node whose dimensions are to be determined
* @param {number} em The number of pixels in an em
* @param {boolean} local True if local coordinates are to be used in SVG elements
* @return {[number, number]} The width and height (in ems) of the element
*/
nodeSize(node: N, em?: number, local?: boolean): [number, number];
/**
* @param {N} node The HTML node whose BBox is to be determined
* @return {PageBBox} BBox as {left, right, top, bottom} position on the page (in pixels)
*/
nodeBBox(node: N): PageBBox;
}
/*****************************************************************/
/**
* Abstract DOMAdaptor class for creating HTML elements
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractDOMAdaptor<N, T, D> implements DOMAdaptor<N, T, D> {
/**
* The document in which the HTML nodes will be created
*/
public document: D;
/**
* @param {D} document The document in which the nodes will be created
* @constructor
*/
constructor(document: D = null) {
this.document = document;
}
/**
* @override
*/
public abstract parse(text: string, format?: string): D;
/**
* @override
*/
public node(kind: string, def: OptionList = {}, children: (N | T)[] = [], ns?: string) {
const node = this.create(kind, ns);
this.setAttributes(node, def);
for (const child of children) {
this.append(node, child);
}
return node as N;
}
/**
* @param {string} kind The type of the node to create
* @param {string} ns The optional namespace in which to create the node
* @return {N} The created node
*/
protected abstract create(kind: string, ns?: string): N;
/**
* @override
*/
public abstract text(text: string): T;
/**
* @param {N} node The HTML element whose attributes are to be set
* @param {OptionList} def The attributes to set on that node
*/
public setAttributes(node: N, def: OptionList) {
if (def.style && typeof(def.style) !== 'string') {
for (let key of Object.keys(def.style)) {
this.setStyle(node, key.replace(/-([a-z])/g, (_m, c) => c.toUpperCase()), def.style[key]);
}
}
if (def.properties) {
for (let key of Object.keys(def.properties)) {
(node as OptionList)[key] = def.properties[key];
}
}
for (let key of Object.keys(def)) {
if ((key !== 'style' || typeof(def.style) === 'string') && key !== 'properties') {
this.setAttribute(node, key, def[key]);
}
}
}
/**
* @override
*/
public abstract head(doc: D): N;
/**
* @override
*/
public abstract body(doc: D): N;
/**
* @override
*/
public abstract root(doc: D): N;
/**
* @override
*/
public abstract doctype(doc: D): string;
/**
* @override
*/
public abstract tags(node: N, name: string, ns?: string): N[];
/**
* @override
*/
public abstract getElements(nodes: (string | N | N[])[], document: D): N[];
/**
* @override
*/
public abstract contains(container: N, node: N | T): boolean;
/**
* @override
*/
public abstract parent(node: N | T): N;
/**
* @override
*/
public abstract append(node: N, child: N | T): N | T;
/**
* @override
*/
public abstract insert(nchild: N | T, ochild: N | T): void;
/**
* @override
*/
public abstract remove(child: N | T): N | T;
/**
* @override
*/
public replace(nnode: N | T, onode: N | T) {
this.insert(nnode, onode);
this.remove(onode);
return onode;
}
/**
* @override
*/
public abstract clone(node: N): N;
/**
* @override
*/
public abstract split(node: T, n: number): T;
/**
* @override
*/
public abstract next(node: N | T): N | T;
/**
* @override
*/
public abstract previous(node: N | T): N | T;
/**
* @override
*/
public abstract firstChild(node: N): N | T;
/**
* @override
*/
public abstract lastChild(node: N): N | T;
/**
* @override
*/
public abstract childNodes(node: N): (N | T)[];
/**
* @override
*/
public childNode(node: N, i: number) {
return this.childNodes(node)[i];
}
/**
* @override
*/
public abstract kind(node: N | T): string;
/**
* @override
*/
public abstract value(node: N | T): string;
/**
* @override
*/
public abstract textContent(node: N): string;
/**
* @override
*/
public abstract innerHTML(node: N): string;
/**
* @override
*/
public abstract outerHTML(node: N): string;
/**
* @override
*/
public abstract serializeXML(node: N): string;
/**
* @override
*/
public abstract setAttribute(node: N, name: string, value: string, ns?: string): void;
/**
* @override
*/
public abstract getAttribute(node: N, name: string): string;
/**
* @override
*/
public abstract removeAttribute(node: N, name: string): void;
/**
* @override
*/
public abstract hasAttribute(node: N, name: string): boolean;
/**
* @override
*/
public abstract allAttributes(node: N): AttributeData[];
/**
* @override
*/
public abstract addClass(node: N, name: string): void;
/**
* @override
*/
public abstract removeClass(node: N, name: string): void;
/**
* @override
*/
public abstract hasClass(node: N, name: string): boolean;
/**
* @override
*/
public allClasses(node: N) {
const classes = this.getAttribute(node, 'class');
return (!classes ? [] as string[] :
classes.replace(/ +/g, ' ').replace(/^ /, '').replace(/ $/, '').split(/ /));
}
/**
* @override
*/
public abstract setStyle(node: N, name: string, value: string): void;
/**
* @override
*/
public abstract getStyle(node: N, name: string): string;
/**
* @override
*/
public abstract allStyles(node: N): string;
/**
* @override
*/
public abstract insertRules(node: N, rules: string[]): void;
/**
* @override
*/
public abstract fontSize(node: N): number;
/**
* @override
*/
public abstract fontFamily(node: N): string;
/**
* @override
*/
public abstract nodeSize(node: N, em?: number, local?: boolean): [number, number];
/**
* @override
*/
public abstract nodeBBox(node: N): PageBBox;
}

90
node_modules/mathjax-full/ts/core/FindMath.ts generated vendored Normal file
View File

@@ -0,0 +1,90 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Interfaces and abstract classes for FindMath objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {userOptions, defaultOptions, OptionList} from '../util/Options.js';
import {ProtoItem} from './MathItem.js';
/*****************************************************************/
/**
* The FindMath interface
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template _D The Document class
*/
export interface FindMath<N, T, _D> {
/**
* One of two possibilities: Look through a DOM element,
* or look through an array of strings for delimited math.
*
* @param {N} node The node to search for math
* @return {ProtoItem<N, T>[]}
*/
findMath(node: N): ProtoItem<N, T>[];
/**
*
* @param {string[]} strings The strings to search for math
* @return {ProtoItem<N, T>[]}
*/
findMath(strings: string[]): ProtoItem<N, T>[];
}
/*****************************************************************/
/**
* The FindMath abstract class
*/
/**
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractFindMath<N, T, D> implements FindMath<N, T, D> {
/**
* The default options for FindMath
*/
public static OPTIONS: OptionList = {};
/**
* The actual options for this instance
*/
protected options: OptionList;
/**
* @param {OptionList} options The user options for this instance
*/
constructor(options: OptionList) {
let CLASS = this.constructor as typeof AbstractFindMath;
this.options = userOptions(defaultOptions({}, CLASS.OPTIONS), options);
}
/**
* Locate math in an Element or a string array;
*
* @param {Element | string[]} where The node or string array to search for math
* @return {ProtoItem[]} The array of proto math items found
*/
public abstract findMath(where: N | string[]): ProtoItem<N, T>[];
}

149
node_modules/mathjax-full/ts/core/Handler.ts generated vendored Normal file
View File

@@ -0,0 +1,149 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Interfaces and abstract classes for Handler objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MathDocument, AbstractMathDocument, MathDocumentConstructor} from './MathDocument.js';
import {OptionList} from '../util/Options.js';
import {DOMAdaptor} from '../core/DOMAdaptor.js';
/*****************************************************************/
/**
* The Handler interface
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface Handler<N, T, D> {
/**
* The name of the handler class
*/
name: string;
/**
* The DOM Adaptor to use for managing HTML elements
*/
adaptor: DOMAdaptor<N, T, D>;
/**
* The priority for the handler when handlers are polled
* to see which one can process a given document.
*/
priority: number;
/**
* The class implementing the MathDocument for this handler
* (so it can be subclassed by extensions as needed)
*/
documentClass: MathDocumentConstructor<AbstractMathDocument<N, T, D>>;
/**
* Checks to see if the handler can process a given document
*
* @param {any} document The document to be processed (string, window, etc.)
* @return {boolean} True if this handler can process the given document
*/
handlesDocument(document: any): boolean;
/**
* Creates a MathDocument for the given handler
*
* @param {any} document The document to be handled
* @param {OptionList} options The options for the handling of the document
* @return {MathDocument} The MathDocument object that manages the processing
*/
create(document: any, options: OptionList): MathDocument<N, T, D>;
}
/*****************************************************************/
/**
* The default MathDocument class (subclasses use their own)
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
class DefaultMathDocument<N, T, D> extends AbstractMathDocument<N, T, D> {}
/*****************************************************************/
/**
* The Handler interface
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractHandler<N, T, D> implements Handler<N, T, D> {
/**
* The name of this class
*/
public static NAME: string = 'generic';
/**
* The DOM Adaptor to use for managing HTML elements
*/
public adaptor: DOMAdaptor<N, T, D>;
/**
* The priority for this handler
*/
public priority: number;
/**
* The class implementing the MathDocument for this handler
* (so it can be subclassed by extensions as needed)
*/
public documentClass: MathDocumentConstructor<AbstractMathDocument<N, T, D>> = DefaultMathDocument;
/**
* @param {number} priority The priority to use for this handler
*
* @constructor
*/
constructor(adaptor: DOMAdaptor<N, T, D>, priority: number = 5) {
this.adaptor = adaptor;
this.priority = priority;
}
/**
* @return {string} The name of this handler class
*/
public get name(): string {
return (this.constructor as typeof AbstractHandler).NAME;
}
/**
* @override
*/
public handlesDocument(_document: any) {
return false;
}
/**
* @override
*/
public create(document: any, options: OptionList) {
return new this.documentClass(document, this.adaptor, options) as MathDocument<N, T, D>;
}
}

81
node_modules/mathjax-full/ts/core/HandlerList.ts generated vendored Normal file
View File

@@ -0,0 +1,81 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the interface and abstract class for HandlerList objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PrioritizedList} from '../util/PrioritizedList.js';
import {OptionList} from '../util/Options.js';
import {Handler} from './Handler.js';
import {MathDocument} from './MathDocument.js';
/*****************************************************************/
/**
* The HandlerList class (extends PrioritizedList of Handlers)
*
* This list is used to find the handler for a given document
* by asking each handler to test if it can handle the document,
* and when one can, it is asked to create its associated MathDocument.
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export class HandlerList<N, T, D> extends PrioritizedList<Handler<N, T, D>> {
/**
* @param {Handler} handler The handler to register
* @return {Handler} The list item created for the handler
*/
public register(handler: Handler<N, T, D>): Handler<N, T, D> {
return this.add(handler, handler.priority);
}
/**
* @param {Handler} Handler The handler to remove from the list
*/
public unregister(handler: Handler<N, T, D>) {
this.remove(handler);
}
/**
* @param {any} document The document (string, window, DOM element, etc) to be handled
* @return {Handler} The handler from the list that can process the given document
*/
public handlesDocument(document: any): Handler<N, T, D> {
for (const item of this) {
let handler = item.item;
if (handler.handlesDocument(document)) {
return handler;
}
}
throw new Error(`Can't find handler for document`);
}
/**
* @param {any} document The document to be processed
* @param {OptionList} options The options for the handler
* @return {MathDocument} The MathDocument created by the handler for this document
*/
public document(document: any, options: OptionList = null): MathDocument<N, T, D> {
return this.handlesDocument(document).create(document, options);
}
}

242
node_modules/mathjax-full/ts/core/InputJax.ts generated vendored Normal file
View File

@@ -0,0 +1,242 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the interface and abstract class for the InputJax
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MathDocument} from './MathDocument.js';
import {MathItem, ProtoItem} from './MathItem.js';
import {MmlNode} from './MmlTree/MmlNode.js';
import {MmlFactory} from './MmlTree/MmlFactory.js';
import {userOptions, defaultOptions, OptionList} from '../util/Options.js';
import {FunctionList} from '../util/FunctionList.js';
import {DOMAdaptor} from '../core/DOMAdaptor.js';
/*****************************************************************/
/**
* The InputJax interface
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface InputJax<N, T, D> {
/**
* The name of the input jax subclass (e.g,. 'TeX')
*/
name: string;
/**
* Whether this input jax processes string arrays or DOM nodes
* (TeX and AsciiMath process strings, MathML processes DOM nodes)
*/
processStrings: boolean;
/**
* The options for this input jax instance
*/
options: OptionList;
/**
* Lists of pre- and post-filters to call before and after processing the input
*/
preFilters: FunctionList;
postFilters: FunctionList;
/**
* The DOM adaptor for managing HTML elements
*/
adaptor: DOMAdaptor<N, T, D>;
/**
* The MmlFactory for this input jax
*/
mmlFactory: MmlFactory;
/**
* @param {DOMAdaptor} adaptor The adaptor to use in this jax
*/
setAdaptor(adaptor: DOMAdaptor<N, T, D>): void;
/**
* @param {MmlFactory} mmlFactory The MmlFactory to use in this jax
*/
setMmlFactory(mmlFactory: MmlFactory): void;
/**
* Do any initialization that depends on the document being set up
*/
initialize(): void;
/**
* Reset any needed features of the input jax
*
* @param {any[]} args The arguments needed by the reset operation
*/
reset(...args: any[]): void;
/**
* Finds the math within the DOM or the list of strings
*
* @param {N | string[]} which The element or array of strings to be searched for math
* @param {OptionList} options The options for the search, if any
* @return {ProtoItem[]} Array of proto math items found (further processed by the
* handler to produce actual MathItem objects)
*/
findMath(which: N | string[], options?: OptionList): ProtoItem<N, T>[];
/**
* Convert the math in a math item into the internal format
*
* @param {MathItem} math The MathItem whose math content is to processed
* @param {MathDocument} document The MathDocument for this input jax.
* @return {MmlNode} The resulting internal node tree for the math
*/
compile(math: MathItem<N, T, D>, document: MathDocument<N, T, D>): MmlNode;
}
/*****************************************************************/
/**
* The abstract InputJax class
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractInputJax<N, T, D> implements InputJax<N, T, D> {
/**
* The name of the input jax
*/
public static NAME: string = 'generic';
/**
* The default options for the input jax
*/
public static OPTIONS: OptionList = {};
/**
* The actual options supplied to the input jax
*/
public options: OptionList;
/**
* Filters to run on the TeX string before it is processed
*/
public preFilters: FunctionList;
/**
* Filters to run on the generated MathML after the TeX string is processed
*/
public postFilters: FunctionList;
/**
* The DOMAdaptor for the MathDocument for this input jax
*/
public adaptor: DOMAdaptor<N, T, D> = null; // set by the handler
/**
* The MathML node factory
*/
public mmlFactory: MmlFactory = null; // set by the handler
/**
* @param {OptionList} options The options to apply to this input jax
*
* @constructor
*/
constructor(options: OptionList = {}) {
let CLASS = this.constructor as typeof AbstractInputJax;
this.options = userOptions(defaultOptions({}, CLASS.OPTIONS), options);
this.preFilters = new FunctionList();
this.postFilters = new FunctionList();
}
/**
* @return {string} The name of this input jax class
*/
public get name(): string {
return (this.constructor as typeof AbstractInputJax).NAME;
}
/**
* @override
*/
public setAdaptor(adaptor: DOMAdaptor<N, T, D>) {
this.adaptor = adaptor;
}
/**
* @override
*/
public setMmlFactory(mmlFactory: MmlFactory) {
this.mmlFactory = mmlFactory;
}
/**
* @override
*/
public initialize() {
}
/**
* @override
*/
public reset(..._args: any[]) {
}
/**
* @return {boolean} True means find math in string array, false means in DOM element
*/
public get processStrings(): boolean {
return true;
}
/**
* @override
*/
public findMath(_node: N | string[], _options?: OptionList) {
return [] as ProtoItem<N, T>[];
}
/**
* @override
*/
public abstract compile(math: MathItem<N, T, D>, document: MathDocument<N, T, D>): MmlNode;
/**
* Execute a set of filters, passing them the MathItem and any needed data,
* and return the (possibly modified) data
*
* @param {FunctionList} filters The list of functions to be performed
* @param {MathItem} math The math item that is being processed
* @param {MathDocument} document The math document containg the math item
* @param {any} data Whatever other data is needed
* @return {any} The (possibly modified) data
*/
protected executeFilters(
filters: FunctionList, math: MathItem<N, T, D>,
document: MathDocument<N, T, D>, data: any
): any {
let args = {math: math, document: document, data: data};
filters.execute(args);
return args.data;
}
}

987
node_modules/mathjax-full/ts/core/MathDocument.ts generated vendored Normal file
View File

@@ -0,0 +1,987 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the interface and abstract class for MathDocument objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {userOptions, defaultOptions, OptionList, expandable} from '../util/Options.js';
import {InputJax, AbstractInputJax} from './InputJax.js';
import {OutputJax, AbstractOutputJax} from './OutputJax.js';
import {MathList, AbstractMathList} from './MathList.js';
import {MathItem, AbstractMathItem, STATE} from './MathItem.js';
import {MmlNode, TextNode} from './MmlTree/MmlNode.js';
import {MmlFactory} from '../core/MmlTree/MmlFactory.js';
import {DOMAdaptor} from '../core/DOMAdaptor.js';
import {BitField, BitFieldClass} from '../util/BitField.js';
import {PrioritizedList} from '../util/PrioritizedList.js';
/*****************************************************************/
/**
* A function to call while rendering a document (usually calls a MathDocument method)
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export type RenderDoc<N, T, D> = (document: MathDocument<N, T, D>) => boolean;
/**
* A function to call while rendering a MathItem (usually calls one of its methods)
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export type RenderMath<N, T, D> = (math: MathItem<N, T, D>, document: MathDocument<N, T, D>) => boolean;
/**
* The data for an action to perform during rendering or conversion
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export type RenderData<N, T, D> = {
id: string, // The name for the action
renderDoc: RenderDoc<N, T, D>, // The action to take during a render() call
renderMath: RenderMath<N, T, D>, // The action to take during a rerender() or convert() call
convert: boolean // Whether the action is to be used during convert()
};
/**
* The data used to define a render action in configurations and options objects
* (the key is used as the id, the number in the data below is the priority, and
* the remainind data is as described below; if no boolean is given, convert = true
* by default)
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export type RenderAction<N, T, D> =
[number] | // id (i.e., key) is method name to use
[number, string] | // string is method to call
[number, string, string] | // the strings are methods names for doc and math
[number, RenderDoc<N, T, D>, RenderMath<N, T, D>] | // explicit functions for doc and math
[number, boolean] | // same as first above, with boolean for convert
[number, string, boolean] | // same as second above, with boolean for convert
[number, string, string, boolean] | // same as third above, with boolean for convert
[number, RenderDoc<N, T, D>, RenderMath<N, T, D>, boolean]; // same as forth above, with boolean for convert
/**
* An object representing a collection of rendering actions (id's tied to priority-and-method data)
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export type RenderActions<N, T, D> = {[id: string]: RenderAction<N, T, D>};
/**
* Implements a prioritized list of render actions. Extensions can add actions to the list
* to make it easy to extend the normal typesetting and conversion operations.
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export class RenderList<N, T, D> extends PrioritizedList<RenderData<N, T, D>> {
/**
* Creates a new RenderList from an initial list of rendering actions
*
* @param {RenderActions} actions The list of actions to take during render(), rerender(), and convert() calls
* @returns {RenderList} The newly created prioritied list
*/
public static create<N, T, D>(actions: RenderActions<N, T, D>): RenderList<N, T, D> {
const list = new this<N, T, D>();
for (const id of Object.keys(actions)) {
const [action, priority] = this.action<N, T, D>(id, actions[id]);
if (priority) {
list.add(action, priority);
}
}
return list;
}
/**
* Parses a RenderAction to produce the correspinding RenderData item
* (e.g., turn method names into actual functions that call the method)
*
* @param {string} id The id of the action
* @param {RenderAction} action The RenderAction defining the action
* @returns {[RenderData,number]} The corresponding RenderData definition for the action and its priority
*/
public static action<N, T, D>(id: string, action: RenderAction<N, T, D>): [RenderData<N, T, D>, number] {
let renderDoc, renderMath;
let convert = true;
let priority = action[0];
if (action.length === 1 || typeof action[1] === 'boolean') {
action.length === 2 && (convert = action[1] as boolean);
[renderDoc, renderMath] = this.methodActions(id);
} else if (typeof action[1] === 'string') {
if (typeof action[2] === 'string') {
action.length === 4 && (convert = action[3] as boolean);
const [method1, method2] = action.slice(1) as [string, string];
[renderDoc, renderMath] = this.methodActions(method1, method2);
} else {
action.length === 3 && (convert = action[2] as boolean);
[renderDoc, renderMath] = this.methodActions(action[1] as string);
}
} else {
action.length === 4 && (convert = action[3] as boolean);
[renderDoc, renderMath] = action.slice(1) as [RenderDoc<N, T, D>, RenderMath<N, T, D>];
}
return [{id, renderDoc, renderMath, convert} as RenderData<N, T, D>, priority];
}
/**
* Produces the doc and math actions for the given method name(s)
* (a blank name is a no-op)
*
* @param {string} method1 The method to use for the render() call
* @param {string} method1 The method to use for the rerender() and convert() calls
*/
protected static methodActions(method1: string, method2: string = method1) {
return [
(document: any) => {method1 && document[method1](); return false; },
(math: any, document: any) => {method2 && math[method2](document); return false; }
];
}
/**
* Perform the document-level rendering functions
*
* @param {MathDocument} document The MathDocument whose methods are to be called
* @param {number=} start The state at which to start rendering (default is UNPROCESSED)
*/
public renderDoc(document: MathDocument<N, T, D>, start: number = STATE.UNPROCESSED) {
for (const item of this.items) {
if (item.priority >= start) {
if (item.item.renderDoc(document)) return;
}
}
}
/**
* Perform the MathItem-level rendering functions
*
* @param {MathItem} math The MathItem whose methods are to be called
* @param {MathDocument} document The MathDocument to pass to the MathItem methods
* @param {number=} start The state at which to start rendering (default is UNPROCESSED)
*/
public renderMath(math: MathItem<N, T, D>, document: MathDocument<N, T, D>, start: number = STATE.UNPROCESSED) {
for (const item of this.items) {
if (item.priority >= start) {
if (item.item.renderMath(math, document)) return;
}
}
}
/**
* Perform the MathItem-level conversion functions
*
* @param {MathItem} math The MathItem whose methods are to be called
* @param {MathDocument} document The MathDocument to pass to the MathItem methods
* @param {number=} end The state at which to end rendering (default is LAST)
*/
public renderConvert(math: MathItem<N, T, D>, document: MathDocument<N, T, D>, end: number = STATE.LAST) {
for (const item of this.items) {
if (item.priority > end) return;
if (item.item.convert) {
if (item.item.renderMath(math, document)) return;
}
}
}
/**
* Find an entry in the list with a given ID
*
* @param {string} id The id to search for
* @returns {RenderData|null} The data for the given id, if found, or null
*/
public findID(id: string): RenderData<N, T, D> | null {
for (const item of this.items) {
if (item.item.id === id) {
return item.item;
}
}
return null;
}
}
/*****************************************************************/
/**
* The ways of specifying a container (a selector string, an actual node,
* or an array of those (e.g., the result of document.getElementsByTagName())
*
* @template N The HTMLElement node class
*/
export type ContainerList<N> = string | N | (string | N | N[])[];
/**
* The options allowed for the reset() method
*/
export type ResetList = {
all?: boolean,
processed?: boolean,
inputJax?: any[],
outputJax?: any[]
};
/**
* The default option list for the reset() method
*/
export const resetOptions: ResetList = {
all: false,
processed: false,
inputJax: null,
outputJax: null
};
/**
* The option list for when all options are to be reset
*/
export const resetAllOptions: ResetList = {
all: true,
processed: true,
inputJax: [],
outputJax: []
};
/*****************************************************************/
/**
* The MathDocument interface
*
* The MathDocument is created by MathJax.Document() and holds the
* document, the math found in it, and so on. The methods of the
* MathDocument all return the MathDocument itself, so you can
* chain the method calls. E.g.,
*
* const html = MathJax.Document('<html>...</html>');
* html.findMath()
* .compile()
* .getMetrics()
* .typeset()
* .updateDocument();
*
* The MathDocument is the main interface for page authors to
* interact with MathJax.
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface MathDocument<N, T, D> {
/**
* The document being processed (e.g., DOM document, or Markdown string)
*/
document: D;
/**
* The kind of MathDocument (e.g., "HTML")
*/
kind: string;
/**
* The options for the document
*/
options: OptionList;
/**
* The list of MathItems found in this page
*/
math: MathList<N, T, D>;
/**
* The list of actions to take during a render() or convert() call
*/
renderActions: RenderList<N, T, D>;
/**
* This object tracks what operations have been performed, so that (when
* asynchronous operations are used), the ones that have already been
* completed won't be performed again.
*/
processed: BitField;
/**
* An array of input jax to run on the document
*/
inputJax: InputJax<N, T, D>[];
/**
* The output jax to use for the document
*/
outputJax: OutputJax<N, T, D>;
/**
* The DOM adaptor to use for input and output
*/
adaptor: DOMAdaptor<N, T, D>;
/**
* The MmlFactory to be used for input jax and error processing
*/
mmlFactory: MmlFactory;
/**
* @param {string} id The id of the action to add
* @param {any[]} action The RenderAction to take
*/
addRenderAction(id: string, ...action: any[]): void;
/**
* @param {string} id The id of the action to remove
*/
removeRenderAction(id: string): void;
/**
* Perform the renderActions on the document
*/
render(): MathDocument<N, T, D>;
/**
* Rerender the MathItems on the page
*
* @param {number=} start The state to start rerendering at
* @return {MathDocument} The math document instance
*/
rerender(start?: number): MathDocument<N, T, D>;
/**
* Convert a math string to the document's output format
*
* @param {string} math The math string to convert
* @params {OptionList} options The options for the conversion (e.g., format, ex, em, etc.)
* @return {MmlNode|N} The MmlNode or N node for the converted content
*/
convert(math: string, options?: OptionList): MmlNode | N;
/**
* Locates the math in the document and constructs the MathList
* for the document.
*
* @param {OptionList} options The options for locating the math
* @return {MathDocument} The math document instance
*/
findMath(options?: OptionList): MathDocument<N, T, D>;
/**
* Calls the input jax to process the MathItems in the MathList
*
* @return {MathDocument} The math document instance
*/
compile(): MathDocument<N, T, D>;
/**
* Gets the metric information for the MathItems
*
* @return {MathDocument} The math document instance
*/
getMetrics(): MathDocument<N, T, D>;
/**
* Calls the output jax to process the compiled math in the MathList
*
* @return {MathDocument} The math document instance
*/
typeset(): MathDocument<N, T, D>;
/**
* Updates the document to include the typeset math
*
* @return {MathDocument} The math document instance
*/
updateDocument(): MathDocument<N, T, D>;
/**
* Removes the typeset math from the document
*
* @param {boolean} restore True if the original math should be put
* back into the document as well
* @return {MathDocument} The math document instance
*/
removeFromDocument(restore?: boolean): MathDocument<N, T, D>;
/**
* Set the state of the document (allowing you to roll back
* the state to a previous one, if needed).
*
* @param {number} state The new state of the document
* @param {boolean} restore True if the original math should be put
* back into the document during the rollback
* @return {MathDocument} The math document instance
*/
state(state: number, restore?: boolean): MathDocument<N, T, D>;
/**
* Clear the processed values so that the document can be reprocessed
*
* @param {ResetList} options The things to be reset
* @return {MathDocument} The math document instance
*/
reset(options?: ResetList): MathDocument<N, T, D>;
/**
* Reset the processed values and clear the MathList (so that new math
* can be processed in the document).
*
* @return {MathDocument} The math document instance
*/
clear(): MathDocument<N, T, D>;
/**
* Merges a MathList into the list for this document.
*
* @param {MathList} list The MathList to be merged into this document's list
* @return {MathDocument} The math document instance
*/
concat(list: MathList<N, T, D>): MathDocument<N, T, D>;
/**
* Clear the typeset MathItems that are within the given container
* from the document's MathList. (E.g., when the content of the
* container has been updated and you want to remove the
* associated MathItems)
*
* @param {ContainerList<N>} elements The container DOM elements whose math items are to be removed
* @return {MathItem<N,T,D>[]} The removed MathItems
*/
clearMathItemsWithin(containers: ContainerList<N>): MathItem<N, T, D>[];
/**
* Get the typeset MathItems that are within a given container.
*
* @param {ContainerList<N>} elements The container DOM elements whose math items are to be found
* @return {MathItem<N,T,D>[]} The list of MathItems within that container
*/
getMathItemsWithin(elements: ContainerList<N>): MathItem<N, T, D>[];
}
/*****************************************************************/
/**
* Defaults used when input jax isn't specified
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
class DefaultInputJax<N, T, D> extends AbstractInputJax<N, T, D> {
/**
* @override
*/
public compile(_math: MathItem<N, T, D>) {
return null as MmlNode;
}
}
/**
* Defaults used when ouput jax isn't specified
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
class DefaultOutputJax<N, T, D> extends AbstractOutputJax<N, T, D> {
/**
* @override
*/
public typeset(_math: MathItem<N, T, D>, _document: MathDocument<N, T, D> = null) {
return null as N;
}
/**
* @override
*/
public escaped(_math: MathItem<N, T, D>, _document?: MathDocument<N, T, D>) {
return null as N;
}
}
/**
* Default for the MathList when one isn't specified
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
class DefaultMathList<N, T, D> extends AbstractMathList<N, T, D> {}
/**
* Default for the Mathitem when one isn't specified
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
class DefaultMathItem<N, T, D> extends AbstractMathItem<N, T, D> {}
/*****************************************************************/
/**
* Implements the abstract MathDocument class
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractMathDocument<N, T, D> implements MathDocument<N, T, D> {
/**
* The type of MathDocument
*/
public static KIND: string = 'MathDocument';
/**
* The default options for the document
*/
public static OPTIONS: OptionList = {
OutputJax: null, // instance of an OutputJax for the document
InputJax: null, // instance of an InputJax or an array of them
MmlFactory: null, // instance of a MmlFactory for this document
MathList: DefaultMathList, // constructor for a MathList to use for the document
MathItem: DefaultMathItem, // constructor for a MathItem to use for the MathList
compileError: (doc: AbstractMathDocument<any, any, any>, math: MathItem<any, any, any>, err: Error) => {
doc.compileError(math, err);
},
typesetError: (doc: AbstractMathDocument<any, any, any>, math: MathItem<any, any, any>, err: Error) => {
doc.typesetError(math, err);
},
renderActions: expandable({
find: [STATE.FINDMATH, 'findMath', '', false],
compile: [STATE.COMPILED],
metrics: [STATE.METRICS, 'getMetrics', '', false],
typeset: [STATE.TYPESET],
update: [STATE.INSERTED, 'updateDocument', false]
}) as RenderActions<any, any, any>
};
/**
* A bit-field for the actions that have been processed
*/
public static ProcessBits = BitFieldClass('findMath', 'compile', 'getMetrics', 'typeset', 'updateDocument');
/**
* The document managed by this MathDocument
*/
public document: D;
/**
* The actual options for this document (with user-supplied ones merged in)
*/
public options: OptionList;
/**
* The list of MathItems for this document
*/
public math: MathList<N, T, D>;
/**
* The list of render actions
*/
public renderActions: RenderList<N, T, D>;
/**
* The bit-field used to tell what steps have been taken on the document (for retries)
*/
public processed: BitField;
/**
* The list of input jax for the document
*/
public inputJax: InputJax<N, T, D>[];
/**
* The output jax for the document
*/
public outputJax: OutputJax<N, T, D>;
/**
* The DOM adaptor for the document
*/
public adaptor: DOMAdaptor<N, T, D>;
/**
* The MathML node factory for the internal MathML representation
*/
public mmlFactory: MmlFactory;
/**
* @param {any} document The document (HTML string, parsed DOM, etc.) to be processed
* @param {DOMAdaptor} adaptor The DOM adaptor for this document
* @param {OptionList} options The options for this document
* @constructor
*/
constructor (document: D, adaptor: DOMAdaptor<N, T, D>, options: OptionList) {
let CLASS = this.constructor as typeof AbstractMathDocument;
this.document = document;
this.options = userOptions(defaultOptions({}, CLASS.OPTIONS), options);
this.math = new (this.options['MathList'] || DefaultMathList)();
this.renderActions = RenderList.create<N, T, D>(this.options['renderActions']);
this.processed = new AbstractMathDocument.ProcessBits();
this.outputJax = this.options['OutputJax'] || new DefaultOutputJax<N, T, D>();
let inputJax = this.options['InputJax'] || [new DefaultInputJax<N, T, D>()];
if (!Array.isArray(inputJax)) {
inputJax = [inputJax];
}
this.inputJax = inputJax;
//
// Pass the DOM adaptor to the jax
//
this.adaptor = adaptor;
this.outputJax.setAdaptor(adaptor);
this.inputJax.map(jax => jax.setAdaptor(adaptor));
//
// Pass the MmlFactory to the jax
//
this.mmlFactory = this.options['MmlFactory'] || new MmlFactory();
this.inputJax.map(jax => jax.setMmlFactory(this.mmlFactory));
//
// Do any initialization that requires adaptors or factories
//
this.outputJax.initialize();
this.inputJax.map(jax => jax.initialize());
}
/**
* @return {string} The kind of document
*/
public get kind(): string {
return (this.constructor as typeof AbstractMathDocument).KIND;
}
/**
* @override
*/
public addRenderAction(id: string, ...action: any[]) {
const [fn, p] = RenderList.action<N, T, D>(id, action as RenderAction<N, T, D>);
this.renderActions.add(fn, p);
}
/**
* @override
*/
public removeRenderAction(id: string) {
const action = this.renderActions.findID(id);
if (action) {
this.renderActions.remove(action);
}
}
/**
* @override
*/
public render() {
this.renderActions.renderDoc(this);
return this;
}
/**
* @override
*/
public rerender(start: number = STATE.RERENDER) {
this.state(start - 1);
this.render();
return this;
}
/**
* @override
*/
public convert(math: string, options: OptionList = {}) {
let {format, display, end, ex, em, containerWidth, lineWidth, scale, family} = userOptions({
format: this.inputJax[0].name, display: true, end: STATE.LAST,
em: 16, ex: 8, containerWidth: null, lineWidth: 1000000, scale: 1, family: ''
}, options);
if (containerWidth === null) {
containerWidth = 80 * ex;
}
const jax = this.inputJax.reduce((jax, ijax) => (ijax.name === format ? ijax : jax), null);
const mitem = new this.options.MathItem(math, jax, display);
mitem.start.node = this.adaptor.body(this.document);
mitem.setMetrics(em, ex, containerWidth, lineWidth, scale);
if (this.outputJax.options.mtextInheritFont) {
mitem.outputData.mtextFamily = family;
}
if (this.outputJax.options.merrorInheritFont) {
mitem.outputData.merrorFamily = family;
}
mitem.convert(this, end);
return (mitem.typesetRoot || mitem.root);
}
/**
* @override
*/
public findMath(_options: OptionList = null) {
this.processed.set('findMath');
return this;
}
/**
* @override
*/
public compile() {
if (!this.processed.isSet('compile')) {
//
// Compile all the math in the list
//
const recompile = [];
for (const math of this.math) {
this.compileMath(math);
if (math.inputData.recompile !== undefined) {
recompile.push(math);
}
}
//
// If any were added to the recompile list,
// compile them again
//
for (const math of recompile) {
const data = math.inputData.recompile;
math.state(data.state);
math.inputData.recompile = data;
this.compileMath(math);
}
this.processed.set('compile');
}
return this;
}
/**
* @param {MathItem} math The item to compile
*/
protected compileMath(math: MathItem<N, T, D>) {
try {
math.compile(this);
} catch (err) {
if (err.retry || err.restart) {
throw err;
}
this.options['compileError'](this, math, err);
math.inputData['error'] = err;
}
}
/**
* Produce an error using MmlNodes
*
* @param {MathItem} math The MathItem producing the error
* @param {Error} err The Error object for the error
*/
public compileError(math: MathItem<N, T, D>, err: Error) {
math.root = this.mmlFactory.create('math', null, [
this.mmlFactory.create('merror', {'data-mjx-error': err.message, title: err.message}, [
this.mmlFactory.create('mtext', null, [
(this.mmlFactory.create('text') as TextNode).setText('Math input error')
])
])
]);
if (math.display) {
math.root.attributes.set('display', 'block');
}
math.inputData.error = err.message;
}
/**
* @override
*/
public typeset() {
if (!this.processed.isSet('typeset')) {
for (const math of this.math) {
try {
math.typeset(this);
} catch (err) {
if (err.retry || err.restart) {
throw err;
}
this.options['typesetError'](this, math, err);
math.outputData['error'] = err;
}
}
this.processed.set('typeset');
}
return this;
}
/**
* Produce an error using HTML
*
* @param {MathItem} math The MathItem producing the error
* @param {Error} err The Error object for the error
*/
public typesetError(math: MathItem<N, T, D>, err: Error) {
math.typesetRoot = this.adaptor.node('mjx-container', {
class: 'MathJax mjx-output-error',
jax: this.outputJax.name,
}, [
this.adaptor.node('span', {
'data-mjx-error': err.message,
title: err.message,
style: {
color: 'red',
'background-color': 'yellow',
'line-height': 'normal'
}
}, [
this.adaptor.text('Math output error')
])
]);
if (math.display) {
this.adaptor.setAttributes(math.typesetRoot, {
style: {
display: 'block',
margin: '1em 0',
'text-align': 'center'
}
});
}
math.outputData.error = err.message;
}
/**
* @override
*/
public getMetrics() {
if (!this.processed.isSet('getMetrics')) {
this.outputJax.getMetrics(this);
this.processed.set('getMetrics');
}
return this;
}
/**
* @override
*/
public updateDocument() {
if (!this.processed.isSet('updateDocument')) {
for (const math of this.math.reversed()) {
math.updateDocument(this);
}
this.processed.set('updateDocument');
}
return this;
}
/**
* @override
*/
public removeFromDocument(_restore: boolean = false) {
return this;
}
/**
* @override
*/
public state(state: number, restore: boolean = false) {
for (const math of this.math) {
math.state(state, restore);
}
if (state < STATE.INSERTED) {
this.processed.clear('updateDocument');
}
if (state < STATE.TYPESET) {
this.processed.clear('typeset');
this.processed.clear('getMetrics');
}
if (state < STATE.COMPILED) {
this.processed.clear('compile');
}
return this;
}
/**
* @override
*/
public reset(options: ResetList = {processed: true}) {
options = userOptions(Object.assign({}, resetOptions), options);
options.all && Object.assign(options, resetAllOptions);
options.processed && this.processed.reset();
options.inputJax && this.inputJax.forEach(jax => jax.reset(...options.inputJax));
options.outputJax && this.outputJax.reset(...options.outputJax);
return this;
}
/**
* @override
*/
public clear() {
this.reset();
this.math.clear();
return this;
}
/**
* @override
*/
public concat(list: MathList<N, T, D>) {
this.math.merge(list);
return this;
}
/**
* @override
*/
public clearMathItemsWithin(containers: ContainerList<N>) {
const items = this.getMathItemsWithin(containers);
this.math.remove(...items);
return items;
}
/**
* @override
*/
public getMathItemsWithin(elements: ContainerList<N>) {
if (!Array.isArray(elements)) {
elements = [elements];
}
const adaptor = this.adaptor;
const items = [] as MathItem<N, T, D>[];
const containers = adaptor.getElements(elements, this.document);
ITEMS:
for (const item of this.math) {
for (const container of containers) {
if (item.start.node && adaptor.contains(container, item.start.node)) {
items.push(item);
continue ITEMS;
}
}
}
return items;
}
}
/**
* The constructor type for a MathDocument
*
* @template D The MathDocument type this constructor is for
*/
export interface MathDocumentConstructor<D extends MathDocument<any, any, any>> {
KIND: string;
OPTIONS: OptionList;
ProcessBits: typeof BitField;
new (...args: any[]): D;
}

458
node_modules/mathjax-full/ts/core/MathItem.ts generated vendored Normal file
View File

@@ -0,0 +1,458 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the interface and abstract class for MathItem objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MathDocument} from './MathDocument.js';
import {InputJax} from './InputJax.js';
import {OptionList} from '../util/Options.js';
import {MmlNode} from './MmlTree/MmlNode.js';
/*****************************************************************/
/**
* The Location gives a location of a position in a document
* (either a node and character position within it, or
* an index into a string array, the character position within
* the string, and the delimiter at that location).
*
* @template N The HTMLElement node class
* @template T The Text node class
*/
export type Location<N, T> = {
i?: number;
n?: number;
delim?: string;
node?: N | T;
};
/*****************************************************************/
/**
* The Metrics object includes the data needed to typeset
* a MathItem.
*/
export type Metrics = {
em: number;
ex: number;
containerWidth: number;
lineWidth: number;
scale: number;
};
/*****************************************************************/
/**
* The MathItem interface
*
* The MathItem is the object that holds the information about a
* particular expression on the page, including pointers to
* where it is in the document, its compiled version (in the
* internal format), its typeset version, its bounding box,
* and so on.
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface MathItem<N, T, D> {
/**
* The string representing the expression to be processed
*/
math: string;
/**
* The input jax used to process the math
*/
inputJax: InputJax<N, T, D>;
/**
* Whether the math is in display mode or inline mode
*/
display: boolean;
/**
* Whether this item is an escaped character or not
*/
isEscaped: boolean;
/**
* The start and ending locations in the document of
* this expression
*/
start: Location<N, T>;
end: Location<N, T>;
/**
* The internal format for this expression (once compiled)
*/
root: MmlNode;
/**
* The typeset version of the expression (once typeset)
*/
typesetRoot: N;
/**
* The metric information at the location of the math
* (the em-size, scaling factor, etc.)
*/
metrics: Metrics;
/**
* Extra data needed by the input or output jax, as needed
*/
inputData: OptionList;
outputData: OptionList;
/**
* Perform the renderActions on the document
*
* @param {MathDocument} document The MathDocument in which the math resides
*/
render(document: MathDocument<N, T, D>): void;
/**
* Rerenders an already rendered item and inserts it into the document
*
* @param {MathDocument} document The MathDocument in which the math resides
* @param {number=} start The state to start rerendering at (default = RERENDER)
*/
rerender(document: MathDocument<N, T, D>, start?: number): void;
/**
* Converts the expression by calling the render actions until the state matches the end state
*
* @param {MathDocument} document The MathDocument in which the math resides
* @param {number=} end The state to end rerendering at (default = LAST)
*/
convert(document: MathDocument<N, T, D>, end?: number): void;
/**
* Converts the expression into the internal format by calling the input jax
*
* @param {MathDocument} document The MathDocument in which the math resides
*/
compile(document: MathDocument<N, T, D>): void;
/**
* Converts the internal format to the typeset version by calling the output jax
*
* @param {MathDocument} document The MathDocument in which the math resides
*/
typeset(document: MathDocument<N, T, D>): void;
/**
* Inserts the typeset version in place of the original form in the document
*
* @param {MathDocument} document The MathDocument in which the math resides
*/
updateDocument(document: MathDocument<N, T, D>): void;
/**
* Removes the typeset version from the document, optionally replacing the original
* form of the expression and its delimiters.
*
* @param {boolean} restore True if the original version is to be restored
*/
removeFromDocument(restore: boolean): void;
/**
* Sets the metric information for this expression
*
* @param {number} em The size of 1 em in pixels
* @param {number} ex The size of 1 ex in pixels
* @param {number} cwidth The container width in pixels
* @param {number} lwidth The line breaking width in pixels
* @param {number} scale The scaling factor (unitless)
*/
setMetrics(em: number, ex: number, cwidth: number, lwidth: number, scale: number): void;
/**
* Set or return the current processing state of this expression,
* optionally restoring the document if rolling back an expression
* that has been added to the document.
*
* @param {number} state The state to set for the expression
* @param {number} restore True if the original form should be restored
* to the document when rolling back a typeset version
* @returns {number} The current state
*/
state(state?: number, restore?: boolean): number;
/**
* Reset the item to its unprocessed state
*
* @param {number} restore True if the original form should be restored
* to the document when rolling back a typeset version
*/
reset(restore?: boolean): void;
}
/*****************************************************************/
/**
* The ProtoItem interface
*
* This is what is returned by the FindMath class, giving the location
* of math within the document, and is used to produce the full
* MathItem later (e.g., when the position within a string array
* is translated back into the actual node location in the DOM).
*
* @template N The HTMLElement node class
* @template T The Text node class
*/
export type ProtoItem<N, T> = {
math: string; // The math expression itself
start: Location<N, T>; // The starting location of the math
end: Location<N, T>; // The ending location of the math
open?: string; // The opening delimiter
close?: string; // The closing delimiter
n?: number; // The index of the string in which this math is found
display: boolean; // True means display mode, false is inline mode
};
/**
* Produce a proto math item that can be turned into a MathItem
*
* @template N The HTMLElement node class
* @template T The Text node class
*/
export function protoItem<N, T>(open: string, math: string, close: string, n: number,
start: number, end: number, display: boolean = null) {
let item: ProtoItem<N, T> = {open: open, math: math, close: close,
n: n, start: {n: start}, end: {n: end}, display: display};
return item;
}
/*****************************************************************/
/**
* Implements the MathItem class
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractMathItem<N, T, D> implements MathItem<N, T, D> {
/**
* The source text for the math (e.g., TeX string)
*/
public math: string;
/**
* The input jax associated with this item
*/
public inputJax: InputJax<N, T, D>;
/**
* True when this math is in display mode
*/
public display: boolean;
/**
* Reference to the beginning of the math in the document
*/
public start: Location<N, T>;
/**
* Reference to the end of the math in the document
*/
public end: Location<N, T>;
/**
* The compiled internal MathML (result of InputJax)
*/
public root: MmlNode = null;
/**
* The typeset result (result of OutputJax)
*/
public typesetRoot: N = null;
/**
* The metric information about the surrounding environment
*/
public metrics: Metrics = {} as Metrics;
/**
* Data private to the input jax
*/
public inputData: OptionList = {};
/**
* Data private to the output jax
*/
public outputData: OptionList = {};
/**
* The current state of the item (how far in the render actions it has been processed)
*/
protected _state: number = STATE.UNPROCESSED;
/**
* @return {boolean} True when this item is an escaped delimiter
*/
public get isEscaped(): boolean {
return this.display === null;
}
/**
* @param {string} math The math expression for this item
* @param {Inputjax} jax The input jax to use for this item
* @param {boolean} display True if display mode, false if inline
* @param {Location} start The starting position of the math in the document
* @param {Location} end The ending position of the math in the document
* @constructor
*/
constructor (math: string, jax: InputJax<N, T, D>, display: boolean = true,
start: Location<N, T> = {i: 0, n: 0, delim: ''},
end: Location<N, T> = {i: 0, n: 0, delim: ''}) {
this.math = math;
this.inputJax = jax;
this.display = display;
this.start = start;
this.end = end;
this.root = null;
this.typesetRoot = null;
this.metrics = {} as Metrics;
this.inputData = {};
this.outputData = {};
}
/**
* @override
*/
public render(document: MathDocument<N, T, D>) {
document.renderActions.renderMath(this, document);
}
/**
* @override
*/
public rerender(document: MathDocument<N, T, D>, start: number = STATE.RERENDER) {
if (this.state() >= start) {
this.state(start - 1);
}
document.renderActions.renderMath(this, document, start);
}
/**
* @override
*/
public convert(document: MathDocument<N, T, D>, end: number = STATE.LAST) {
document.renderActions.renderConvert(this, document, end);
}
/**
* @override
*/
public compile(document: MathDocument<N, T, D>) {
if (this.state() < STATE.COMPILED) {
this.root = this.inputJax.compile(this, document);
this.state(STATE.COMPILED);
}
}
/**
* @override
*/
public typeset(document: MathDocument<N, T, D>) {
if (this.state() < STATE.TYPESET) {
this.typesetRoot = document.outputJax[this.isEscaped ? 'escaped' : 'typeset'](this, document);
this.state(STATE.TYPESET);
}
}
/**
* @override
*/
public updateDocument(_document: MathDocument<N, T, D>) {}
/**
* @override
*/
public removeFromDocument(_restore: boolean = false) {}
/**
* @override
*/
public setMetrics(em: number, ex: number, cwidth: number, lwidth: number, scale: number) {
this.metrics = {
em: em, ex: ex,
containerWidth: cwidth,
lineWidth: lwidth,
scale: scale
};
}
/**
* @override
*/
public state(state: number = null, restore: boolean = false) {
if (state != null) {
if (state < STATE.INSERTED && this._state >= STATE.INSERTED) {
this.removeFromDocument(restore);
}
if (state < STATE.TYPESET && this._state >= STATE.TYPESET) {
this.outputData = {};
}
if (state < STATE.COMPILED && this._state >= STATE.COMPILED) {
this.inputData = {};
}
this._state = state;
}
return this._state;
}
/**
* @override
*/
public reset(restore: boolean = false) {
this.state(STATE.UNPROCESSED, restore);
}
}
/*****************************************************************/
/**
* The various states that a MathItem (or MathDocument) can be in
* (open-ended so that extensions can add to it)
*/
export const STATE: {[state: string]: number} = {
UNPROCESSED: 0,
FINDMATH: 10,
COMPILED: 20,
CONVERT: 100,
METRICS: 110,
RERENDER: 125,
TYPESET: 150,
INSERTED: 200,
LAST: 10000
};
/**
* Allocate a new named state
*
* @param {string} name The name of the new state
* @param {number} state The value for the new state
*/
export function newState(name: string, state: number) {
if (name in STATE) {
throw Error('State ' + name + ' already exists');
}
STATE[name] = state;
}

63
node_modules/mathjax-full/ts/core/MathList.ts generated vendored Normal file
View File

@@ -0,0 +1,63 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the interface and abstract class for MathList objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {LinkedList} from '../util/LinkedList.js';
import {MathItem} from './MathItem.js';
/*****************************************************************/
/**
* The MathList interface (extends LinkedList<MathItem>)
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface MathList<N, T, D> extends LinkedList<MathItem<N, T, D>> {
/**
* Test if one math item is before the other in the document (a < b)
*
* @param {MathItem} a The first MathItem
* @param {MathItem} b The second MathItem
*/
isBefore(a: MathItem<N, T, D>, b: MathItem<N, T, D>): boolean;
}
/*****************************************************************/
/**
* The MathList abstract class (extends LinkedList<MathItem>)
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractMathList<N, T, D> extends
LinkedList<MathItem<N, T, D>> implements MathList<N, T, D> {
/**
* @override
*/
public isBefore(a: MathItem<N, T, D>, b: MathItem<N, T, D>) {
return (a.start.i < b.start.i || (a.start.i === b.start.i && a.start.n < b.start.n));
}
}

219
node_modules/mathjax-full/ts/core/MmlTree/Attributes.ts generated vendored Normal file
View File

@@ -0,0 +1,219 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements Attribute class for MmlNodes
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList, Property} from '../Tree/Node.js';
/**
* A constant for when a property should be inherited from the global defaults lists
*/
export const INHERIT = '_inherit_';
/******************************************************************/
/**
* Implements the Attributes class for MmlNodes
* (These can be set explicitly, inherited from parent nodes,
* taken from a default list of values, or taken from global
* defaults.)
*/
export class Attributes {
/**
* The attributes explicitly set on a node
*/
protected attributes: PropertyList;
/**
* The attributes inherited from parent nodes
*/
protected inherited: PropertyList;
/**
* The default attributes for the node type
*/
protected defaults: PropertyList;
/**
* Global attributes from the math node itself
*/
protected global: PropertyList;
/**
* @param {PropertyList} defaults The defaults for this node type
* @param {PropertyList} global The global properties (from the math node)
*
* @constructor
*/
constructor(defaults: PropertyList, global: PropertyList) {
this.global = global;
this.defaults = Object.create(global);
this.inherited = Object.create(this.defaults);
this.attributes = Object.create(this.inherited);
Object.assign(this.defaults, defaults);
}
/**
* @param {string} name The name of the attribute to set
* @param {Property} value The value to give the named attribute
*/
public set(name: string, value: Property) {
this.attributes[name] = value;
}
/**
* @param {PropertyList} list An object containing the properties to set
*/
public setList(list: PropertyList) {
Object.assign(this.attributes, list);
}
/**
* @param {string} name The name of the attribute whose value is to be returned
* @return {Property} The value of the named attribute (including inheritance and defaults)
*/
public get(name: string): Property {
let value = this.attributes[name];
if (value === INHERIT) {
value = this.global[name];
}
return value;
}
/**
* @param {string} name The value of the attribute whose value is to be returned
* @return {Property} The attribute whose name was given if it is explicit on the
* node (not inherited or defaulted), null otherwise
*/
public getExplicit(name: string): Property {
if (!this.attributes.hasOwnProperty(name)) {
return undefined;
}
return this.attributes[name];
}
/**
* @param {string[]} names The names of attributes whose values are to be returned
* @return {PropertyList} An object containing the attributes and their values
*/
public getList(...names: string[]): PropertyList {
let values: PropertyList = {};
for (const name of names) {
values[name] = this.get(name);
}
return values;
}
/**
* @param {string} name The name of an inherited attribute to be set
* @param {Property} value The value to assign to the named attribute
*/
public setInherited(name: string, value: Property) {
this.inherited[name] = value;
}
/**
* @param {string} name The name of an inherited attribute whose value is to be returned
* @return {Property} The value of the named attribute if it is inherited, null otherwise
*/
public getInherited(name: string): Property {
return this.inherited[name];
}
/**
* @param {string} name The name of a default attribute whose value is to be returned
* @return {Property} The value of the named attribute if a default exists for it, null otherwise
*/
public getDefault(name: string): Property {
return this.defaults[name];
}
/**
* @param {string} name The name of a attribute to check
* @return {boolean} True if attribute is set explicitly or inherited
* from an explicit mstyle or math attribute
*/
public isSet(name: string): boolean {
return this.attributes.hasOwnProperty(name) || this.inherited.hasOwnProperty(name);
}
/**
* @param {string} name The name of an attribute to test for the existence of a default
* @return {boolean} True of there is a default for the named attribute, false otherwise
*/
public hasDefault(name: string): boolean {
return (name in this.defaults);
}
/**
* @return {string[]} The names of all the attributes explicitly set on the node
*/
public getExplicitNames(): string[] {
return Object.keys(this.attributes);
}
/**
* @return {string[]} The names of all the inherited attributes for the node
*/
public getInheritedNames(): string[] {
return Object.keys(this.inherited);
}
/**
* @return {string[]} The names of all the default attributes for the node
*/
public getDefaultNames(): string[] {
return Object.keys(this.defaults);
}
/**
* @return {string[]} The names of all the global attributes
*/
public getGlobalNames(): string[] {
return Object.keys(this.global);
}
/**
* @return {PropertyList} The attribute object
*/
public getAllAttributes(): PropertyList {
return this.attributes;
}
/**
* @return {PropertyList} The inherited object
*/
public getAllInherited(): PropertyList {
return this.inherited;
}
/**
* @return {PropertyList} The defaults object
*/
public getAllDefaults(): PropertyList {
return this.defaults;
}
/**
* @return {PropertyList} The global object
*/
public getAllGlobals(): PropertyList {
return this.global;
}
}

View File

@@ -0,0 +1,151 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 A visitor that produces a JSON version of an MmlNode tree
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../Tree/Node.js';
import {MmlVisitor} from './MmlVisitor.js';
import {MmlNode, TextNode, XMLNode} from './MmlNode.js';
export type MmlNodeJSON = {
kind: string,
texClass: number
isEmbellished?: boolean,
isSpacelike?: boolean,
isInferred?: boolean,
childNodes: MmlJSON[],
attributes: PropertyList,
inherited: PropertyList,
properties: PropertyList
};
export type MmlTextJSON = {
kind: string,
text: string
};
export type MmlXmlJSON = {
kind: string,
xml: any
};
export type MmlJSON = MmlNodeJSON | MmlTextJSON | MmlXmlJSON;
/*****************************************************************/
/**
* Implements the JsonMmlVisitor (subclass of MmlVisitor)
*/
export class JsonMmlVisitor extends MmlVisitor {
/**
* Convert the tree rooted at a particular node into a JSON structure
*
* @param {MmlNode} node The node to use as the root of the tree to traverse
* @return {MmlJSON} The JSON object representing the internal tree
*/
public visitTree(node: MmlNode): MmlJSON {
return this.visitNode(node);
}
/**
* @param {TextNode} node The text node to visit
* @return {MmlJSON} The JSON for the text element
*/
public visitTextNode(node: TextNode): MmlTextJSON {
return {kind: node.kind, text: node.getText()};
}
/**
* @param {XMLNode} node The XML node to visit
* @return {MmlJSON} The JSON for the XML node
*/
public visitXMLNode(node: XMLNode): MmlXmlJSON {
return {kind: node.kind, xml: node.getXML()};
}
/**
* The generic visiting function:
* Create a DOM node of the correct type.
* Add its explicit attributes.
* Append its children nodes.
* Append the new node to the DOM parent.
*
* @param {MmlNode} node The node to visit
* @return {MmlJSON} The JSON object representing it
*/
public visitDefault(node: MmlNode): MmlJSON {
let json: MmlJSON = {
kind: node.kind.replace(/inferredM/, 'm'),
texClass: node.texClass,
attributes: this.getAttributes(node),
inherited: this.getInherited(node),
properties: this.getProperties(node),
childNodes: this.getChildren(node)
};
if (node.isInferred) {
json.isInferred = true;
}
if (node.isEmbellished) {
json.isEmbellished = true;
}
if (node.isSpacelike) {
json.isSpacelike = true;
}
return json;
}
/**
* @param {MmlNode} node The node whose children are to be copied
* @return {MmlJSON[]} The array of child JSON objects
*/
public getChildren(node: MmlNode): MmlJSON[] {
let children = [];
for (const child of node.childNodes) {
children.push(this.visitNode(child));
}
return children;
}
/**
* @param {MmlNode} node The node whose attributes are to be copied
* @return {PropertyList} The object containing the attributes;
*/
public getAttributes(node: MmlNode): PropertyList {
return Object.assign({}, node.attributes.getAllAttributes());
}
/**
* @param {MmlNode} node The node whose inherited attributes are to be copied
* @return {PropertyList} The object containing the inherited attributes;
*/
public getInherited(node: MmlNode): PropertyList {
return Object.assign({}, node.attributes.getAllInherited());
}
/**
* @param {MmlNode} node The node whose properties are to be copied
* @return {PropertyList} The object containing the properties;
*/
public getProperties(node: MmlNode): PropertyList {
return Object.assign({}, node.getAllProperties());
}
}

View File

@@ -0,0 +1,128 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 A visitor to convert the new to the old internal format.
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MmlVisitor} from './MmlVisitor.js';
import {MmlNode, TextNode, XMLNode} from './MmlNode.js';
/**
* Get access to legacy MML Element Jax
*/
declare var MathJax: any;
let MML = MathJax.ElementJax.mml;
/*****************************************************************/
/**
* Implements the LegacyMmlVisitor (subclass of MmlVisitor)
*/
export class LegacyMmlVisitor extends MmlVisitor {
/**
* Convert the tree rooted at a particular node into the old-style
* internal format used by MathJax v2.
*
* @param {MmlNode} node The node to use as the root of the tree to traverse
* @return {any} The old-style internal format equivalent of the tree
*/
public visitTree(node: MmlNode): any {
let root = MML.mrow();
this.visitNode(node, root);
root = root.data[0];
root.parent = null;
return root;
}
/**
* @param {TextNode} node The text node to visit
* @param {any} parent The old-style parent to which this node should be added
*/
public visitTextNode(node: TextNode, parent: any) {
parent.Append(MML.chars(node.getText()));
}
/**
* @param {XMLNode} node The XML node to visit
* @param {any} parent The old-style parent to which this node should be added
*/
public visitXMLNode(node: XMLNode, parent: any) {
parent.Append(MML.xml(node.getXML()));
}
/**
* Visit an inferred mrow, but don't add the inferred row itself (the old-style
* nodes will add one automatically).
*
* @param {MmlNode} node The inferred mrow to visit
* @param {any} parent The old-style parent to which this node's children should be added
*/
public visitInferredMrowNode(node: MmlNode, parent: any) {
for (const child of node.childNodes) {
this.visitNode(child, parent);
}
}
/**
* The generic visiting function:
* Create a node of the correct type.
* Add its explicit attributes.
* Add its non-attribute properties.
* Append its children nodes.
* Append the new node to the old-style parent.
*
* @param {MmlNode} node The node to visit
* @param {any} parent The old-style parent to which this node should be added
*/
public visitDefault(node: MmlNode, parent: any) {
let mml = MML[node.kind]();
this.addAttributes(node, mml);
this.addProperties(node, mml);
for (const child of node.childNodes) {
this.visitNode(child, mml);
}
parent.Append(mml);
}
/**
* @param {MmlNode} node The node who attributes are to be copied
* @param {any} mml The old-style node to which attributes are being added
*/
public addAttributes(node: MmlNode, mml: any) {
let attributes = node.attributes;
let names = attributes.getExplicitNames();
for (const name of names) {
mml[name] = attributes.getExplicit(name);
}
}
/**
* @param {MmlNode} node The node whose properties are to be copied
* @param {any} mml The old-stype node to which the properties are being copied
*/
public addProperties(node: MmlNode, mml: any) {
let names = node.getPropertyNames();
for (const name of names) {
mml[name] = node.getProperty(name);
}
}
}

125
node_modules/mathjax-full/ts/core/MmlTree/MML.ts generated vendored Normal file
View File

@@ -0,0 +1,125 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 An object listing all the MathML node types
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MmlNodeClass, TextNode, XMLNode} from './MmlNode.js';
import {MmlMath} from './MmlNodes/math.js';
import {MmlMi} from './MmlNodes/mi.js';
import {MmlMn} from './MmlNodes/mn.js';
import {MmlMo} from './MmlNodes/mo.js';
import {MmlMtext} from './MmlNodes/mtext.js';
import {MmlMspace} from './MmlNodes/mspace.js';
import {MmlMs} from './MmlNodes/ms.js';
import {MmlMrow, MmlInferredMrow} from './MmlNodes/mrow.js';
import {MmlMfrac} from './MmlNodes/mfrac.js';
import {MmlMsqrt} from './MmlNodes/msqrt.js';
import {MmlMroot} from './MmlNodes/mroot.js';
import {MmlMstyle} from './MmlNodes/mstyle.js';
import {MmlMerror} from './MmlNodes/merror.js';
import {MmlMpadded} from './MmlNodes/mpadded.js';
import {MmlMphantom} from './MmlNodes/mphantom.js';
import {MmlMfenced} from './MmlNodes/mfenced.js';
import {MmlMenclose} from './MmlNodes/menclose.js';
import {MmlMaction} from './MmlNodes/maction.js';
import {MmlMsubsup, MmlMsub, MmlMsup} from './MmlNodes/msubsup.js';
import {MmlMunderover, MmlMunder, MmlMover} from './MmlNodes/munderover.js';
import {MmlMmultiscripts, MmlMprescripts, MmlNone} from './MmlNodes/mmultiscripts.js';
import {MmlMtable} from './MmlNodes/mtable.js';
import {MmlMtr, MmlMlabeledtr} from './MmlNodes/mtr.js';
import {MmlMtd} from './MmlNodes/mtd.js';
import {MmlMaligngroup} from './MmlNodes/maligngroup.js';
import {MmlMalignmark} from './MmlNodes/malignmark.js';
import {MmlMglyph} from './MmlNodes/mglyph.js';
import {MmlSemantics, MmlAnnotation, MmlAnnotationXML} from './MmlNodes/semantics.js';
import {TeXAtom} from './MmlNodes/TeXAtom.js';
import {MathChoice} from './MmlNodes/mathchoice.js';
/************************************************************************/
/**
* This object collects all the MathML node types together so that
* they can be used to seed an MmlNodeFactory. One could copy this
* object to override existing classes with subclasses, or to add new
* classes as necessary.
*/
export let MML: {[kind: string]: MmlNodeClass} = {
[MmlMath.prototype.kind]: MmlMath,
[MmlMi.prototype.kind]: MmlMi,
[MmlMn.prototype.kind]: MmlMn,
[MmlMo.prototype.kind]: MmlMo,
[MmlMtext.prototype.kind]: MmlMtext,
[MmlMspace.prototype.kind]: MmlMspace,
[MmlMs.prototype.kind]: MmlMs,
[MmlMrow.prototype.kind]: MmlMrow,
[MmlInferredMrow.prototype.kind]: MmlInferredMrow,
[MmlMfrac.prototype.kind]: MmlMfrac,
[MmlMsqrt.prototype.kind]: MmlMsqrt,
[MmlMroot.prototype.kind]: MmlMroot,
[MmlMstyle.prototype.kind]: MmlMstyle,
[MmlMerror.prototype.kind]: MmlMerror,
[MmlMpadded.prototype.kind]: MmlMpadded,
[MmlMphantom.prototype.kind]: MmlMphantom,
[MmlMfenced.prototype.kind]: MmlMfenced,
[MmlMenclose.prototype.kind]: MmlMenclose,
[MmlMaction.prototype.kind]: MmlMaction,
[MmlMsub.prototype.kind]: MmlMsub,
[MmlMsup.prototype.kind]: MmlMsup,
[MmlMsubsup.prototype.kind]: MmlMsubsup,
[MmlMunder.prototype.kind]: MmlMunder,
[MmlMover.prototype.kind]: MmlMover,
[MmlMunderover.prototype.kind]: MmlMunderover,
[MmlMmultiscripts.prototype.kind]: MmlMmultiscripts,
[MmlMprescripts.prototype.kind]: MmlMprescripts,
[MmlNone.prototype.kind]: MmlNone,
[MmlMtable.prototype.kind]: MmlMtable,
[MmlMlabeledtr.prototype.kind]: MmlMlabeledtr,
[MmlMtr.prototype.kind]: MmlMtr,
[MmlMtd.prototype.kind]: MmlMtd,
[MmlMaligngroup.prototype.kind]: MmlMaligngroup,
[MmlMalignmark.prototype.kind]: MmlMalignmark,
[MmlMglyph.prototype.kind]: MmlMglyph,
[MmlSemantics.prototype.kind]: MmlSemantics,
[MmlAnnotation.prototype.kind]: MmlAnnotation,
[MmlAnnotationXML.prototype.kind]: MmlAnnotationXML,
[TeXAtom.prototype.kind]: TeXAtom,
[MathChoice.prototype.kind]: MathChoice,
[TextNode.prototype.kind]: TextNode,
[XMLNode.prototype.kind]: XMLNode
};

View File

@@ -0,0 +1,112 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 A visitor that produces MathML DOM nodes from the iternal nodes
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MmlVisitor} from './MmlVisitor.js';
import {MmlNode, TextNode, XMLNode} from './MmlNode.js';
/*****************************************************************/
/**
* Implements the MathMLVisitor (subclass of MmlVisitor)
*/
export class MathMLVisitor extends MmlVisitor {
/**
* The document in which the nodes are being made
*/
protected document: Document = null;
/**
* Convert the tree rooted at a particular node into DOM nodes.
*
* @param {MmlNode} node The node to use as the root of the tree to traverse
* @param {Document} document The document in which the nodes are created
* @return {Node} The MathML DOM nodes representing the internal tree
*/
public visitTree(node: MmlNode, document: Document): Node {
this.document = document;
let root = document.createElement('top');
this.visitNode(node, root);
this.document = null;
return root.firstChild;
}
/**
* @param {TextNode} node The text node to visit
* @param {Element} parent The DOM parent to which this node should be added
*/
public visitTextNode(node: TextNode, parent: Element) {
parent.appendChild(this.document.createTextNode(node.getText()));
}
/**
* @param {XMLNode} node The XML node to visit
* @param {Element} parent The DOM parent to which this node should be added
*/
public visitXMLNode(node: XMLNode, parent: Element) {
parent.appendChild((node.getXML() as Element).cloneNode(true));
}
/**
* Visit an inferred mrow, but don't add the inferred row itself (since
* it is supposed to be inferred).
*
* @param {MmlNode} node The inferred mrow to visit
* @param {Element} parent The DOM parent to which this node's children should be added
*/
public visitInferredMrowNode(node: MmlNode, parent: Element) {
for (const child of node.childNodes) {
this.visitNode(child, parent);
}
}
/**
* The generic visiting function:
* Create a DOM node of the correct type.
* Add its explicit attributes.
* Append its children nodes.
* Append the new node to the DOM parent.
*
* @param {MmlNode} node The node to visit
* @param {Element} parent The DOM parent to which this node should be added
*/
public visitDefault(node: MmlNode, parent: Element) {
let mml = this.document.createElement(node.kind);
this.addAttributes(node, mml);
for (const child of node.childNodes) {
this.visitNode(child, mml);
}
parent.appendChild(mml);
}
/**
* @param {MmlNode} node The node who attributes are to be copied
* @param {Element} mml The MathML DOM node to which attributes are being added
*/
public addAttributes(node: MmlNode, mml: Element) {
let attributes = node.attributes;
let names = attributes.getExplicitNames();
for (const name of names) {
mml.setAttribute(name, attributes.getExplicit(name).toString());
}
}
}

View File

@@ -0,0 +1,48 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlFactory to create Mml Nodes
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {AbstractNodeFactory} from '../Tree/NodeFactory.js';
import {MmlNode, MmlNodeClass} from './MmlNode.js';
import {MML} from './MML.js';
/*****************************************************************/
/**
* Implements the MmlFactory (subclass of NodeFactory)
*/
export class MmlFactory extends AbstractNodeFactory<MmlNode, MmlNodeClass> {
/**
* The default node-creation functions
*/
public static defaultNodes = MML;
/**
* @return {Object} The list of node-creation functions (similar to the
* MML object from MathJax v2).
*/
get MML(): Object {
return this.node;
}
}

1314
node_modules/mathjax-full/ts/core/MmlTree/MmlNode.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the TeXAtom node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MmlFactory} from '../MmlFactory.js';
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlBaseNode, MmlNode, TEXCLASS} from '../MmlNode.js';
import {MmlMo} from './mo.js';
/*****************************************************************/
/**
* Implements the TeXAtom node class (subclass of AbstractMmlBaseNode)
*/
export class TeXAtom extends AbstractMmlBaseNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlBaseNode.defaults
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'TeXAtom';
}
/**
* Inferred mrow with any number of children
* @override
*/
public get arity() {
return -1;
}
/**
* This element is not considered a MathML container
* @override
*/
public get notParent() {
return this.childNodes[0] && this.childNodes[0].childNodes.length === 1;
}
/**
* @override
*/
constructor(factory: MmlFactory, attributes: PropertyList, children: MmlNode[]) {
super(factory, attributes, children);
this.setProperty('texClass', this.texClass); // needed for serialization to include the texClass
}
/**
* @override
*/
public setTeXclass(prev: MmlNode) {
this.childNodes[0].setTeXclass(null);
return this.adjustTeXclass(prev);
}
/**
* (Replaced below by the version from the MmlMo node)
*
* @override
*/
public adjustTeXclass(prev: MmlNode) {
return prev;
}
}
/**
* Use the method from the MmlMo class
*/
TeXAtom.prototype.adjustTeXclass = MmlMo.prototype.adjustTeXclass;

View File

@@ -0,0 +1,134 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMaction node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlNode} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMaction node class (subclass of AbstractMmlNode)
*/
export class MmlMaction extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults,
actiontype: 'toggle',
selection: 1
};
/**
* @override
*/
public get kind() {
return 'maction';
}
/**
* At least one child
* @override
*/
public get arity() {
return 1;
}
/**
* @return {MmlNode} The selected child node (or an mrow if none selected)
*/
public get selected(): MmlNode {
const selection = this.attributes.get('selection') as number;
const i = Math.max(1, Math.min(this.childNodes.length, selection)) - 1;
return this.childNodes[i] || this.factory.create('mrow');
}
/**
* @override
*/
public get isEmbellished() {
return this.selected.isEmbellished;
}
/**
* @override
*/
public get isSpacelike() {
return this.selected.isSpacelike;
}
/**
* @override
*/
public core(): MmlNode {
return this.selected.core();
}
/**
* @override
*/
public coreMO(): MmlNode {
return this.selected.coreMO();
}
/**
* @override
*/
protected verifyAttributes(options: PropertyList) {
super.verifyAttributes(options);
if (this.attributes.get('actiontype') !== 'toggle' &&
this.attributes.getExplicit('selection') !== undefined) {
const attributes = this.attributes.getAllAttributes();
delete attributes.selection;
}
}
/**
* Get the TeX class from the selceted node
* For tooltips, set TeX classes within the tip as a separate math list
*
* @override
*/
public setTeXclass(prev: MmlNode) {
if (this.attributes.get('actiontype') === 'tooltip' && this.childNodes[1]) {
this.childNodes[1].setTeXclass(null);
}
let selected = this.selected;
prev = selected.setTeXclass(prev);
this.updateTeXclass(selected);
return prev;
}
/**
* Select the next child for a toggle action
*/
public nextToggleSelection() {
let selection = Math.max(1, (this.attributes.get('selection') as number) + 1);
if (selection > this.childNodes.length) {
selection = 1;
}
this.attributes.set('selection', selection);
}
}

View File

@@ -0,0 +1,67 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMaligngroup node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlLayoutNode, AttributeList} from '../MmlNode.js';
import {INHERIT} from '../Attributes.js';
/*****************************************************************/
/**
* Implements the MmlMaligngroup node class (subclass of AbstractMmlNode)
*/
export class MmlMaligngroup extends AbstractMmlLayoutNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlLayoutNode.defaults,
groupalign: INHERIT
};
/**
* @override
*/
public get kind() {
return 'maligngroup';
}
/**
* <maligngroup> is space-like
* @override
*/
public get isSpacelike() {
return true;
}
/**
* Children can inherit from <maligngroup>
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
attributes = this.addInheritedAttributes(attributes, this.attributes.getAllAttributes());
super.setChildInheritedAttributes(attributes, display, level, prime);
}
}

View File

@@ -0,0 +1,65 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMalignmark node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlNode} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMalignmark node class (subclass of AbstractMmlNode)
*/
export class MmlMalignmark extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults,
edge: 'left'
};
/**
* @override
*/
public get kind() {
return 'malignmark';
}
/**
* No children allowed
* @override
*/
public get arity() {
return 0;
}
/**
* <malignmark> is space-like
* @override
*/
public get isSpacelike() {
return true;
}
}

View File

@@ -0,0 +1,104 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMath node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlLayoutNode, AttributeList} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMath node class (subclass of AbstractMmlLayoutNode)
*/
export class MmlMath extends AbstractMmlLayoutNode {
/**
* These are used as the defaults for any attributes marked INHERIT in other classes
*/
public static defaults: PropertyList = {
...AbstractMmlLayoutNode.defaults,
mathvariant: 'normal',
mathsize: 'normal',
mathcolor: '', // Should be 'black', but allow it to inherit from surrounding text
mathbackground: 'transparent',
dir: 'ltr',
scriptlevel: 0,
displaystyle: false,
display: 'inline',
maxwidth: '',
overflow: 'linebreak',
altimg: '',
'altimg-width': '',
'altimg-height': '',
'altimg-valign': '',
alttext: '',
cdgroup: '',
scriptsizemultiplier: 1 / Math.sqrt(2),
scriptminsize: '8px', // Should be 8pt, but that's too big
infixlinebreakstyle: 'before',
lineleading: '1ex',
linebreakmultchar: '\u2062', // Invisible times
indentshift: 'auto', // Use user configuration
indentalign: 'auto',
indenttarget: '',
indentalignfirst: 'indentalign',
indentshiftfirst: 'indentshift',
indentalignlast: 'indentalign',
indentshiftlast: 'indentshift'
};
/**
* @override
*/
public get kind() {
return 'math';
}
/**
* Linebreaking can occur in math nodes
* @override
*/
public get linebreakContainer() {
return true;
}
/**
* The attributes of math nodes are inherited, so add them into the list.
* The displaystyle attribute comes from the display attribute if not given explicitly
* The scriptlevel comes from the scriptlevel attribute or default
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
if (this.attributes.get('mode') === 'display') {
this.attributes.setInherited('display', 'block');
}
attributes = this.addInheritedAttributes(attributes, this.attributes.getAllAttributes());
display = (!!this.attributes.get('displaystyle') ||
(!this.attributes.get('displaystyle') && this.attributes.get('display') === 'block'));
this.attributes.setInherited('displaystyle', display);
level = (this.attributes.get('scriptlevel') ||
(this.constructor as typeof MmlMath).defaults['scriptlevel']) as number;
super.setChildInheritedAttributes(attributes, display, level, prime);
}
}

View File

@@ -0,0 +1,80 @@
/*************************************************************
*
* Copyright (c) 2018-2022 The 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 Implements the MathChoice node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlBaseNode, AttributeList} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MathChoice node class (subclass of AbstractMmlBaseNode)
*
* This is used by TeX's \mathchoice macro, but removes itself
* during the setInheritedAttributes process
*/
export class MathChoice extends AbstractMmlBaseNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlBaseNode.defaults
};
/**
* @override
*/
public get kind() {
return 'MathChoice';
}
/**
* 4 children (display, text, script, and scriptscript styles)
* @override
*/
public get arity() {
return 4;
}
/**
* This element is not considered a MathML container
* @override
*/
public get notParent() {
return true;
}
/**
* Replace the MathChoice node with the selected on based on the displaystyle and scriptlevel settings
* (so the MathChoice never ends up in a finished MmlNode tree)
*
* @override
*/
public setInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
const selection = (display ? 0 : Math.max(0, Math.min(level, 2)) + 1);
const child = this.childNodes[selection] || this.factory.create('mrow');
this.parent.replaceChild(child, this);
child.setInheritedAttributes(attributes, display, level, prime);
}
}

View File

@@ -0,0 +1,80 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMenclose node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlEnclose node class (subclass of AbstractMmlNode)
*/
export class MmlMenclose extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults,
notation: 'longdiv'
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* The menclose kind
* @override
*/
public get kind() {
return 'menclose';
}
/**
* <menclose> has an inferred mrow
* @override
*/
public get arity() {
return -1;
}
/**
* <menclose> is a linebreak container
* @override
*/
public get linebreakContininer() {
return true;
}
/**
* @override
*/
public setTeXclass(prev: MmlNode) {
prev = this.childNodes[0].setTeXclass(prev);
this.updateTeXclass(this.childNodes[0]);
return prev;
}
}

View File

@@ -0,0 +1,69 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMerror node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMerror node class (subclass of AbstractMmlNode)
*/
export class MmlMerror extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'merror';
}
/**
* <merror> gets an inferred mrow
* @override
*/
public get arity() {
return -1;
}
/**
* <merror> can contain line breaks
* @override
*/
public get linebreakContainer() {
return true;
}
}

View File

@@ -0,0 +1,165 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMfenced node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, TextNode, AbstractMmlNode, AttributeList, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMfenced node class (subclass of AbstractMmlNode)
*/
export class MmlMfenced extends AbstractMmlNode {
/**
* @overeride
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults,
open: '(',
close: ')',
separators: ','
};
/**
* TeX class is INNER
*/
protected texclass = TEXCLASS.INNER;
/**
* Storage for "fake" nodes for the separators
*/
public separators: MmlNode[] = [];
/**
* Storage for "fake" open node
*/
public open: MmlNode = null;
/**
* Storage for "fake" close node
*/
public close: MmlNode = null;
/**
* @override
*/
public get kind() {
return 'mfenced';
}
/**
* Include the fake nodes in the process, since they will be used
* to produce the output.
*
* @override
*/
public setTeXclass(prev: MmlNode) {
this.getPrevClass(prev);
if (this.open) {
prev = this.open.setTeXclass(prev);
}
if (this.childNodes[0]) {
prev = this.childNodes[0].setTeXclass(prev);
}
for (let i = 1, m = this.childNodes.length; i < m; i++) {
if (this.separators[i - 1]) {
prev = this.separators[i - 1].setTeXclass(prev);
}
if (this.childNodes[i]) {
prev = this.childNodes[i].setTeXclass(prev);
}
}
if (this.close) {
prev = this.close.setTeXclass(prev);
}
this.updateTeXclass(this.open);
return prev;
}
/**
* Create the fake nodes and do their inheritance
* Then do inheridence of usual children
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
this.addFakeNodes();
for (const child of [this.open, this.close].concat(this.separators)) {
if (child) {
child.setInheritedAttributes(attributes, display, level, prime);
}
}
super.setChildInheritedAttributes(attributes, display, level, prime);
}
/**
* Create <mo> elements for the open and close delimiters, and for the separators (if any)
*/
protected addFakeNodes() {
let {open, close, separators} = this.attributes.getList('open', 'close', 'separators') as
{open: string, close: string, separators: string};
open = open.replace(/[ \t\n\r]/g, '');
close = close.replace(/[ \t\n\r]/g, '');
separators = separators.replace(/[ \t\n\r]/g, '');
//
// Create open node
//
if (open) {
this.open = this.fakeNode(open, {fence: true, form: 'prefix'}, TEXCLASS.OPEN);
}
//
// Create nodes for the separators
//
if (separators) {
while (separators.length < this.childNodes.length - 1) {
separators += separators.charAt(separators.length - 1);
}
let i = 0;
for (const child of this.childNodes.slice(1)) {
if (child) {
this.separators.push(this.fakeNode(separators.charAt(i++)));
}
}
}
//
// Create close node
//
if (close) {
this.close = this.fakeNode(close, {fence: true, form: 'postfix'}, TEXCLASS.CLOSE);
}
}
/**
* @param {string} c The character for the text of the node
* @param {PropertyList} properties The attributes for the node
* @param {number} texClass The TeX class for the node
* @return {MmlNode} The generated <mo> node
*/
protected fakeNode(c: string, properties: PropertyList = {}, texClass: number = null): MmlNode {
let text = (this.factory.create('text') as TextNode).setText(c);
let node = this.factory.create('mo', properties, [text]);
node.texClass = texClass;
node.parent = this;
return node;
}
}

View File

@@ -0,0 +1,92 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMfrac node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlBaseNode, AttributeList} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMfrac node class (subclass of AbstractMmlBaseNode)
*/
export class MmlMfrac extends AbstractMmlBaseNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlBaseNode.defaults,
linethickness: 'medium',
numalign: 'center',
denomalign: 'center',
bevelled: false
};
/**
* @override
*/
public get kind() {
return 'mfrac';
}
/**
* <mfrac> requires two children
* @override
*/
public get arity() {
return 2;
}
/**
* The children of <mfrac> can include line breaks
* @override
*/
public get linebreakContainer() {
return true;
}
/**
* Update the children separately
* @override
*/
public setTeXclass(prev: MmlNode) {
this.getPrevClass(prev);
for (const child of this.childNodes) {
child.setTeXclass(null);
}
return this;
}
/**
* Adjust the display level, and use prime style in denominator
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
if (!display || level > 0) {
level++;
}
this.childNodes[0].setInheritedAttributes(attributes, false, level, prime);
this.childNodes[1].setInheritedAttributes(attributes, false, level, true);
}
}

View File

@@ -0,0 +1,71 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMglyph node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlTokenNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMglyph node class (subclass of AbstractMmlTokenNode)
*/
export class MmlMglyph extends AbstractMmlTokenNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlTokenNode.defaults,
alt: '',
src: '',
index: '',
width: 'auto',
height: 'auto',
valign: '0em'
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'mglyph';
}
/**
* @override
*/
public verifyAttributes(options: PropertyList) {
const {src, fontfamily, index} = this.attributes.getList('src', 'fontfamily', 'index');
if (src === '' && (fontfamily === '' || index === '')) {
this.mError('mglyph must have either src or fontfamily and index attributes', options, true);
} else {
super.verifyAttributes(options);
}
}
}

View File

@@ -0,0 +1,96 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMi node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlTokenNode, AbstractMmlNode, AttributeList, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMi node class (subclass of AbstractMmlTokenNode)
*/
export class MmlMi extends AbstractMmlTokenNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlTokenNode.defaults
};
/**
* Pattern for operator names
*/
public static operatorName: RegExp = /^[a-z][a-z0-9]*$/i;
/**
* Pattern for single-character texts
*/
public static singleCharacter: RegExp =
/^[\uD800-\uDBFF]?.[\u0300-\u036F\u1AB0-\u1ABE\u1DC0-\u1DFF\u20D0-\u20EF]*$/;
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'mi';
}
/**
* Do the usual inheritance, then check the text length to see
* if mathvariant should be normal or italic.
*
* @override
*/
public setInheritedAttributes(attributes: AttributeList = {},
display: boolean = false, level: number = 0, prime: boolean = false) {
super.setInheritedAttributes(attributes, display, level, prime);
let text = this.getText();
if (text.match(MmlMi.singleCharacter) && !attributes.mathvariant) {
this.attributes.setInherited('mathvariant', 'italic');
}
}
/**
* Mark multi-character texts as OP rather than ORD for spacing purposes
*
* @override
*/
public setTeXclass(prev: AbstractMmlNode) {
this.getPrevClass(prev);
let name = this.getText();
if (name.length > 1 && name.match(MmlMi.operatorName) &&
this.attributes.get('mathvariant') === 'normal' &&
this.getProperty('autoOP') === undefined &&
this.getProperty('texClass') === undefined) {
this.texClass = TEXCLASS.OP;
this.setProperty('autoOP', true);
}
return this;
}
}

View File

@@ -0,0 +1,203 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMmultiscripts node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlNode, AttributeList} from '../MmlNode.js';
import {MmlMsubsup} from './msubsup.js';
/*****************************************************************/
/**
* Implements the MmlMmultiscripts node class (subclass of MmlMsubsup)
*/
export class MmlMmultiscripts extends MmlMsubsup {
/**
* @override
*/
public static defaults: PropertyList = {
...MmlMsubsup.defaults
};
/**
* @override
*/
public get kind() {
return 'mmultiscripts';
}
/**
* <mmultiscripts> requires at least one child (the base)
* @override
*/
public get arity() {
return 1;
}
/**
* Push the inherited values to the base
* Make sure the number of pre- and post-scripts are even by adding mrows, if needed.
* For the scripts, use displaystyle = false, scriptlevel + 1, and
* set the primestyle in the subscripts.
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
this.childNodes[0].setInheritedAttributes(attributes, display, level, prime);
let prescripts = false;
for (let i = 1, n = 0; i < this.childNodes.length; i++) {
let child = this.childNodes[i];
if (child.isKind('mprescripts')) {
if (!prescripts) {
prescripts = true;
if (i % 2 === 0) {
let mrow = this.factory.create('mrow');
this.childNodes.splice(i, 0, mrow);
mrow.parent = this;
i++;
}
}
} else {
let primestyle = prime || (n % 2 === 0);
child.setInheritedAttributes(attributes, false, level + 1, primestyle);
n++;
}
}
if (this.childNodes.length % 2 === (prescripts ? 1 : 0)) {
this.appendChild(this.factory.create('mrow'));
this.childNodes[this.childNodes.length - 1].setInheritedAttributes(attributes, false, level + 1, prime);
}
}
/**
* Check that mprescripts only occurs once, and that the number of pre- and post-scripts are even.
*
* @override
*/
protected verifyChildren(options: PropertyList) {
let prescripts = false;
let fix = options['fixMmultiscripts'];
for (let i = 0; i < this.childNodes.length; i++) {
let child = this.childNodes[i];
if (child.isKind('mprescripts')) {
if (prescripts) {
child.mError(child.kind + ' can only appear once in ' + this.kind, options, true);
} else {
prescripts = true;
if (i % 2 === 0 && !fix) {
this.mError('There must be an equal number of prescripts of each type', options);
}
}
}
}
if (this.childNodes.length % 2 === (prescripts ? 1 : 0) && !fix) {
this.mError('There must be an equal number of scripts of each type', options);
}
super.verifyChildren(options);
}
}
/*****************************************************************/
/**
* Implements the MmlMprescripts node class (subclass of AbstractMmlNode)
*/
export class MmlMprescripts extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults
};
/**
* @return {string} The mprescripts kind
*/
public get kind(): string {
return 'mprescripts';
}
/**
* @return {number} <mprescripts> can have no children
*/
public get arity(): number {
return 0;
}
/**
* Check that parent is mmultiscripts
*
* @override
*/
public verifyTree(options: PropertyList) {
super.verifyTree(options);
if (this.parent && !this.parent.isKind('mmultiscripts')) {
this.mError(this.kind + ' must be a child of mmultiscripts', options, true);
}
}
}
/*****************************************************************/
/**
* Implements the MmlNone node class (subclass of AbstractMmlNode)
*/
export class MmlNone extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults
};
/**
* @return {string} The none kind
*/
public get kind(): string {
return 'none';
}
/**
* @return {number} <none> can have no children
*/
public get arity(): number {
return 0;
}
/**
* Check that parent is mmultiscripts
*
* @override
*/
public verifyTree(options: PropertyList) {
super.verifyTree(options);
if (this.parent && !this.parent.isKind('mmultiscripts')) {
this.mError(this.kind + ' must be a child of mmultiscripts', options, true);
}
}
}

View File

@@ -0,0 +1,53 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMn node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlTokenNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMn node class (subclass of AbstractMmlTokenNode)
*/
export class MmlMn extends AbstractMmlTokenNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlTokenNode.defaults
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'mn';
}
}

View File

@@ -0,0 +1,476 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMo node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlTokenNode, MmlNode, AttributeList, TEXCLASS} from '../MmlNode.js';
import {MmlMrow} from './mrow.js';
import {MmlMover, MmlMunder, MmlMunderover} from './munderover.js';
import {OperatorList, OPTABLE, getRange, MMLSPACING} from '../OperatorDictionary.js';
import {unicodeChars, unicodeString} from '../../../util/string.js';
/*****************************************************************/
/**
* Implements the MmlMo node class (subclass of AbstractMmlTokenNode)
*/
export class MmlMo extends AbstractMmlTokenNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlTokenNode.defaults,
form: 'infix',
fence: false,
separator: false,
lspace: 'thickmathspace',
rspace: 'thickmathspace',
stretchy: false,
symmetric: false,
maxsize: 'infinity',
minsize: '0em', // MathML says '1em', but that is larger than some natural sizes
largeop: false,
movablelimits: false,
accent: false,
linebreak: 'auto',
lineleading: '1ex',
linebreakstyle: 'before',
indentalign: 'auto',
indentshift: '0',
indenttarget: '',
indentalignfirst: 'indentalign',
indentshiftfirst: 'indentshift',
indentalignlast: 'indentalign',
indentshiftlast: 'indentshift'
};
/**
* The MathML spacing values for the TeX classes
*/
public static MMLSPACING = MMLSPACING;
/**
* The Operator Dictionary
*/
public static OPTABLE: {[form: string]: OperatorList} = OPTABLE;
/**
* Pattern for matching when the contents is one ore more pseudoscripts
*/
public static pseudoScripts = new RegExp([
'^["\'*`',
'\u00AA', // FEMININE ORDINAL INDICATOR
'\u00B0', // DEGREE SIGN
'\u00B2-\u00B4', // SUPERSCRIPT 2 and 3, ACUTE ACCENT
'\u00B9', // SUPERSCRIPT ONE
'\u00BA', // MASCULINE ORDINAL INDICATOR
'\u2018-\u201F', // Various double and single quotation marks (up and down)
'\u2032-\u2037\u2057', // Primes and reversed primes (forward and reversed)
'\u2070\u2071', // SUPERSCRIPT 0 and i
'\u2074-\u207F', // SUPERCRIPT 4 through 9, -, =, (, ), and n
'\u2080-\u208E', // SUBSCRIPT 0 through 9, -, =, (, ).
']+$'
].join(''));
/**
* Pattern for when contents is a collection of primes
*/
protected static primes = new RegExp([
'^["\'`',
'\u2018-\u201F', // Various double and single quotation marks (up and down)
']+$'
].join(''));
/**
* Default map for remapping prime characters
*/
protected static remapPrimes: {[n: number]: number} = {
0x0022: 0x2033, // double quotes
0x0027: 0x2032, // single quote
0x0060: 0x2035, // back quote
0x2018: 0x2035, // open single quote
0x2019: 0x2032, // close single quote
0x201A: 0x2032, // low open single quote
0x201B: 0x2035, // reversed open single quote
0x201C: 0x2036, // open double quote
0x201D: 0x2033, // close double quote
0x201E: 0x2033, // low open double quote
0x201F: 0x2036, // reversed open double quote
};
/**
* Regular expression matching characters that are marked as math accents
*/
protected static mathaccents = new RegExp([
'^[',
'\u00B4\u0301\u02CA', // acute
'\u0060\u0300\u02CB', // grave
'\u00A8\u0308', // ddot
'\u007E\u0303\u02DC', // tilde
'\u00AF\u0304\u02C9', // bar
'\u02D8\u0306', // breve
'\u02C7\u030C', // check
'\u005E\u0302\u02C6', // hat
'\u2192\u20D7', // vec
'\u02D9\u0307', // dot
'\u02DA\u030A', // mathring
'\u20DB', // dddot
'\u20DC', // ddddot
']$'
].join(''));
/**
* The internal TeX class of the node (for use with getter/setter below)
*/
public _texClass: number = null;
/**
* Use a getter to look up the TeX class from the operator table if it hasn't
* been set yet (but don't save it in case the form changes when it is in its
* location).
*/
public get texClass() {
if (this._texClass === null) {
let mo = this.getText();
let [form1, form2, form3] = this.handleExplicitForm(this.getForms());
let OPTABLE = (this.constructor as typeof MmlMo).OPTABLE;
let def = OPTABLE[form1][mo] || OPTABLE[form2][mo] || OPTABLE[form3][mo];
return def ? def[2] : TEXCLASS.REL;
}
return this._texClass;
}
/**
* Use a setter to store the actual value in _texClass;
*/
public set texClass(value: number) {
this._texClass = value;
}
/**
* The default MathML spacing on the left
*/
/* tslint:disable-next-line:whitespace */
public lspace = 5/18;
/**
* The default MathML spacing on the right
*/
/* tslint:disable-next-line:whitespace */
public rspace = 5/18;
/**
* @override
*/
public get kind() {
return 'mo';
}
/**
* All <mo> are considered embellished
* @override
*/
public get isEmbellished() {
return true;
}
/**
* @return {boolean} Is <mo> marked as an explicit linebreak?
*/
public get hasNewLine(): boolean {
return this.attributes.get('linebreak') === 'newline';
}
/**
* @return {MmlNode} The node that is the outermost embellished operator
* with this node as its core
*/
public coreParent(): MmlNode {
let embellished = this as MmlNode;
let parent = this as MmlNode;
let math = this.factory.getNodeClass('math');
while (parent && parent.isEmbellished && parent.coreMO() === this && !(parent instanceof math)) {
embellished = parent;
parent = (parent as MmlNode).parent;
}
return embellished;
}
/**
* @param {MmlNode} parent The node whose core text is to be obtained
* @return {string} The text of the core MO of the given parent element
*/
public coreText(parent: MmlNode): string {
if (!parent) {
return '';
}
if (parent.isEmbellished) {
return (parent.coreMO() as MmlMo).getText();
}
while ((((parent.isKind('mrow') ||
(parent.isKind('TeXAtom') && parent.texClass !== TEXCLASS.VCENTER) ||
parent.isKind('mstyle') ||
parent.isKind('mphantom')) && parent.childNodes.length === 1) ||
parent.isKind('munderover')) && parent.childNodes[0]) {
parent = parent.childNodes[0] as MmlNode;
}
return (parent.isToken ? (parent as AbstractMmlTokenNode).getText() : '');
}
/**
* @override
*/
public hasSpacingAttributes() {
return this.attributes.isSet('lspace') ||
this.attributes.isSet('rspace');
}
/**
* @return {boolean} True is this mo is an accent in an munderover construction
*/
get isAccent(): boolean {
let accent = false;
const node = this.coreParent().parent;
if (node) {
const key = (node.isKind('mover') ?
((node.childNodes[(node as MmlMover).over] as MmlNode).coreMO() ?
'accent' : '') :
node.isKind('munder') ?
((node.childNodes[(node as MmlMunder).under] as MmlNode).coreMO() ?
'accentunder' : '') :
node.isKind('munderover') ?
(this === (node.childNodes[(node as MmlMunderover).over] as MmlNode).coreMO() ?
'accent' :
this === (node.childNodes[(node as MmlMunderover).under] as MmlNode).coreMO() ?
'accentunder' : '') :
'');
if (key) {
const value = node.attributes.getExplicit(key);
accent = (value !== undefined ? accent : this.attributes.get('accent')) as boolean;
}
}
return accent;
}
/**
* Produce the texClass based on the operator dictionary values
*
* @override
*/
public setTeXclass(prev: MmlNode): MmlNode {
let {form, fence} = this.attributes.getList('form', 'fence') as {form: string, fence: string};
if (this.getProperty('texClass') === undefined &&
(this.attributes.isSet('lspace') || this.attributes.isSet('rspace'))) {
return null;
}
if (fence && this.texClass === TEXCLASS.REL) {
if (form === 'prefix') {
this.texClass = TEXCLASS.OPEN;
}
if (form === 'postfix') {
this.texClass = TEXCLASS.CLOSE;
}
}
return this.adjustTeXclass(prev);
}
/**
* Follow the TeXBook rules for adjusting the TeX class once its neighbors are known
*
* @param {MmlNode} prev The node appearing before this one in the output
* @return {MmlNode} The last node displayed (this node)
*/
public adjustTeXclass(prev: MmlNode): MmlNode {
let texClass = this.texClass;
let prevClass = this.prevClass;
if (texClass === TEXCLASS.NONE) {
return prev;
}
if (prev) {
if (prev.getProperty('autoOP') && (texClass === TEXCLASS.BIN || texClass === TEXCLASS.REL)) {
prevClass = prev.texClass = TEXCLASS.ORD;
}
prevClass = this.prevClass = (prev.texClass || TEXCLASS.ORD);
this.prevLevel = this.attributes.getInherited('scriptlevel') as number;
} else {
prevClass = this.prevClass = TEXCLASS.NONE;
}
if (texClass === TEXCLASS.BIN &&
(prevClass === TEXCLASS.NONE || prevClass === TEXCLASS.BIN || prevClass === TEXCLASS.OP ||
prevClass === TEXCLASS.REL || prevClass === TEXCLASS.OPEN || prevClass === TEXCLASS.PUNCT)) {
this.texClass = TEXCLASS.ORD;
} else if (prevClass === TEXCLASS.BIN &&
(texClass === TEXCLASS.REL || texClass === TEXCLASS.CLOSE || texClass === TEXCLASS.PUNCT)) {
prev.texClass = this.prevClass = TEXCLASS.ORD;
} else if (texClass === TEXCLASS.BIN) {
//
// Check if node is the last one in its container since the rule
// above only takes effect if there is a node that follows.
//
let child: MmlNode = this;
let parent = this.parent;
while (parent && parent.parent && parent.isEmbellished &&
(parent.childNodes.length === 1 ||
(!parent.isKind('mrow') && parent.core() === child))) {
child = parent;
parent = parent.parent;
}
if (parent.childNodes[parent.childNodes.length - 1] === child) {
this.texClass = TEXCLASS.ORD;
}
}
return this;
}
/**
* Do the normal inheritance, then look up the attributes from the operator dictionary.
* If there is no dictionary entry, get the TeX class from the Unicode range list.
*
* @override
*/
public setInheritedAttributes(attributes: AttributeList = {},
display: boolean = false, level: number = 0, prime: boolean = false) {
super.setInheritedAttributes(attributes, display, level, prime);
let mo = this.getText();
this.checkOperatorTable(mo);
this.checkPseudoScripts(mo);
this.checkPrimes(mo);
this.checkMathAccent(mo);
}
/**
* Set the attributes from the operator table
*
* @param {string} mo The test of the mo element
*/
protected checkOperatorTable(mo: string) {
let [form1, form2, form3] = this.handleExplicitForm(this.getForms());
this.attributes.setInherited('form', form1);
let OPTABLE = (this.constructor as typeof MmlMo).OPTABLE;
let def = OPTABLE[form1][mo] || OPTABLE[form2][mo] || OPTABLE[form3][mo];
if (def) {
if (this.getProperty('texClass') === undefined) {
this.texClass = def[2];
}
for (const name of Object.keys(def[3] || {})) {
this.attributes.setInherited(name, def[3][name]);
}
this.lspace = (def[0] + 1) / 18;
this.rspace = (def[1] + 1) / 18;
} else {
let range = getRange(mo);
if (range) {
if (this.getProperty('texClass') === undefined) {
this.texClass = range[2];
}
const spacing = (this.constructor as typeof MmlMo).MMLSPACING[range[2]];
this.lspace = (spacing[0] + 1) / 18;
this.rspace = (spacing[1] + 1) / 18;
}
}
}
/**
* @return {[string, string, string]} The list of form attribute values in the
* order they should be tested, based on the
* position of the element in its parent.
*/
public getForms(): [string, string, string] {
let core: MmlNode = this;
let parent = this.parent;
let Parent = this.Parent;
while (Parent && Parent.isEmbellished) {
core = parent;
parent = Parent.parent;
Parent = Parent.Parent;
}
if (parent && parent.isKind('mrow') && (parent as MmlMrow).nonSpaceLength() !== 1) {
if ((parent as MmlMrow).firstNonSpace() === core) {
return ['prefix', 'infix', 'postfix'];
}
if ((parent as MmlMrow).lastNonSpace() === core) {
return ['postfix', 'infix', 'prefix'];
}
}
return ['infix', 'prefix', 'postfix'];
}
/**
* @param {string[]} forms The three forms in the default order they are to be tested
* @return {string[]} The forms in the new order, if there is an explicit form attribute
*/
protected handleExplicitForm(forms: string[]): string[] {
if (this.attributes.isSet('form')) {
const form = this.attributes.get('form') as string;
forms = [form].concat(forms.filter(name => (name !== form)));
}
return forms;
}
/**
* Mark the mo as a pseudoscript if it is one. True means it is,
* false means it is a pseudo-script character, but in an msup (so needs a variant form)
*
* @param {string} mo The test of the mo element
*/
protected checkPseudoScripts(mo: string) {
const PSEUDOSCRIPTS = (this.constructor as typeof MmlMo).pseudoScripts;
if (!mo.match(PSEUDOSCRIPTS)) return;
const parent = this.coreParent().Parent;
const isPseudo = !parent || !(parent.isKind('msubsup') && !parent.isKind('msub'));
this.setProperty('pseudoscript', isPseudo);
if (isPseudo) {
this.attributes.setInherited('lspace', 0);
this.attributes.setInherited('rspace', 0);
}
}
/**
* Determine whether the mo consists of primes, and remap them if so.
*
* @param {string} mo The test of the mo element
*/
protected checkPrimes(mo: string) {
const PRIMES = (this.constructor as typeof MmlMo).primes;
if (!mo.match(PRIMES)) return;
const REMAP = (this.constructor as typeof MmlMo).remapPrimes;
const primes = unicodeString(unicodeChars(mo).map(c => REMAP[c]));
this.setProperty('primes', primes);
}
/**
* Determine whether the mo is a mathaccent character
*
* @param {string} mo The test of the mo element
*/
protected checkMathAccent(mo: string) {
const parent = this.Parent;
if (this.getProperty('mathaccent') !== undefined || !parent || !parent.isKind('munderover')) return;
const base = parent.childNodes[0] as MmlNode;
if (base.isEmbellished && base.coreMO() === this) return;
const MATHACCENT = (this.constructor as typeof MmlMo).mathaccents;
if (mo.match(MATHACCENT)) {
this.setProperty('mathaccent', true);
}
}
}

View File

@@ -0,0 +1,53 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMpadded node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlLayoutNode} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMpadded node class (subclass of AbstractMmlLayoutNode)
*/
export class MmlMpadded extends AbstractMmlLayoutNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlLayoutNode.defaults,
width: '',
height: '',
depth: '',
lspace: 0,
voffset: 0
};
/**
* @override
*/
public get kind() {
return 'mpadded';
}
}

View File

@@ -0,0 +1,53 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMphantom node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlLayoutNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMphantom node class (subclass of AbstractMmlLayoutNode)
*/
export class MmlMphantom extends AbstractMmlLayoutNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlLayoutNode.defaults
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'mphantom';
}
}

View File

@@ -0,0 +1,84 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMroot node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlNode, AttributeList, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMroot node class (subclass of AbstractMmlNode)
*/
export class MmlMroot extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'mroot';
}
/**
* <mroot> requires two children
* @override
*/
public get arity() {
return 2;
}
/**
* Set the TeX class for the content of the root and the root separately.
* Return ourself as the previous item.
*
* @override
*/
public setTeXclass(prev: MmlNode) {
this.getPrevClass(prev);
this.childNodes[0].setTeXclass(null);
this.childNodes[1].setTeXclass(null);
return this;
}
/**
* Set the children display/level/prime for the base and root.
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
this.childNodes[0].setInheritedAttributes(attributes, display, level, true);
this.childNodes[1].setInheritedAttributes(attributes, false, level + 2, prime);
}
}

View File

@@ -0,0 +1,229 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMrow node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMrow node class (subclass of AbstractMmlNode)
*/
export class MmlMrow extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults
};
/**
* The index of the core child, when acting as an embellish mrow
*/
protected _core: number = null;
/**
* @override
*/
public get kind() {
return 'mrow';
}
/**
* An mrow is space-like if all its children are.
*
* @override
*/
public get isSpacelike() {
for (const child of this.childNodes) {
if (!child.isSpacelike) {
return false;
}
}
return true;
}
/**
* An mrow is embellished if it contains one embellished operator
* and any number of space-like nodes
*
* @override
*/
public get isEmbellished() {
let embellished = false;
let i = 0;
for (const child of this.childNodes) {
if (child) {
if (child.isEmbellished) {
if (embellished) {
return false;
}
embellished = true;
this._core = i;
} else if (!child.isSpacelike) {
return false;
}
}
i++;
}
return embellished;
}
/**
* @override
*/
public core(): MmlNode {
if (!this.isEmbellished || this._core == null) {
return this;
}
return this.childNodes[this._core];
}
/**
* @override
*/
public coreMO(): MmlNode {
if (!this.isEmbellished || this._core == null) {
return this;
}
return this.childNodes[this._core].coreMO();
}
/**
* @return {number} The number of non-spacelike child nodes
*/
public nonSpaceLength(): number {
let n = 0;
for (const child of this.childNodes) {
if (child && !child.isSpacelike) {
n++;
}
}
return n;
}
/**
* @return {MmlNode|null} The first non-space-like child node
*/
public firstNonSpace(): MmlNode | null {
for (const child of this.childNodes) {
if (child && !child.isSpacelike) {
return child;
}
}
return null;
}
/**
* @return {MmlNode|null} The last non-space-like child node
*/
public lastNonSpace(): MmlNode | null {
let i = this.childNodes.length;
while (--i >= 0) {
let child = this.childNodes[i];
if (child && !child.isSpacelike) {
return child;
}
}
return null;
}
/**
* @override
*/
public setTeXclass(prev: MmlNode) {
if (this.getProperty('open') != null || this.getProperty('close') != null) {
//
// <mrow> looks like it came from \left...\right
// so treat as subexpression (TeX class INNER).
// Use prev = null for the initial element in the
// delimiters, since there is nothing previous to
// it in what would be the TeX math list.
//
this.getPrevClass(prev);
prev = null;
for (const child of this.childNodes) {
prev = child.setTeXclass(prev);
}
if (this.texClass == null) {
this.texClass = TEXCLASS.INNER;
}
} else {
//
// Normal <mrow>, so treat as though mrow is not there
//
for (const child of this.childNodes) {
prev = child.setTeXclass(prev);
}
if (this.childNodes[0]) {
this.updateTeXclass(this.childNodes[0]);
}
}
return prev;
}
}
/*****************************************************************/
/**
* Implements the MmlInferredMrow node class (subclass of MmlMrow)
*/
export class MmlInferredMrow extends MmlMrow {
/**
* @override
*/
public static defaults: PropertyList = MmlMrow.defaults;
/**
* @return {string} The inferred-mrow kind
*/
public get kind(): string {
return 'inferredMrow';
}
/**
* @return {boolean} This is inferred
*/
public get isInferred(): boolean {
return true;
}
/**
* @override
*/
public get notParent() {
return true;
}
/**
* Show the child nodes in brackets
*/
public toString() {
return '[' + this.childNodes.join(',') + ']';
}
}

View File

@@ -0,0 +1,55 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMs node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlTokenNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMs node class (subclass of AbstractMmlTokenNode)
*/
export class MmlMs extends AbstractMmlTokenNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlTokenNode.defaults,
lquote: '"',
rquote: '"'
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'ms';
}
}

View File

@@ -0,0 +1,90 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMspace node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlTokenNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMspace node class (subclass of AbstractMmlTokenNode)
*/
export class MmlMspace extends AbstractMmlTokenNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlTokenNode.defaults,
width: '0em',
height: '0ex',
depth: '0ex',
linebreak: 'auto'
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.NONE;
/**
* @override
*/
public setTeXclass(prev: MmlNode): MmlNode {
return prev;
}
/**
* @override
*/
public get kind() {
return 'mspace';
}
/**
* mspace can't have children
* @override
*/
public get arity() {
return 0;
}
/**
* @override
*/
public get isSpacelike() {
return true;
}
/**
* Only process linebreak if the space has no explicit dimensions (according to spec)
*
* @override
*/
public get hasNewline() {
let attributes = this.attributes;
return (attributes.getExplicit('width') == null && attributes.getExplicit('height') == null &&
attributes.getExplicit('depth') == null && attributes.get('linebreak') === 'newline');
}
}

View File

@@ -0,0 +1,87 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMsqrt node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlNode, AttributeList, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMsqrt node class (subclass of AbstractMmlNode)
*/
export class MmlMsqrt extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'msqrt';
}
/**
* <msqrt> has an inferred mrow
* @override
*/
public get arity() {
return -1;
}
/**
* <msqrt> can contain line breaks
* @override
*/
public get linebreakContainer() {
return true;
}
/**
* @override
*/
public setTeXclass(prev: MmlNode) {
this.getPrevClass(prev);
this.childNodes[0].setTeXclass(null);
return this;
}
/**
* The contents of sqrt are in TeX prime style.
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, _prime: boolean) {
this.childNodes[0].setInheritedAttributes(attributes, display, level, true);
}
}

View File

@@ -0,0 +1,93 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMstyle node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlLayoutNode, AttributeList} from '../MmlNode.js';
import {INHERIT} from '../Attributes.js';
/*****************************************************************/
/**
* Implements the MmlMstyle node class (subclass of AbstractMmlLayoutNode)
*/
export class MmlMstyle extends AbstractMmlLayoutNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlLayoutNode.defaults,
scriptlevel: INHERIT,
displaystyle: INHERIT,
scriptsizemultiplier: 1 / Math.sqrt(2),
scriptminsize: '8px', // should be 8pt, but that is too large
mathbackground: INHERIT,
mathcolor: INHERIT,
dir: INHERIT,
infixlinebreakstyle: 'before'
};
/**
* @override
*/
public get kind() {
return 'mstyle';
}
/**
* @override
*/
public get notParent() {
return this.childNodes[0] && this.childNodes[0].childNodes.length === 1;
}
/**
* Handle scriptlevel changes, and add mstyle attributes to the ones being inherited.
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
let scriptlevel = this.attributes.getExplicit('scriptlevel');
if (scriptlevel != null) {
scriptlevel = scriptlevel.toString();
if (scriptlevel.match(/^\s*[-+]/)) {
level += parseInt(scriptlevel);
} else {
level = parseInt(scriptlevel);
}
prime = false; // style change resets tex prime style
}
let displaystyle = this.attributes.getExplicit('displaystyle') as boolean;
if (displaystyle != null) {
display = (displaystyle === true);
prime = false; // style change resets tex prime style
}
const cramped = this.attributes.getExplicit('data-cramped') as boolean; // manual control of tex prime style
if (cramped != null) {
prime = cramped;
}
attributes = this.addInheritedAttributes(attributes, this.attributes.getAllAttributes());
this.childNodes[0].setInheritedAttributes(attributes, display, level, prime);
}
}

View File

@@ -0,0 +1,173 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMsubsup, MmlMsub, and MmlMsup nodes
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlBaseNode, AttributeList} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMsubsup node class (subclass of AbstractMmlBaseNode)
*/
export class MmlMsubsup extends AbstractMmlBaseNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlBaseNode.defaults,
subscriptshift: '',
superscriptshift: ''
};
/**
* @override
*/
public get kind() {
return 'msubsup';
}
/**
* <msubsup> requires three children
* @override
*/
public get arity() {
return 3;
}
/**
* @return {number} The position of the base element
*/
public get base(): number {
return 0;
}
/**
* @return {number} The position of the subscript (overridden in msup below)
*/
public get sub(): number {
return 1;
}
/**
* @return {number} The position of the superscript (overridden in msup below)
*/
public get sup(): number {
return 2;
}
/**
* Super- and subscripts are not in displaymode, have scriptlevel increased, and prime style in subscripts.
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
let nodes = this.childNodes;
nodes[0].setInheritedAttributes(attributes, display, level, prime);
nodes[1].setInheritedAttributes(attributes, false, level + 1, prime || this.sub === 1);
if (!nodes[2]) {
return;
}
nodes[2].setInheritedAttributes(attributes, false, level + 1, prime || this.sub === 2);
}
}
/*****************************************************************/
/**
* Implements the MmlMsub node class (subclass of MmlMsubsup)
*/
export class MmlMsub extends MmlMsubsup {
/**
* @override
*/
public static defaults: PropertyList = {
...MmlMsubsup.defaults
};
/**
* @override
*/
public get kind() {
return 'msub';
}
/**
* <msub> only gets two children
* @override
*/
public get arity() {
return 2;
}
}
/*****************************************************************/
/**
* Implements the MmlMsup node class (subclass of MmlMsubsup)
*/
export class MmlMsup extends MmlMsubsup {
/**
* @override
*/
public static defaults: PropertyList = {
...MmlMsubsup.defaults
};
/**
* @override
*/
public get kind() {
return 'msup';
}
/**
* <msup> only gets two children
* @override
*/
get arity() {
return 2;
}
/**
* child 1 is superscript
* @override
*/
get sup() {
return 1;
}
/**
* child 2 is null (no subscript)
* @override
*/
get sub() {
return 2;
}
}

View File

@@ -0,0 +1,182 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMtable node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlNode, AttributeList, TEXCLASS, indentAttributes} from '../MmlNode.js';
import {split} from '../../../util/string.js';
/*****************************************************************/
/**
* Implements the MmlMtable node class (subclass of AbstractMmlNode)
*/
export class MmlMtable extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults,
align: 'axis',
rowalign: 'baseline',
columnalign: 'center',
groupalign: '{left}',
alignmentscope: true,
columnwidth: 'auto',
width: 'auto',
rowspacing: '1ex',
columnspacing: '.8em',
rowlines: 'none',
columnlines: 'none',
frame: 'none',
framespacing: '0.4em 0.5ex',
equalrows: false,
equalcolumns: false,
displaystyle: false,
side: 'right',
minlabelspacing: '0.8em'
};
/**
* Extra properties for this node
*/
public properties = {
useHeight: true
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'mtable';
}
/**
* Linebreaks are allowed in tables
* @override
*/
public get linebreakContainer() {
return true;
}
/**
* @override
*/
public setInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
//
// Force inheritance of shift and align values (since they are needed to output tables with labels)
// but make sure they are not given explicitly on the <mtable> tag.
//
for (const name of indentAttributes) {
if (attributes[name]) {
this.attributes.setInherited(name, attributes[name][1]);
}
if (this.attributes.getExplicit(name) !== undefined) {
delete (this.attributes.getAllAttributes())[name];
}
}
super.setInheritedAttributes(attributes, display, level, prime);
}
/**
* Make sure all children are mtr or mlabeledtr nodes
* Inherit the table attributes, and set the display attribute based on the table's displaystyle attribute
* Reset the prime value to false
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, _prime: boolean) {
for (const child of this.childNodes) {
if (!child.isKind('mtr')) {
this.replaceChild(this.factory.create('mtr'), child)
.appendChild(child);
}
}
level = this.getProperty('scriptlevel') as number || level;
display = !!(this.attributes.getExplicit('displaystyle') || this.attributes.getDefault('displaystyle'));
attributes = this.addInheritedAttributes(attributes, {
columnalign: this.attributes.get('columnalign'),
rowalign: 'center'
});
const cramped = this.attributes.getExplicit('data-cramped') as boolean;
const ralign = split(this.attributes.get('rowalign') as string);
for (const child of this.childNodes) {
attributes.rowalign[1] = ralign.shift() || attributes.rowalign[1];
child.setInheritedAttributes(attributes, display, level, !!cramped);
}
}
/**
* Check that children are mtr or mlabeledtr
*
* @override
*/
protected verifyChildren(options: PropertyList) {
let mtr: MmlNode = null; // all consecutive non-mtr elements are collected into one mtr
const factory = this.factory;
for (let i = 0; i < this.childNodes.length; i++) {
const child = this.childNodes[i];
if (child.isKind('mtr')) {
mtr = null; // start a new row if there are non-mtr children
} else {
const isMtd = child.isKind('mtd');
//
// If there is already an mtr for previous children, just remove the child
// otherwise replace the child with a new mtr
//
if (mtr) {
this.removeChild(child);
i--; // there is one fewer child now
} else {
mtr = this.replaceChild(factory.create('mtr'), child) as MmlNode;
}
mtr.appendChild(isMtd ? child : factory.create('mtd', {}, [child])); // Move the child into the mtr
if (!options['fixMtables']) {
child.parent.removeChild(child); // remove the child from its mtd or mtr
child.parent = this; // ... and make it think it is a child of the table again
isMtd && mtr.appendChild(factory.create('mtd')); // child will be replaced, so make sure there is an mtd
const merror = child.mError('Children of ' + this.kind + ' must be mtr or mlabeledtr', options, isMtd);
mtr.childNodes[mtr.childNodes.length - 1].appendChild(merror); // append the error to the mtd in the mtr
}
}
}
super.verifyChildren(options);
}
/**
* @override
*/
public setTeXclass(prev: MmlNode) {
this.getPrevClass(prev);
for (const child of this.childNodes) {
child.setTeXclass(null);
}
return this;
}
}

View File

@@ -0,0 +1,92 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMtd node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlBaseNode, MmlNode} from '../MmlNode.js';
import {INHERIT} from '../Attributes.js';
/*****************************************************************/
/**
* Implements the MmlMtd node class (subclass of AbstractMmlBaseNode)
*/
export class MmlMtd extends AbstractMmlBaseNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlBaseNode.defaults,
rowspan: 1,
columnspan: 1,
rowalign: INHERIT,
columnalign: INHERIT,
groupalign: INHERIT
};
/**
* @override
*/
public get kind() {
return 'mtd';
}
/**
* <mtd> has an inferred mrow
* @overrride
*/
public get arity() {
return -1;
}
/**
* <mtd> can contain line breaks
* @override
*/
public get linebreakContainer() {
return true;
}
/**
* Check that parent is mtr
*
* @override
*/
protected verifyChildren(options: PropertyList) {
if (this.parent && !this.parent.isKind('mtr')) {
this.mError(this.kind + ' can only be a child of an mtr or mlabeledtr', options, true);
return;
}
super.verifyChildren(options);
}
/**
* @override
*/
public setTeXclass(prev: MmlNode) {
this.getPrevClass(prev);
this.childNodes[0].setTeXclass(null);
return this;
}
}

View File

@@ -0,0 +1,61 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMtext node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlTokenNode, TEXCLASS} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMtext node class (subclass of AbstractMmlTokenNode)
*/
export class MmlMtext extends AbstractMmlTokenNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlTokenNode.defaults
};
/**
* TeX class is ORD
*/
protected texclass = TEXCLASS.ORD;
/**
* @override
*/
public get kind() {
return 'mtext';
}
/**
* <mtext> is always space-like according to the spec
* @override
*/
public get isSpacelike() {
return true;
}
}

View File

@@ -0,0 +1,144 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMtr and MmlMlabeledtr nodes
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {MmlNode, AbstractMmlNode, AttributeList} from '../MmlNode.js';
import {INHERIT} from '../Attributes.js';
import {split} from '../../../util/string.js';
/*****************************************************************/
/**
* Implements the MmlMtr node class (subclass of AbstractMmlNode)
*/
export class MmlMtr extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults,
rowalign: INHERIT,
columnalign: INHERIT,
groupalign: INHERIT
};
/**
* @override
*/
public get kind() {
return 'mtr';
}
/**
* <mtr> can contain linebreaks
* @override
*/
public get linebreakContainer() {
return true;
}
/**
* Inherit the mtr attributes
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
for (const child of this.childNodes) {
if (!child.isKind('mtd')) {
this.replaceChild(this.factory.create('mtd'), child)
.appendChild(child);
}
}
const calign = split(this.attributes.get('columnalign') as string);
if (this.arity === 1) {
calign.unshift(this.parent.attributes.get('side') as string);
}
attributes = this.addInheritedAttributes(attributes, {
rowalign: this.attributes.get('rowalign'),
columnalign: 'center'
});
for (const child of this.childNodes) {
attributes.columnalign[1] = calign.shift() || attributes.columnalign[1];
child.setInheritedAttributes(attributes, display, level, prime);
}
}
/**
* Check that parent is mtable and children are mtd
*
* @override
*/
protected verifyChildren(options: PropertyList) {
if (this.parent && !this.parent.isKind('mtable')) {
this.mError(this.kind + ' can only be a child of an mtable', options, true);
return;
}
for (const child of this.childNodes) {
if (!child.isKind('mtd')) {
let mtd = this.replaceChild(this.factory.create('mtd'), child) as MmlNode;
mtd.appendChild(child);
if (!options['fixMtables']) {
child.mError('Children of ' + this.kind + ' must be mtd', options);
}
}
}
super.verifyChildren(options);
}
/**
* @override
*/
public setTeXclass(prev: MmlNode) {
this.getPrevClass(prev);
for (const child of this.childNodes) {
child.setTeXclass(null);
}
return this;
}
}
/*****************************************************************/
/**
* Implements the MmlMlabeledtr node class (subclass of MmlMtr)
*/
export class MmlMlabeledtr extends MmlMtr {
/**
* @override
*/
public get kind() {
return 'mlabeledtr';
}
/**
* <mlabeledtr> requires at least one child (the label)
* @override
*/
get arity() {
return 1;
}
}

View File

@@ -0,0 +1,238 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlMunderover node
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlBaseNode, AttributeList} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMunderover node class (subclass of AbstractMmlNode)
*/
export class MmlMunderover extends AbstractMmlBaseNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlBaseNode.defaults,
accent: false,
accentunder: false,
align: 'center'
};
/**
* The names of attributes controling accents for each child node (reversed for mover below)
*/
protected static ACCENTS = ['', 'accentunder', 'accent'];
/**
* @override
*/
public get kind() {
return 'munderover';
}
/**
* <munderover> requires three children
* @override
*/
public get arity() {
return 3;
}
/**
* @return {number} The base is child 0
*/
public get base(): number {
return 0;
}
/**
* @return {number} Child 1 goes under (overridden by mover below)
*/
public get under(): number {
return 1;
}
/**
* @return {number} Child 2 goes over (overridden by mover below)
*/
public get over(): number {
return 2;
}
/**
* <munderover> can contain line breaks
* @override
*/
public get linebreakContainer() {
return true;
}
/**
* Base is in prime style if there is an over node
* Force scriptlevel change if converted to sub-sup by movablelimits on the base in non-display mode
* Adjust displaystyle, scriptlevel, and primestyle for the under/over nodes and check if accent
* values have changed due to the inheritance (e.g., settings in operator dictionary)
*
* @override
*/
protected setChildInheritedAttributes(attributes: AttributeList, display: boolean, level: number, prime: boolean) {
let nodes = this.childNodes;
nodes[0].setInheritedAttributes(attributes, display, level, prime || !!nodes[this.over]);
let force = !!(!display && nodes[0].coreMO().attributes.get('movablelimits'));
let ACCENTS = (this.constructor as typeof MmlMunderover).ACCENTS;
nodes[1].setInheritedAttributes(attributes, false,
this.getScriptlevel(ACCENTS[1], force, level),
prime || this.under === 1);
this.setInheritedAccent(1, ACCENTS[1], display, level, prime, force);
if (!nodes[2]) {
return;
}
nodes[2].setInheritedAttributes(attributes, false,
this.getScriptlevel(ACCENTS[2], force, level),
prime || this.under === 2);
this.setInheritedAccent(2, ACCENTS[2], display, level, prime, force);
}
/**
* @param {string} accent The name of the accent attribute to check ("accent" or "accentunder")
* @param {boolean} force True if the scriptlevel change is to be forced to occur
* @param {number} level The current scriptlevel
* @return {number} The new script level based on the accent attribute
*/
protected getScriptlevel(accent: string, force: boolean, level: number): number {
if (force || !this.attributes.get(accent)) {
level++;
}
return level;
}
/**
* Check if an under or over accent should cause the appropriate accent attribute to be inherited
* on the munderover node, and if it is not the default, re-inherit the scriptlevel, since that
* is affected by the accent attribute
*
* @param {number} n The index of the node to check
* @param {string} accent The name of the accent attribute to check ("accent" or "accentunder")
* @param {boolean} display The displaystyle
* @param {number} level The scriptlevel
* @param {number} prime The TeX prime style
* @param {boolean} force Whether to force the scriptlevel change
*/
protected setInheritedAccent(n: number, accent: string, display: boolean, level: number,
prime: boolean, force: boolean) {
let node = this.childNodes[n];
if (this.attributes.getExplicit(accent) == null && node.isEmbellished) {
let value = node.coreMO().attributes.get('accent');
this.attributes.setInherited(accent, value);
if (value !== this.attributes.getDefault(accent)) {
node.setInheritedAttributes({}, display, this.getScriptlevel(accent, force, level), prime);
}
}
}
}
/*****************************************************************/
/**
* Implements the MmlMunder node class (subclass of MmlMunderover)
*/
export class MmlMunder extends MmlMunderover {
/**
* @override
*/
public static defaults: PropertyList = {
...MmlMunderover.defaults
};
/**
* @override
*/
public get kind() {
return 'munder';
}
/**
* <munder> has only two children
* @override
*/
public get arity() {
return 2;
}
}
/*****************************************************************/
/**
* Implements the MmlMover node class (subclass of MmlMunderover)
*/
export class MmlMover extends MmlMunderover {
/**
* @override
*/
public static defaults: PropertyList = {
...MmlMunderover.defaults
};
/**
* The first child is the over accent (second never occurs)
*/
protected static ACCENTS = ['', 'accent', 'accentunder'];
/**
* @override
*/
public get kind() {
return 'mover';
}
/**
* <mover> has only two children
* @override
*/
get arity() {
return 2;
}
/**
* Child 1 is the over node
* @override
*/
public get over() {
return 1;
}
/**
* Child 2 is the null (the under node)
* @override
*/
public get under() {
return 2;
}
}

View File

@@ -0,0 +1,130 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the MmlSemantics, MmlAnnotation, and MmlAnnotationXML nodes
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {PropertyList} from '../../Tree/Node.js';
import {AbstractMmlNode, AbstractMmlBaseNode} from '../MmlNode.js';
/*****************************************************************/
/**
* Implements the MmlMroot node class (subclass of AbstractMmlBaseNode)
*/
export class MmlSemantics extends AbstractMmlBaseNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlBaseNode.defaults,
definitionUrl: null,
encoding: null
};
/**
* @override
*/
public get kind() {
return 'semantics';
}
/**
* <semantics> requires at least one node
* @override
*/
public get arity() {
return 1;
}
/**
* Ignore <semantics> when looking for partent node
* @override
*/
public get notParent() {
return true;
}
}
/*****************************************************************/
/**
* Implements the MmlMroot node class (subclass of AbstractMmlNode)
*/
export class MmlAnnotationXML extends AbstractMmlNode {
/**
* @override
*/
public static defaults: PropertyList = {
...AbstractMmlNode.defaults,
definitionUrl: null,
encoding: null,
cd: 'mathmlkeys',
name: '',
src: null
};
/**
* @override
*/
public get kind() {
return 'annotation-xml';
}
/**
* Children are XMLNodes, so don't bother inheritting to them
* @override
*/
protected setChildInheritedAttributes() {}
}
/*****************************************************************/
/**
* Implements the MmlMroot node class (subclass of MmlAnnotationXML)
*/
export class MmlAnnotation extends MmlAnnotationXML {
/**
* @override
*/
public static defaults = {
...MmlAnnotationXML.defaults
};
/**
* Extra properties for this node
*/
public properties = {
isChars: true
};
/**
* @override
*/
public get kind() {
return 'annotation';
}
}

View File

@@ -0,0 +1,67 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 A visitor class that visits MmlNode trees
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {TextNode, XMLNode} from './MmlNode.js';
import {MmlFactory} from './MmlFactory.js';
import {AbstractVisitor} from '../Tree/Visitor.js';
/*****************************************************************/
/**
* Implements the MmlVisitor (subclass of Visitor, and base class
* for visitors that accept MmlNode trees)
*/
export class MmlVisitor extends AbstractVisitor {
/**
* @param {MmlFactory} factory The MmlNode factory (defaults to MmlFactory if not given)
*
* @constructor
* @extends {AbstractVisitor}
*/
constructor(factory: MmlFactory = null) {
if (!factory) {
factory = new MmlFactory();
}
super(factory);
}
/***********************************************/
/**
* Stubs for overriding in subclasses
*/
/**
* @param {TextNode} node The TextNode to visit
* @param {any[]} args Any arguments needed by the visitor
* @return {any} Any return value needed for the visitor
*/
public visitTextNode(_node: TextNode, ..._args: any[]): any {}
/**
* @param {XMLNode} node The XMLNode to visit
* @param {any[]} args Any arguments needed by the visitor
* @return {any} Any return value needed for the visitor
*/
public visitXMLNode(_node: XMLNode, ..._args: any[]): any {}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,248 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 A visitor that produces a serilaied MathML string
* (replacement for toMathML() output from v2)
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {MmlVisitor} from './MmlVisitor.js';
import {MmlNode, TextNode, XMLNode, TEXCLASS, TEXCLASSNAMES} from './MmlNode.js';
import {MmlMi} from './MmlNodes/mi.js';
export const DATAMJX = 'data-mjx-';
export const toEntity = (c: string) => '&#x' + c.codePointAt(0).toString(16).toUpperCase() + ';';
type PropertyList = {[name: string]: string};
/*****************************************************************/
/**
* Implements the SerializedMmlVisitor (subclass of MmlVisitor)
*/
export class SerializedMmlVisitor extends MmlVisitor {
/**
* Translations for the internal mathvariants
*/
public static variants: PropertyList = {
'-tex-calligraphic': 'script',
'-tex-bold-calligraphic': 'bold-script',
'-tex-oldstyle': 'normal',
'-tex-bold-oldstyle': 'bold',
'-tex-mathit': 'italic'
};
/**
* Attributes to include on every element of a given kind
*/
public static defaultAttributes: {[kind: string]: PropertyList} = {
math: {
xmlns: 'http://www.w3.org/1998/Math/MathML'
}
};
/**
* Convert the tree rooted at a particular node into a serialized MathML string
*
* @param {MmlNode} node The node to use as the root of the tree to traverse
* @return {string} The MathML string representing the internal tree
*/
public visitTree(node: MmlNode): string {
return this.visitNode(node, '');
}
/**
* @param {TextNode} node The text node to visit
* @param {string} space The amount of indenting for this node
* @return {string} The (HTML-quoted) text of the node
*/
public visitTextNode(node: TextNode, _space: string): string {
return this.quoteHTML(node.getText());
}
/**
* @param {XMLNode} node The XML node to visit
* @param {string} space The amount of indenting for this node
* @return {string} The serialization of the XML node
*/
public visitXMLNode(node: XMLNode, space: string): string {
return space + node.getSerializedXML();
}
/**
* Visit an inferred mrow, but don't add the inferred row itself (since
* it is supposed to be inferred).
*
* @param {MmlNode} node The inferred mrow to visit
* @param {string} space The amount of indenting for this node
* @return {string} The serialized contents of the mrow, properly indented
*/
public visitInferredMrowNode(node: MmlNode, space: string): string {
let mml = [];
for (const child of node.childNodes) {
mml.push(this.visitNode(child, space));
}
return mml.join('\n');
}
/**
* Visit a TeXAtom node. It is turned into a mrow with the appropriate TeX class
* indicator.
*
* @param {MmlNode} node The TeXAtom to visit.
* @param {string} space The amount of indenting for this node.
* @return {string} The serialized contents of the mrow, properly indented.
*/
public visitTeXAtomNode(node: MmlNode, space: string): string {
let children = this.childNodeMml(node, space + ' ', '\n');
let mml = space + '<mrow' + this.getAttributes(node) + '>' +
(children.match(/\S/) ? '\n' + children + space : '') + '</mrow>';
return mml;
}
/**
* @param {MmlNode} node The annotation node to visit
* @param {string} space The number of spaces to use for indentation
* @return {string} The serializied annotation element
*/
public visitAnnotationNode(node: MmlNode, space: string): string {
return space + '<annotation' + this.getAttributes(node) + '>'
+ this.childNodeMml(node, '', '')
+ '</annotation>';
}
/**
* The generic visiting function:
* Make the string version of the open tag, properly indented, with it attributes
* Increate the indentation level
* Add the childnodes
* Add the end tag with proper spacing (empty tags have the close tag following directly)
*
* @param {MmlNode} node The node to visit
* @param {string} space The number of spaces to use for indentation
* @return {string} The serialization of the given node
*/
public visitDefault(node: MmlNode, space: string): string {
let kind = node.kind;
let [nl, endspace] = (node.isToken || node.childNodes.length === 0 ? ['', ''] : ['\n', space]);
const children = this.childNodeMml(node, space + ' ', nl);
return space + '<' + kind + this.getAttributes(node) + '>'
+ (children.match(/\S/) ? nl + children + endspace : '')
+ '</' + kind + '>';
}
/**
* @param {MmlNode} node The node whose children are to be added
* @param {string} space The spaces to use for indentation
* @param {string} nl The newline character (or empty)
* @return {string} The serializied children
*/
protected childNodeMml(node: MmlNode, space: string, nl: string): string {
let mml = '';
for (const child of node.childNodes) {
mml += this.visitNode(child, space) + nl;
}
return mml;
}
/**
* @param {MmlNode} node The node whose attributes are to be produced
* @return {string} The attribute list as a string
*/
protected getAttributes(node: MmlNode): string {
const attr = [];
const defaults = (this.constructor as typeof SerializedMmlVisitor).defaultAttributes[node.kind] || {};
const attributes = Object.assign({},
defaults,
this.getDataAttributes(node),
node.attributes.getAllAttributes()
);
const variants = (this.constructor as typeof SerializedMmlVisitor).variants;
if (attributes.hasOwnProperty('mathvariant') && variants.hasOwnProperty(attributes.mathvariant)) {
attributes.mathvariant = variants[attributes.mathvariant];
}
for (const name of Object.keys(attributes)) {
const value = String(attributes[name]);
if (value === undefined) continue;
attr.push(name + '="' + this.quoteHTML(value) + '"');
}
return attr.length ? ' ' + attr.join(' ') : '';
}
/**
* Create the list of data-mjx-* attributes
*
* @param {MmlNode} node The node whose data list is to be generated
* @return {PropertyList} The final class attribute list
*/
protected getDataAttributes(node: MmlNode): PropertyList {
const data = {} as PropertyList;
const variant = node.attributes.getExplicit('mathvariant') as string;
const variants = (this.constructor as typeof SerializedMmlVisitor).variants;
variant && variants.hasOwnProperty(variant) && this.setDataAttribute(data, 'variant', variant);
node.getProperty('variantForm') && this.setDataAttribute(data, 'alternate', '1');
node.getProperty('pseudoscript') && this.setDataAttribute(data, 'pseudoscript', 'true');
node.getProperty('autoOP') === false && this.setDataAttribute(data, 'auto-op', 'false');
const scriptalign = node.getProperty('scriptalign') as string;
scriptalign && this.setDataAttribute(data, 'script-align', scriptalign);
const texclass = node.getProperty('texClass') as number;
if (texclass !== undefined) {
let setclass = true;
if (texclass === TEXCLASS.OP && node.isKind('mi')) {
const name = (node as MmlMi).getText();
setclass = !(name.length > 1 && name.match(MmlMi.operatorName));
}
setclass && this.setDataAttribute(data, 'texclass', texclass < 0 ? 'NONE' : TEXCLASSNAMES[texclass]);
}
node.getProperty('scriptlevel') && node.getProperty('useHeight') === false &&
this.setDataAttribute(data, 'smallmatrix', 'true');
return data;
}
/**
* @param {PropertyList} data The class attribute list
* @param {string} name The name for the data-mjx-name attribute
* @param {string} value The value of the attribute
*/
protected setDataAttribute(data: PropertyList, name: string, value: string) {
data[DATAMJX + name] = value;
}
/**
* Convert HTML special characters to entities (&amp;, &lt;, &gt;, &quot;)
* Convert multi-character Unicode characters to entities
* Convert non-ASCII characters to entities.
*
* @param {string} value The string to be made HTML escaped
* @return {string} The string with escaping performed
*/
protected quoteHTML(value: string): string {
return value
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/\"/g, '&quot;')
.replace(/[\uD800-\uDBFF]./g, toEntity)
.replace(/[\u0080-\uD7FF\uE000-\uFFFF]/g, toEntity);
}
}

View File

@@ -0,0 +1,106 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 A visitor that produces a serilaied MathML string
* that contains addition information about inherited
* attributes and internal properties.
* (For testing purposes only.)
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {SerializedMmlVisitor} from './SerializedMmlVisitor.js';
import {MmlNode} from './MmlNode.js';
import {PropertyList} from '../Tree/Node.js';
/*****************************************************************/
/**
* Implements the TestMmlVisitor (subclass of SerializedMmlVisitor)
*/
export class TestMmlVisitor extends SerializedMmlVisitor {
/**
* The generic visiting function:
* Make the string versino of the open tag with it attributes (explicit and
* inherited) and properties
* Increate the indentation level
* Add the childnodes
* Add the end tag with proper spacing (empty tags have the close tag following directly)
*
* @param {MmlNode} node The node to visit
* @param {string} space The number of spaces to use for indentation
*/
public visitDefault(node: MmlNode, space: string) {
let kind = node.kind;
let [nl, endspace] = (node.isToken || node.childNodes.length === 0 ? ['', ''] : ['\n', space]);
let mml = space + '<' + kind + this.getAttributes(node) +
this.getInherited(node) + this.getProperties(node) + '\n' + space + ' ' +
this.attributeString({
isEmbellished: node.isEmbellished,
isSpacelike: node.isSpacelike,
texClass: node.texClass
}, '{', '}') +
'>' + nl;
space += ' ';
for (const child of node.childNodes) {
mml += this.visitNode(child, space) + nl;
}
mml += endspace + '</' + kind + '>';
return mml;
}
/**
* @param {MmlNode} node The node whose attributes are to be produced
* @return {string} The attribute list as a string
*/
protected getAttributes(node: MmlNode): string {
return this.attributeString(node.attributes.getAllAttributes(), '', '');
}
/**
* @param {MmlNode} node The node whose inherited attributes are to be produced
* @return {string} The inhertited attribute list as a string (with each in [...])
*/
protected getInherited(node: MmlNode): string {
return this.attributeString(node.attributes.getAllInherited(), '[', ']');
}
/**
* @param {MmlNode} node The node whose properties are to be produced
* @return {string} The property list as a string (with each in [[...]])
*/
protected getProperties(node: MmlNode): string {
return this.attributeString(node.getAllProperties(), '[[', ']]');
}
/**
* @param {PropertyList} attributes The attributes to be made into a list
* @param {string} open The opening delimiter to add before each attribute
* @param {string} close The closing delimiter to add after each attribute
* @return {string} The attribute list as a string
*/
protected attributeString(attributes: PropertyList, open: string, close: string): string {
let ATTR = '';
for (const name of Object.keys(attributes)) {
ATTR += ' ' + open + name + '="' + this.quoteHTML(String(attributes[name])) + '"' + close;
}
return ATTR;
}
}

236
node_modules/mathjax-full/ts/core/OutputJax.ts generated vendored Normal file
View File

@@ -0,0 +1,236 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Implements the interface and abstract class for the OutputJax
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {userOptions, defaultOptions, OptionList} from '../util/Options.js';
import {MathDocument} from './MathDocument.js';
import {MathItem} from './MathItem.js';
import {DOMAdaptor} from '../core/DOMAdaptor.js';
import {FunctionList} from '../util/FunctionList.js';
/*****************************************************************/
/**
* The OutputJax interface
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface OutputJax<N, T, D> {
/**
* The name of this output jax class
*/
name: string;
/**
* The options for the instance
*/
options: OptionList;
/**
* Lists of post-filters to call after typesetting the math
*/
postFilters: FunctionList;
/**
* The DOM adaptor for managing HTML elements
*/
adaptor: DOMAdaptor<N, T, D>;
/**
* @param {DOMAdaptor} adaptor The adaptor to use in this jax
*/
setAdaptor(adaptor: DOMAdaptor<N, T, D>): void;
/**
* Do any initialization that depends on the document being set up
*/
initialize(): void;
/**
* Reset any needed features of the output jax
*
* @param {any[]} args The arguments needed by the reset operation
*/
reset(...args: any[]): void;
/**
* Typset a given MathItem
*
* @param {MathItem} math The MathItem to be typeset
* @param {MathDocument} document The MathDocument in which the typesetting should occur
* @return {N} The DOM tree for the typeset math
*/
typeset(math: MathItem<N, T, D>, document?: MathDocument<N, T, D>): N;
/**
* Handle an escaped character (e.g., \$ from the TeX input jax preventing it from being a delimiter)
*
* @param {MathItem} math The MathItem to be escaped
* @param {MathDocument} document The MathDocument in which the math occurs
* @return {N} The DOM tree for the escaped item
*/
escaped(math: MathItem<N, T, D>, document?: MathDocument<N, T, D>): N;
/**
* Get the metric information for all math in the given document
*
* @param {MathDocument} document The MathDocument being processed
*/
getMetrics(document: MathDocument<N, T, D>): void;
/**
* Produce the stylesheet needed for this output jax
*
* @param {MathDocument} document The MathDocument being processed
*/
styleSheet(document: MathDocument<N, T, D>): N;
/**
* Produce any page-specific elements needed for this output jax
*
* @param {MathDocument} document The MathDocument being processed
*/
pageElements(document: MathDocument<N, T, D>): N;
}
/*****************************************************************/
/**
* The OutputJax abstract class
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export abstract class AbstractOutputJax<N, T, D> implements OutputJax<N, T, D> {
/**
* The name for the output jax
*/
public static NAME: string = 'generic';
/**
* The default options for the output jax
*/
public static OPTIONS: OptionList = {};
/**
* The actual options supplied to the output jax
*/
public options: OptionList;
/**
* Filters to run after the output is processed
*/
public postFilters: FunctionList;
/**
* The MathDocument's DOMAdaptor
*/
public adaptor: DOMAdaptor<N, T, D> = null; // set by the handler
/**
* @param {OptionList} options The options for this instance
*/
constructor(options: OptionList = {}) {
let CLASS = this.constructor as typeof AbstractOutputJax;
this.options = userOptions(defaultOptions({}, CLASS.OPTIONS), options);
this.postFilters = new FunctionList();
}
/**
* @return {string} The name for this output jax class
*/
public get name(): string {
return (this.constructor as typeof AbstractOutputJax).NAME;
}
/**
* @override
*/
public setAdaptor(adaptor: DOMAdaptor<N, T, D>) {
this.adaptor = adaptor;
}
/**
* @override
*/
public initialize() {
}
/**
* @override
*/
public reset(..._args: any[]) {
}
/**
* @override
*/
public abstract typeset(math: MathItem<N, T, D>, document?: MathDocument<N, T, D>): N;
/**
* @override
*/
public abstract escaped(math: MathItem<N, T, D>, document?: MathDocument<N, T, D>): N;
/**
* @override
*/
public getMetrics(_document: MathDocument<N, T, D>) {
}
/**
* @override
*/
public styleSheet(_document: MathDocument<N, T, D>) {
return null as N;
}
/**
* @override
*/
public pageElements(_document: MathDocument<N, T, D>) {
return null as N;
}
/**
* Execute a set of filters, passing them the MathItem and any needed data,
* and return the (possibly modified) data
*
* @param {FunctionList} filters The list of functions to be performed
* @param {MathItem} math The math item that is being processed
* @param {MathDocument} document The math document contaiing the math item
* @param {any} data Whatever other data is needed
* @return {any} The (possibly modified) data
*/
protected executeFilters(
filters: FunctionList, math: MathItem<N, T, D>,
document: MathDocument<N, T, D>, data: any
): any {
let args = {math, document, data};
filters.execute(args);
return args.data;
}
}

200
node_modules/mathjax-full/ts/core/Tree/Factory.ts generated vendored Normal file
View File

@@ -0,0 +1,200 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 The generic Factory class for creating arbitrary objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
/*****************************************************************/
/**
* The Factory node interfaces (one for the node instance, one for the node class)
*/
export interface FactoryNode {
readonly kind: string;
}
/**
* @template N The Node type being created by the factory
*/
export interface FactoryNodeClass<N extends FactoryNode> {
/**
* @param {Factory<N, FactoryNodeClass<N>>} factory The factory for creating more nodes
* @param {any[]} args Any additional arguments needed by the node
* @return {N} The newly created node
*/
new(factory: Factory<N, FactoryNodeClass<N>>, ...args: any[]): N;
}
/*****************************************************************/
/**
* The Factory interface
*
* Factory<N, C> takes a node type N and a node class C, which give
* the interfaces for the node instance and the node constructors. We
* need both for two reasons: first, you can't use typeof N to get C,
* since N is a type not an object, and if N has static members, we
* may want to access them from the results of getNodeClass(kind)
* (this is done in MmlNodes, for example).
*
* @template N The node type created by the factory
* @template C The class of the node being constructed (for access to static properties)
*/
export interface Factory<N extends FactoryNode, C extends FactoryNodeClass<N>> {
/**
* @param {string} kind The kind of node to create
* @return {N} The newly created node of the given kind
*/
create(kind: string): N;
/**
* Defines a class for a given node kind
*
* @param {string} kind The kind whose class is being defined
* @param {C} nodeClass The class for the given kind
*/
setNodeClass(kind: string, nodeClass: C): void;
/**
* @param {string} kind The kind of node whose class is to be returned
* @return {C} The class object for the given kind
*/
getNodeClass(kind: string): C;
/**
* @param {string} kind The kind whose definition is to be deleted
*/
deleteNodeClass(kind: string): void;
/**
* @param {N} node The node to test if it is of a given kind
* @param {string} kind The kind to test for
* @return {boolean} True if the node is of the given kind, false otherwise
*/
nodeIsKind(node: N, kind: string): boolean;
/**
* @return {string[]} The names of all the available kinds of nodes
*/
getKinds(): string[];
}
/*****************************************************************/
/**
* The generic AbstractFactoryClass interface
* (needed for access to defaultNodes via the constructor)
*
* @template N The node type created by the factory
* @template C The class of the node being constructed (for access to static properties)
*/
interface AbstractFactoryClass<N extends FactoryNode, C extends FactoryNodeClass<N>> extends Function {
defaultNodes: {[kind: string]: C};
}
/*****************************************************************/
/**
* The generic AbstractFactory class
*
* @template N The node type created by the factory
* @template C The class of the node being constructed (for access to static properties)
*/
export abstract class AbstractFactory<N extends FactoryNode, C extends FactoryNodeClass<N>> implements Factory<N, C> {
/**
* The default collection of objects to use for the node map
*/
public static defaultNodes = {};
/**
* The default kind
*/
public defaultKind = 'unknown';
/**
* The map of node kinds to node classes
*/
protected nodeMap: Map<string, C> = new Map();
/**
* An object containing functions for creating the various node kinds
*/
protected node: {[kind: string]: (...args: any[]) => N} = {};
/**
* @override
*/
constructor(nodes: {[kind: string]: C} = null) {
if (nodes === null) {
nodes = (this.constructor as AbstractFactoryClass<N, C>).defaultNodes;
}
for (const kind of Object.keys(nodes)) {
this.setNodeClass(kind, nodes[kind]);
}
}
/**
* @override
*/
public create(kind: string, ...args: any[]) {
return (this.node[kind] || this.node[this.defaultKind])(...args);
}
/**
* @override
*/
public setNodeClass(kind: string, nodeClass: C) {
this.nodeMap.set(kind, nodeClass);
let THIS = this;
let KIND = this.nodeMap.get(kind);
this.node[kind] = (...args: any[]) => {
return new KIND(THIS, ...args);
};
}
/**
* @override
*/
public getNodeClass(kind: string): C {
return this.nodeMap.get(kind);
}
/**
* @override
*/
public deleteNodeClass(kind: string) {
this.nodeMap.delete(kind);
delete this.node[kind];
}
/**
* @override
*/
public nodeIsKind(node: N, kind: string) {
return (node instanceof this.getNodeClass(kind));
}
/**
* @override
*/
public getKinds() {
return Array.from(this.nodeMap.keys());
}
}

395
node_modules/mathjax-full/ts/core/Tree/Node.ts generated vendored Normal file
View File

@@ -0,0 +1,395 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Generic Node classes for node trees
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {NodeFactory} from './NodeFactory.js';
/**
* PropertyList and Property are for string data like
* attributes and other properties
*/
export type Property = string | number | boolean;
export type PropertyList = {[key: string]: Property};
/*********************************************************/
/**
* The generic Node interface
*/
export interface Node {
readonly kind: string;
/**
* The NodeFactory to use to create additional nodes, as needed
*/
readonly factory: NodeFactory<Node, NodeClass>;
parent: Node;
childNodes: Node[];
/**
* @param {string} name The name of the property to set
* @param {Property} value The value to which the property will be set
*/
setProperty(name: string, value: Property): void;
/**
* @param {string} name The name of the property to get
* @return {Property} The value of the named property
*/
getProperty(name: string): Property;
/**
* @return {string[]} An array of the names of every property currently defined
*/
getPropertyNames(): string[];
/**
* @return {PropertyList} The propery list containing all the properties of the node
*/
getAllProperties(): PropertyList;
/**
* @param {string[]} names The names of the properties to be removed
*/
removeProperty(...names: string[]): void;
/**
* @param {string} kind The type of node to test for
* @return {boolean} True when the node is of the given type
*/
isKind(kind: string): boolean;
/**
* @param {Node[]} children The child nodes to add to this node
*/
setChildren(children: Node[]): void;
/**
* @param {Node} child A node to add to this node's children
* @return {Node} The child node that was added
*/
appendChild(child: Node): Node;
/**
* @param {Node} newChild A child node to be inserted
* @param {Node} oldChild A child node to be replaced
* @return {Node} The old child node that was removed
*/
replaceChild(newChild: Node, oldChild: Node): Node;
/**
* @param {Node} child Child node to be removed
* @return {Node} The old child node that was removed
*/
removeChild(child: Node): Node;
/**
* @param {Node} child A child node whose index in childNodes is desired
* @return {number} The index of the child in childNodes, or null if not found
*/
childIndex(child: Node): number;
/**
* Make a deep copy of the node (but with no parent).
*/
copy(): Node;
/**
* @param {string} kind The kind of nodes to be located in the tree
* @return {Node[]} An array of nodes that are children (at any depth) of the given kind
*/
findNodes(kind: string): Node[];
/**
* @param {Function} func A function to apply to each node in the tree rooted at this node
* @param {any} data Data to pass to the function (as state information)
*/
walkTree(func: (node: Node, data?: any) => void, data?: any): void;
}
/*********************************************************/
/**
* The generic Node class interface
*/
export interface NodeClass {
/**
* @param {NodeFactory} factory The NodeFactory to use to create new nodes when needed
* @param {PropertyList} properties Any properties to be added to the node, if any
* @param {Node[]} children The initial child nodes, if any
* @return {Node} The newly created node
*/
new (factory: NodeFactory<Node, NodeClass>, properties?: PropertyList, children?: Node[]): Node;
}
/*********************************************************/
/**
* The abstract Node class
*/
export abstract class AbstractNode implements Node {
/**
* The parent node for this one
*/
public parent: Node = null;
/**
* The properties for this node
*/
protected properties: PropertyList = {};
/**
* The children for this node
*/
public childNodes: Node[] = [];
/**
* @param {NodeFactory} factory The NodeFactory to use to create new nodes when needed
* @param {PropertyList} properties Any properties to be added to the node, if any
* @param {Node[]} children The initial child nodes, if any
*
* @constructor
* @implements {Node}
*/
constructor(readonly factory: NodeFactory<Node, NodeClass>, properties: PropertyList = {}, children: Node[] = []) {
for (const name of Object.keys(properties)) {
this.setProperty(name, properties[name]);
}
if (children.length) {
this.setChildren(children);
}
}
/**
* @override
*/
public get kind() {
return 'unknown';
}
/**
* @override
*/
public setProperty(name: string, value: Property) {
this.properties[name] = value;
}
/**
* @override
*/
public getProperty(name: string) {
return this.properties[name];
}
/**
* @override
*/
public getPropertyNames() {
return Object.keys(this.properties);
}
/**
* @override
*/
public getAllProperties() {
return this.properties;
}
/**
* @override
*/
public removeProperty(...names: string[]) {
for (const name of names) {
delete this.properties[name];
}
}
/**
* @override
*/
public isKind(kind: string): boolean {
return this.factory.nodeIsKind(this, kind);
}
/**
* @override
*/
public setChildren(children: Node[]) {
this.childNodes = [];
for (let child of children) {
this.appendChild(child);
}
}
/**
* @override
*/
public appendChild(child: Node) {
this.childNodes.push(child);
child.parent = this;
return child;
}
/**
* @override
*/
public replaceChild(newChild: Node, oldChild: Node) {
let i = this.childIndex(oldChild);
// If i === null should we error? return null? silently fail?
if (i !== null) {
this.childNodes[i] = newChild;
newChild.parent = this;
oldChild.parent = null;
}
return newChild;
}
/**
* @override
*/
public removeChild(child: Node) {
const i = this.childIndex(child);
if (i !== null) {
this.childNodes.splice(i, 1);
child.parent = null;
}
return child;
}
/**
* @override
*/
public childIndex(node: Node) {
let i = this.childNodes.indexOf(node);
return (i === -1 ? null : i);
}
/**
* @override
*/
public copy() {
const node = (this as AbstractNode).factory.create(this.kind) as AbstractNode;
node.properties = {...this.properties};
for (const child of this.childNodes || []) {
if (child) {
node.appendChild(child.copy());
}
}
return node;
}
/**
* @override
*/
public findNodes(kind: string) {
let nodes: Node[] = [];
this.walkTree((node: Node) => {
if (node.isKind(kind)) {
nodes.push(node);
}
});
return nodes;
}
/**
* @override
*/
public walkTree(func: (node: Node, data?: any) => void, data?: any) {
func(this, data);
for (const child of this.childNodes) {
if (child) {
child.walkTree(func, data);
}
}
return data;
}
/**
* Simple string version for debugging, just to get the structure.
*/
public toString() {
return this.kind + '(' + this.childNodes.join(',') + ')';
}
}
/*********************************************************/
/**
* The abstract EmptyNode class
*/
export abstract class AbstractEmptyNode extends AbstractNode {
/**
* We don't have children, so ignore these methods
*/
/**
* @override
*/
public setChildren(_children: Node[]) {
}
/**
* @override
*/
public appendChild(child: Node) {
return child;
}
/**
* @override
*/
public replaceChild(_newChild: Node, oldChild: Node) {
return oldChild;
}
/**
* @override
*/
public childIndex(_node: Node) {
return null as number;
}
/**
* Don't step into children (there aren't any)
*
* @override
*/
public walkTree(func: (node: Node, data?: any) => void, data?: any) {
func(this, data);
return data;
}
/**
* Simple string version for debugging, just to get the structure.
*/
public toString() {
return this.kind;
}
}

59
node_modules/mathjax-full/ts/core/Tree/NodeFactory.ts generated vendored Normal file
View File

@@ -0,0 +1,59 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 The generic NodeFactory class for creating Node objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {Node, PropertyList} from './Node.js';
import {Factory, FactoryNodeClass, AbstractFactory} from './Factory.js';
/*****************************************************************/
/**
* The NodeFactory interface
*
* @template N The node type created by the factory
* @template C The class of the node being constructed (for access to static properties)
*/
export interface NodeFactory<N extends Node, C extends FactoryNodeClass<N>> extends Factory<N, C> {
/**
* @param {string} kind The kind of node to create
* @param {PropertyList} properties The list of initial properties for the node (if any)
* @param {N[]} children The array of initial child nodes (if any)
* @return {N} The newly created node of the given kind
*/
create(kind: string, properties?: PropertyList, children?: N[]): N;
}
/*****************************************************************/
/**
* The generic NodeFactory class
*
* @template N The node type created by the factory
* @template C The class of the node being constructed (for access to static properties)
*/
export abstract class AbstractNodeFactory<N extends Node, C extends FactoryNodeClass<N>> extends AbstractFactory<N, C> {
/**
* @override
*/
public create(kind: string, properties: PropertyList = {}, children: N[] = []) {
return this.node[kind](properties, children);
}
}

166
node_modules/mathjax-full/ts/core/Tree/Visitor.ts generated vendored Normal file
View File

@@ -0,0 +1,166 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 The generic visitor class for node trees
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {Node, NodeClass, AbstractNode} from './Node.js';
import {NodeFactory} from './NodeFactory.js';
/**
* The type for the functions associated with each node class
*/
export type VisitorFunction = (visitor: NodeFactory<Node, NodeClass>, node: Node, ...args: any[]) => any;
/*****************************************************************/
/**
* Implements the Visitor interface
*/
export interface Visitor {
/**
* Visit the tree rooted at the given node (passing along any needed parameters)
*
* @param {Node} tree The node that is the root of the tree
* @param {any[]} args The arguments to pass to the visitNode functions
* @return {any} Whatever the visitNode function returns for the root tree node
*/
visitTree(tree: Node, ...args: any[]): any;
/**
* Visit a node by calling the visitor function for the given type of node
* (passing along any needed parameters)
*
* @param {Node} node The node to visit
* @param {any[]} args The arguments to pass to the visitor function for this node
* @return {any} Whatever the visitor function returns for this node
*/
visitNode(node: Node, ...args: any[]): any;
/**
* The default visitor function for when no node-specific function is defined
*
* @param {Node} node The node to visit
* @param {any[]} args The arguments to pass to the visitor function for this node
* @return {any} Whatever the visitor function returns for this node
*/
visitDefault(node: Node, ...args: any[]): any;
/**
* Define a visitor function for a given node kind
*
* @param {string} kind The node kind for which the handler is being defined
* @param {VisitorFunction} handler The function to call to handle nodes of this kind
*/
setNodeHandler(kind: string, handler: VisitorFunction): void;
/**
* Remove the visitor function for a given node kind
*
* @param {string} kind The node kind whose visitor function is to be removed
*/
removeNodeHandler(kind: string): void;
/**
* The various visitor functions implemented by the subclasses, and any data they need
*/
[property: string]: any;
}
/*****************************************************************/
/**
* Implements the generic Visitor object
*/
export abstract class AbstractVisitor implements Visitor {
/**
* Holds the mapping from node kinds to visitor funcitons
*/
protected nodeHandlers: Map<string, VisitorFunction> = new Map();
/**
* Visitor functions are named "visitKindNode" where "Kind" is replaced by
* the node kind; e.g., visitTextNode for kind = text.
*
* @param {string} kind The node kind whose method name is needed
* @return {string} The name of the visitor method for the given node kind
*/
protected static methodName(kind: string): string {
return 'visit' + (kind.charAt(0).toUpperCase() + kind.substr(1)).replace(/[^a-z0-9_]/ig, '_') + 'Node';
}
/**
* Create the node handler map by looking for methods with the correct names
* based on the node kinds available from the factory.
*
* @constructor
* @param {NodeFactory} factory The node factory for the kinds of nodes this visitor handles
*/
constructor(factory: NodeFactory<Node, NodeClass>) {
for (const kind of factory.getKinds()) {
let method = (this as Visitor)[AbstractVisitor.methodName(kind)] as VisitorFunction;
if (method) {
this.nodeHandlers.set(kind, method);
}
}
}
/**
* @override
*/
public visitTree(tree: Node, ...args: any[]) {
return this.visitNode(tree, ...args);
}
/**
* @override
*/
public visitNode(node: Node, ...args: any[]) {
let handler = this.nodeHandlers.get(node.kind) || this.visitDefault;
return handler.call(this, node, ...args);
}
/**
* @override
*/
public visitDefault(node: Node, ...args: any[]) {
if (node instanceof AbstractNode) {
for (const child of node.childNodes) {
this.visitNode(child, ...args);
}
}
}
/**
* @override
*/
public setNodeHandler(kind: string, handler: VisitorFunction) {
this.nodeHandlers.set(kind, handler);
}
/**
* @override
*/
public removeNodeHandler(kind: string) {
this.nodeHandlers.delete(kind);
}
}

109
node_modules/mathjax-full/ts/core/Tree/Wrapper.ts generated vendored Normal file
View File

@@ -0,0 +1,109 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Generic Wrapper class for adding methods to a Node class for visitors
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {Node} from './Node.js';
import {WrapperFactory} from './WrapperFactory.js';
/*********************************************************/
/**
* The Wrapper interface
*
* It points to a Node object. Subclasses add methods for the visitor to call.
*
* @template N The Node type being wrapped
* @template W The Wrapper type being produced
*/
export interface Wrapper<N extends Node, W extends Wrapper<N, W>> {
node: N;
readonly kind: string;
/**
* @param {Node} node A node to be wrapped
* @param {any[]} args Any additional arguments needed when creating the wrapper
* @return {Wrapper} The wrapped node
*/
wrap(node: N, ...args: any[]): W;
}
/*********************************************************/
/**
* The Wrapper class interface
*
* @template N The Node type being wrapped
* @template W The Wrapper type being produced
*/
export interface WrapperClass<N extends Node, W extends Wrapper<N, W>> {
/**
* @param {WrapperFactory} factory The factory used to create more wrappers
* @param {N} node The node to be wrapped
* @param {any[]} args Any additional arguments needed when creating the wrapper
* @return {W} The wrapped node
*/
new(factory: WrapperFactory<N, W, WrapperClass<N, W>>, node: N, ...args: any[]): W;
}
/*********************************************************/
/**
* The abstract Wrapper class
*
* @template N The Node type being created by the factory
* @template W The Wrapper type being produced
*/
export class AbstractWrapper<N extends Node, W extends Wrapper<N, W>> implements Wrapper<N, W> {
/**
* The Node object associated with this instance
*/
public node: N;
/**
* The WrapperFactory to use to wrap child nodes, as needed
*/
protected factory: WrapperFactory<N, W, WrapperClass<N, W>>;
/**
* The kind of this wrapper
*/
get kind() {
return this.node.kind;
}
/**
* @param {WrapperFactory} factory The WrapperFactory to use to wrap child nodes when needed
* @param {Node} node The node to wrap
*
* @constructor
* @implements {Wrapper}
*/
constructor(factory: WrapperFactory<N, W, WrapperClass<N, W>>, node: N) {
this.factory = factory;
this.node = node;
}
/**
* @override
*/
public wrap(node: N) {
return this.factory.wrap(node);
}
}

View File

@@ -0,0 +1,64 @@
/*************************************************************
*
* Copyright (c) 2017-2022 The 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 Generic WrapperFactory class for creating Wrapper objects
*
* @author dpvc@mathjax.org (Davide Cervone)
*/
import {Node} from './Node.js';
import {Wrapper, WrapperClass} from './Wrapper.js';
import {Factory, AbstractFactory} from './Factory.js';
/*****************************************************************/
/**
* The generic WrapperFactory class
*
* @template N The Node type being created by the factory
* @template W The Wrapper type being produced (instance type)
* @template C The Wrapper class (for static values)
*/
export interface WrapperFactory<N extends Node, W extends Wrapper<N, W>, C extends WrapperClass<N, W>>
extends Factory<W, C> {
/**
* @param {N} node The node to be wrapped
* @param {any[]} args Any additional arguments needed when wrapping the node
* @return {W} The newly wrapped node
*/
wrap(node: N, ...args: any[]): W;
}
/*****************************************************************/
/**
* The generic WrapperFactory class
*
* @template N The Node type being created by the factory
* @template W The Wrapper type being produced (instance type)
* @template C The Wrapper class (for static values)
*/
export abstract class AbstractWrapperFactory<N extends Node, W extends Wrapper<N, W>, C extends WrapperClass<N, W>>
extends AbstractFactory<W, C> implements WrapperFactory<N, W, C> {
/**
* @param {N} node The node to be wrapped
* @param {any[]} args Any additional arguments needed when wrapping the node
* @return {W} The newly wrapped node
*/
public wrap(node: N, ...args: any[]): W {
return this.create(node.kind, node, ...args);
}
}