A world-class math input for the web
at main 60 lines 1.9 kB view raw
1import type { TokenFlow } from "./flow"; 2import { EditorState } from "./editorState"; 3import { Strand } from "./strand"; 4import { VNode } from "./vdom"; 5 6export abstract class Token { 7 abstract flow: TokenFlow; 8 abstract get children(): readonly Strand[]; 9 10 protected _parentStrand: Strand | undefined; 11 set parentStrand(parent: Strand) { 12 if (this._parentStrand !== undefined) { 13 throw new Error("Parent token is already set"); 14 } 15 this._parentStrand = parent; 16 } 17 get parentStrand(): Strand | undefined { 18 return this._parentStrand; 19 } 20 21 get editorState(): EditorState | undefined { 22 return this._parentStrand?.editorState; 23 } 24 25 /** 26 * Create a new token with its children mapped through the given function. 27 * @param fn Function to map each child strand. 28 * @returns A new token with the mapped children. 29 */ 30 abstract mapChildren(fn: (child: Strand, index: number) => Strand): Token; 31 32 /** 33 * Create a deep clone of this token. 34 * @returns A deep clone of this token. 35 */ 36 clone(): Token { 37 return this.mapChildren( 38 (strand, index) => new Strand(strand.tokens.map((token) => token.clone())) 39 ); 40 } 41 42 /** 43 * @deprecated This function is only for debugging purposes. Actual rendering of tokens should be done via a separate rendering system. 44 */ 45 renderToDebugText(): string { 46 return `${this.constructor.name}(${this.children 47 .map((child) => child.renderToDebugText()) 48 .join(", ")})`; 49 } 50 51 /** 52 * @deprecated This function is only for debugging purposes. Actual rendering of tokens should be done via a separate rendering system. 53 */ 54 abstract renderToDebugHTML(): VNode; 55 56 /** 57 * @deprecated This function is only for debugging purposes. Actual rendering of tokens should be done via a separate rendering system. 58 */ 59 abstract renderToDebugMathML(): VNode; 60}