add initial marp implementation with sample content and build configuration
This commit is contained in:
563
node_modules/mathjax-full/ts/adaptors/HTMLAdaptor.ts
generated
vendored
Normal file
563
node_modules/mathjax-full/ts/adaptors/HTMLAdaptor.ts
generated
vendored
Normal file
@@ -0,0 +1,563 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 HTML DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {OptionList} from '../util/Options.js';
|
||||
import {AttributeData, AbstractDOMAdaptor, DOMAdaptor, PageBBox} from '../core/DOMAdaptor.js';
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* The minimum fields needed for a Document
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
* @template T The Text node class
|
||||
*/
|
||||
export interface MinDocument<N, T> {
|
||||
documentElement: N;
|
||||
head: N;
|
||||
body: N;
|
||||
title: string;
|
||||
doctype: {name: string};
|
||||
/* tslint:disable:jsdoc-require */
|
||||
createElement(kind: string): N;
|
||||
createElementNS(ns: string, kind: string): N;
|
||||
createTextNode(text: string): T;
|
||||
querySelectorAll(selector: string): ArrayLike<N>;
|
||||
/* tslint:enable */
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* The minimum fields needed for an HTML Element
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
* @template T The Text node class
|
||||
*/
|
||||
export interface MinHTMLElement<N, T> {
|
||||
nodeType: number;
|
||||
nodeName: string;
|
||||
nodeValue: string;
|
||||
textContent: string;
|
||||
innerHTML: string;
|
||||
outerHTML: string;
|
||||
parentNode: N | Node;
|
||||
nextSibling: N | T | Node;
|
||||
previousSibling: N | T | Node;
|
||||
offsetWidth: number;
|
||||
offsetHeight: number;
|
||||
|
||||
attributes: AttributeData[] | NamedNodeMap;
|
||||
className: string;
|
||||
classList: DOMTokenList;
|
||||
style: OptionList;
|
||||
sheet?: {insertRule: (rule: string, index?: number) => void};
|
||||
|
||||
childNodes: (N | T)[] | NodeList;
|
||||
firstChild: N | T | Node;
|
||||
lastChild: N | T | Node;
|
||||
/* 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;
|
||||
insertBefore(nchild: N | T, ochild: N | T): void;
|
||||
cloneNode(deep: boolean): N | Node;
|
||||
setAttribute(name: string, value: string): void;
|
||||
setAttributeNS(ns: string, name: string, value: string): void;
|
||||
getAttribute(name: string): string;
|
||||
removeAttribute(name: string): void;
|
||||
hasAttribute(name: string): boolean;
|
||||
getBoundingClientRect(): Object;
|
||||
getBBox?(): {x: number, y: number, width: number, height: number};
|
||||
/* tslint:endable */
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* The minimum fields needed for a Text element
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
* @template T The Text node class
|
||||
*/
|
||||
export interface MinText<N, T> {
|
||||
nodeType: number;
|
||||
nodeName: string;
|
||||
nodeValue: string;
|
||||
parentNode: N | Node;
|
||||
nextSibling: N | T | Node;
|
||||
previousSibling: N | T | Node;
|
||||
splitText(n: number): T;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* The minimum fields needed for a DOMParser
|
||||
*
|
||||
* @template D The Document class
|
||||
*/
|
||||
export interface MinDOMParser<D> {
|
||||
parseFromString(text: string, format?: string): D;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* The minimum fields needed for a DOMParser
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
*/
|
||||
export interface MinXMLSerializer<N> {
|
||||
serializeToString(node: N): string;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* The minimum fields needed for a Window
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
* @template D The Document class
|
||||
*/
|
||||
export interface MinWindow<N, D> {
|
||||
document: D;
|
||||
DOMParser: {
|
||||
new(): MinDOMParser<D>
|
||||
};
|
||||
XMLSerializer: {
|
||||
new(): MinXMLSerializer<N>;
|
||||
};
|
||||
NodeList: any;
|
||||
HTMLCollection: any;
|
||||
HTMLElement: any;
|
||||
DocumentFragment: any;
|
||||
Document: any;
|
||||
getComputedStyle(node: N): any;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* The minimum needed for an HTML Adaptor
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
* @template T The Text node class
|
||||
* @template D The Document class
|
||||
*/
|
||||
export interface MinHTMLAdaptor<N, T, D> extends DOMAdaptor<N, T, D> {
|
||||
window: MinWindow<N, D>;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/**
|
||||
* Abstract HTMLAdaptor class for manipulating HTML elements
|
||||
* (subclass of AbstractDOMAdaptor)
|
||||
*
|
||||
* N = HTMLElement node class
|
||||
* T = Text node class
|
||||
* D = Document class
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
* @template T The Text node class
|
||||
* @template D The Document class
|
||||
*/
|
||||
export class HTMLAdaptor<N extends MinHTMLElement<N, T>, T extends MinText<N, T>, D extends MinDocument<N, T>> extends
|
||||
AbstractDOMAdaptor<N, T, D> implements MinHTMLAdaptor<N, T, D> {
|
||||
/**
|
||||
* The window object for this adaptor
|
||||
*/
|
||||
public window: MinWindow<N, D>;
|
||||
|
||||
/**
|
||||
* The DOMParser used to parse a string into a DOM tree
|
||||
*/
|
||||
public parser: MinDOMParser<D>;
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @constructor
|
||||
*/
|
||||
constructor(window: MinWindow<N, D>) {
|
||||
super(window.document);
|
||||
this.window = window;
|
||||
this.parser = new (window.DOMParser as any)();
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public parse(text: string, format: string = 'text/html') {
|
||||
return this.parser.parseFromString(text, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
protected create(kind: string, ns?: string) {
|
||||
return (ns ?
|
||||
this.document.createElementNS(ns, kind) :
|
||||
this.document.createElement(kind));
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public text(text: string) {
|
||||
return this.document.createTextNode(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public head(doc: D) {
|
||||
return doc.head || (doc as any as N);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public body(doc: D) {
|
||||
return doc.body || (doc as any as N);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public root(doc: D) {
|
||||
return doc.documentElement || (doc as any as N);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public doctype(doc: D) {
|
||||
return (doc.doctype ? `<!DOCTYPE ${doc.doctype.name}>` : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public tags(node: N, name: string, ns: string = null) {
|
||||
let nodes = (ns ? node.getElementsByTagNameNS(ns, name) : node.getElementsByTagName(name));
|
||||
return Array.from(nodes as N[]) as N[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getElements(nodes: (string | N | N[])[], _document: D) {
|
||||
let containers: N[] = [];
|
||||
for (const node of nodes) {
|
||||
if (typeof(node) === 'string') {
|
||||
containers = containers.concat(Array.from(this.document.querySelectorAll(node)));
|
||||
} else if (Array.isArray(node)) {
|
||||
containers = containers.concat(Array.from(node) as N[]);
|
||||
} else if (node instanceof this.window.NodeList || node instanceof this.window.HTMLCollection) {
|
||||
containers = containers.concat(Array.from(node as any as N[]));
|
||||
} else {
|
||||
containers.push(node);
|
||||
}
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public contains(container: N, node: N | T) {
|
||||
return container.contains(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public parent(node: N | T) {
|
||||
return node.parentNode as N;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public append(node: N, child: N | T) {
|
||||
return node.appendChild(child) as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public insert(nchild: N | T, ochild: N | T) {
|
||||
return this.parent(ochild).insertBefore(nchild, ochild);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public remove(child: N | T) {
|
||||
return this.parent(child).removeChild(child) as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public replace(nnode: N | T, onode: N | T) {
|
||||
return this.parent(onode).replaceChild(nnode, onode) as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public clone(node: N) {
|
||||
return node.cloneNode(true) as N;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public split(node: T, n: number) {
|
||||
return node.splitText(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public next(node: N | T) {
|
||||
return node.nextSibling as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public previous(node: N | T) {
|
||||
return node.previousSibling as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public firstChild(node: N) {
|
||||
return node.firstChild as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public lastChild(node: N) {
|
||||
return node.lastChild as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public childNodes(node: N) {
|
||||
return Array.from(node.childNodes as (N | T)[]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public childNode(node: N, i: number) {
|
||||
return node.childNodes[i] as N | T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public kind(node: N | T) {
|
||||
const n = node.nodeType;
|
||||
return (n === 1 || n === 3 || n === 8 ? node.nodeName.toLowerCase() : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public value(node: N | T) {
|
||||
return node.nodeValue || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public textContent(node: N) {
|
||||
return node.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public innerHTML(node: N) {
|
||||
return node.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public outerHTML(node: N) {
|
||||
return node.outerHTML;
|
||||
}
|
||||
|
||||
public serializeXML(node: N) {
|
||||
const serializer = new this.window.XMLSerializer();
|
||||
return serializer.serializeToString(node) as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public setAttribute(node: N, name: string, value: string, ns: string = null) {
|
||||
if (!ns) {
|
||||
return node.setAttribute(name, value);
|
||||
}
|
||||
name = ns.replace(/.*\//, '') + ':' + name.replace(/^.*:/, '');
|
||||
return node.setAttributeNS(ns, name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getAttribute(node: N, name: string) {
|
||||
return node.getAttribute(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public removeAttribute(node: N, name: string) {
|
||||
return node.removeAttribute(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public hasAttribute(node: N, name: string) {
|
||||
return node.hasAttribute(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public allAttributes(node: N) {
|
||||
return Array.from(node.attributes).map(
|
||||
(x: AttributeData) => {
|
||||
return {name: x.name, value: x.value} as AttributeData;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public addClass(node: N, name: string) {
|
||||
if (node.classList) {
|
||||
node.classList.add(name);
|
||||
} else {
|
||||
node.className = (node.className + ' ' + name).trim();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public removeClass(node: N, name: string) {
|
||||
if (node.classList) {
|
||||
node.classList.remove(name);
|
||||
} else {
|
||||
node.className = node.className.split(/ /).filter((c) => c !== name).join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public hasClass(node: N, name: string) {
|
||||
if (node.classList) {
|
||||
return node.classList.contains(name);
|
||||
}
|
||||
return node.className.split(/ /).indexOf(name) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public setStyle(node: N, name: string, value: string) {
|
||||
(node.style as OptionList)[name] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getStyle(node: N, name: string) {
|
||||
return (node.style as OptionList)[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public allStyles(node: N) {
|
||||
return node.style.cssText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public insertRules(node: N, rules: string[]) {
|
||||
for (const rule of rules.reverse()) {
|
||||
try {
|
||||
node.sheet.insertRule(rule, 0);
|
||||
} catch (e) {
|
||||
console.warn(`MathJax: can't insert css rule '${rule}': ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public fontSize(node: N) {
|
||||
const style = this.window.getComputedStyle(node);
|
||||
return parseFloat(style.fontSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public fontFamily(node: N) {
|
||||
const style = this.window.getComputedStyle(node);
|
||||
return style.fontFamily || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public nodeSize(node: N, em: number = 1, local: boolean = false) {
|
||||
if (local && node.getBBox) {
|
||||
let {width, height} = node.getBBox();
|
||||
return [width / em , height / em] as [number, number];
|
||||
}
|
||||
return [node.offsetWidth / em, node.offsetHeight / em] as [number, number];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public nodeBBox(node: N) {
|
||||
const {left, right, top, bottom} = node.getBoundingClientRect() as PageBBox;
|
||||
return {left, right, top, bottom};
|
||||
}
|
||||
}
|
||||
160
node_modules/mathjax-full/ts/adaptors/NodeMixin.ts
generated
vendored
Normal file
160
node_modules/mathjax-full/ts/adaptors/NodeMixin.ts
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* Copyright (c) 2022-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 a mixin for node-based adaptors that overrides
|
||||
* the methods that obtain DOM node sizes, when those aren't
|
||||
* available from the DOM itself.
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {DOMAdaptor} from '../core/DOMAdaptor.js';
|
||||
import {userOptions, defaultOptions, OptionList} from '../util/Options.js';
|
||||
|
||||
/**
|
||||
* A constructor for a given class
|
||||
*
|
||||
* @template T The class to construct
|
||||
*/
|
||||
export type Constructor<T> = (new(...args: any[]) => T);
|
||||
|
||||
/**
|
||||
* The type of an Adaptor class
|
||||
*/
|
||||
export type AdaptorConstructor<N, T, D> = Constructor<DOMAdaptor<N, T, D>>;
|
||||
|
||||
/**
|
||||
* The options to the NodeMixin
|
||||
*/
|
||||
export const NodeMixinOptions: OptionList = {
|
||||
badCSS: true, // getComputedStyles() is not implemented in the DOM
|
||||
badSizes: true, // element sizes (e.g., ClientWidth, etc.) are not implemented in the DOM
|
||||
};
|
||||
|
||||
/**
|
||||
* @template N The HTMLElement node class
|
||||
* @template T The Text node class
|
||||
* @template D The Document class
|
||||
*/
|
||||
export function NodeMixin<N, T, D, A extends AdaptorConstructor<N, T, D>>(
|
||||
Base: A,
|
||||
options: typeof NodeMixinOptions = {}
|
||||
): A {
|
||||
|
||||
options = userOptions(defaultOptions({}, NodeMixinOptions), options);
|
||||
|
||||
return class NodeAdaptor extends Base {
|
||||
|
||||
/**
|
||||
* The default options
|
||||
*/
|
||||
public static OPTIONS: OptionList = {
|
||||
...(options.badCSS ? {
|
||||
fontSize: 16, // We can't compute the font size, so always use this
|
||||
fontFamily: 'Times', // We can't compute the font family, so always use this
|
||||
} : {}),
|
||||
...(options.badSizes ? {
|
||||
cjkCharWidth: 1, // Width (in em units) of full width characters
|
||||
unknownCharWidth: .6, // Width (in em units) of unknown (non-full-width) characters
|
||||
unknownCharHeight: .8, // Height (in em units) of unknown characters
|
||||
} : {})
|
||||
};
|
||||
|
||||
/**
|
||||
* Pattern to identify CJK (i.e., full-width) characters
|
||||
*/
|
||||
public static cjkPattern = new RegExp([
|
||||
'[',
|
||||
'\u1100-\u115F', // Hangul Jamo
|
||||
'\u2329\u232A', // LEFT-POINTING ANGLE BRACKET, RIGHT-POINTING ANGLE BRACKET
|
||||
'\u2E80-\u303E', // CJK Radicals Supplement ... CJK Symbols and Punctuation
|
||||
'\u3040-\u3247', // Hiragana ... Enclosed CJK Letters and Months
|
||||
'\u3250-\u4DBF', // Enclosed CJK Letters and Months ... CJK Unified Ideographs Extension A
|
||||
'\u4E00-\uA4C6', // CJK Unified Ideographs ... Yi Radicals
|
||||
'\uA960-\uA97C', // Hangul Jamo Extended-A
|
||||
'\uAC00-\uD7A3', // Hangul Syllables
|
||||
'\uF900-\uFAFF', // CJK Compatibility Ideographs
|
||||
'\uFE10-\uFE19', // Vertical Forms
|
||||
'\uFE30-\uFE6B', // CJK Compatibility Forms ... Small Form Variants
|
||||
'\uFF01-\uFF60\uFFE0-\uFFE6', // Halfwidth and Fullwidth Forms
|
||||
'\u{1B000}-\u{1B001}', // Kana Supplement
|
||||
'\u{1F200}-\u{1F251}', // Enclosed Ideographic Supplement
|
||||
'\u{20000}-\u{3FFFD}', // CJK Unified Ideographs Extension B ... Tertiary Ideographic Plane
|
||||
']'
|
||||
].join(''), 'gu');
|
||||
|
||||
/**
|
||||
* The options for the instance
|
||||
*/
|
||||
public options: OptionList;
|
||||
|
||||
/**
|
||||
* @param {any} window The window to work with
|
||||
* @param {OptionList} options The options for the adaptor
|
||||
* @constructor
|
||||
*/
|
||||
constructor(...args: any[]) {
|
||||
super(args[0]);
|
||||
let CLASS = this.constructor as typeof NodeAdaptor;
|
||||
this.options = userOptions(defaultOptions({}, CLASS.OPTIONS), args[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* For DOMs that don't handle CSS well, use the font size from the options
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public fontSize(node: N) {
|
||||
return (options.badCSS ? this.options.fontSize : super.fontSize(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* For DOMs that don't handle CSS well, use the font family from the options
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public fontFamily(node: N) {
|
||||
return (options.badCSS ? this.options.fontFamily : super.fontFamily(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public nodeSize(node: N, em: number = 1, local: boolean = null) {
|
||||
if (!options.badSizes) {
|
||||
return super.nodeSize(node, em, local);
|
||||
}
|
||||
const text = this.textContent(node);
|
||||
const non = Array.from(text.replace(NodeAdaptor.cjkPattern, '')).length; // # of non-CJK chars
|
||||
const CJK = Array.from(text).length - non; // # of cjk chars
|
||||
return [
|
||||
CJK * this.options.cjkCharWidth + non * this.options.unknownCharWidth,
|
||||
this.options.unknownCharHeight
|
||||
] as [number, number];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public nodeBBox(node: N) {
|
||||
return (options.badSizes ? {left: 0, right: 0, top: 0, bottom: 0} : super.nodeBBox(node));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
48
node_modules/mathjax-full/ts/adaptors/browserAdaptor.ts
generated
vendored
Normal file
48
node_modules/mathjax-full/ts/adaptors/browserAdaptor.ts
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 browser DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {HTMLAdaptor} from './HTMLAdaptor.js';
|
||||
|
||||
//
|
||||
// Let Typescript know about these
|
||||
//
|
||||
declare global {
|
||||
interface Window {
|
||||
Document: typeof Document;
|
||||
DOMParser: typeof DOMParser;
|
||||
XMLSerializer: typeof XMLSerializer;
|
||||
HTMLElement: typeof HTMLElement;
|
||||
HTMLCollection: typeof HTMLCollection;
|
||||
NodeList: typeof NodeList;
|
||||
DocumentFragment: typeof DocumentFragment;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create an HTML adpator for browsers
|
||||
*
|
||||
* @return {HTMLAdaptor} The newly created adaptor
|
||||
*/
|
||||
export function browserAdaptor(): HTMLAdaptor<HTMLElement, Text, Document> {
|
||||
return new HTMLAdaptor<HTMLElement, Text, Document>(window);
|
||||
}
|
||||
39
node_modules/mathjax-full/ts/adaptors/chooseAdaptor.ts
generated
vendored
Normal file
39
node_modules/mathjax-full/ts/adaptors/chooseAdaptor.ts
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 Chooses between jdsom and browser DOM adaptors
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {liteAdaptor} from './liteAdaptor.js';
|
||||
import {browserAdaptor} from './browserAdaptor.js';
|
||||
|
||||
let choose;
|
||||
|
||||
try {
|
||||
document; // errors if not in browser
|
||||
choose = browserAdaptor;
|
||||
} catch (e) {
|
||||
choose = liteAdaptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to select which adaptor to use (depending on whether we are in a browser or node.js)
|
||||
*/
|
||||
export const chooseAdaptor = choose;
|
||||
46
node_modules/mathjax-full/ts/adaptors/jsdomAdaptor.ts
generated
vendored
Normal file
46
node_modules/mathjax-full/ts/adaptors/jsdomAdaptor.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 jdsom DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {HTMLAdaptor} from './HTMLAdaptor.js';
|
||||
import {NodeMixin, Constructor} from './NodeMixin.js';
|
||||
import {OptionList} from '../util/Options.js';
|
||||
|
||||
/**
|
||||
* The constructor for an HTMLAdaptor
|
||||
*/
|
||||
export type HTMLAdaptorConstructor = Constructor<HTMLAdaptor<HTMLElement, Text, Document>>;
|
||||
|
||||
/**
|
||||
* The JsdomAdaptor class
|
||||
*/
|
||||
export class JsdomAdaptor extends NodeMixin<HTMLElement, Text, Document, HTMLAdaptorConstructor>(HTMLAdaptor) {}
|
||||
|
||||
/**
|
||||
* Function for creating an HTML adaptor using jsdom
|
||||
*
|
||||
* @param {any} JSDOM The jsdom object to use for this adaptor
|
||||
* @return {HTMLAdaptor} The newly created adaptor
|
||||
*/
|
||||
export function jsdomAdaptor(JSDOM: any, options: OptionList = null): JsdomAdaptor {
|
||||
return new JsdomAdaptor(new JSDOM().window, options);
|
||||
}
|
||||
71
node_modules/mathjax-full/ts/adaptors/linkedomAdaptor.ts
generated
vendored
Normal file
71
node_modules/mathjax-full/ts/adaptors/linkedomAdaptor.ts
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* Copyright (c) 2022-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 linkedom DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {HTMLAdaptor} from './HTMLAdaptor.js';
|
||||
import {NodeMixin, Constructor} from './NodeMixin.js';
|
||||
import {OptionList} from '../util/Options.js';
|
||||
|
||||
/**
|
||||
* The constructor for an HTMLAdaptor
|
||||
*/
|
||||
export type HTMLAdaptorConstructor = Constructor<HTMLAdaptor<HTMLElement, Text, Document>>;
|
||||
|
||||
/**
|
||||
* The LinkedomAdaptor class
|
||||
*/
|
||||
export class LinkedomAdaptor extends NodeMixin<HTMLElement, Text, Document, HTMLAdaptorConstructor>(HTMLAdaptor) {
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public parse(text: string, format: string = 'text/html') {
|
||||
//
|
||||
// Make sure the text string has nodes (in particular, it can't be empty)
|
||||
//
|
||||
if (!text.match(/^(?:\s|\n)*</)) text = '<html>' + text + '</html>';
|
||||
return this.parser.parseFromString(text, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*
|
||||
* This will do an HTML serialization, which may be good enough, but
|
||||
* won't necessarily close some tags properly.
|
||||
*/
|
||||
public serializeXML(node: HTMLElement) {
|
||||
return this.outerHTML(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for creating an HTML adaptor using linkedom
|
||||
*
|
||||
* @param {any} parseHTML The linkedom HTML parser to use for this adaptor
|
||||
* @return {LinkeddomAdaptor} The newly created adaptor
|
||||
*/
|
||||
export function linkedomAdaptor(parseHTML: any, options: OptionList = null): LinkedomAdaptor {
|
||||
const window = parseHTML('<html></html>');
|
||||
window.constructor.prototype.HTMLCollection = class {}; // add fake class for missing HTMLCollecton
|
||||
return new LinkedomAdaptor(window, options);
|
||||
}
|
||||
66
node_modules/mathjax-full/ts/adaptors/lite/Document.ts
generated
vendored
Normal file
66
node_modules/mathjax-full/ts/adaptors/lite/Document.ts
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 a lightweight DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {LiteElement} from './Element.js';
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* Implements a lightweight Document replacement
|
||||
*/
|
||||
export class LiteDocument {
|
||||
/**
|
||||
* The document's <html> element
|
||||
*/
|
||||
public root: LiteElement;
|
||||
/**
|
||||
* The document's <head> element
|
||||
*/
|
||||
public head: LiteElement;
|
||||
/**
|
||||
* The document's <body> element
|
||||
*/
|
||||
public body: LiteElement;
|
||||
|
||||
/**
|
||||
* the DOCTYPE comment
|
||||
*/
|
||||
public type: string;
|
||||
|
||||
/**
|
||||
* The kind is always #document
|
||||
*/
|
||||
public get kind() {
|
||||
return '#document';
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
constructor() {
|
||||
this.root = new LiteElement('html', {}, [
|
||||
this.head = new LiteElement('head'),
|
||||
this.body = new LiteElement('body')
|
||||
]);
|
||||
this.type = '';
|
||||
}
|
||||
}
|
||||
84
node_modules/mathjax-full/ts/adaptors/lite/Element.ts
generated
vendored
Normal file
84
node_modules/mathjax-full/ts/adaptors/lite/Element.ts
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 a lightweight HTML Element replacement
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {OptionList} from '../../util/Options.js';
|
||||
import {Styles} from '../../util/Styles.js';
|
||||
import {LiteText} from './Text.js';
|
||||
|
||||
/**
|
||||
* Type for attribute lists
|
||||
*/
|
||||
export type LiteAttributeList = OptionList;
|
||||
|
||||
/**
|
||||
* Type for generic nodes in LiteAdaptor
|
||||
*/
|
||||
export type LiteNode = LiteElement | LiteText;
|
||||
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* Implements a lightweight HTML element replacement
|
||||
*/
|
||||
export class LiteElement {
|
||||
/**
|
||||
* The type of element (tag name)
|
||||
*/
|
||||
public kind: string;
|
||||
|
||||
/**
|
||||
* The element's attribute list
|
||||
*/
|
||||
public attributes: LiteAttributeList;
|
||||
|
||||
/**
|
||||
* The element's children
|
||||
*/
|
||||
public children: LiteNode[];
|
||||
|
||||
/**
|
||||
* The element's parent
|
||||
*/
|
||||
public parent: LiteElement;
|
||||
|
||||
/**
|
||||
* The styles for the element
|
||||
*/
|
||||
public styles: Styles;
|
||||
|
||||
/**
|
||||
* @param {string} kind The type of node to create
|
||||
* @param {LiteAttributeList} attributes The list of attributes to set (if any)
|
||||
* @param {LiteNode[]} children The children for the node (if any)
|
||||
* @constructor
|
||||
*/
|
||||
constructor(kind: string, attributes: LiteAttributeList = {}, children: LiteNode[] = []) {
|
||||
this.kind = kind;
|
||||
this.attributes = {...attributes};
|
||||
this.children = [...children];
|
||||
for (const child of this.children) {
|
||||
child.parent = this;
|
||||
}
|
||||
this.styles = null;
|
||||
}
|
||||
}
|
||||
70
node_modules/mathjax-full/ts/adaptors/lite/List.ts
generated
vendored
Normal file
70
node_modules/mathjax-full/ts/adaptors/lite/List.ts
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 a lightweight DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {LiteNode} from './Element.js';
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* Implements a lightweight DocumentFragment or NodeList replacement
|
||||
*
|
||||
* @template N The HTMLElement node class
|
||||
*/
|
||||
export class LiteList<N> {
|
||||
/**
|
||||
* The nodes held in the fragment
|
||||
*/
|
||||
public nodes: N[] = [];
|
||||
|
||||
/**
|
||||
* @param {N[]} children The children for the fragment
|
||||
* @constructor
|
||||
*/
|
||||
constructor(children: N[]) {
|
||||
this.nodes = [...children];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {N} node A node to append to the fragment
|
||||
*/
|
||||
public append(node: N) {
|
||||
this.nodes.push(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this class iterable (so it can be used with Array.from())
|
||||
*/
|
||||
public [Symbol.iterator](): Iterator<LiteNode> {
|
||||
let i = 0;
|
||||
return {
|
||||
/**
|
||||
* @return {IteratorResult<LiteNode>}
|
||||
*/
|
||||
next(): IteratorResult<LiteNode> {
|
||||
return (i === this.nodes.length ?
|
||||
{value: null, done: true} :
|
||||
{value: this.nodes[i++], done: false});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
405
node_modules/mathjax-full/ts/adaptors/lite/Parser.ts
generated
vendored
Normal file
405
node_modules/mathjax-full/ts/adaptors/lite/Parser.ts
generated
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 a lightweight DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {AttributeData} from '../../core/DOMAdaptor.js';
|
||||
import {MinDOMParser} from '../HTMLAdaptor.js';
|
||||
import * as Entities from '../../util/Entities.js';
|
||||
import {LiteDocument} from './Document.js';
|
||||
import {LiteElement} from './Element.js';
|
||||
import {LiteText, LiteComment} from './Text.js';
|
||||
import {LiteAdaptor} from '../liteAdaptor.js';
|
||||
|
||||
/**
|
||||
* Patterns used in parsing serialized HTML
|
||||
*/
|
||||
export namespace PATTERNS {
|
||||
export const TAGNAME = '[a-z][^\\s\\n>]*';
|
||||
export const ATTNAME = '[a-z][^\\s\\n>=]*';
|
||||
export const VALUE = `(?:'[^']*'|"[^"]*"|[^\\s\\n]+)`;
|
||||
export const VALUESPLIT = `(?:'([^']*)'|"([^"]*)"|([^\\s\\n]+))`;
|
||||
export const SPACE = '(?:\\s|\\n)+';
|
||||
export const OPTIONALSPACE = '(?:\\s|\\n)*';
|
||||
export const ATTRIBUTE = ATTNAME + '(?:' + OPTIONALSPACE + '=' + OPTIONALSPACE + VALUE + ')?';
|
||||
export const ATTRIBUTESPLIT = '(' + ATTNAME + ')(?:' + OPTIONALSPACE + '=' + OPTIONALSPACE + VALUESPLIT + ')?';
|
||||
export const TAG = '(<(?:' + TAGNAME + '(?:' + SPACE + ATTRIBUTE + ')*'
|
||||
+ OPTIONALSPACE + '/?|/' + TAGNAME + '|!--[^]*?--|![^]*?)(?:>|$))';
|
||||
export const tag = new RegExp(TAG, 'i');
|
||||
export const attr = new RegExp(ATTRIBUTE, 'i');
|
||||
export const attrsplit = new RegExp(ATTRIBUTESPLIT, 'i');
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* Implements a lightweight DOMParser replacement
|
||||
* (Not perfect, but handles most well-formed HTML)
|
||||
*/
|
||||
export class LiteParser implements MinDOMParser<LiteDocument> {
|
||||
|
||||
/**
|
||||
* The list of self-closing tags
|
||||
*/
|
||||
public static SELF_CLOSING: {[name: string]: boolean} = {
|
||||
area: true,
|
||||
base: true,
|
||||
br: true,
|
||||
col: true,
|
||||
command: true,
|
||||
embed: true,
|
||||
hr: true,
|
||||
img: true,
|
||||
input: true,
|
||||
keygen: true,
|
||||
link: true,
|
||||
menuitem: true,
|
||||
meta: true,
|
||||
param: true,
|
||||
source: true,
|
||||
track: true,
|
||||
wbr: true
|
||||
};
|
||||
|
||||
/**
|
||||
* The list of tags chose content is not parsed (PCDATA)
|
||||
*/
|
||||
public static PCDATA: {[name: string]: boolean} = {
|
||||
option: true,
|
||||
textarea: true,
|
||||
fieldset: true,
|
||||
title: true,
|
||||
style: true,
|
||||
script: true
|
||||
};
|
||||
|
||||
/**
|
||||
* The list of attributes that don't get entity translation
|
||||
*/
|
||||
public static CDATA_ATTR: {[name: string]: boolean} = {
|
||||
style: true,
|
||||
datafld: true,
|
||||
datasrc: true,
|
||||
href: true,
|
||||
src: true,
|
||||
longdesc: true,
|
||||
usemap: true,
|
||||
cite: true,
|
||||
datetime: true,
|
||||
action: true,
|
||||
axis: true,
|
||||
profile: true,
|
||||
content: true,
|
||||
scheme: true
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public parseFromString(text: string, _format: string = 'text/html', adaptor: LiteAdaptor = null) {
|
||||
const root = adaptor.createDocument();
|
||||
let node = adaptor.body(root);
|
||||
//
|
||||
// Split the HTML into an array of text, tag, text, tag, ...
|
||||
// Then loop through them and add text nodes and process tags.
|
||||
//
|
||||
let parts = text.replace(/<\?.*?\?>/g, '').split(PATTERNS.tag);
|
||||
while (parts.length) {
|
||||
const text = parts.shift();
|
||||
const tag = parts.shift();
|
||||
if (text) {
|
||||
this.addText(adaptor, node, text);
|
||||
}
|
||||
if (tag && tag.charAt(tag.length - 1) === '>') {
|
||||
if (tag.charAt(1) === '!') {
|
||||
this.addComment(adaptor, node, tag);
|
||||
} else if (tag.charAt(1) === '/') {
|
||||
node = this.closeTag(adaptor, node, tag);
|
||||
} else {
|
||||
node = this.openTag(adaptor, node, tag, parts);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.checkDocument(adaptor, root);
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The node to add a text element to
|
||||
* @param {string} text The text for the text node
|
||||
* @return {LiteText} The text element
|
||||
*/
|
||||
protected addText(adaptor: LiteAdaptor, node: LiteElement, text: string): LiteText {
|
||||
text = Entities.translate(text);
|
||||
return adaptor.append(node, adaptor.text(text)) as LiteText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The node to add a comment to
|
||||
* @param {string} comment The text for the comment node
|
||||
* @return {LiteComment} The comment element
|
||||
*/
|
||||
protected addComment(adaptor: LiteAdaptor, node: LiteElement, comment: string): LiteComment {
|
||||
return adaptor.append(node, new LiteComment(comment)) as LiteComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The node to close
|
||||
* @param {string} tag The close tag being processed
|
||||
* @return {LiteElement} The first unclosed parent node
|
||||
*/
|
||||
protected closeTag(adaptor: LiteAdaptor, node: LiteElement, tag: string): LiteElement {
|
||||
const kind = tag.slice(2, tag.length - 1).toLowerCase();
|
||||
while (adaptor.parent(node) && adaptor.kind(node) !== kind) {
|
||||
node = adaptor.parent(node);
|
||||
}
|
||||
return adaptor.parent(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The parent node for the tag
|
||||
* @param {string} tag The tag being processed
|
||||
* @param {string[]} parts The rest of the text/tag array
|
||||
* @return {LiteElement} The node to which the next tag will be added
|
||||
*/
|
||||
protected openTag(adaptor: LiteAdaptor, node: LiteElement, tag: string, parts: string[]): LiteElement {
|
||||
const PCDATA = (this.constructor as typeof LiteParser).PCDATA;
|
||||
const SELF_CLOSING = (this.constructor as typeof LiteParser).SELF_CLOSING;
|
||||
//
|
||||
// Get the child to be added to the node
|
||||
//
|
||||
const kind = tag.match(/<(.*?)[\s\n>\/]/)[1].toLowerCase();
|
||||
const child = adaptor.node(kind) as LiteElement;
|
||||
//
|
||||
// Split out the tag attributes as an array of space, name, value1, value3, value3,
|
||||
// where value1, value2, and value3 are the value of the node (only one is defined)
|
||||
// that come from matching quoted strings with ' (value1), " (value2) or no quotes (value3).
|
||||
//
|
||||
const attributes = tag.replace(/^<.*?[\s\n>]/, '').split(PATTERNS.attrsplit);
|
||||
//
|
||||
// If the tag was complete (it ends with > or has no attributes)
|
||||
//
|
||||
if (attributes.pop().match(/>$/) || attributes.length < 5) {
|
||||
this.addAttributes(adaptor, child, attributes);
|
||||
adaptor.append(node, child);
|
||||
//
|
||||
// For non-self-closing tags,
|
||||
// For tags whose contents is PCDATA (like <script>), collect the
|
||||
// content up until the end tag, and continue adding nee tags
|
||||
// to the current parent node.
|
||||
// Otherwise, the child tag becames the parent node to which
|
||||
// new tags are added
|
||||
//
|
||||
if (!SELF_CLOSING[kind] && !tag.match(/\/>$/)) {
|
||||
if (PCDATA[kind]) {
|
||||
this.handlePCDATA(adaptor, child, kind, parts);
|
||||
} else {
|
||||
node = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The node getting the attributes
|
||||
* @param {string[]} attributes The array of space, name, value1, value2, value3
|
||||
* as described above.
|
||||
*/
|
||||
protected addAttributes(adaptor: LiteAdaptor, node: LiteElement, attributes: string[]) {
|
||||
const CDATA_ATTR = (this.constructor as typeof LiteParser).CDATA_ATTR;
|
||||
while (attributes.length) {
|
||||
let [ , name, v1, v2, v3] = attributes.splice(0, 5);
|
||||
let value = v1 || v2 || v3 || '';
|
||||
if (!CDATA_ATTR[name]) {
|
||||
value = Entities.translate(value);
|
||||
}
|
||||
adaptor.setAttribute(node, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The node whose PCDATA content is being collected
|
||||
* @param {string} kind The tag name being handled
|
||||
* @param {string[]} parts The array of text/tag data for the document
|
||||
*/
|
||||
protected handlePCDATA(adaptor: LiteAdaptor, node: LiteElement, kind: string, parts: string[]) {
|
||||
const pcdata = [] as string[];
|
||||
const etag = '</' + kind + '>';
|
||||
let ptag = '';
|
||||
//
|
||||
// Look through the parts until the end tag is found
|
||||
// Add the unmatched tag and the following text
|
||||
// and try the next tag until we find the end tag.
|
||||
//
|
||||
while (parts.length && ptag !== etag) {
|
||||
pcdata.push(ptag);
|
||||
pcdata.push(parts.shift());
|
||||
ptag = parts.shift();
|
||||
}
|
||||
//
|
||||
// Add the collected contents as a text node
|
||||
//
|
||||
adaptor.append(node, adaptor.text(pcdata.join('')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the contents of the parsed document and move html, head, and body
|
||||
* tags into the document structure. That way, you can parse fragments or
|
||||
* full documents and still get a valid document.
|
||||
*
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteDocument} root The document being checked
|
||||
*/
|
||||
protected checkDocument(adaptor: LiteAdaptor, root: LiteDocument) {
|
||||
let node = this.getOnlyChild(adaptor, adaptor.body(root));
|
||||
if (!node) return;
|
||||
for (const child of adaptor.childNodes(adaptor.body(root))) {
|
||||
if (child === node) {
|
||||
break;
|
||||
}
|
||||
if (child instanceof LiteComment && child.value.match(/^<!DOCTYPE/)) {
|
||||
root.type = child.value;
|
||||
}
|
||||
}
|
||||
switch (adaptor.kind(node)) {
|
||||
case 'html':
|
||||
//
|
||||
// Look through the children for the head and body
|
||||
//
|
||||
for (const child of node.children) {
|
||||
switch (adaptor.kind(child)) {
|
||||
case 'head':
|
||||
root.head = child as LiteElement;
|
||||
break;
|
||||
case 'body':
|
||||
root.body = child as LiteElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Make sure the elements are linked in properly
|
||||
//
|
||||
root.root = node;
|
||||
adaptor.remove(node);
|
||||
if (adaptor.parent(root.body) !== node) {
|
||||
adaptor.append(node, root.body);
|
||||
}
|
||||
if (adaptor.parent(root.head) !== node) {
|
||||
adaptor.insert(root.head, root.body);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'head':
|
||||
root.head = adaptor.replace(node, root.head) as LiteElement;
|
||||
break;
|
||||
|
||||
case 'body':
|
||||
root.body = adaptor.replace(node, root.body) as LiteElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the body has only one element child (as opposed to comments or text nodes)
|
||||
* and returns that sole element (or null if none or more than one)
|
||||
*
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} body The body element being checked
|
||||
* @return {LiteElement} The sole LiteElement child of the body, or null if none or more than one
|
||||
*/
|
||||
protected getOnlyChild(adaptor: LiteAdaptor, body: LiteElement): LiteElement {
|
||||
let node: LiteElement = null;
|
||||
for (const child of adaptor.childNodes(body)) {
|
||||
if (child instanceof LiteElement) {
|
||||
if (node) return null;
|
||||
node = child;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The node to serialize
|
||||
* @param {boolean} xml True when producing XML, false for HTML
|
||||
* @return {string} The serialized element (like outerHTML)
|
||||
*/
|
||||
public serialize(adaptor: LiteAdaptor, node: LiteElement, xml: boolean = false): string {
|
||||
const SELF_CLOSING = (this.constructor as typeof LiteParser).SELF_CLOSING;
|
||||
const CDATA = (this.constructor as typeof LiteParser).CDATA_ATTR;
|
||||
const tag = adaptor.kind(node);
|
||||
const attributes = adaptor.allAttributes(node).map(
|
||||
(x: AttributeData) => x.name + '="' + (CDATA[x.name] ? x.value : this.protectAttribute(x.value)) + '"'
|
||||
).join(' ');
|
||||
const content = this.serializeInner(adaptor, node, xml);
|
||||
const html =
|
||||
'<' + tag + (attributes ? ' ' + attributes : '')
|
||||
+ ((!xml || content) && !SELF_CLOSING[tag] ? `>${content}</${tag}>` : xml ? '/>' : '>');
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
|
||||
* @param {LiteElement} node The node whose innerHTML is needed
|
||||
* @return {string} The serialized element (like innerHTML)
|
||||
*/
|
||||
public serializeInner(adaptor: LiteAdaptor, node: LiteElement, xml: boolean = false): string {
|
||||
const PCDATA = (this.constructor as typeof LiteParser).PCDATA;
|
||||
if (PCDATA.hasOwnProperty(node.kind)) {
|
||||
return adaptor.childNodes(node).map(x => adaptor.value(x)).join('');
|
||||
}
|
||||
return adaptor.childNodes(node).map(x => {
|
||||
const kind = adaptor.kind(x);
|
||||
return (kind === '#text' ? this.protectHTML(adaptor.value(x)) :
|
||||
kind === '#comment' ? (x as LiteComment).value :
|
||||
this.serialize(adaptor, x as LiteElement, xml));
|
||||
}).join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text The attribute value to be HTML escaped
|
||||
* @return {string} The string with " replaced by entities
|
||||
*/
|
||||
public protectAttribute(text: string): string {
|
||||
if (typeof text !== 'string') {
|
||||
text = String(text);
|
||||
}
|
||||
return text.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text The text to be HTML escaped
|
||||
* @return {string} The string with &, <, and > replaced by entities
|
||||
*/
|
||||
public protectHTML(text: string): string {
|
||||
return text.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
}
|
||||
65
node_modules/mathjax-full/ts/adaptors/lite/Text.ts
generated
vendored
Normal file
65
node_modules/mathjax-full/ts/adaptors/lite/Text.ts
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 a lightweight Text element replacement
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {LiteElement} from './Element.js';
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* Implements a lightweight Text node replacement
|
||||
*/
|
||||
export class LiteText {
|
||||
/**
|
||||
* The text stored in the node
|
||||
*/
|
||||
public value: string;
|
||||
|
||||
/**
|
||||
* The parent holding this text
|
||||
*/
|
||||
public parent: LiteElement;
|
||||
|
||||
/**
|
||||
* The kind of node is #text
|
||||
*/
|
||||
public get kind() {
|
||||
return '#text';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text The text for the node
|
||||
* @constructor
|
||||
*/
|
||||
constructor(text: string = '') {
|
||||
this.value = text;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* Implements a lightweight Comment node replacement
|
||||
*/
|
||||
export class LiteComment extends LiteText {
|
||||
public get kind() {
|
||||
return '#comment';
|
||||
}
|
||||
}
|
||||
69
node_modules/mathjax-full/ts/adaptors/lite/Window.ts
generated
vendored
Normal file
69
node_modules/mathjax-full/ts/adaptors/lite/Window.ts
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 a lightweight DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {LiteElement} from './Element.js';
|
||||
import {LiteDocument} from './Document.js';
|
||||
import {LiteList} from './List.js';
|
||||
import {LiteParser} from './Parser.js';
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* Implements a lightweight Window replacement
|
||||
*/
|
||||
export class LiteWindow {
|
||||
/**
|
||||
* The window's document instance
|
||||
*/
|
||||
public document: LiteDocument;
|
||||
/**
|
||||
* The DOMParser class
|
||||
*/
|
||||
public DOMParser: typeof LiteParser = LiteParser;
|
||||
/**
|
||||
* The NodeList class
|
||||
*/
|
||||
public NodeList: typeof LiteList = LiteList;
|
||||
/**
|
||||
* The HTMLCollection class
|
||||
*/
|
||||
public HTMLCollection: typeof LiteList = LiteList;
|
||||
/**
|
||||
* The HTMLElement class
|
||||
*/
|
||||
public HTMLElement: typeof LiteElement = LiteElement;
|
||||
/**
|
||||
* The DocumentFragment class
|
||||
*/
|
||||
public DocumentFragment: typeof LiteList = LiteList;
|
||||
/**
|
||||
* The Document class
|
||||
*/
|
||||
public Document: typeof LiteDocument = LiteDocument;
|
||||
|
||||
/**
|
||||
* Create the LiteWindow and its LiteDocument
|
||||
*/
|
||||
constructor() {
|
||||
this.document = new LiteDocument();
|
||||
}
|
||||
}
|
||||
603
node_modules/mathjax-full/ts/adaptors/liteAdaptor.ts
generated
vendored
Normal file
603
node_modules/mathjax-full/ts/adaptors/liteAdaptor.ts
generated
vendored
Normal file
@@ -0,0 +1,603 @@
|
||||
/*************************************************************
|
||||
*
|
||||
* 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 a lightweight DOM adaptor
|
||||
*
|
||||
* @author dpvc@mathjax.org (Davide Cervone)
|
||||
*/
|
||||
|
||||
import {AbstractDOMAdaptor} from '../core/DOMAdaptor.js';
|
||||
import {NodeMixin, Constructor} from './NodeMixin.js';
|
||||
import {LiteDocument} from './lite/Document.js';
|
||||
import {LiteElement, LiteNode} from './lite/Element.js';
|
||||
import {LiteText, LiteComment} from './lite/Text.js';
|
||||
import {LiteList} from './lite/List.js';
|
||||
import {LiteWindow} from './lite/Window.js';
|
||||
import {LiteParser} from './lite/Parser.js';
|
||||
import {Styles} from '../util/Styles.js';
|
||||
import {OptionList} from '../util/Options.js';
|
||||
|
||||
/************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Implements a lightweight DOMAdaptor on liteweight HTML elements
|
||||
*/
|
||||
export class LiteBase extends AbstractDOMAdaptor<LiteElement, LiteText, LiteDocument> {
|
||||
/**
|
||||
* The document in which the HTML nodes will be created
|
||||
*/
|
||||
public document: LiteDocument;
|
||||
|
||||
/**
|
||||
* The window for the document
|
||||
*/
|
||||
public window: LiteWindow;
|
||||
|
||||
/**
|
||||
* The parser for serialized HTML
|
||||
*/
|
||||
public parser: LiteParser;
|
||||
|
||||
/**
|
||||
* @param {OptionList} options The options for the lite adaptor (e.g., fontSize)
|
||||
* @constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
this.parser = new LiteParser();
|
||||
this.window = new LiteWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public parse(text: string, format?: string): LiteDocument {
|
||||
return this.parser.parseFromString(text, format, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
protected create(kind: string, _ns: string = null) {
|
||||
return new LiteElement(kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public text(text: string) {
|
||||
return new LiteText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text The text of the comment
|
||||
* @return {LiteComment} The comment node
|
||||
*/
|
||||
public comment(text: string): LiteComment {
|
||||
return new LiteComment(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {LiteDocument} A new document element
|
||||
*/
|
||||
public createDocument(): LiteDocument {
|
||||
return new LiteDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public head(doc: LiteDocument) {
|
||||
return doc.head;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public body(doc: LiteDocument) {
|
||||
return doc.body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public root(doc: LiteDocument) {
|
||||
return doc.root;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public doctype(doc: LiteDocument) {
|
||||
return doc.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public tags(node: LiteElement, name: string, ns: string = null) {
|
||||
let stack = [] as LiteNode[];
|
||||
let tags = [] as LiteElement[];
|
||||
if (ns) {
|
||||
return tags; // we don't have namespaces
|
||||
}
|
||||
let n: LiteNode = node;
|
||||
while (n) {
|
||||
let kind = n.kind;
|
||||
if (kind !== '#text' && kind !== '#comment') {
|
||||
n = n as LiteElement;
|
||||
if (kind === name) {
|
||||
tags.push(n);
|
||||
}
|
||||
if (n.children.length) {
|
||||
stack = n.children.concat(stack);
|
||||
}
|
||||
}
|
||||
n = stack.shift();
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteElement} node The node to be searched
|
||||
* @param {string} id The id of the node to look for
|
||||
* @return {LiteElement} The child node having the given id
|
||||
*/
|
||||
public elementById(node: LiteElement, id: string): LiteElement {
|
||||
let stack = [] as LiteNode[];
|
||||
let n = node as LiteNode;
|
||||
while (n) {
|
||||
if (n.kind !== '#text' && n.kind !== '#comment') {
|
||||
n = n as LiteElement;
|
||||
if (n.attributes['id'] === id) {
|
||||
return n;
|
||||
}
|
||||
if (n.children.length) {
|
||||
stack = n.children.concat(stack);
|
||||
}
|
||||
}
|
||||
n = stack.shift();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteElement} node The node to be searched
|
||||
* @param {string} name The name of the class to find
|
||||
* @return {LiteElement[]} The nodes with the given class
|
||||
*/
|
||||
public elementsByClass(node: LiteElement, name: string): LiteElement[] {
|
||||
let stack = [] as LiteNode[];
|
||||
let tags = [] as LiteElement[];
|
||||
let n: LiteNode = node;
|
||||
while (n) {
|
||||
if (n.kind !== '#text' && n.kind !== '#comment') {
|
||||
n = n as LiteElement;
|
||||
const classes = (n.attributes['class'] || '').trim().split(/ +/);
|
||||
if (classes.includes(name)) {
|
||||
tags.push(n);
|
||||
}
|
||||
if (n.children.length) {
|
||||
stack = n.children.concat(stack);
|
||||
}
|
||||
}
|
||||
n = stack.shift();
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getElements(nodes: (string | LiteElement | LiteElement[])[], document: LiteDocument) {
|
||||
let containers = [] as LiteElement[];
|
||||
const body = this.body(document);
|
||||
for (const node of nodes) {
|
||||
if (typeof(node) === 'string') {
|
||||
if (node.charAt(0) === '#') {
|
||||
const n = this.elementById(body, node.slice(1));
|
||||
if (n) {
|
||||
containers.push(n);
|
||||
}
|
||||
} else if (node.charAt(0) === '.') {
|
||||
containers = containers.concat(this.elementsByClass(body, node.slice(1)));
|
||||
} else if (node.match(/^[-a-z][-a-z0-9]*$/i)) {
|
||||
containers = containers.concat(this.tags(body, node));
|
||||
}
|
||||
} else if (Array.isArray(node)) {
|
||||
containers = containers.concat(node);
|
||||
} else if (node instanceof this.window.NodeList || node instanceof this.window.HTMLCollection) {
|
||||
containers = containers.concat((node as LiteList<LiteElement>).nodes);
|
||||
} else {
|
||||
containers.push(node);
|
||||
}
|
||||
}
|
||||
return containers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public contains(container: LiteNode, node: LiteNode | LiteText) {
|
||||
while (node && node !== container) {
|
||||
node = this.parent(node);
|
||||
}
|
||||
return !!node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public parent(node: LiteNode) {
|
||||
return node.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LiteNode} node The node whose index is needed
|
||||
* @return {number} The index of the node it its parent's children array
|
||||
*/
|
||||
public childIndex(node: LiteNode): number {
|
||||
return (node.parent ? node.parent.children.findIndex(n => n === node) : -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public append(node: LiteElement, child: LiteNode) {
|
||||
if (child.parent) {
|
||||
this.remove(child);
|
||||
}
|
||||
node.children.push(child);
|
||||
child.parent = node;
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public insert(nchild: LiteNode, ochild: LiteNode) {
|
||||
if (nchild.parent) {
|
||||
this.remove(nchild);
|
||||
}
|
||||
if (ochild && ochild.parent) {
|
||||
const i = this.childIndex(ochild);
|
||||
ochild.parent.children.splice(i, 0, nchild);
|
||||
nchild.parent = ochild.parent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public remove(child: LiteNode) {
|
||||
const i = this.childIndex(child);
|
||||
if (i >= 0) {
|
||||
child.parent.children.splice(i, 1);
|
||||
}
|
||||
child.parent = null;
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public replace(nnode: LiteNode, onode: LiteNode) {
|
||||
const i = this.childIndex(onode);
|
||||
if (i >= 0) {
|
||||
onode.parent.children[i] = nnode;
|
||||
nnode.parent = onode.parent;
|
||||
onode.parent = null;
|
||||
}
|
||||
return onode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public clone(node: LiteElement) {
|
||||
const nnode = new LiteElement(node.kind);
|
||||
nnode.attributes = {...node.attributes};
|
||||
nnode.children = node.children.map(n => {
|
||||
if (n.kind === '#text') {
|
||||
return new LiteText((n as LiteText).value);
|
||||
} else if (n.kind === '#comment') {
|
||||
return new LiteComment((n as LiteComment).value);
|
||||
} else {
|
||||
const m = this.clone(n as LiteElement);
|
||||
m.parent = nnode;
|
||||
return m;
|
||||
}
|
||||
});
|
||||
return nnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public split(node: LiteText, n: number) {
|
||||
const text = new LiteText(node.value.slice(n));
|
||||
node.value = node.value.slice(0, n);
|
||||
node.parent.children.splice(this.childIndex(node) + 1, 0, text);
|
||||
text.parent = node.parent;
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public next(node: LiteNode) {
|
||||
const parent = node.parent;
|
||||
if (!parent) return null;
|
||||
const i = this.childIndex(node) + 1;
|
||||
return (i >= 0 && i < parent.children.length ? parent.children[i] : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public previous(node: LiteNode) {
|
||||
const parent = node.parent;
|
||||
if (!parent) return null;
|
||||
const i = this.childIndex(node) - 1;
|
||||
return (i >= 0 ? parent.children[i] : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public firstChild(node: LiteElement) {
|
||||
return node.children[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public lastChild(node: LiteElement) {
|
||||
return node.children[node.children.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public childNodes(node: LiteElement) {
|
||||
return [...node.children];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public childNode(node: LiteElement, i: number) {
|
||||
return node.children[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public kind(node: LiteNode) {
|
||||
return node.kind;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public value(node: LiteNode | LiteText) {
|
||||
return (node.kind === '#text' ? (node as LiteText).value :
|
||||
node.kind === '#comment' ? (node as LiteComment).value.replace(/^<!(--)?((?:.|\n)*)\1>$/, '$2') : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public textContent(node: LiteElement): string {
|
||||
return node.children.reduce((s: string, n: LiteNode) => {
|
||||
return s + (n.kind === '#text' ? (n as LiteText).value :
|
||||
n.kind === '#comment' ? '' : this.textContent(n as LiteElement));
|
||||
}, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public innerHTML(node: LiteElement): string {
|
||||
return this.parser.serializeInner(this, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public outerHTML(node: LiteElement): string {
|
||||
return this.parser.serialize(this, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public serializeXML(node: LiteElement): string {
|
||||
return this.parser.serialize(this, node, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public setAttribute(node: LiteElement, name: string, value: string | number, ns: string = null) {
|
||||
if (typeof value !== 'string') {
|
||||
value = String(value);
|
||||
}
|
||||
if (ns) {
|
||||
name = ns.replace(/.*\//, '') + ':' + name.replace(/^.*:/, '');
|
||||
}
|
||||
node.attributes[name] = value;
|
||||
if (name === 'style') {
|
||||
node.styles = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getAttribute(node: LiteElement, name: string) {
|
||||
return node.attributes[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public removeAttribute(node: LiteElement, name: string) {
|
||||
delete node.attributes[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public hasAttribute(node: LiteElement, name: string) {
|
||||
return node.attributes.hasOwnProperty(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public allAttributes(node: LiteElement) {
|
||||
const attributes = node.attributes;
|
||||
const list = [];
|
||||
for (const name of Object.keys(attributes)) {
|
||||
list.push({name: name, value: attributes[name] as string});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public addClass(node: LiteElement, name: string) {
|
||||
const classes = (node.attributes['class'] as string || '').split(/ /);
|
||||
if (!classes.find(n => n === name)) {
|
||||
classes.push(name);
|
||||
node.attributes['class'] = classes.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public removeClass(node: LiteElement, name: string) {
|
||||
const classes = (node.attributes['class'] as string || '').split(/ /);
|
||||
const i = classes.findIndex(n => n === name);
|
||||
if (i >= 0) {
|
||||
classes.splice(i, 1);
|
||||
node.attributes['class'] = classes.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public hasClass(node: LiteElement, name: string) {
|
||||
const classes = (node.attributes['class'] as string || '').split(/ /);
|
||||
return !!classes.find(n => n === name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public setStyle(node: LiteElement, name: string, value: string) {
|
||||
if (!node.styles) {
|
||||
node.styles = new Styles(this.getAttribute(node, 'style'));
|
||||
}
|
||||
node.styles.set(name, value);
|
||||
node.attributes['style'] = node.styles.cssText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getStyle(node: LiteElement, name: string) {
|
||||
if (!node.styles) {
|
||||
const style = this.getAttribute(node, 'style');
|
||||
if (!style) {
|
||||
return '';
|
||||
}
|
||||
node.styles = new Styles(style);
|
||||
}
|
||||
return node.styles.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public allStyles(node: LiteElement) {
|
||||
return this.getAttribute(node, 'style');
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public insertRules(node: LiteElement, rules: string[]) {
|
||||
node.children = [this.text(rules.join('\n\n') + '\n\n' + this.textContent(node))];
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
/*
|
||||
* The next four methods get overridden by the NodeMixin below
|
||||
*/
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public fontSize(_node: LiteElement) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public fontFamily(_node: LiteElement) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public nodeSize(_node: LiteElement, _em: number = 1, _local: boolean = null) {
|
||||
return [0, 0] as [number, number];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public nodeBBox(_node: LiteElement) {
|
||||
return {left: 0, right: 0, top: 0, bottom: 0};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The LiteAdaptor class (add in the NodeMixin methods and options)
|
||||
*/
|
||||
export class LiteAdaptor extends NodeMixin<LiteElement, LiteText, LiteDocument, Constructor<LiteBase>>(LiteBase) {}
|
||||
|
||||
/************************************************************/
|
||||
/**
|
||||
* The function to call to obtain a LiteAdaptor
|
||||
*
|
||||
* @param {OptionList} options The options for the adaptor
|
||||
* @return {LiteAdaptor} The newly created adaptor
|
||||
*/
|
||||
export function liteAdaptor(options: OptionList = null): LiteAdaptor {
|
||||
return new LiteAdaptor(null, options);
|
||||
}
|
||||
Reference in New Issue
Block a user