import type { TokenFlow } from "./flow"; import { EditorState } from "./editorState"; import { Strand } from "./strand"; import { VNode } from "./vdom"; export abstract class Token { abstract flow: TokenFlow; abstract get children(): readonly Strand[]; protected _parentStrand: Strand | undefined; set parentStrand(parent: Strand) { if (this._parentStrand !== undefined) { throw new Error("Parent token is already set"); } this._parentStrand = parent; } get parentStrand(): Strand | undefined { return this._parentStrand; } get editorState(): EditorState | undefined { return this._parentStrand?.editorState; } /** * Create a new token with its children mapped through the given function. * @param fn Function to map each child strand. * @returns A new token with the mapped children. */ abstract mapChildren(fn: (child: Strand, index: number) => Strand): Token; /** * Create a deep clone of this token. * @returns A deep clone of this token. */ clone(): Token { return this.mapChildren( (strand, index) => new Strand(strand.tokens.map((token) => token.clone())) ); } /** * @deprecated This function is only for debugging purposes. Actual rendering of tokens should be done via a separate rendering system. */ renderToDebugText(): string { return `${this.constructor.name}(${this.children .map((child) => child.renderToDebugText()) .join(", ")})`; } /** * @deprecated This function is only for debugging purposes. Actual rendering of tokens should be done via a separate rendering system. */ abstract renderToDebugHTML(): VNode; /** * @deprecated This function is only for debugging purposes. Actual rendering of tokens should be done via a separate rendering system. */ abstract renderToDebugMathML(): VNode; }