package svg
import "github.com/d2lang/mathjax-go/internal/mml"
func prepareTeXClasses(node *mml .Node ) {
setTeXClass (node , nil )
}
func setTeXClass(node , previous *mml .Node ) *mml .Node {
if node == nil {
return previous
}
switch node .Kind {
case "text" , "XML" , "xml" , "annotation" , "annotation-xml" , "mspace" , "mprescripts" , "none" :
return previous
case "math" , "mstyle" , "mpadded" , "mphantom" :
if len (node .Children ) == 0 {
return previous
}
previous = setTeXClass (node .Children [0 ], previous )
updateTeXClass (node , node .Children [0 ])
return previous
case "mrow" :
return setRowTeXClass (node , previous )
case "mfenced" :
setPreviousClass (node , previous )
if node .Fenced != nil && node .Fenced .Open != nil {
previous = setTeXClass (node .Fenced .Open , previous )
}
for i , child := range node .Children {
if i > 0 && node .Fenced != nil && i -1 < len (node .Fenced .Separators ) {
previous = setTeXClass (node .Fenced .Separators [i -1 ], previous )
}
previous = setTeXClass (child , previous )
}
if node .Fenced != nil {
if node .Fenced .Close != nil {
previous = setTeXClass (node .Fenced .Close , previous )
}
updateTeXClass (node , node .Fenced .Open )
}
return previous
case "mfrac" , "msqrt" , "mroot" , "mtable" , "mtr" , "mlabeledtr" , "mtd" :
setPreviousClass (node , previous )
for _ , child := range node .Children {
setTeXClass (child , nil )
}
return node
case "menclose" :
if len (node .Children ) == 0 {
return previous
}
previous = setTeXClass (node .Children [0 ], previous )
updateTeXClass (node , node .Children [0 ])
return previous
case "TeXAtom" :
if len (node .Children ) != 0 {
setTeXClass (node .Children [0 ], nil )
}
return adjustTeXClass (node , previous )
case "mi" :
setPreviousClass (node , previous )
_ , hasAutoOP := node .Property ("autoOP" )
_ , hasTeXClass := node .Property ("texClass" )
if !hasAutoOP && !hasTeXClass && stringAttribute (node , "mathvariant" , "" ) == "normal" && isIdentifierOperatorName (nodeText (node )) {
node .TeXClass = mml .TeXClassOp
node .SetProperty ("autoOP" , true )
}
return node
case "mo" :
if _ , explicit := node .Property ("texClass" ); !explicit &&
(node .Attributes .IsSet ("lspace" ) || node .Attributes .IsSet ("rspace" )) {
return nil
}
return adjustTeXClass (node , previous )
case "msub" , "msup" , "msubsup" , "munder" , "mover" , "munderover" , "mmultiscripts" , "semantics" :
return setBaseTeXClass (node , previous )
case "maction" :
selected := actionSelection (node )
if selected == nil {
return previous
}
previous = setTeXClass (selected , previous )
updateTeXClass (node , selected )
return previous
}
setPreviousClass (node , previous )
if node .TeXClass == mml .TeXClassNone {
return previous
}
return node
}
func isIdentifierOperatorName(name string ) bool {
if len (name ) < 2 {
return false
}
for i := 0 ; i < len (name ); i ++ {
c := name [i ]
if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || i > 0 && c >= '0' && c <= '9' {
continue
}
return false
}
return true
}
func setRowTeXClass(node , previous *mml .Node ) *mml .Node {
_ , hasOpen := node .Property ("open" )
_ , hasClose := node .Property ("close" )
if hasOpen || hasClose {
setPreviousClass (node , previous )
previous = nil
}
for _ , child := range node .Children {
previous = setTeXClass (child , previous )
}
if hasOpen || hasClose {
if node .TeXClass == mml .TeXClassNone {
node .TeXClass = mml .TeXClassInner
}
} else if len (node .Children ) != 0 {
updateTeXClass (node , node .Children [0 ])
}
return previous
}
func setBaseTeXClass(node , previous *mml .Node ) *mml .Node {
setPreviousClass (node , previous )
node .TeXClass = mml .TeXClassOrd
if len (node .Children ) == 0 || node .Children [0 ] == nil {
return node
}
base := node .Children [0 ]
if node .Flags .Embellished || base .Kind == "mi" {
previous = setTeXClass (base , previous )
updateTeXClass (node , base )
} else {
setTeXClass (base , nil )
previous = node
}
for _ , child := range node .Children [1 :] {
setTeXClass (child , nil )
}
return previous
}
func coreNode(node *mml .Node ) *mml .Node {
for node != nil && node .Flags .Embellished && node .Kind != "mo" {
index := node .Flags .CoreIndex
if index < 0 || index >= len (node .Children ) {
break
}
node = node .Children [index ]
}
return node
}
func actionSelection(node *mml .Node ) *mml .Node {
if len (node .Children ) == 0 {
return nil
}
selection := 1
if value , ok := numberAttribute (node , "selection" ); ok {
selection = int (value )
}
if selection < 1 || selection > len (node .Children ) {
selection = 1
}
return node .Children [selection -1 ]
}
func setPreviousClass(node , previous *mml .Node ) {
node .PrevClass = mml .TeXClassNone
node .PrevLevel = 0
if previous == nil {
return
}
node .PrevClass = previous .TeXClass
if level , ok := numberAttribute (previous , "scriptlevel" ); ok {
node .PrevLevel = int (level )
}
}
func updateTeXClass(node , core *mml .Node ) {
if node == nil || core == nil {
return
}
node .PrevClass = core .PrevClass
node .PrevLevel = core .PrevLevel
core .PrevClass = mml .TeXClassNone
core .PrevLevel = 0
node .TeXClass = core .TeXClass
}
func adjustTeXClass(node , previous *mml .Node ) *mml .Node {
class := effectiveTeXClass (node )
if class == mml .TeXClassNone {
return previous
}
previousClass := mml .TeXClassNone
if previous != nil {
previousClass = effectiveTeXClass (previous )
if auto , ok := previous .Property ("autoOP" ); ok && truthy (auto ) &&
(class == mml .TeXClassBin || class == mml .TeXClassRel ) {
previous .TeXClass = mml .TeXClassOrd
previousClass = mml .TeXClassOrd
}
}
node .PrevClass = previousClass
if previous != nil {
node .PrevLevel = 0
if value , ok := node .Attributes .GetInherited ("scriptlevel" ); ok {
switch level := value .(type ) {
case int :
node .PrevLevel = level
case int64 :
node .PrevLevel = int (level )
case float64 :
node .PrevLevel = int (level )
}
}
}
if class == mml .TeXClassBin &&
(previousClass == mml .TeXClassNone || previousClass == mml .TeXClassBin ||
previousClass == mml .TeXClassOp || previousClass == mml .TeXClassRel ||
previousClass == mml .TeXClassOpen || previousClass == mml .TeXClassPunct ) {
node .TeXClass = mml .TeXClassOrd
class = mml .TeXClassOrd
} else if previousClass == mml .TeXClassBin &&
(class == mml .TeXClassRel || class == mml .TeXClassClose || class == mml .TeXClassPunct ) {
previous .TeXClass = mml .TeXClassOrd
node .PrevClass = mml .TeXClassOrd
} else if class == mml .TeXClassBin && isLastTeXAtom (node ) {
node .TeXClass = mml .TeXClassOrd
}
return node
}
func isLastTeXAtom(node *mml .Node ) bool {
child := node
parent := child .Parent
for parent != nil && parent .Parent != nil && parent .Flags .Embellished &&
(len (parent .Children ) == 1 || (parent .Kind != "mrow" && parent .Core () == child )) {
child = parent
parent = parent .Parent
}
return parent != nil && len (parent .Children ) != 0 && parent .Children [len (parent .Children )-1 ] == child
}
func effectiveTeXClass(node *mml .Node ) mml .TeXClass {
if node == nil {
return mml .TeXClassNone
}
if node .Kind == "TeXAtom" || node .TeXClass != mml .TeXClassNone {
return node .TeXClass
}
if value , ok := node .Property ("texClass" ); ok {
switch class := value .(type ) {
case mml .TeXClass :
return class
case int :
return mml .TeXClass (class )
case int64 :
return mml .TeXClass (class )
case float64 :
return mml .TeXClass (int (class ))
}
}
switch node .Kind {
case "text" , "mspace" , "mprescripts" , "none" , "annotation" , "annotation-xml" , "XML" , "xml" :
return mml .TeXClassNone
default :
return mml .TeXClassOrd
}
}
The pages are generated with Golds v0.8.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .