diff --git a/lib/LaTeXML/Core/Alignment.pm b/lib/LaTeXML/Core/Alignment.pm index 54b05bca18..6b6458bf53 100644 --- a/lib/LaTeXML/Core/Alignment.pm +++ b/lib/LaTeXML/Core/Alignment.pm @@ -204,7 +204,6 @@ sub getColumnAfter { my ($self) = @_; my $column; if (($column = $self->currentColumn) && !$$column{omitted}) { - # Possible \@@eat@space ??? (if LaTeX style???) return Tokens(@{ $$column{after} }, T_CS('\@column@after')); } else { return Tokens(); } } @@ -329,7 +328,23 @@ sub beAbsorbed { # Normalize the border attribute my $border = join(' ', sort(map { split(/ */, $_) } $$cell{border} || '')); $border =~ s/(.) \1/$1$1/g; - my $empty = $$cell{empty} || !$$cell{boxes} || !scalar($$cell{boxes}->unlist); + my @classes = ($$cell{class}); + my $empty = $$cell{empty}; + my ($pre, $post); + # Heuristic: use common td CSS padding, or none, or explicit spacing within cell + # Ideally, we'd compare to a current \(tab|array)colsep + # and create a special CSS class for non-standard values + my $lpad = ($$cell{lspaces} ? $$cell{lspaces}->getWidth->valueOf : 0); + my $rpad = ($$cell{rspaces} ? $$cell{rspaces}->getWidth->valueOf : 0); + if ((!$empty || $$cell{boxes}) && ($lpad < Dimension('0.2em')->valueOf)) { + push(@classes, 'ltx_nopad_l') unless $ismath; } + elsif ($lpad < Dimension('1.5em')->valueOf) { } # do nothing + else { $pre = $$cell{lspaces}; } + if ((!$empty || $$cell{boxes}) && ($rpad < Dimension('0.2em')->valueOf)) { + push(@classes, 'ltx_nopad_r') unless $ismath; } + elsif ($rpad < Dimension('1.5em')->valueOf) { } # do nothing + else { $post = $$cell{rspaces}; } + my $class = join(' ', grep { $_; } @classes); $$cell{cell} = &{ $$self{openColumn} }($document, align => $$cell{align}, width => $$cell{width}, vattach => $$cell{vattach}, @@ -341,11 +356,14 @@ sub beAbsorbed { # Which properties do we expose to the constructor? x => $$cell{x}, y => $$cell{y}, cwidth => $$cell{cwidth}, cheight => $$cell{cheight}, cdepth => $$cell{cdepth}, + class => $class ); - if (!$empty) { + if (!$$cell{skippable}) { local $LaTeXML::BOX = $$cell{boxes}; $document->openElement('ltx:XMArg', rule => 'Anything,') if $ismath; # Hacky! + $document->absorb($pre) if $pre; $document->absorb($$cell{boxes}); + $document->absorb($post) if $post; $document->closeElement('ltx:XMArg') if $ismath; } &{ $$self{closeColumn} }($document); } @@ -406,33 +424,88 @@ sub normalize_cell_sizes { my ($self) = @_; # Examines: boxes, align, vattach # Sets: cwidth, cheight, cdepth (per cell) & empty + my $i = -1; foreach my $row (@{ $$self{rows} }) { + my $j = -1; + $i++; # Do we need to account for any space in the $$row{before} or $$row{after}? foreach my $cell (@{ $$row{columns} }) { + $j++; if (my $boxes = $$cell{boxes}) { my ($w, $h, $d, $cw, $ch, $cd) = $boxes->getSize(align => $$cell{align}, width => $$cell{width}, vattach => $$cell{vattach}); - Debug("CELL (" . join(',', map { $_ . "=" . ToString($$cell{$_}); } qw(align width vattach)) - . ") size " . showSize($w, $h, $d) - . " csize " . showSize($cw, $ch, $cd) - . " Boxes=" . ToString($boxes)) if $LaTeXML::DEBUG{halign} && $LaTeXML::DEBUG{size}; + my $fullw = $cw; + my ($lpad, $rpad, $padh, $padd); + if (my $lspaces = $$cell{lspaces}) { + ($lpad, $padh, $padd) = $lspaces->getSize; + $fullw = ($fullw ? $fullw->add($lpad) : $lpad) if $lpad; + $h = ($h ? $h->larger($padh) : $padh) if $padh; + $d = ($d ? $d->larger($padd) : $padd) if $padd; } + if (my $rspaces = $$cell{rspaces}) { + ($rpad, $padh, $padd) = $rspaces->getSize; + $fullw = ($fullw ? $fullw->add($rpad) : $rpad) if $rpad; + $h = ($h ? $h->larger($padh) : $padh) if $padh; + $d = ($d ? $d->larger($padd) : $padd) if $padd; } + my @boxes = $boxes->unlist; + my $isrule = scalar(@boxes) + && !(grep { !($_->getProperty('isHorizontalRule') || $_->getProperty('isVerticalRule') + || $_->getProperty('alignmentSkippable') + || (ref $_ eq 'LaTeXML::Core::Comment') + ); } @boxes); my $empty = - (((!$cw) || $cw->valueOf < 1) + (((!$fullw) || $fullw->valueOf < 1) && (((!$ch) || $ch->valueOf < 1) && ((!$cd) || $cd->valueOf < 1)) - || !(grep { !($_->getProperty('isSpace') || $_->getProperty('isHorizontalRule') || $_->getProperty('isVerticalRule')); } $boxes->unlist) + || $isrule ) && !preservedBoxes($boxes); - $$cell{cwidth} = $w || Dimension(0); - $$cell{cheight} = $h || Dimension(0); - $$cell{cdepth} = $d || Dimension(0); - $$cell{empty} = $empty; - $$cell{align} = undef if $empty; } + $$cell{cwidth} = $w || Dimension(0); + $$cell{cheight} = $h || Dimension(0); + $$cell{cdepth} = $d || Dimension(0); + $$cell{lpadding} = $lpad; + $$cell{rpadding} = $rpad; + $$cell{empty} = $empty; + $$cell{skippable} = $empty || isSkippable($boxes); + $$cell{align} = undef if $$cell{skippable}; + Debug("CELL[$i,$j] size=" . showSize($w, $h, $d) . " csize " . showSize($cw, $ch, $cd) + . ";\n " . join(',', map { $_ . "=" . ToString($$cell{$_}); } sort keys %$cell) + . "\n Boxes=" . Stringify($boxes) + ) if $LaTeXML::DEBUG{alignment_normalize}; + } else { - $$cell{empty} = 1; } + $$cell{empty} = 1; + $$cell{skippable} = 1; } } } return; } +# Check whether all these things are "empty" or only spaces or otherwise skippable in a table cell +# Very similar to IsEmpty, but also recognizes spaces or alignmentSkippable items +sub isSkippable { + my (@things) = @_; + foreach my $thing (@things) { + my $ref = ref $thing; + if (!$thing) { } + elsif ($ref eq 'LaTeXML::Core::Comment') { } + elsif ($ref eq 'LaTeXML::Core::Tokens') { + return 0 unless isSkippable($thing->unlist); } + elsif ($ref eq 'LaTeXML::Core::Token') { + my $cc = $$thing[1]; + return 0 if ($cc == CC_LETTER) || ($cc == CC_OTHER) || ($cc == CC_ACTIVE) || ($cc == CC_CS); } + elsif ((!$thing->getProperty('isEmpty')) + && (!$thing->getProperty('isSpace')) + && (!$thing->getProperty('alignmentSkippable'))) { + if ($ref eq 'LaTeXML::Core::Box') { + my $s = $thing->getString; + return 0 if (defined $s) && ($s !~ /^\s*$/); } + elsif ($ref eq 'LaTeXML::Core::List') { + return 0 unless isSkippable($thing->unlist); } + elsif ($ref eq 'LaTeXML::Core::Whatsit') { + if (my $body = $thing->getProperty('content_box')) { + return 0 unless isSkippable($body); } + else { + return 0; } } } } + return 1; } + sub showSize { my ($w, $h, $d) = @_; return '[' . ToString($w) . ' x ' . ToString($h) . ' + ' . ToString($d) . ']'; } @@ -535,7 +608,7 @@ sub normalize_sum_sizes { elsif ($a eq 'right') { $colx = $colx->add($dx); } } $$cell{x} = $colx; $$cell{y} = $rowpos[$i]; - Debug("CELL[$j,$i] " . showSize($$cell{cwidth}, $$cell{cheight}, $$cell{cdepth}) + Debug("CELL[$i,$j] " . showSize($$cell{cwidth}, $$cell{cheight}, $$cell{cdepth}) . " @ " . ToString($$cell{x}) . "," . ToString($$cell{y}) . " w/ " . join(',', map { $_ . '=' . ToString($$cell{$_}); } (qw(align vattach skipped colspan rowspan)))) @@ -580,7 +653,7 @@ sub normalize_mark_spans { if ($rrow) { for (my $jj = $j ; $jj < $j + $ncspan ; $jj++) { if (my $ccol = $$rrow{columns}[$jj]) { - if (!$$ccol{empty}) { + if (!$$ccol{skippable}) { $rowempty = 0; } } } } if (!$nrc) { } elsif (!$rrow || !$rowempty) { @@ -618,12 +691,26 @@ sub normalize_prune_rows { my @rows = @{ $$self{rows} }; my @filtered = (); for (my $i = 0 ; $i < scalar(@rows) ; $i++) { - my $row = $rows[$i]; - if (grep { !$$_{empty} } @{ $$row{columns} }) { # Not empty! so keep it + my $row = $rows[$i]; + my $next = $rows[$i + 1]; + # prunable if all cells are empty + # OR are only spacing NOT made visible by requiring both top & bottom borders + my $prunable = 1; + my $check_bracketting; + foreach my $c (@{ $$row{columns} }) { # Check if all cells are either empty or space only + $check_bracketting = 1 if $$c{skippable} && !$$c{empty}; + $prunable = 0 unless $$c{skippable}; } + if ($prunable && $check_bracketting # If spaces, make sure not bracketted by borders + && scalar(grep { ($$_{border} || '') =~ /t/i } @{ $$row{columns} })) { + if ($next) { + $prunable = 0 if scalar(grep { ($$_{border} || '') =~ /t/i } @{ $$next{columns} }); } + else { + $prunable = 0 if scalar(grep { ($$_{border} || '') =~ /b/i } @{ $$row{columns} }); } } + if (!$prunable) { push(@filtered, $row); } - elsif (my $next = $rows[$i + 1]) { # Remove empty row, but copy top border to NEXT row + elsif ($next) { # Remove empty row, but copy top border to NEXT row if ($preserve) { - push(@filtered, $row); next; } # don't remove inner rows from math EXCEPT last row!! + push(@filtered, $row); next; } # don't remove inner rows from math EXCEPT last row!! my $nc = scalar(@{ $$row{columns} }); my ($pruneh, $pruned) = (0, 0); for (my $j = 0 ; $j < $nc ; $j++) { @@ -638,7 +725,9 @@ sub normalize_prune_rows { $border =~ s/B/T/g; # but convert to top $$next{columns}[$j]{border} .= $border; } # add to NEXT row # This tpadding should be combined w/any extra rowspacing from \\[dim] ! - $$next{tpadding} = Dimension($pruneh + $pruned) if $pruneh + $pruned; } # And save padding. + $$next{tpadding} = Dimension($pruneh + $pruned) if $pruneh + $pruned; # And save padding. + Debug("PRUNE ROW $i") if $LaTeXML::DEBUG{alignment_normalize}; + } else { # Remove empty last row, but copy top border to bottom of prev. my $prev = $filtered[-1]; my $nc = scalar(@{ $$row{columns} }); @@ -657,7 +746,8 @@ sub normalize_prune_rows { if (defined $$ccol{rowspanned}) { # skip to spanning column if rowspanned! $ccol = $rows[$$ccol{rowspanned}]{columns}[$j]; } $$ccol{border} .= $border; } # add to PREVIOUS row. - $$prev{bpadding} = Dimension($pruneh + $pruned) if $pruneh + $pruned; } # And save padding. + $$prev{bpadding} = Dimension($pruneh + $pruned) if $pruneh + $pruned; # And save padding. + Debug("PRUNE ROW (last) $i") if $LaTeXML::DEBUG{alignment_normalize}; } } @rows = @filtered; $$self{rows} = [@filtered]; @@ -686,10 +776,13 @@ sub normalize_prune_columns { my $prev = $$row{columns}[$j - 1]; if (my $jj = $$prev{colspanned}) { $prev = $$row{columns}[$jj]; } - $border =~ s/[^rRlL]//g; # mask all but left border - $border =~ s/l/r/g; # convert to right - $border =~ s/L/R/g; # convert to right + $border =~ s/[^rRlL]//g; # mask all but left border + $border =~ s/l/r/g; # convert to right + $border =~ s/L/R/g; # convert to right $$prev{border} .= $border; + # Copy left spacing to right column, as well + $$prev{rspaces} = LaTeXML::Core::List::List($$prev{rspaces} || (), $$col{lspaces} || ()) if $$col{lspaces}; + $$prev{rpadding} = $$prev{rspaces}->getWidth if $$prev{rspaces}; if (my @preserve = preservedBoxes($$col{boxes})) { # Copy boxes over, in case side effects? $$prev{boxes} = LaTeXML::Core::List($$prev{boxes} ? ($$prev{boxes}->unlist, @preserve) : @preserve); } @@ -705,14 +798,16 @@ sub normalize_prune_columns { } # Now, remove the column $$row{columns} = [grep { $_ ne $col } @{ $$row{columns} }]; } } + $prunew = Dimension($prunew); if ($j) { # If not 1st row, add right padding to previous column foreach my $row (@rows) { if (my $col = $$row{columns}[$j - 1]) { - $$col{rpadding} = Dimension($prunew); } } } + $$col{rpadding} = ($$col{rpadding} ? $$col{rpadding}->add($prunew) : $prunew); } } } else { # Else add left padding to (newly) first column foreach my $row (@rows) { # And add the padding to previous column if (my $col = $$row{columns}[0]) { - $$col{lpadding} = Dimension($prunew); } } } + $$col{lpadding} = ($$col{lpadding} ? $$col{lpadding}->add($prunew) : $prunew); } } } + Debug("PRUNE COLUMN $j") if $LaTeXML::DEBUG{alignment_normalize}; } } } return; } @@ -769,6 +864,7 @@ sub ReadAlignmentTemplate { last unless $nopens; } push(@tokens, T_END); $LaTeXML::BUILD_TEMPLATE->setReversion(@tokens); + $LaTeXML::BUILD_TEMPLATE->finish; return $LaTeXML::BUILD_TEMPLATE; } sub parseAlignmentTemplate { diff --git a/lib/LaTeXML/Core/Alignment/Template.pm b/lib/LaTeXML/Core/Alignment/Template.pm index a828b29caf..16cd7d8895 100644 --- a/lib/LaTeXML/Core/Alignment/Template.pm +++ b/lib/LaTeXML/Core/Alignment/Template.pm @@ -53,11 +53,11 @@ sub addBeforeColumn { unshift(@{ $$self{save_before} }, @tokens); # NOTE: goes all the way to front! return; } -# NOTE: \@@eat@space should ONLY be added to LaTeX tabular style templates!!!! +# NOTE: \lx@column@trimright should ONLY be added to LaTeX tabular style templates!!!! # NOT \halign style templates! sub addAfterColumn { my ($self, @tokens) = @_; - $$self{current_column}{after} = Tokens(T_CS('\@@eat@space'), + $$self{current_column}{after} = Tokens(T_CS('\lx@column@trimright'), @tokens, @{ $$self{current_column}{after} }); return; } @@ -65,25 +65,38 @@ sub addAfterColumn { sub addBetweenColumn { my ($self, @tokens) = @_; my @cols = @{ $$self{columns} }; - if ($$self{current_column}) { + if (my $col = $$self{current_column}) { + if (!$$self{disabled_intercolumn}) { + unshift(@tokens, T_CS('\lx@intercol')); } $$self{current_column}{after} = Tokens(@{ $$self{current_column}{after} }, @tokens); } else { push(@{ $$self{save_between} }, @tokens); } return; } +sub disableIntercolumn { + my ($self) = @_; + if (my $col = $$self{current_column}) { + $$self{disabled_intercolumn} = 1; } + return; } + sub addColumn { my ($self, %properties) = @_; - my $col = {%properties}; + my $col = {%properties}; + if (my $prev = $$self{current_column}) { + $$prev{after} = Tokens(($$prev{after} || ()), T_CS('\lx@intercol')) + unless $$self{disabled_intercolumn}; } my @before = (); - push(@before, @{ $$self{save_between} }) if $$self{save_between}; + push(@before, @{ $$self{save_between} }) if $$self{save_between}; + push(@before, T_CS('\lx@intercol')) unless $$self{disabled_intercolumn}; + delete $$self{disabled_intercolumn}; + push(@before, $properties{before}->unlist) if $properties{before}; push(@before, @{ $$self{save_before} }) if $$self{save_before}; $$col{before} = Tokens(@before); my @after = (); - push(@after, T_CS('\@@eat@space')); + push(@after, T_CS('\lx@column@trimright')); push(@after, $properties{after}->unlist) if $properties{after}; - $$col{after} = Tokens(@after); -### $$col{after} = Tokens() unless $properties{after}; + $$col{after} = Tokens(@after); $$col{thead} = $properties{thead}; $$col{empty} = 1; $$self{save_between} = []; @@ -97,6 +110,13 @@ sub addColumn { push(@{ $$self{columns} }, $col); } return; } +sub finish { + my ($self) = @_; + if (my $prev = $$self{current_column}) { + $$prev{after} = Tokens(($$prev{after} || ()), T_CS('\lx@intercol')) + unless $$self{disabled_intercolumn}; } + return; } + # Methods for using a template. sub clone { my ($self) = @_; @@ -104,7 +124,7 @@ sub clone { foreach my $cell (@{ $$self{columns} }) { push(@dup, {%$cell}); } return bless { columns => [@dup], - repeated => $$self{repeated}, non_repeating => $$self{non_repeating}, + repeated => $$self{repeated}, non_repeating => $$self{non_repeating}, repeating => $$self{repeating} }, ref $self; } sub show { diff --git a/lib/LaTeXML/Package.pm b/lib/LaTeXML/Package.pm index 8d36279b09..d7a00a5f1d 100644 --- a/lib/LaTeXML/Package.pm +++ b/lib/LaTeXML/Package.pm @@ -974,9 +974,8 @@ sub TokenizeInternal { local $STATE = $STY_CATTABLE; return LaTeXML::Core::Mouth->new($string)->readTokens; } -# Check whether all these things are "empty" (spaces are empty!!) +# Check whether all these things are "empty" (spaces are NOT empty!!) # short-circuit: return 0 quickly if anything is NOT empty. -# Will we need to distinguish between "empty" and "not visible"?? sub IsEmpty { my (@things) = @_; foreach my $thing (@things) { @@ -988,16 +987,18 @@ sub IsEmpty { elsif ($ref eq 'LaTeXML::Core::Token') { my $cc = $$thing[1]; return 0 if ($cc == CC_LETTER) || ($cc == CC_OTHER) || ($cc == CC_ACTIVE) || ($cc == CC_CS); } - elsif ((!$thing->getProperty('isEmpty')) - && (!$thing->getProperty('isSpace'))) { # A space-like thing + elsif (!$thing->getProperty('isEmpty')) { if ($ref eq 'LaTeXML::Core::Box') { my $s = $thing->getString; - return 0 if (defined $s) && ($s !~ /^\s*$/); } + return 0 if (defined $s) && length($s); } elsif ($ref eq 'LaTeXML::Core::List') { return 0 unless IsEmpty($thing->unlist); } elsif ($ref eq 'LaTeXML::Core::Whatsit') { - return 0 unless ($thing->getDefinition eq $STATE->lookupDefinition(T_BEGIN)) - && IsEmpty($thing->getBody->unlist); } } } + # Sneaky Whatsit property for something (an arg) that stands-in for the whatsit's content. + if (my $body = $thing->getProperty('content_box')) { + return 0 unless IsEmpty($body); } + else { + return 0; } } } } return 1; } #====================================================================== diff --git a/lib/LaTeXML/Package/LaTeX.pool.ltxml b/lib/LaTeXML/Package/LaTeX.pool.ltxml index 5b21235ab8..94438288a8 100644 --- a/lib/LaTeXML/Package/LaTeX.pool.ltxml +++ b/lib/LaTeXML/Package/LaTeX.pool.ltxml @@ -2422,6 +2422,7 @@ sub eqnarrayBindings { properties => { preserve_structure => 1, attributes => {%attributes} })); Let("\\\\", '\@alignment@newline'); + Let('\lx@intercol', '\lx@math@intercol'); Let('\@row@before', '\eqnarray@row@before'); Let('\@row@after', '\eqnarray@row@after'); Let('\lx@eqnarray@save@label', '\label'); @@ -3647,11 +3648,14 @@ DefMacroI('\@tabbing@nexttab', undef, '\@tabbing@nexttab@marker&'); DefMacro('\@tabbing@newline OptionalMatch:* [Dimension]', '\@tabbing@newline@marker\cr'); DefMacroI('\@tabbing@kill', undef, '\@tabbing@kill@marker\cr\@tabbing@start@tabs'); -DefConstructorI('\@tabbing@tabset@marker', undef, '', reversion => '\='); -DefConstructorI('\@tabbing@nexttab@marker', undef, '', reversion => '\>'); +DefConstructorI('\@tabbing@tabset@marker', undef, '', reversion => '\=', + properties => { alignmentSkippable => 1 }); +DefConstructorI('\@tabbing@nexttab@marker', undef, '', reversion => '\>', + properties => { alignmentSkippable => 1 }); DefConstructorI('\@tabbing@newline@marker', undef, '', reversion => Tokens(T_CS("\\\\"), T_CR)); DefConstructorI('\@tabbing@kill@marker', undef, '', reversion => '\kill', - afterDigest => sub { LookupValue('Alignment')->removeRow; return; }); + afterDigest => sub { LookupValue('Alignment')->removeRow; return; }, + properties => { alignmentSkippable => 1 }); AssignValue(tabbing_start_tabs => Tokens()); DefMacroI('\@tabbing@start@tabs', undef, sub { LookupValue('tabbing_start_tabs')->unlist; }); @@ -3681,7 +3685,8 @@ DefMacro('\@tabbing@accent{}', sub { T_CS('\@tabbing@' . ToString($_[1])); }); sub tabbingBindings { AssignValue(Alignment => LaTeXML::Core::Alignment->new( template => LaTeXML::Core::Alignment::Template->new( - repeated => [{ after => Tokens(T_CS('\hfil')) }]), + repeated => [{ before => Tokens(T_CS('\lx@text@intercol')), + after => Tokens(T_CS('\hfil'), T_CS('\lx@text@intercol')) }]), openContainer => sub { $_[0]->openElement('ltx:tabular', @_[1 .. $#_]); }, closeContainer => sub { $_[0]->closeElement('ltx:tabular'); }, openRow => sub { $_[0]->openElement('ltx:tr', @_[1 .. $#_]); }, @@ -3757,6 +3762,7 @@ sub tabularBindings { $properties{strut} = LookupRegister('\baselineskip')->multiply(1.5); } # Account for html space alignmentBindings($template, 'text', %properties); Let("\\\\", '\@tabularcr'); + Let('\lx@intercol', '\lx@text@intercol'); Let('\tabularnewline', "\\\\"); # NOTE: Fit this back in!!!!!!! # # Do like AddToMacro, but NOT global! @@ -3873,7 +3879,8 @@ DefPrimitive('\@array@bindings [] AlignmentTemplate', sub { $$attr{rowsep} = Dimension(($str - 1) . 'em'); } alignmentBindings($template, 'math', attributes => $attr); MergeFont(mathstyle => 'text'); - Let("\\\\", '\@alignment@newline'); + Let("\\\\", '\@alignment@newline'); + Let('\lx@intercol', '\lx@math@intercol'); return; }); DefMacro('\array[]{}', diff --git a/lib/LaTeXML/Package/TeX.pool.ltxml b/lib/LaTeXML/Package/TeX.pool.ltxml index c0fbe5a98e..218a86e87b 100644 --- a/lib/LaTeXML/Package/TeX.pool.ltxml +++ b/lib/LaTeXML/Package/TeX.pool.ltxml @@ -2017,9 +2017,9 @@ DefParameterType('BoxSpecification', sub { reversion => sub { my ($spec) = @_; if (my $to = $spec && $spec->getValue('to')) { - return Tokens(Tokenize('to'), T_SPACE, Revert($to)); } + return Tokens(Tokenize('to'), Revert($to)); } elsif (my $spread = $spec && $spec->getValue('spread')) { - return Tokens(Tokenize('spread'), T_SPACE, Revert($spread)); } + return Tokens(Tokenize('spread'), Revert($spread)); } else { return; } }, optional => 1, undigested => 1); @@ -2202,6 +2202,7 @@ DefConstructor('\hbox BoxSpecification HBoxContents', sub { $whatsit->setWidth($w); } elsif (my $s = GetKeyVal($spec, 'spread')) { $whatsit->setWidth($box->getWidth->add($s)); } + $whatsit->setProperty(content_box => $box); return; }); # Cleanup foreignObjects: remove empty (or only

); and determine size @@ -2345,6 +2346,7 @@ DefConstructor('\vbox BoxSpecification VBoxContents', sub { $whatsit->setHeight($h); } elsif (my $s = GetKeyVal($spec, 'spread')) { $whatsit->setHeight($box->getHeight->add($s)); } + $whatsit->setProperty(content_box => $box); return; }); DefConstructor('\vtop BoxSpecification VBoxContents', sub { @@ -2361,6 +2363,7 @@ DefConstructor('\vtop BoxSpecification VBoxContents', sub { $whatsit->setHeight($h); } elsif (my $s = GetKeyVal($spec, 'spread')) { $whatsit->setHeight($box->getHeight->add($s)); } + $whatsit->setProperty(content_box => $box); return; }); DefParameterType('RuleSpecification', sub { @@ -2450,7 +2453,7 @@ DefConstructor('\hrule RuleSpecification', DefPrimitive('{', sub { my ($stomach) = @_; $stomach->bgroup; - my $open = Box(undef, undef, undef, T_BEGIN, isEmpty => 1); + my $open = Box(undef, undef, undef, T_BEGIN, isEmpty => 1, alignmentSkippable => 1); my $ismath = $STATE->lookupValue('IN_MATH'); my @body = $stomach->digestNextBody(); List($open, @body, mode => ($ismath ? 'math' : 'text')); }); @@ -2458,7 +2461,7 @@ DefPrimitive('{', sub { DefPrimitive('}', sub { my $f = LookupValue('font'); $_[0]->egroup; - Box(undef, $f, undef, T_END, isEmpty => 1); }); + Box(undef, $f, undef, T_END, isEmpty => 1, alignmentSkippable => 1); }); # These are for those screwy cases where you need to create a group like box, # more than just bgroup, egroup, @@ -2831,7 +2834,10 @@ DefColumnType('*{Number}{}', sub { DefColumnType('@{}', sub { my ($gullet, $filler) = @_; - $LaTeXML::BUILD_TEMPLATE->addBetweenColumn($filler->unlist); return; }); + $LaTeXML::BUILD_TEMPLATE->disableIntercolumn; + $LaTeXML::BUILD_TEMPLATE->addBetweenColumn($filler->unlist); + $LaTeXML::BUILD_TEMPLATE->disableIntercolumn; + return; }); #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Alignment code @@ -2965,6 +2971,29 @@ DefConstructor('\@alignment@newline@markertall {Dimension}', '', DefMacroI('\tabularnewline', undef, '\cr'); # ??? +# \lx@intercol is our replacement for LaTeX's \@acol which places intercolumn space in tabular +# (but NOT used by TeX's \halign!) +DefMacro('\lx@intercol', ''); +# Candidates for binding \lx@intercol for LaTeX tabular or math arrays +# These provide "padding" of half tabcolsep, since added before & after columns +# [these could be \hskip\tabcolsep, but the expansion confounds trimColumnSpec] +DefConstructor('\lx@text@intercol', sub { + my ($document, %props) = @_; + $document->absorb(DimensionToSpaces($props{width})); }, + reversion => '\lx@intercol', + properties => sub { + my $defn; + my $w = (($defn = $STATE->lookupDefinition(T_CS('\tabcolsep'))) && $defn->isRegister + ? $defn->valueOf : Dimension(0)); + (width => $w, isSpace => 1); }); +DefConstructor('\lx@math@intercol', "", # mspace ??? + reversion => '\lx@intercol', + properties => sub { + my $defn; + my $w = (($defn = $STATE->lookupDefinition(T_CS('\arraycolsep'))) && $defn->isRegister + ? $defn->valueOf : Dimension(0)); + (width => $w, isSpace => 1); }); + #====================================================================== # Various decorations within alignments, rules, headers, etc @@ -3093,25 +3122,29 @@ sub translateAttachment { $pos = ($pos ? ToString($pos) : ''); return ($pos eq 't' ? 'top' : ($pos eq 'b' ? 'bottom' : 'middle')); } # undef meaning 'baseline' -# This removes trailing whitespace from the current digested list. -# It is useful as the 1st thing in the rhs template of things like {tabular}. +# This trims trailing whitespace from the current digested list, +# for use within latex tabular-style columns. # But note that \halign does NOT remove this trailing space! -DefPrimitiveI('\@@eat@space', undef, sub { +DefPrimitiveI('\lx@column@trimright', undef, sub { my $box; my @save = (); + my $s; while ($box = $LaTeXML::LIST[-1]) { if ($box->getProperty('alignmentSkippable') - || $box->getProperty('isFill')) { + || $box->getProperty('isFill') + || IsEmpty($box)) { push(@save, pop(@LaTeXML::LIST)); } - elsif (IsEmpty($box)) { - pop(@LaTeXML::LIST); } + elsif (ref $box eq 'LaTeXML::Core::List') { # Unwrap and continue + pop(@LaTeXML::LIST); + push(@LaTeXML::LIST, $box->unlist); } + elsif ((ref $box eq 'LaTeXML::Core::Box') + && defined($s = $box->getString) && ($s =~ /^\s*$/)) { + pop(@LaTeXML::LIST); } # remove any box containing only spaces else { last; } } push(@LaTeXML::LIST, @save); return; }); -#DefMacroI('\@@eat@space',undef,undef); - use constant T_hfil => T_CS('\hfil'); # Yet more special case hacking. Sometimes the order of tokens works for # TeX, but confuses us... In particular the order of $ and \hfil! @@ -3180,22 +3213,22 @@ sub parseHAlignTemplate { my ($gullet, $whatsit) = @_; my $t = $gullet->readNonSpace; Error('expected', '\bgroup', $gullet, "Missing \\halign box") unless $t->defined_as(T_BEGIN); - my $before = 1; # true if we're before a # in current column - my @pre = (); - my @post = (); - my @cols = (); - my $repeated = 0; - my @nonreps = (); - my $tabskip; # Need to use this somehow! - my @tokens = (); + my $before = 1; # true if we're before a # in current column + my @pre = (); + my @post = (); + my @cols = (); + my $repeated = 0; + my @nonreps = (); + my $tabskip = LookupRegister('\tabskip'); + my $nexttabskip = $tabskip; + my @tokens = (); ## Only expand certain things; See TeX book p.238 local $LaTeXML::ALIGN_STATE = 1000000; while ($t = $gullet->readToken) { my $cc = $t->getCatcode; if ($t->equals(T_CS('\tabskip'))) { # Read the tabskip assignment $gullet->readKeyword('='); - $tabskip = $gullet->readGlue; - push(@tokens, $t, $tabskip); } + $nexttabskip = $gullet->readGlue; } elsif ($t->equals(T_CS('\span'))) { # ex-span-ded next token. $gullet->unread($gullet->readXToken(0)); } elsif ($cc == CC_PARAM) { # Found the template's column slot @@ -3209,9 +3242,11 @@ sub parseHAlignTemplate { else { # Finished column spec; add it ## How should we be handling tabskip? An attribute on the cell or spacing? push(@cols, { - before => Tokens(beforeCellUnlist(Tokens(@pre))), - after => Tokens(afterCellUnlist(Tokens(@post))) }); - @pre = @post = (); $before = 1; } + tabskip => $tabskip, + before => Tokens(beforeCellUnlist(Tokens(@pre))), + after => Tokens(afterCellUnlist(Tokens(@post))) }); + $tabskip = $nexttabskip; + @pre = @post = (); $before = 1; } last unless $cc == CC_ALIGN; push(@tokens, $t); } elsif ($before) { # Other random tokens go into the column's pre-template @@ -3461,6 +3496,9 @@ sub extractAlignmentColumn { my @boxes = $boxes->unlist; my @saveleft = (); my @saveright = (); + my (@lspaces, @rspaces); + if (my $skip = $$colspec{tabskip}) { + push(@lspaces, Digest(Tokens(T_CS('\hskip'), $skip->revert, T_CS('\relax')))); } while (@boxes) { if (ref $boxes[0] eq 'LaTeXML::Core::List') { unshift(@boxes, shift(@boxes)->unlist); } @@ -3470,12 +3508,15 @@ sub extractAlignmentColumn { last; } elsif ($boxes[0]->getProperty('isVerticalRule')) { $border .= 'l'; + if (my $prev = $alignment->getColumn($n0 - 1)) { # space before | ? move to previous column + $$prev{rspaces} = List(($$prev{rspaces} || ()), @lspaces) if @lspaces; } + @lspaces = (); # then discard shift(@boxes); } + elsif ($boxes[0]->getProperty('isSpace')) { + push(@lspaces, shift(@boxes)); } elsif ($boxes[0]->getProperty('isHorizontalRule') || $boxes[0]->getProperty('alignmentSkippable') - || (ref $boxes[0] eq 'LaTeXML::Core::Comment') - || $boxes[0]->getProperty('isSpace') - || IsEmpty($boxes[0])) { + || (ref $boxes[0] eq 'LaTeXML::Core::Comment')) { push(@saveleft, shift(@boxes)); } else { last; } } @@ -3488,12 +3529,13 @@ sub extractAlignmentColumn { last; } elsif ($boxes[-1]->getProperty('isVerticalRule')) { $border .= 'r'; + @rspaces = (); # discard spacing after rule!!! (should save for next column?) pop(@boxes); } + elsif ($boxes[-1]->getProperty('isSpace')) { + unshift(@rspaces, pop(@boxes)); } elsif ($boxes[-1]->getProperty('isHorizontalRule') || $boxes[-1]->getProperty('alignmentSkippable') - || (ref $boxes[-1] eq 'LaTeXML::Core::Comment') - || $boxes[-1]->getProperty('isSpace') - || IsEmpty($boxes[-1])) { + || (ref $boxes[-1] eq 'LaTeXML::Core::Comment')) { unshift(@saveright, pop(@boxes)); } else { last; } } @@ -3505,7 +3547,10 @@ sub extractAlignmentColumn { $$colspec{align} = $align; $$colspec{border} = $border = ($$colspec{border} || '') . $border; $$colspec{boxes} = $boxes; + $$colspec{lspaces} = List(@lspaces) if @lspaces; + $$colspec{rspaces} = List(@rspaces) if @rspaces; $$colspec{colspan} = $n1 - $n0 + 1; + if ($$alignment{in_tabular_head} || $$alignment{in_tabular_foot}) { $$colspec{thead}{column} = 1; } for (my $i = $n0 + 1 ; $i <= $n1 ; $i++) { @@ -4360,6 +4405,7 @@ sub scriptHandler { # Parsing is too late! while (my $prev = pop(@LaTeXML::LIST)) { if (($prev->getProperty('isSpace')) + || ($prev->getProperty('isEmpty')) # EXPLICITLY empty, rather than {} || (ref $prev eq 'LaTeXML::Core::Comment')) { $prevspace = 1; # a space avoids double-scripts unshift(@putback, $prev); # put back? assuming it will add rpadding to previous??? @@ -6014,14 +6060,14 @@ DefMathI('\biguplus', undef, "\x{2A04}", # versus \x{228e} mathstyle => \&doVariablesizeOp); DefConstructorI('\limits', undef, '', afterDigest => sub { mergeLimits('mid'); }, - properties => { isSpace => 1 }); + properties => { isEmpty => 1 }); DefConstructorI('\nolimits', undef, '', afterDigest => sub { mergeLimits('post'); }, - properties => { isSpace => 1 }); + properties => { isEmpty => 1 }); DefConstructorI('\displaylimits', undef, '', afterDigest => sub { mergeLimits((($_[1]->getProperty('mathstyle') || '') eq 'display' ? 'mid' : 'post')); }, - properties => { isSpace => 1 }); + properties => { isEmpty => 1 }); sub mergeLimits { my ($pos) = @_; @@ -6765,6 +6811,7 @@ DefPrimitive('\lx@gen@matrix@bindings RequiredKeyVals:lx@GEN', sub { 'math', (keys %attributes ? (attributes => {%attributes}) : ())); # }); Let("\\\\", '\@alignment@newline'); + Let('\lx@intercol', '\lx@math@intercol'); Let('\@row@before', '\@empty'); # Disable special row treatment (eg. numbering) unless requested Let('\@row@after', '\@empty'); }); @@ -6889,11 +6936,12 @@ DefPrimitive('\lx@gen@cases@bindings RequiredKeyVals:lx@GEN', sub { { before => Tokens($style), after => Tokens(T_CS('\hfil')) }, { before => Tokens($style, ($condtext ? (T_CS('\lx@cases@condition')) : ())), - after => Tokens(T_CS('\@@eat@space'), + after => Tokens(T_CS('\lx@column@trimright'), ($condtext ? (T_CS('\lx@cases@end@condition')) : ()), T_CS('\hfil')) }]), 'math'); - Let("\\\\", '\@alignment@newline'); + Let("\\\\", '\@alignment@newline'); + Let('\lx@intercol', '\lx@math@intercol'); DefMacro('\@row@before', ''); # Don't inherit counter stepping from containing environments DefMacro('\@row@after', ''); }); diff --git a/lib/LaTeXML/Package/siunitx.sty.ltxml b/lib/LaTeXML/Package/siunitx.sty.ltxml index 1891f62cf2..e239690cf6 100644 --- a/lib/LaTeXML/Package/siunitx.sty.ltxml +++ b/lib/LaTeXML/Package/siunitx.sty.ltxml @@ -1466,7 +1466,7 @@ DefMacro('\lx@si@column@parse XUntil:\lx@si@column@end', sub { push(@pre, T_BEGIN, $p, T_END); } else { last; } } - pop(@tokens) if @tokens && Equals($tokens[-1], T_CS('\@@eat@space')); + pop(@tokens) if @tokens && Equals($tokens[-1], T_CS('\lx@column@trimright')); if (my $defns = six_convertUnits(Tokens(@tokens))) { $result = six_format_units(six_parse_units($defns)); } else { diff --git a/lib/LaTeXML/resources/CSS/LaTeXML.css b/lib/LaTeXML/resources/CSS/LaTeXML.css index 96e72f8b08..32dd24474e 100644 --- a/lib/LaTeXML/resources/CSS/LaTeXML.css +++ b/lib/LaTeXML/resources/CSS/LaTeXML.css @@ -358,6 +358,21 @@ span.ltx_rowspan { position:absolute; top:0; bottom:0; } .ltx_tabular .ltx_td, .ltx_tabular .ltx_th { padding:0.1em 0.5em; } +.ltx_tabular .ltx_td.ltx_nopad_l, +.ltx_tabular .ltx_th.ltx_nopad_l { padding-left:0; } +.ltx_tabular .ltx_td.ltx_nopad_r, +.ltx_tabular .ltx_th.ltx_nopad_r { padding-right:0; } + +/* min-height does NOT apply to tr! */ +.ltx_tabular .ltx_tr td:first-child::after, +.ltx_tabular .ltx_tr th:first-child::after { + content: ""; + display: inline-block; + vertical-align: top; + min-height: 1em; +} + + /* regular lines */ .ltx_border_t { border-top:1px solid black; } .ltx_border_r { border-right:1px solid black; } diff --git a/t/alignment/array.xml b/t/alignment/array.xml index 30fa034c84..3f915b98b8 100644 --- a/t/alignment/array.xml +++ b/t/alignment/array.xml @@ -46,11 +46,11 @@ - a – + a   – b - c – + c   – d diff --git a/t/alignment/cells.xml b/t/alignment/cells.xml index 8e4b4b06b8..6b581a685c 100644 --- a/t/alignment/cells.xml +++ b/t/alignment/cells.xml @@ -25,32 +25,32 @@ - Multilined + Multilined - cell text + cell text - + 28–31 - Left aligned + Left aligned - cell text + cell text - + 37–43 - Right aligned + Right aligned - cell text + cell text 37–43 @@ -58,18 +58,18 @@ - Bottom aligned + Bottom aligned - cell text + cell text - + 52–58 -

Cell long text with predefined width

+

Cell long text with predefined width

52–58 @@ -77,7 +77,7 @@ -

Cell long…

+

Cell long…

52–58 @@ -98,20 +98,20 @@ - First column head + First column head - + - Second + Second - multlined + multlined - column head + column head - + @@ -136,23 +136,23 @@ - First column head + First column head - + - +

-

Second multilined

+

Second multilined

-

column head

+

column head

- + @@ -209,64 +209,64 @@ - First … + First … - + - Multicolumn head + Multicolumn head - + - Second … + Second … - + - Third … + Third … - + Cell text A - 28–31 + 28–31 - + - Multilined + Multilined - Cell text + Cell text - + B - Left … + Left … - + C - 37–43 + 37–43 - + - Right … + Right … D @@ -274,23 +274,23 @@ - Bottom … + Bottom … - + E - 37–43 + 37–43 - 52–58 + 52–58 -

Cell …

+

Cell …

F @@ -298,7 +298,7 @@ -

Cell …

+

Cell …

G @@ -317,12 +317,20 @@ - 1 - 2 - 3 - 4 - 5 - 6 + + + + + + + + + 1 + 2 + 3 + 4 + 5 + 6 @@ -383,20 +391,20 @@ - Second + Second - column + column - + - Third + Third - column + column - + diff --git a/t/alignment/halign.xml b/t/alignment/halign.xml index 4a1e313a0f..5857ba1392 100644 --- a/t/alignment/halign.xml +++ b/t/alignment/halign.xml @@ -14,18 +14,18 @@ - [a] - (b) - {c} + [a] + (b) + {c} - [a] - (b) - {c} + [a] + (b) + {c} @@ -39,9 +39,9 @@ - [a] - (b) - {c} + [a] + (b) + {c} @@ -56,29 +56,29 @@ - [a] - (b) - {c} + [a] + (b) +       {c} - [a] - (b) - {c} - [d] + [a] + (b) +                               {c} +                               [d] - [a] - (b) - {c} - [d] + [a] + (b) +                               {c} +                               [d] @@ -93,60 +93,60 @@ - [a] - (b) - {c} + [a] + (b) + {c} - [a] - (b) - {c} - {a} - {b} - {c} + [a] + (b) + {c} + {a} + {b} + {c} - [a] - (b) - {c} - {a} - {b} - {c} - {a} - {b} - {c} - {b} - {c} + [a] + (b) + {c} + {a} + {b} + {c} + {a} + {b} + {c} + {b} + {c} - [a] - (b) - {c} + [a] + (b) + {c} - [a] - (b) - {c} - [a] - (b) - {c} + [a] + (b) + {c} + [a] + (b) + {c} - [a] - (b) - {c} - [a] - (b) - {c} - [a] - (b) - {c} - [b] - (c) + [a] + (b) + {c} + [a] + (b) + {c} + [a] + (b) + {c} + [b] + (c) @@ -169,74 +169,74 @@ - [a] - [b] - [c] + [a] + [b] + [c] - [d] - [e] - [f] + [d] + [e] + [f] - [] + [] - [a] + [a] - [a] - [] + [a] + [] - [a] - [b] + [a] + [b] - [a] - [b] - [] + [a] + [b] + [] - [a] - [b] - [c] + [a] + [b] + [c] - [] - [] + [] + [] - [] - [] - [] + [] + [] + [] - [a] - [b] - [c] + [a] + [b] + [c] - [] + [] - [a] - [b] - [c] + [a] + [b] + [c] - [e] - [f] - [g] + [e] + [f] + [g] @@ -251,29 +251,29 @@ - [a] - (b) - {c} + [a] + (b) + {c} - a - (b) - {c} + a + (b) + {c} - a - b - {c} + a + b + {c} - [a] - b - c + [a] + b + c - [a] - (b) - {c} + [a] + (b) + {c} @@ -288,25 +288,25 @@ - [a] - (b) - {c} + [a] + (b) + {c} - [a](b) - {c} + [a](b) + {c} - [a] - (b){c} + [a] + (b){c} - [a](b){c} + [a](b){c} - [a] - (b) - {c} + [a] + (b) + {c} @@ -321,22 +321,22 @@ - [a] - (b) - {c} + [a] + (b) + {c} - [a] - c + [a] + c - [a] - c + [a] + c - [a] - (b) - {c} + [a] + (b) + {c} @@ -351,49 +351,49 @@ - [a] - [b] + [a] + [b] - X + X - [a] - [b ] + [a] + [b ] - Y + Y - Z + Z - [a] - [b ] + [a] + [b ] - [a] - [b] + [a] + [b] - [c] - [d] + [c] + [d] - [a] - [b] + [a] + [b] - [c] - [d] + [c] + [d] @@ -409,21 +409,21 @@ - [a] - [b] + [a] + [b] - [ + [ - (a) - (b) + (a) + (b) ] - [ + [ - {a} - {b} + {a} + {b} ] @@ -441,28 +441,28 @@ - [a] - [[b]] - [c] + [a] + [[b]] + [c] - [d] - [[e]] - [f] + [d] + [[e]] + [f] - [a] - [[b]] - [c] + [a] + [[b]] + [c] - [d] - [[e]] - [f] + [d] + [[e]] + [f] diff --git a/t/alignment/halignatt.xml b/t/alignment/halignatt.xml index 5f0ffee8be..41296325bb 100644 --- a/t/alignment/halignatt.xml +++ b/t/alignment/halignatt.xml @@ -7,53 +7,53 @@ - - AT&T Common Stock + + AT&T Common Stock - + Year Price Dividend - + 1971 41–54 $2.60 - + 2 41–54 2.70 - + 3 46–55 2.87 - + 4 40–53 3.24 - + 5 45–52 3.40 - + 6 51–59 .95* - * (first quarter only) + * (first quarter only) diff --git a/t/alignment/supertabular.xml b/t/alignment/supertabular.xml index 4967a52e96..afd5ae0e03 100644 --- a/t/alignment/supertabular.xml +++ b/t/alignment/supertabular.xml @@ -71,46 +71,46 @@ - Entity - Unicode Name - Unicode +       Entity +       Unicode Name +       Unicode - alpha - GREEK SMALL LETTER ALPHA - 03B1 +       alpha +       GREEK SMALL LETTER ALPHA +       03B1 - beta - GREEK SMALL LETTER BETA - 03B2 +       beta +       GREEK SMALL LETTER BETA +       03B2 - chi - GREEK SMALL LETTER CHI - 03C7 +       chi +       GREEK SMALL LETTER CHI +       03C7 - Delta - GREEK CAPITAL LETTER DELTA - 0394 +       Delta +       GREEK CAPITAL LETTER DELTA +       0394 - delta - GREEK SMALL LETTER DELTA - 03B4 +       delta +       GREEK SMALL LETTER DELTA +       03B4 - epsi - GREEK SMALL LETTER EPSILON - 03B5 +       epsi +       GREEK SMALL LETTER EPSILON +       03B5 - epsis - GREEK LUNATE EPSILON SYMBOL - 03F5 +       epsis +       GREEK LUNATE EPSILON SYMBOL +       03F5 @@ -174,46 +174,46 @@ - Entity - Unicode Name - Unicode +       Entity +       Unicode Name +       Unicode - alpha - GREEK SMALL LETTER ALPHA - 03B1 +       alpha +       GREEK SMALL LETTER ALPHA +       03B1 - beta - GREEK SMALL LETTER BETA - 03B2 +       beta +       GREEK SMALL LETTER BETA +       03B2 - chi - GREEK SMALL LETTER CHI - 03C7 +       chi +       GREEK SMALL LETTER CHI +       03C7 - Delta - GREEK CAPITAL LETTER DELTA - 0394 +       Delta +       GREEK CAPITAL LETTER DELTA +       0394 - delta - GREEK SMALL LETTER DELTA - 03B4 +       delta +       GREEK SMALL LETTER DELTA +       03B4 - epsi - GREEK SMALL LETTER EPSILON - 03B5 +       epsi +       GREEK SMALL LETTER EPSILON +       03B5 - epsis - GREEK LUNATE EPSILON SYMBOL - 03F5 +       epsis +       GREEK LUNATE EPSILON SYMBOL +       03F5 diff --git a/t/alignment/tabular.pdf b/t/alignment/tabular.pdf index e82e818f3b..e745d6f5fb 100644 Binary files a/t/alignment/tabular.pdf and b/t/alignment/tabular.pdf differ diff --git a/t/alignment/tabular.tex b/t/alignment/tabular.tex index abd477a015..9749c3ab7d 100644 --- a/t/alignment/tabular.tex +++ b/t/alignment/tabular.tex @@ -14,4 +14,11 @@ 72 & 245 & 245 & Light trading due to a heavy winter. \\ \hline 73 & 245 & 2001 & No gnus was very good gnus this year. \\ \hline \end{tabular} + +\begin{tabular}{|c|c|c|}\hline +x&&x\\\hline +&&\\\hline +x&&x\\\hline +\end{tabular} + \end{document} diff --git a/t/alignment/tabular.xml b/t/alignment/tabular.xml index 2383a478ab..aa6e7ff84e 100644 --- a/t/alignment/tabular.xml +++ b/t/alignment/tabular.xml @@ -17,31 +17,54 @@ Year - low - high + low + high Comments 1971 - 97– - 245 + 97– + 245

Bad year.

72 - 245– - 245 + 245– + 245

Light trading due to a heavy winter.

73 - 245– - 2001 + 245– + 2001

No gnus was very good gnus this year.

+ + + + + x + + x + + + + + + + + + + x + + x + + + + diff --git a/t/babel/numprints.xml b/t/babel/numprints.xml index 2eb182059d..0e02b7fb63 100644 --- a/t/babel/numprints.xml +++ b/t/babel/numprints.xml @@ -600,7 +600,7 @@ vs. - + 123.45e12 @@ -625,7 +625,7 @@ vs. - + 123.45e12 @@ -654,7 +654,7 @@ vs. - + 123.45e12 @@ -683,10 +683,10 @@ vs. - 123.45×1012 + 123.45×1012
- + 12345.678e123 @@ -722,7 +722,7 @@ vs. - + 12345.678e123 @@ -762,7 +762,7 @@ vs. - + 12345.678e123 @@ -802,7 +802,7 @@ vs. - 12,345.678×10123 + 12,345.678×10123
diff --git a/t/encoding/ly1.xml b/t/encoding/ly1.xml index f886839621..f0279442da 100644 --- a/t/encoding/ly1.xml +++ b/t/encoding/ly1.xml @@ -72,7 +72,7 @@ ´4x - + ! " # diff --git a/t/graphics/graphrot.xml b/t/graphics/graphrot.xml index 5748a2ddbf..c42e84d0c7 100644 --- a/t/graphics/graphrot.xml +++ b/t/graphics/graphrot.xml @@ -75,7 +75,7 @@ 2 Table 2 - + @@ -122,7 +122,7 @@ 3 Table 3 - + @@ -169,7 +169,7 @@ 4 Table 4 - + @@ -448,7 +448,7 @@ the whales Save the whale Save the + Table 5 Table 5 diff --git a/t/graphics/picture.xml b/t/graphics/picture.xml index 98ab7fe47d..c609ecf8b6 100644 --- a/t/graphics/picture.xml +++ b/t/graphics/picture.xml @@ -1100,8 +1100,8 @@ square. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -336,7 +336,7 @@ A=100*13 = 1300pt;

- + @@ -344,7 +344,7 @@ A=100*13 = 1300pt;

- + @@ -352,7 +352,7 @@ A=100*13 = 1300pt;

- + @@ -360,7 +360,7 @@ A=100*13 = 1300pt;

- + @@ -368,7 +368,7 @@ A=100*13 = 1300pt;

- + @@ -376,7 +376,7 @@ A=100*13 = 1300pt;

- + @@ -384,7 +384,7 @@ A=100*13 = 1300pt;

- + @@ -392,7 +392,7 @@ A=100*13 = 1300pt;

- + @@ -400,7 +400,7 @@ A=100*13 = 1300pt;

- + @@ -408,7 +408,7 @@ A=100*13 = 1300pt;

- + @@ -416,7 +416,7 @@ A=100*13 = 1300pt;

- + @@ -424,7 +424,7 @@ A=100*13 = 1300pt;

- + @@ -432,7 +432,7 @@ A=100*13 = 1300pt;

- + @@ -440,7 +440,7 @@ A=100*13 = 1300pt;

- + @@ -448,7 +448,7 @@ A=100*13 = 1300pt;

- + @@ -456,7 +456,7 @@ A=100*13 = 1300pt;

- + @@ -464,7 +464,7 @@ A=100*13 = 1300pt;

- + @@ -472,7 +472,7 @@ A=100*13 = 1300pt;

- + @@ -480,7 +480,7 @@ A=100*13 = 1300pt;

- + @@ -488,7 +488,7 @@ A=100*13 = 1300pt;

- + @@ -496,7 +496,7 @@ A=100*13 = 1300pt;

- + @@ -504,7 +504,7 @@ A=100*13 = 1300pt;

- + @@ -512,7 +512,7 @@ A=100*13 = 1300pt;

- + @@ -520,7 +520,7 @@ A=100*13 = 1300pt;

- + @@ -528,7 +528,7 @@ A=100*13 = 1300pt;

- + @@ -536,7 +536,7 @@ A=100*13 = 1300pt;

- + @@ -544,7 +544,7 @@ A=100*13 = 1300pt;

- + @@ -552,7 +552,7 @@ A=100*13 = 1300pt;

- + @@ -560,7 +560,7 @@ A=100*13 = 1300pt;

- + @@ -568,7 +568,7 @@ A=100*13 = 1300pt;

- + @@ -576,7 +576,7 @@ A=100*13 = 1300pt;

- + @@ -584,7 +584,7 @@ A=100*13 = 1300pt;

- + @@ -592,7 +592,7 @@ A=100*13 = 1300pt;

- + @@ -600,7 +600,7 @@ A=100*13 = 1300pt;

- + @@ -608,7 +608,7 @@ A=100*13 = 1300pt;

- + @@ -616,7 +616,7 @@ A=100*13 = 1300pt;

- + @@ -624,7 +624,7 @@ A=100*13 = 1300pt;

- + @@ -632,7 +632,7 @@ A=100*13 = 1300pt;

- + diff --git a/t/structure/glossary.xml b/t/structure/glossary.xml index 197809d0a8..985caaaca9 100644 --- a/t/structure/glossary.xml +++ b/t/structure/glossary.xml @@ -31,7 +31,8 @@ spanning from the end of the Silurian Period to the beginning of the Carboniferous Period. This age was known for its remarkable variety of -fish species. +fish species. +Fish AgeFish Age
Diagram + Diagram + @@ -1145,7 +1145,7 @@ square.
+ @@ -1289,12 +1289,12 @@ square. +
+ @@ -1343,7 +1343,7 @@ square.
+ @@ -1376,7 +1376,7 @@ square.
+ @@ -1409,7 +1409,7 @@ square.
+ @@ -1550,12 +1550,12 @@ square. +
+ @@ -1626,7 +1626,7 @@ square.
+ @@ -1782,12 +1782,12 @@ square. +
+ @@ -1836,7 +1836,7 @@ square.
+ @@ -1889,7 +1889,7 @@ square.
+ @@ -1941,7 +1941,7 @@ square.
+ @@ -2091,12 +2091,12 @@ square. +
+ @@ -2145,7 +2145,7 @@ square.
+ @@ -2190,7 +2190,7 @@ square.
+ @@ -2250,7 +2250,7 @@ square.
+ @@ -2415,12 +2415,12 @@ square. +
+ @@ -2469,7 +2469,7 @@ square.
+ @@ -2522,7 +2522,7 @@ square.
+ @@ -2558,7 +2558,7 @@ square.
+ @@ -2708,12 +2708,12 @@ square. +
+ @@ -2792,7 +2792,7 @@ square.
+ @@ -2957,12 +2957,12 @@ square. +
+ @@ -3011,7 +3011,7 @@ square.
+ @@ -3086,7 +3086,7 @@ square.
+ diff --git a/t/graphics/xcolors.xml b/t/graphics/xcolors.xml index 24b92b1344..bb8f43e5c2 100644 --- a/t/graphics/xcolors.xml +++ b/t/graphics/xcolors.xml @@ -328,7 +328,7 @@ A=100*13 = 1300pt;

cmyk hsb HTML - gray + gray
red XX 0 1 1 0 XX 0 1 1 XX FF0000XX 0.3XX 0.3
green XX 1 0 1 0 XX 0.3333 1 1 XX 00FF00XX 0.59XX 0.59
blue XX 1 1 0 0 XX 0.6667 1 1 XX 0000FFXX 0.11XX 0.11
cyan XX 1 0 0 0 XX 0.5 1 1 XX 00FFFFXX 0.7XX 0.7
magenta XX 0 1 0 0 XX 0.8333 1 1 XX FF00FFXX 0.41XX 0.41
yellow XX 0 0 1 0 XX 0.1667 1 1 XX FFFF00XX 0.89XX 0.89
orange XX 0 0.5 1 0 XX 0.0833 1 1 XX FF8000XX 0.595XX 0.595
violet XX 0 0.5 0 0.5 XX 0.8333 1 0.5 XX 800080XX 0.205XX 0.205
purple XX 0 0.75 0.5 0.25 XX 0.9444 1 0.75 XX BF0040XX 0.2525XX 0.2525
brown XX 0 0.25 0.5 0.25 XX 0.0833 0.6667 0.75 XX BF8040XX 0.5475XX 0.5475
pink XX 0 0.25 0.25 0 XX 0 0.25 1 XX FFBFBFXX 0.825XX 0.825
olive XX 0 0 1 0.5 XX 0.1667 1 0.5 XX 808000XX 0.39XX 0.39
black XX 0 0 0 1 XX 0 0 0 XX 000000XX 0XX 0
darkgray XX 0 0 0 0.75 XX 0 0 0.25 XX 404040XX 0.25XX 0.25
gray XX 0 0 0 0.5 XX 0 0 0.5 XX 808080XX 0.5XX 0.5
lightgray XX 0 0 0 0.25 XX 0 0 0.75 XX BFBFBFXX 0.75XX 0.75
white XX 0 0 0 0 XX 0 0 1 XX FFFFFFXX 1XX 1
-red XX 1 0 0 0 XX 0.5 1 1 XX 00FFFFXX 0.7XX 0.7
-green XX 0 1 0 0 XX 0.8333 1 1 XX FF00FFXX 0.41XX 0.41
-blue XX 0 0 1 0 XX 0.1667 1 1 XX FFFF00XX 0.89XX 0.89
-cyan XX 0 1 1 0 XX 0 1 1 XX FF0000XX 0.3XX 0.3
-magenta XX 1 0 1 0 XX 0.3333 1 1 XX 00FF00XX 0.59XX 0.59
-yellow XX 1 1 0 0 XX 0.6667 1 1 XX 0000FFXX 0.11XX 0.11
-orange XX 1 0.5 0 0 XX 0.5833 1 1 XX 0080FFXX 0.405XX 0.405
-violet XX 0.5 0 0.5 0 XX 0.3333 0.5 1 XX 80FF80XX 0.795XX 0.795
-purple XX 0.75 0 0.25 0 XX 0.4444 0.75 1 XX 40FFBFXX 0.7475XX 0.7475
-brown XX 0.5 0.25 0 0.25 XX 0.5833 0.6667 0.75 XX 4080BFXX 0.4525XX 0.4525
-pink XX 0.25 0 0 0.75 XX 0.5 1 0.25 XX 004040XX 0.175XX 0.175
-olive XX 0.5 0.5 0 0 XX 0.6667 0.5 1 XX 8080FFXX 0.555XX 0.555
-black XX 0 0 0 0 XX 0 0 1 XX FFFFFFXX 1XX 1
-darkgray XX 0 0 0 0.25 XX 0 0 0.75 XX BFBFBFXX 0.75XX 0.75
-gray XX 0 0 0 0.5 XX 0 0 0.5 XX 808080XX 0.5XX 0.5
-lightgray XX 0 0 0 0.75 XX 0 0 0.25 XX 404040XX 0.25XX 0.25
-white XX 0 0 0 1 XX 0 0 0 XX 000000XX 0XX 0
JungleGreen XX 0.99 0 0.52 0 XX 0.4125 0.99 1 XX 03FF7AXX 0.6458XX 0.6458
DarkOrchid XX 0.4 0.8 0.2 0 XX 0.7778 0.75 0.8 XX 9933CCXX 0.386XX 0.386
-JungleGreen XX 0 0.99 0.47 0.01 XX 0.9125 1 0.99 XX FC0085XX 0.3542XX 0.3542
-DarkOrchid XX 0.4 0 0.6 0.2 XX 0.2778 0.75 0.8 XX 66CC33XX 0.614XX 0.614