diff --git a/lib/LaTeXML/Engine/latex_constructs.pool.ltxml b/lib/LaTeXML/Engine/latex_constructs.pool.ltxml index 97d5b676c..c9997ea4f 100644 --- a/lib/LaTeXML/Engine/latex_constructs.pool.ltxml +++ b/lib/LaTeXML/Engine/latex_constructs.pool.ltxml @@ -292,10 +292,11 @@ DefMacro('\@icentercr[]', '\vskip #1\ignorespaces'); # text # \end{document} -DefMacro('\AtBeginDocument{}', sub { - PushValue('@at@begin@document', $_[1]->unlist); }); -DefMacro('\AtEndDocument{}', sub { - PushValue('@at@end@document', $_[1]->unlist); }); +# Support optional [label] argument from modern LaTeX hooks system (e.g. \AtBeginDocument[tcolorbox]{...}) +DefMacro('\AtBeginDocument[]{}', sub { + PushValue('@at@begin@document', $_[2]->unlist); }); +DefMacro('\AtEndDocument[]{}', sub { + PushValue('@at@end@document', $_[2]->unlist); }); # Like "#body", # But more complicated due to id, at begin/end document and so forth. diff --git a/lib/LaTeXML/Engine/math_common.pool.ltxml b/lib/LaTeXML/Engine/math_common.pool.ltxml index d1508bc4d..276ee1bce 100644 --- a/lib/LaTeXML/Engine/math_common.pool.ltxml +++ b/lib/LaTeXML/Engine/math_common.pool.ltxml @@ -356,7 +356,7 @@ DefRewrite(select => ["descendant-or-self::ltx:XMTok[text()='\x{FF0F}' and \@mea if (my $id = $not->getAttribute('xml:id')) { foreach my $n ($doc->findnodes("descendant-or-self::ltx:XMRef[\@idref='$id']")) { $doc->removeNode($n); } } # ? Hopefully this is safe. -} }); + } }); #---------------------------------------------------------------------- # \joinrel @@ -400,7 +400,7 @@ DefConstructor('\@@joinrel{}{}', sub { my $role = (scalar(keys %roles) == 1 ? [keys %roles]->[0] : ($roles{ARROW} ? 'ARROW' : 'RELOP')); map { $node->removeChild($_) } @rels; $document->insertElement('ltx:XMTok', [map { $_->textContent } @rels], role => $role); - } } }, + } } }, reversion => '#1\joinrel #2'); #---------------------------------------------------------------------- @@ -468,9 +468,9 @@ DefConstructorI('\lx@ldots', undef, # And so can \vdots DefConstructorI('\vdots', undef, "?#isMath(\x{22EE})(\x{22EE})", - sizer => "\x{22EE}", + sizer => "\x{22EE}", enterHorizontal => 1, - properties => sub { + properties => sub { (LookupValue('IN_MATH') ? (font => LookupValue('font')->merge(family => 'serif', series => 'medium', shape => 'upright')->specialize("\x{22EE}")) @@ -484,9 +484,9 @@ DefMathI('\colon', undef, ':', role => 'METARELOP'); # Seems like good # Aha, also can be in text... DefConstructorI('\dots', undef, "?#isMath(\x{2026})(\x{2026})", - sizer => "\x{2026}", + sizer => "\x{2026}", enterHorizontal => 1, - properties => sub { + properties => sub { (LookupValue('IN_MATH') ? (font => LookupValue('font')->merge(family => 'serif', series => 'medium', shape => 'upright')->specialize("\x{2026}")) @@ -574,9 +574,9 @@ DefMathI('\langle', undef, "\x{27E8}", role => 'OPEN', stretchy => 'false'); # L DefMathI('\rangle', undef, "\x{27E9}", role => 'CLOSE', stretchy => 'false'); # RIGHT-POINTING ANGLE BRACKET # Not sure these should be defined here, or latex, or even latex compat mode. -DefMathI('\lgroup', undef, "\x{27EE}", role => 'OPEN', stretchy => 'false'); -DefMathI('\rgroup', undef, "\x{27EF}", role => 'CLOSE', stretchy => 'false'); -DefMathI('\bracevert', undef, "|", font => { series => 'bold' }, role => 'VERTBAR'); +DefMathI('\lgroup', undef, "\x{27EE}", role => 'OPEN', stretchy => 'false'); +DefMathI('\rgroup', undef, "\x{27EF}", role => 'CLOSE', stretchy => 'false'); +DefMathI('\bracevert', undef, "|", font => { series => 'bold' }, role => 'VERTBAR'); ## DefMath('\lmoustache',"???", font=>{series=>'bold'}, role=>'OPEN'); ## DefMath('\rmoustache',"???", font=>{series=>'bold'}, role=>'OPEN'); @@ -587,9 +587,9 @@ DefMathI('\bracevert', undef, "|", font => { series => 'bold' }, role => 'VERTBA # mapping. Unfortunately, this doesn't (yet) support people declaring thier own delimiters! # These expand into \left#1, so the bracing disappears; only enlarge the 1st part of #1! -DefConstructor('\big TeXDelimiter', '#1', bounded => 1, font => { size => 'big' }, +DefConstructor('\big TeXDelimiter', '#1', bounded => 1, font => { size => 'big' }, afterConstruct => sub { augmentDelimiterProperties($_[0], $_[1], undef, 0); }); -DefConstructor('\Big TeXDelimiter', '#1', bounded => 1, font => { size => 'Big' }, +DefConstructor('\Big TeXDelimiter', '#1', bounded => 1, font => { size => 'Big' }, afterConstruct => sub { augmentDelimiterProperties($_[0], $_[1], undef, 0); }); DefConstructor('\bigg TeXDelimiter', '#1', bounded => 1, font => { size => 'bigg' }, afterConstruct => sub { augmentDelimiterProperties($_[0], $_[1], undef, 0); }); @@ -655,9 +655,24 @@ DefConstructor('\phantom{}', DefConstructor('\hphantom{}', "?#isMath()" . "(#1)", # !?!?!?! - properties => { isSpace => 1 }, + properties => { isSpace => 1 }, + # In TeX, \hphantom always processes its argument inside an \hbox. + # In text/horizontal mode, we enforce restricted_horizontal to prevent + # display math from leaking through the argument (as can happen with + # complex TikZ library expansions like quantikz2). + # In math mode, we preserve the current mode for correct font metrics. + beforeDigest => sub { + my ($stomach) = @_; + if (!$STATE->lookupValue('IN_MATH')) { + $stomach->beginMode('restricted_horizontal'); + AssignValue('_hphantom_mode_override' => 1); } + else { + AssignValue('_hphantom_mode_override' => 0); } + return; }, afterDigest => sub { - my $whatsit = $_[1]; + my ($stomach, $whatsit) = @_; + if (LookupValue('_hphantom_mode_override')) { + $stomach->endMode('restricted_horizontal'); } my ($w, $h, $d) = $whatsit->getArg(1)->getSize; $whatsit->setProperties(width => $w, height => $h, depth => $d); return; }); @@ -795,7 +810,7 @@ DefRewrite(xpath => 'descendant-or-self::ltx:XMWrap[count(child::*)=1]', $document->setNodeFont($wrap, $document->getNodeFont($node)); ## WHY THIS???? $document->getNode->appendChild($node); -} }); + } }); #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Stop at diff --git a/lib/LaTeXML/Package/color.sty.ltxml b/lib/LaTeXML/Package/color.sty.ltxml index a97269b7c..1e7a1a275 100644 --- a/lib/LaTeXML/Package/color.sty.ltxml +++ b/lib/LaTeXML/Package/color.sty.ltxml @@ -108,7 +108,7 @@ DefMacro('\colorbox[]{}{}', '\hbox{\ifx.#1.\pagecolor{#2}\else\pagecolor[#1]{#2} DefConstructor('\fcolorbox[]{}{} Undigested', "#text", - mode => 'internal_vertical', + mode => 'internal_vertical', afterDigest => sub { my ($stomach, $whatsit) = @_; my ($model, $fspec, $bspec, $text) = $whatsit->getArgs; @@ -119,8 +119,12 @@ DefConstructor('\fcolorbox[]{}{} Undigested', #******************************************************************************** # Low-level stuff; redefined from LaTeX stubs -# Not sure what \current@color should return... the string form? -# \current@color +# \current@color holds the current color specification for the DVI driver. +# For LaTeXML, provide a safe default so packages using it (e.g. pgf/tikz) don't error. +# The value must NOT contain braces since it may appear inside \csname...\endcsname. +DefMacroI('\current@color', undef, '0 0 0'); +DefMacroI('\default@color', undef, '0 0 0'); +DefMacroI('\reset@color', undef, ''); # Similarly, I'm not sure what set@color needs to do that isn't redundant DefMacroI('\set@color', undef, ''); diff --git a/lib/LaTeXML/Package/tcolorbox.sty.ltxml b/lib/LaTeXML/Package/tcolorbox.sty.ltxml index acca67778..b9ca83dda 100644 --- a/lib/LaTeXML/Package/tcolorbox.sty.ltxml +++ b/lib/LaTeXML/Package/tcolorbox.sty.ltxml @@ -20,8 +20,9 @@ DefRegister('\doublecol@number' => Number(0)); # Ensure only unbreakable mode is possible DefMacro('\tcb@init@breakable', '\tcb@init@unbreakable', locked => 1); -RequirePackage('expl3'); -RequirePackage('xparse'); +# Pre-define \tcb@use@autoparskip before loading the raw tcolorbox.sty, +# as a safety net in case the pgfkeys initialization doesn't fully complete. +DefMacroI('\tcb@use@autoparskip', undef, '\relax'); InputDefinitions('tcolorbox', type => 'sty', noltxml => 1);