// Copyright (c) 2009-2022 The MathJax Consortium // SPDX-License-Identifier: Apache-2.0 // Sources: ts/input/tex/braket/{BraketMethods,BraketItems}.ts.
package tex import type braketItem struct { stretchy, single bool barcount, barmax int open, close string singleFence *mml.Node } // Braket parses on the caller: an unbraced control sequence may consume its // own arguments or install a macro expansion before delivering its first node. func ( *parser) ( string) ([]*mml.Node, error) { .skipNextSpaces() if .pos == len(.source) { return nil, texError("MissingArgFor", "Missing argument for %s", "\\"+) } := &braketItem{stretchy: != "set", single: true, barmax: -1} , := "⟨", "⟩" if == "Set" || == "set" { , = "{", "}" .barmax = 1 } .open, .close = , := byte(0) if .source[.pos] == '{' { .pos++ .single = false = '}' } , , , := .braketOwner, .cdArrayEntry, .environmentRow, .ordinaryArray .environmentRow, .ordinaryArray = nil, nil .braketOwner = if !.single { .cdArrayEntry = false } defer func() { .braketOwner, .cdArrayEntry, .environmentRow, .ordinaryArray = , , , }() , , := .parseRowWithInfix(, false, false) if != nil { return nil, } := .environmentPopped if { // SpreadLines calls the popped BraketItem's toMml(), which still // constructs its fences even without a matching close item. .environmentPopped = false } if .single && .pendingCell != nil { // A final MML closed this Braket before the CellItem was replayed. // Its copied lexical environment is now gone; the enclosing open // owner must save its own environment when it receives the cell. .pendingCell.envSaved = false } var []*mml.Node if .single && len() > 1 { = [1:] = [:1] } // NodeUtil.appendChildren flattens the inferred inner row when the // BraketItem constructs its explicit fenced row. := .singleFence if == nil { = .leftRightFenced(, row(, true), , .stretchy) } if { if := mathtoolsSpreadPop(, nil); != nil { return nil, } } return append([]*mml.Node{}, ...), nil } func ( *parser) () []*mml.Node { := .braketOwner if == nil || .barmax >= 0 && .barcount >= .barmax { return []*mml.Node{.operator("∥", mml.TeXClassOrd, map[string]any{"stretchy": false})} } if !.stretchy { // Fixed sets do not increment barcount. return []*mml.Node{setAttributes(.token("mo", "∥"), map[string]any{"stretchy": false, "braketbar": true})} } := texAtom(row(nil, true), mml.TeXClassClose) // Delivering CLOSE completes a single owner before the bar is created. // Preserve that order in the parse's operator-creation list as well as // keeping the remaining bar and OPEN outside the resulting fences. if .single { .singleFence = .leftRightFenced(.open, , .close, true) .braketOwner = nil } .barcount++ := setAttributes(.token("mo", "∥"), map[string]any{"stretchy": true, "braketbar": true}) return []*mml.Node{, , texAtom(row(nil, true), mml.TeXClassOpen)} }