Skip to content

Commit

Permalink
Merge pull request #502 from mathjax/container-api
Browse files Browse the repository at this point in the history
Add functions to manage math items within a given container. (#351)
  • Loading branch information
dpvc authored Jun 16, 2020
2 parents 8b8e9a5 + b94f49e commit 48509e1
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 4 deletions.
8 changes: 8 additions & 0 deletions ts/adaptors/HTMLAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export interface MinHTMLElement<N, T> {
/* tslint:disable:jsdoc-require */
getElementsByTagName(name: string): N[] | HTMLCollectionOf<Element>;
getElementsByTagNameNS(ns: string, name: string): N[] | HTMLCollectionOf<Element>;
contains(child: N | T): boolean;
appendChild(child: N | T): N | T | Node;
removeChild(child: N | T): N | T | Node;
replaceChild(nnode: N | T, onode: N | T): N | T | Node;
Expand Down Expand Up @@ -254,6 +255,13 @@ AbstractDOMAdaptor<N, T, D> implements MinHTMLAdaptor<N, T, D> {
return containers;
}

/**
* @override
*/
public contains(container: N, node: N | T) {
return container.contains(node);
}

/**
* @override
*/
Expand Down
12 changes: 12 additions & 0 deletions ts/adaptors/liteAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,16 @@ export class LiteAdaptor extends AbstractDOMAdaptor<LiteElement, LiteText, LiteD
return containers;
}

/**
* @override
*/
public contains(container: LiteNode, node: LiteNode | LiteText) {
while (node && node !== container) {
node = this.parent(node);
}
return !!node;
}

/**
* @override
*/
Expand Down Expand Up @@ -296,6 +306,8 @@ export class LiteAdaptor extends AbstractDOMAdaptor<LiteElement, LiteText, LiteD
const i = this.childIndex(onode);
if (i >= 0) {
onode.parent.children[i] = nnode;
nnode.parent = onode.parent;
onode.parent = null;
}
return onode;
}
Expand Down
13 changes: 10 additions & 3 deletions ts/components/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,19 +353,26 @@ export namespace Startup {
* TypeseClear() clears all the MathItems from the document.
*/
export function makeTypesetMethods() {
MathJax.typeset = (elements: any = null) => {
MathJax.typeset = (elements: any[] = null) => {
document.options.elements = elements;
document.reset();
document.render();
};
MathJax.typesetPromise = (elements: any = null) => {
MathJax.typesetPromise = (elements: any[] = null) => {
document.options.elements = elements;
document.reset();
return mathjax.handleRetriesFor(() => {
document.render();
});
};
MathJax.typesetClear = () => document.clear();
MathJax.typesetClear = (elements: any[] = null) => {
if (elements) {
document.reset();
document.clearMathItemsWithin(elements);
} else {
document.clear();
}
};
}

/**
Expand Down
14 changes: 14 additions & 0 deletions ts/core/DOMAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ export interface DOMAdaptor<N, T, D> {
*/
getElements(nodes: (string | N | N[])[], document: D): N[];

/**
* Determine if a container node contains a given node is 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
Expand Down Expand Up @@ -437,6 +446,11 @@ export abstract class AbstractDOMAdaptor<N, T, D> implements DOMAdaptor<N, T, D>
*/
public abstract getElements(nodes: (string | N | N[])[], document: D): N[];

/**
* @override
*/
public abstract contains(container: N, node: N | T): boolean;

/**
* @override
*/
Expand Down
56 changes: 56 additions & 0 deletions ts/core/MathDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,15 @@ export class RenderList<N, T, D> extends PrioritizedList<RenderData<N, T, D>> {

}

/*****************************************************************/
/**
* 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 MathDocument interface
Expand Down Expand Up @@ -428,6 +437,24 @@ export interface MathDocument<N, T, D> {
*/
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
*/
clearMathItemsWithin(containers: ContainerList<N>): void;

/**
* 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>[];

}

/*****************************************************************/
Expand Down Expand Up @@ -880,6 +907,35 @@ export abstract class AbstractMathDocument<N, T, D> implements MathDocument<N, T
return this;
}

/**
* @override
*/
public clearMathItemsWithin(containers: ContainerList<N>) {
this.math.remove(...this.getMathItemsWithin(containers));
}

/**
* @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;
}

}

/**
Expand Down
24 changes: 23 additions & 1 deletion ts/util/LinkedList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
* A symbol used to mark the special node used to indicate
* the start and end of the list.
*/
const END = Symbol();
export const END = Symbol();

/**
* Shorthand type for the functions used to sort the data items
Expand Down Expand Up @@ -190,6 +190,28 @@ export class LinkedList<DataClass> {
return item.data as DataClass;
}

/**
* Remove items from the list
*
* @param {DataClass[]} items The items to remove
*/
public remove(...items: DataClass[]) {
const map = new Map<DataClass, boolean>();
for (const item of items) {
map.set(item, true);
}
let item = this.list.next;
while (item.data !== END) {
const next = item.next;
if (map.has(item.data as DataClass)) {
item.prev.next = item.next;
item.next.prev = item.prev;
item.next = item.prev = null;
}
item = next;
}
}

/**
* Empty the list
*
Expand Down

0 comments on commit 48509e1

Please sign in to comment.