You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is the third time this exact rendering defect has surfaced (see #46, #48, #64). It keeps coming back because the two available bar renderers are not equivalent, and every time the bar path is re-aligned to straightenTallBars, the general case regresses again. This report is meant to end the cycle: it states the invariant and the one implementation that satisfies it.
Symptom
A modulus / norm bar renders with a visible mid-height seam (a "bump") whenever its argument is taller than one text line but is not a bra/ket. The canonical case is the quantum probability |\psi(x)|^2:
|\psi(x)|^2
The parenthesised argument \psi(x) pushes the bar past one line, the front end builds its extensible bracketing-bar glyph from pieces, and it seams. Same for |\frac{a}{b}|, \|\frac{\psi}{\phi}\|, etc. A bare braket |\langle\phi|\psi\rangle| does not bump, which is exactly why the defect hides.
Why it recurs
There are two bar renderers in the history of this repo, and only one is complete:
straightenTallBars (the one currently in texBoxes): rewrites an Abs / NormTemplateBox to a fixed-scale glyph StyleBox["\[VerticalLine]" / "\[DoubleVerticalBar]", FontSize -> 1.3 Inherited], guarded by
tallArgQ is braket-only.|\psi(x)|^2 is an Abs of a parenthesised row, not a braket, so tallArgQ is False, straightenTallBars never fires, and the extensible Abs template survives and seams.
The scale is fixed at 1.3x. Even where it does fire, 1.3 Inherited is a guess: too tall for a scalar, far too short for a two-line fraction. A bar height that does not track the content is wrong by construction.
barsToGrid (the content-adaptive renderer): after templatizeBars has folded every modulus into an Abs / NormTemplateBox, rewrite those to a GridBox column-rule
A GridBox divider is a plain solid rule that spans exactly the cell (content) height and is not a glyph, so it cannot be built up and cannot seam: short around |a|, tall around |\psi(x)| or a braket or a fraction, correct at every height with no per-argument tuning.
The regression path is always the same: a reconcile/refactor swaps barsToGrid back to straightenTallBars (because upstream main only ever had straightenTallBars), and |\psi(x)|^2 silently starts bumping again while the braket tests stay green.
How to avoid it (the invariant)
Render moduli/norms with the content-adaptive GridBox rule (barsToGrid), not the fixed-scale braket-only straightenTallBars. Do not swap it back.
Test the general case, not just brakets. The test that would have caught every recurrence asserts that a parenthesised modulus leaves no extensible template and produces the divider rule:
A green suite that only checks |\langle\phi|\psi\rangle| will pass while |\psi(x)|^2 bumps. Include a parenthesised argument.
N2M integration caveat (important since NotebookToMarkdown delegates box→LaTeX to WolframParserExportLaTeX).ExportLaTeX reads a bare one-cell GridBox as \begin{matrix}, and it is monolithic (it consumes the whole box tree; it does not call back per sub-box). So a walkerMath[g_GridBox /; absGridQ[g]] rule only catches a modulus standing alone at top level, not the common |\psi(x)|^2 nested inside a SuperscriptBox. Fold the GridBox back to a template before delegating:
ExportLaTeX turns the Abs / Norm templates back into \lvert / \lVert (nested-safe), and a genuine matrix grid has no dividers so it falls through to the matrix path unchanged.
Recurring issue
This is the third time this exact rendering defect has surfaced (see #46, #48, #64). It keeps coming back because the two available bar renderers are not equivalent, and every time the bar path is re-aligned to
straightenTallBars, the general case regresses again. This report is meant to end the cycle: it states the invariant and the one implementation that satisfies it.Symptom
A modulus / norm bar renders with a visible mid-height seam (a "bump") whenever its argument is taller than one text line but is not a bra/ket. The canonical case is the quantum probability
|\psi(x)|^2:The parenthesised argument
\psi(x)pushes the bar past one line, the front end builds its extensible bracketing-bar glyph from pieces, and it seams. Same for|\frac{a}{b}|,\|\frac{\psi}{\phi}\|, etc. A bare braket|\langle\phi|\psi\rangle|does not bump, which is exactly why the defect hides.Why it recurs
There are two bar renderers in the history of this repo, and only one is complete:
straightenTallBars(the one currently intexBoxes): rewrites anAbs/NormTemplateBoxto a fixed-scale glyphStyleBox["\[VerticalLine]" / "\[DoubleVerticalBar]", FontSize -> 1.3 Inherited], guarded byTwo independent limits make this incomplete:
tallArgQis braket-only.|\psi(x)|^2is anAbsof a parenthesised row, not a braket, sotallArgQisFalse,straightenTallBarsnever fires, and the extensibleAbstemplate survives and seams.1.3 Inheritedis a guess: too tall for a scalar, far too short for a two-line fraction. A bar height that does not track the content is wrong by construction.barsToGrid(the content-adaptive renderer): aftertemplatizeBarshas folded every modulus into anAbs/NormTemplateBox, rewrite those to a GridBox column-ruleA GridBox divider is a plain solid rule that spans exactly the cell (content) height and is not a glyph, so it cannot be built up and cannot seam: short around
|a|, tall around|\psi(x)|or a braket or a fraction, correct at every height with no per-argument tuning.The regression path is always the same: a reconcile/refactor swaps
barsToGridback tostraightenTallBars(because upstreammainonly ever hadstraightenTallBars), and|\psi(x)|^2silently starts bumping again while the braket tests stay green.How to avoid it (the invariant)
Render moduli/norms with the content-adaptive GridBox rule (
barsToGrid), not the fixed-scale braket-onlystraightenTallBars. Do not swap it back.Concretely:
texBoxesends withbarsToGrid @ applyMathFont @ templatizeBars @ …— notstraightenTallBars @ …. KeeptemplatizeBars(it does the promotion, incl. the templatizeBars: an unpairable\|/\lVertnorm keeps the non-stretching \[DoubleVerticalBar], so bars around a ket render one line tall #64 bare-\|and the norm-squared scripted-closer rules) and keeptallArgQ(those rules still use it); only the final render step isbarsToGrid.Test the general case, not just brakets. The test that would have caught every recurrence asserts that a parenthesised modulus leaves no extensible template and produces the divider rule:
A green suite that only checks
|\langle\phi|\psi\rangle|will pass while|\psi(x)|^2bumps. Include a parenthesised argument.N2M integration caveat (important since
NotebookToMarkdowndelegates box→LaTeX toWolframParserExportLaTeX).ExportLaTeXreads a bare one-cell GridBox as\begin{matrix}, and it is monolithic (it consumes the whole box tree; it does not call back per sub-box). So awalkerMath[g_GridBox /; absGridQ[g]]rule only catches a modulus standing alone at top level, not the common|\psi(x)|^2nested inside aSuperscriptBox. Fold the GridBox back to a template before delegating:ExportLaTeXturns theAbs/Normtemplates back into\lvert/\lVert(nested-safe), and a genuine matrix grid has no dividers so it falls through to the matrix path unchanged.Reproduce
With
straightenTallBars:SuperscriptBox[RowBox[{TemplateBox[{RowBox[{…"("…")"…}]}, "Abs"]}], "2"]— the extensibleAbstemplate survives → bump.With
barsToGrid:SuperscriptBox[RowBox[{GridBox[{{…}}, GridBoxDividers -> {"Columns" -> {True, True}, …}]}], "2"]— the divider rule → no bump, round-trips to\lvert \psi(x)\rvert^{2}.