import { isArray } from '../common/types' ; import type { Atom } from '../core/atom' ; import { GenfracAtom } from '../core-atoms/genfrac' ; import { LeftRightAtom } from '../core-atoms/leftright' ; import { ArrayAtom } from '../core-atoms/array' ; const SPECIAL_IDENTIFIERS = { '\u2212' : '-' , '-' : '-' , '\\alpha' : 'alpha' , '\\beta' : 'beta' , '\\gamma' : 'gamma' , '\\delta' : 'delta' , '\\epsilon' : 'epsilon' , '\\varepsilon' : 'varepsilon' , '\\zeta' : 'zeta' , '\\eta' : 'eta' , '\\theta' : 'theta' , '\\vartheta' : 'vartheta' , '\\iota' : 'iota' , '\\kappa' : 'kappa' , '\\lambda' : 'lambda' , '\\mu' : 'mu' , '\\nu' : 'nu' , '\\xi' : 'xi' , '\\pi' : 'pi' , '\\rho' : 'rho' , '\\sigma' : 'sigma' , '\\tau' : 'tau' , '\\upsilon' : 'upsilon' , '\\phi' : 'phi' , '\\varphi' : 'varphi' , '\\chi' : 'chi' , '\\psi' : 'psi' , '\\omega' : 'omega' , '\\Gamma' : 'Gamma' , '\\Delta' : 'Delta' , '\\Theta' : 'Theta' , '\\Lambda' : 'Lambda' , '\\Xi' : 'Xi' , '\\Pi' : 'Pi' , '\\Sigma' : 'Sigma' , '\\Phi' : 'Phi' , '\\Psi' : 'Psi' , '\\Omega' : 'Omega' , '\\exponentialE' : 'e' , '\\imaginaryI' : 'i' , '\\imaginaryJ' : 'j' , } ; const SPECIAL_OPERATORS = { '\\pm' : '+-' , '\\times' : 'xx' , '\\colon' : ':' , '\\vert' : '|' , '\\Vert' : '||' , '\\mid' : '|' , '\\lbrace' : '{' , '\\rbrace' : '}' , '\\lparen' : '(' , '\\rparen' : ')' , '\\langle' : '(:' , '\\rangle' : ':)' , } ; export function atomToAsciiMath ( atom ) { if ( ! atom ) return '' ; if ( isArray < Atom > ( atom ) ) { let result = '' ; if ( atom . length === 0 ) return '' ; if ( atom [ 0 ] . type === 'first' ) atom = atom . slice ( 1 ) ; if ( atom . length === 0 ) return '' ; if ( atom [ 0 ] . mode === 'text' ) { let i = 0 ; result = '"' ; while ( atom [ i ] ?. mode === 'text' ) { result += atom [ i ] . body ? atomToAsciiMath ( atom [ i ] . body ) : atom [ i ] . value ; i ++ ; } result += '"' + atomToAsciiMath ( atom . slice ( i ) ) ; } else if ( atom [ 0 ] . mode === 'math' ) { let i = 0 ; while ( atom [ i ] && atom [ i ] . mode === 'math' ) { result += atomToAsciiMath ( atom [ i ] ) ; i ++ ; } result += atomToAsciiMath ( atom . slice ( i ) ) ; } else { console . warn ( 'toASCIIMath: Unexpected mode' ) ; } return result . trim ( ) ; } if ( atom . mode === 'text' ) { return '"' + atom . value + '"' ; } let result = '' ; const { command } = atom ; let m ; switch ( atom . type ) { case 'first' : return '' ; case 'group' : case 'root' : result = atomToAsciiMath ( atom . body ) ; break ; case 'genfrac' : { const genfracAtom = atom as GenfracAtom ; if ( genfracAtom . leftDelim || genfracAtom . rightDelim ) { result += genfracAtom . leftDelim === '.' || ! genfracAtom . leftDelim ? '{:' : genfracAtom . leftDelim ; } if ( genfracAtom . hasBarLine ) { result += '(' ; result += atomToAsciiMath ( genfracAtom . above ) ; result += ')/(' ; result += atomToAsciiMath ( genfracAtom . below ) ; result += ')' ; } else { result += '(' + atomToAsciiMath ( genfracAtom . above ) + '),' ; result += '(' + atomToAsciiMath ( genfracAtom . below ) + ')' ; } if ( genfracAtom . leftDelim || genfracAtom . rightDelim ) { result += genfracAtom . rightDelim === '.' || ! genfracAtom . rightDelim ? '{:' : genfracAtom . rightDelim ; } } break ; case 'surd' : result += ! atom . hasEmptyBranch ( 'above' ) ? 'root(' + atomToAsciiMath ( atom . above ) + ')(' + atomToAsciiMath ( atom . body ) + ')' : 'sqrt(' + atomToAsciiMath ( atom . body ) + ')' ; break ; case 'leftright' : { const leftrightAtom = atom as LeftRightAtom ; result += leftrightAtom . leftDelim === '.' || ! leftrightAtom . leftDelim ? '{:' : leftrightAtom . leftDelim ; result += atomToAsciiMath ( leftrightAtom . body ) ; result += leftrightAtom . rightDelim === '.' || ! leftrightAtom . rightDelim ? ':}' : leftrightAtom . rightDelim ; } break ; case 'sizeddelim' : case 'delim' : break ; case 'overlap' : break ; case 'overunder' : break ; case 'mord' : result = SPECIAL_IDENTIFIERS [ command ! ] ?? command ?? ( typeof atom . value === 'string' ? atom . value : '' ) ; if ( result . startsWith ( '\\' ) ) result += ' ' ; m = command ? command . match ( /{?\\char"([\dabcdefABCDEF]*)}?/ ) : null ; if ( m ) { result = String . fromCodePoint ( Number . parseInt ( '0x' + m [ 1 ] ) ) ; } else if ( result . length > 0 && result . startsWith ( '\\' ) ) { result = typeof atom . value === 'string' ? atom . value . charAt ( 0 ) ! : atom . command ! ; } break ; case 'mbin' : case 'mrel' : case 'minner' : result = SPECIAL_IDENTIFIERS [ command ! ] ?? SPECIAL_OPERATORS [ command ! ] ?? atom . value ; break ; case 'mopen' : case 'mclose' : result += atom . value ; break ; case 'mpunct' : result = SPECIAL_OPERATORS [ command ! ] ?? command ; break ; case 'mop' : if ( atom . value !== '\u200B' ) { result = '' ; result += command === '\\operatorname' ? atomToAsciiMath ( atom . body ) : atom . value ?? command ; result += ' ' ; } break ; case 'array' : const array = ( atom as ArrayAtom ) . array ; const environment = ( atom as ArrayAtom ) . environmentName ; const rowDelim = { 'bmatrix' : [ '[' , ']' ] , 'bmatrix*' : [ '[' , ']' ] , } [ environment ] ?? [ '(' , ')' ] ; const rows = [ ] ; for ( const row of array ) { const cells = [ ] ; for ( const cell of row ) { cells . push ( rowDelim [ 0 ] + atomToAsciiMath ( cell ) + rowDelim [ 1 ] ) ; } rows . push ( cells . join ( ',' ) ) ; } const delim = { 'bmatrix' : [ '[' , ']' ] , 'bmatrix*' : [ '[' , ']' ] , 'cases' : [ '{' , ':}' ] , } [ environment ] ?? [ '(' , ')' ] ; result = delim [ 0 ] + rows . join ( ',' ) + delim [ 1 ] ; break ; case 'box' : break ; case 'spacing' : break ; case 'enclose' : result = '(' + atomToAsciiMath ( atom . body ) + ')' ; break ; case 'space' : result = ' ' ; break ; case 'msubsup' : result = '' ; break ; case 'macro' : result = SPECIAL_IDENTIFIERS [ command ! ] ?? SPECIAL_OPERATORS [ command ! ] ?? atomToAsciiMath ( atom . body ) ; break ; } if ( ! atom . hasEmptyBranch ( 'subscript' ) ) { result += '_' ; const arg = atomToAsciiMath ( atom . subscript ) ; result += arg . length > 1 ? '(' + arg + ')' : arg ; } if ( ! atom . hasEmptyBranch ( 'superscript' ) ) { result += '^' ; const arg = atomToAsciiMath ( atom . superscript ) ; result += arg . length > 1 ? '(' + arg + ')' : arg ; } return result ; }