From 44802218e0e92dbd6125856a05a050e708961bc0 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Wed, 27 May 2020 16:22:32 -0400 Subject: [PATCH 1/4] Add functions to manage math items withing a given container. --- ts/adaptors/HTMLAdaptor.ts | 8 ++++++++ ts/adaptors/liteAdaptor.ts | 12 ++++++++++++ ts/core/DOMAdaptor.ts | 14 ++++++++++++++ ts/core/MathDocument.ts | 29 +++++++++++++++++++++++++++++ ts/util/LinkedList.ts | 24 +++++++++++++++++++++++- 5 files changed, 86 insertions(+), 1 deletion(-) diff --git a/ts/adaptors/HTMLAdaptor.ts b/ts/adaptors/HTMLAdaptor.ts index 97b2b05c3..565c213ae 100644 --- a/ts/adaptors/HTMLAdaptor.ts +++ b/ts/adaptors/HTMLAdaptor.ts @@ -74,6 +74,7 @@ export interface MinHTMLElement { /* tslint:disable:jsdoc-require */ getElementsByTagName(name: string): N[] | HTMLCollectionOf; getElementsByTagNameNS(ns: string, name: string): N[] | HTMLCollectionOf; + 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; @@ -254,6 +255,13 @@ AbstractDOMAdaptor implements MinHTMLAdaptor { return containers; } + /** + * @override + */ + public contains(container: N, node: N | T) { + return container.contains(node); + } + /** * @override */ diff --git a/ts/adaptors/liteAdaptor.ts b/ts/adaptors/liteAdaptor.ts index 9fa7bc594..0332027fe 100644 --- a/ts/adaptors/liteAdaptor.ts +++ b/ts/adaptors/liteAdaptor.ts @@ -235,6 +235,16 @@ export class LiteAdaptor extends AbstractDOMAdaptor= 0) { onode.parent.children[i] = nnode; + nnode.parent = onode.parent; + onode.parent = null; } return onode; } diff --git a/ts/core/DOMAdaptor.ts b/ts/core/DOMAdaptor.ts index 6ad61d77a..84c8b8ed4 100644 --- a/ts/core/DOMAdaptor.ts +++ b/ts/core/DOMAdaptor.ts @@ -114,6 +114,15 @@ export interface DOMAdaptor { */ getElements(nodes: (string | N | N[])[], document: D): N[]; + /** + * Determine if a container node contains a given node in 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 @@ -431,6 +440,11 @@ export abstract class AbstractDOMAdaptor implements DOMAdaptor */ public abstract getElements(nodes: (string | N | N[])[], document: D): N[]; + /** + * @override + */ + public abstract contains(container: N, node: N | T): boolean; + /** * @override */ diff --git a/ts/core/MathDocument.ts b/ts/core/MathDocument.ts index d9e882b5e..da5cef512 100644 --- a/ts/core/MathDocument.ts +++ b/ts/core/MathDocument.ts @@ -857,6 +857,35 @@ export abstract class AbstractMathDocument implements MathDocument[]} The list of MathItems within that container + */ + public getMathItemsWithin(container: N): MathItem[] { + const adaptor = this.adaptor; + const items = [] as MathItem[]; + for (const item of this.math) { + if (item.start.node && adaptor.contains(container, item.start.node)) { + items.push(item); + } + } + return items; + } + } /** diff --git a/ts/util/LinkedList.ts b/ts/util/LinkedList.ts index c5600887d..856e84256 100644 --- a/ts/util/LinkedList.ts +++ b/ts/util/LinkedList.ts @@ -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 @@ -190,6 +190,28 @@ export class LinkedList { 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(); + 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 * From c75bc461fcdea2c83a512eef6fded8bb77eb9360 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 29 May 2020 15:02:42 -0400 Subject: [PATCH 2/4] Make clearMathItemsWithin() and getMathItemsWithin() to work with collections of containers, and with CSS selectors --- ts/core/MathDocument.ts | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/ts/core/MathDocument.ts b/ts/core/MathDocument.ts index da5cef512..c2bced36d 100644 --- a/ts/core/MathDocument.ts +++ b/ts/core/MathDocument.ts @@ -230,6 +230,15 @@ export class RenderList extends PrioritizedList> { } +/*****************************************************************/ +/** + * 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 = string | N | (string | N | N[])[]; + /*****************************************************************/ /** * The MathDocument interface @@ -863,24 +872,31 @@ export abstract class AbstractMathDocument implements MathDocument} elements The container DOM elements whose math items are to be removed */ - public clearMathItemsWithin(container: N) { - this.math.remove(...this.getMathItemsWithin(container)); + public clearMathItemsWithin(containers: ContainerList) { + this.math.remove(...this.getMathItemsWithin(containers)); } /** * Get the typeset MathItems that are within a given container. * - * @param {N} container The container DOM element whose math items are to be found - * @return {MathItem[]} The list of MathItems within that container + * @param {ContainerList} elements The container DOM elements whose math items are to be found + * @return {MathItem[]} The list of MathItems within that container */ - public getMathItemsWithin(container: N): MathItem[] { + public getMathItemsWithin(elements: ContainerList): MathItem[] { + if (!Array.isArray(elements)) { + elements = [elements]; + } const adaptor = this.adaptor; const items = [] as MathItem[]; - for (const item of this.math) { - if (item.start.node && adaptor.contains(container, item.start.node)) { - items.push(item); + 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; From bd9d477c02be634ef151681af8743909753c901e Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Mon, 1 Jun 2020 10:14:59 -0400 Subject: [PATCH 3/4] Add support for clearing container to MathJax.typesetClear(), and include the clear and get functions in the MathDocument interface. --- ts/components/startup.ts | 13 ++++++++++--- ts/core/MathDocument.ts | 32 +++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/ts/components/startup.ts b/ts/components/startup.ts index 79a9d82b8..a9b2699ba 100644 --- a/ts/components/startup.ts +++ b/ts/components/startup.ts @@ -327,19 +327,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(); + } + }; } /** diff --git a/ts/core/MathDocument.ts b/ts/core/MathDocument.ts index c2bced36d..9a8f5c871 100644 --- a/ts/core/MathDocument.ts +++ b/ts/core/MathDocument.ts @@ -437,6 +437,24 @@ export interface MathDocument { */ concat(list: MathList): MathDocument; + /** + * 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} elements The container DOM elements whose math items are to be removed + */ + clearMathItemsWithin(containers: ContainerList): void; + + /** + * Get the typeset MathItems that are within a given container. + * + * @param {ContainerList} elements The container DOM elements whose math items are to be found + * @return {MathItem[]} The list of MathItems within that container + */ + getMathItemsWithin(elements: ContainerList): MathItem[]; + } /*****************************************************************/ @@ -867,24 +885,16 @@ export abstract class AbstractMathDocument implements MathDocument} elements The container DOM elements whose math items are to be removed + * @override */ public clearMathItemsWithin(containers: ContainerList) { this.math.remove(...this.getMathItemsWithin(containers)); } /** - * Get the typeset MathItems that are within a given container. - * - * @param {ContainerList} elements The container DOM elements whose math items are to be found - * @return {MathItem[]} The list of MathItems within that container + * @override */ - public getMathItemsWithin(elements: ContainerList): MathItem[] { + public getMathItemsWithin(elements: ContainerList) { if (!Array.isArray(elements)) { elements = [elements]; } From b94f49ed0a99472013ee6786e5ab6f633d4029e0 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Tue, 16 Jun 2020 10:35:11 -0400 Subject: [PATCH 4/4] Fix typos spotted by Volker. --- ts/core/DOMAdaptor.ts | 2 +- ts/core/MathDocument.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ts/core/DOMAdaptor.ts b/ts/core/DOMAdaptor.ts index 84c8b8ed4..09eac9d97 100644 --- a/ts/core/DOMAdaptor.ts +++ b/ts/core/DOMAdaptor.ts @@ -115,7 +115,7 @@ export interface DOMAdaptor { getElements(nodes: (string | N | N[])[], document: D): N[]; /** - * Determine if a container node contains a given node in somewhere in its DOM tree + * 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 diff --git a/ts/core/MathDocument.ts b/ts/core/MathDocument.ts index 9a8f5c871..da5a88a30 100644 --- a/ts/core/MathDocument.ts +++ b/ts/core/MathDocument.ts @@ -901,7 +901,8 @@ export abstract class AbstractMathDocument implements MathDocument[]; const containers = adaptor.getElements(elements, this.document); - ITEMS: for (const item of this.math) { + 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);