Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block consistency #2286

Merged
merged 18 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b457b21
Schema changes: More consistent naming and use of "block" elements,
brucemiller Dec 19, 2023
ab7aace
Add XSLT for the new (or renamed) block elements
brucemiller Dec 19, 2023
d16c52f
Add support for an internal ltx:_CaptureBlock_ element useful for tem…
brucemiller Dec 19, 2023
bb63cbd
Enhance document->renameNode with option to 're-insert' the contents …
brucemiller Dec 19, 2023
293c661
Replace ltx:inline-para with ltx:inline-logical-block
brucemiller Dec 19, 2023
3f7ca71
Replacement insertBlock based on _CaptureBlock
brucemiller Dec 19, 2023
5a6c792
\hbox creates inline-block if placed where #PCDATA is allowed
brucemiller Dec 19, 2023
3286cfa
Have p{} column type pass the desired width to \hbox, so that can cre…
brucemiller Dec 19, 2023
53f9662
Simplify but generalize \normal@par, \lx@newline to recognize block m…
brucemiller Dec 19, 2023
168e1b6
Fixup CSS styling for various blocks, inline, etc
brucemiller Dec 20, 2023
09dbc03
Enhance tabular test-case for interation between @ and p column speci…
brucemiller Dec 20, 2023
6281316
Enhance framed test-case to show framing of more awkward combinations
brucemiller Dec 20, 2023
5f7f064
Updated test-cases for changes to block processing
brucemiller Dec 20, 2023
fe7d141
always allow (internal) attributes that start with _; allow svg:g, sv…
brucemiller Dec 21, 2023
7765da9
Change svg:foreignObject content from Flow.model to Inline.model (usi…
brucemiller Dec 21, 2023
2b0f239
In renameNode, only copy allowed attributes
brucemiller Dec 21, 2023
2890273
Fix copy mistake
brucemiller Dec 21, 2023
545fdca
Careful about insertBlock into svg which may or may not need an svg:f…
brucemiller Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion lib/LaTeXML/Common/Model.pm
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ sub loadSchema {
$self->loadCompiledSchema($compiled); }
else {
$$self{schema}->loadSchema; }
$self->loadInternalExtensions;
$self->describeModel if $LaTeXML::Common::Model::DEBUG;
$$self{schema_loaded} = 1;
return $$self{schema}; }
Expand All @@ -88,6 +89,30 @@ sub addSchemaDeclaration {
$$self{schema}->addSchemaDeclaration($document, $tag);
return; }

sub loadInternalExtensions {
my ($self) = @_;
if (!exists $$self{tagprop}{'ltx:_CaptureBlock_'}) {
# Synthesize ltx:_CaptureBlock_ to act like the union of ltx:block, ltx:para,
$self->synthesizeElement('ltx:_CaptureBlock_',
qw(ltx:block ltx:logical-block ltx:sectional-block Caption)); }
return; }

# Clone the tagprop's (allowed content & attributes) of @other to $tag
sub synthesizeElement {
my ($self, $tag, @others) = @_;
$$self{tagprop}{$tag} = {} unless $$self{tagprop}{$tag};
my $capture = $$self{tagprop}{$tag};
foreach my $other (@others) {
if (my $content = $$self{schemaclass}{$other}) {
foreach my $child (keys %$content) {
$$capture{model}{$child} = $$content{$child}; } }
elsif (my $entry = $$self{tagprop}{$other}) {
foreach my $child (keys %{ $$entry{model} }) {
$$capture{model}{$child} = $$entry{model}{$child}; }
foreach my $attr (keys %{ $$entry{attributes} }) {
$$capture{attributes}{$attr} = $$entry{attributes}{$attr}; } } }
return; }

#=====================================================================
# Make provision to precompile the schema.
sub compileSchema {
Expand Down Expand Up @@ -378,7 +403,8 @@ sub canContain {
return 0 if !$tag || ($tag eq '#PCDATA') || ($tag eq '#Comment');
return 1 if $tag =~ /(.*?:)?_Capture_$/; # with or without namespace prefix
return 1 if $tag eq '_WildCard_';
return 1 if $childtag =~ /(.*?:)?_Capture_$/;
return 1 if $childtag =~ /(.*?:)?_Capture_$/; # anything can contain these
return 1 if $childtag =~ /(.*?:)?_CaptureBlock_$/;
return 1 if $childtag eq '_WildCard_';
return 1 if $childtag eq '#Comment';
return 1 if $childtag eq '#ProcessingInstruction';
Expand Down
18 changes: 15 additions & 3 deletions lib/LaTeXML/Core/Document.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1957,7 +1957,7 @@ sub replaceNode {
# initially since $node->setNodeName was broken in XML::LibXML 1.58
# but this can provide for more options & correctness?
sub renameNode {
my ($self, $node, $newname) = @_;
my ($self, $node, $newname, $reinsert) = @_;
my $model = $$self{model};
my ($ns, $tag) = $model->decodeQName($newname);
my $parent = $node->parentNode;
Expand All @@ -1972,8 +1972,20 @@ sub renameNode {
$id = $value if $key eq 'xml:id'; # Save to register after removal of old node.
$new->setAttribute($key, $value); }
# AND move all content from $node to $newnode
foreach my $child ($node->childNodes) {
$new->appendChild($child); }
if (!$reinsert) {
foreach my $child ($node->childNodes) {
$new->appendChild($child); } }
else {
my $savenode = $$self{node};
$$self{node} = $new;
foreach my $child ($node->childNodes) {
if ($child->nodeType == XML_TEXT_NODE) {
openText_internal($self, $child->data);
closeText_internal($self); }
else {
my $point = find_insertion_point($self, getNodeQName($self, $child));
$point->appendChild($child); } }
$$self{node} = $savenode; }
## THEN call afterOpen... ?
# It would normally be called before children added,
# but how can we know if we're duplicated auto-added stuff?
Expand Down
56 changes: 26 additions & 30 deletions lib/LaTeXML/Package/LaTeX.pool.ltxml
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,21 @@ EOTeX
# C.1.6 The \\ Command
#======================================================================
# In math, \\ is just a formatting hint, unless within an array, cases, .. environment.
DefConstructor("\\\\ OptionalMatch:* [Glue]",
"?#isMath(<ltx:XMHint name='newline'/>)(<ltx:break/>)",
DefConstructor('\lx@newline OptionalMatch:* [Glue]', sub {
my ($document, $star, $skip, %props) = @_;
if ($STATE->lookupValue('IN_MATH')) {
$document->insertElement('ltx:XMHint', undef, name => 'newline'); }
else {
my $context = $document->getElement;
if ($context->getAttribute('_vertical_mode_')) { }
elsif (($document->getNodeQName($context) eq 'ltx:p')
&& $context->parentNode->getAttribute('_vertical_mode_')) {
$document->maybeCloseElement('ltx:p'); }
elsif ($document->canContain($context, 'ltx:break')) {
$document->insertElement('ltx:break'); } } },
reversion => Tokens(T_CS("\\\\"), T_CR),
properties => { isBreak => 1 });
Let('\\\\', '\lx@newline');

DefConstructor('\newline',
"?#isMath(<ltx:XMHint name='newline'/>)(<ltx:break/>)",
Expand Down Expand Up @@ -1340,27 +1351,19 @@ DefMacroI('\@evenfoot', undef, Tokens());
#**********************************************************************

DefEnvironment('{center}', sub {
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
aligningEnvironment('center', 'ltx_centering', @_); }, # aligning will take care of \\\\ "rows"
beforeDigest => sub {
Let('\par', '\inner@par');
Let('\\\\', '\inner@par'); });
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
aligningEnvironment('center', 'ltx_centering', @_); }); # aligning will take care of \\\\ "rows"

# HOWEVER, define a plain \center to act like \centering (?)
DefMacroI('\center', undef, '\centering');
DefMacroI('\endcenter', undef, '');

DefEnvironment('{flushleft}', sub {
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
aligningEnvironment('left', 'ltx_align_left', @_); },
beforeDigest => sub {
Let('\par', '\inner@par');
Let('\\\\', '\inner@par'); });
aligningEnvironment('left', 'ltx_align_left', @_); });
DefEnvironment('{flushright}', sub {
$_[0]->maybeCloseElement('ltx:p'); # this starts a new vertical block
aligningEnvironment('right', 'ltx_align_right', @_); },
beforeDigest => sub {
Let('\par', '\inner@par');
Let('\\\\', '\inner@par'); });
aligningEnvironment('right', 'ltx_align_right', @_); });

# These add an operation to be carried out on the current node & following siblings, when the current group ends.
# These operators will add alignment (class) attributes to each "line" in the current block.
Expand Down Expand Up @@ -3451,7 +3454,7 @@ sub SubfigureAndID {
# A little verbose, but much easier to do than XSLT 1.0 would allow.
my $contents_count = 0; # count with author breaks excluded
my @contents = grep { my $name = $document->getNodeQName($_);
my $ok = ($name =~ /^ltx:(?:graphics|float|figure|table|tabular|break|inline-para|inline-block|listing)$/);
my $ok = ($name =~ /^ltx:(?:graphics|float|figure|table|tabular|break|inline-logical-block|inline-block|listing)$/);
$contents_count += 1 if $ok and $name ne 'ltx:break';
$ok; } element_nodes($node);
if ($contents_count > 1) {
Expand Down Expand Up @@ -3618,9 +3621,9 @@ DefConditional('\if@reversemargin');
Let('\reversemarginpar', '\@reversemargintrue');
Let('\normalmarginpar', '\@reversemarginfalse');
DefConstructor('\marginpar[]{}',
"?#1(<ltx:note role='margin' class='ltx_marginpar_left'><ltx:inline-para>#1</ltx:inline-para></ltx:note>"
. "?#2(<ltx:note role='margin' class='ltx_marginpar_right'><ltx:inline-para>#2</ltx:inline-para></ltx:note>))"
. "(<ltx:note role='margin' class='ltx_marginpar'><ltx:inline-para>#2</ltx:inline-para></ltx:note>)");
"?#1(<ltx:note role='margin' class='ltx_marginpar_left'><ltx:inline-logical-block>#1</ltx:inline-logical-block></ltx:note>"
. "?#2(<ltx:note role='margin' class='ltx_marginpar_right'><ltx:inline-logical-block>#2</ltx:inline-logical-block></ltx:note>))"
. "(<ltx:note role='margin' class='ltx_marginpar'><ltx:inline-logical-block>#2</ltx:inline-logical-block></ltx:note>)");
DefRegister('\marginparpush', Dimension(0));

#**********************************************************************
Expand Down Expand Up @@ -4835,13 +4838,7 @@ RawTeX(<<'EOL');
\DeclareRobustCommand\usebox[1]{\leavevmode\copy #1\relax}
EOL

# A soft sorta \par that only closes an ltx:p, but not ltx:para
DefConstructor('\lx@parboxnewline[]', sub {
my ($document, $ignore, %props) = @_;
$document->maybeCloseElement('ltx:p');
return; },
properties => { isBreak => 1 });

Let('\lx@parboxnewline[]', '\lx@newline'); # Obsolete, but in case still used
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably the [] arg should go away for the Let?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops

# NOTE: There are 2 extra arguments (See LaTeX Companion, p.866)
# for height and inner-pos. We're ignoring them, for now, though.
DefConstructor('\parbox[] OptionalUndigested OptionalUndigested {Dimension} VBoxContents', sub {
Expand All @@ -4861,7 +4858,7 @@ DefConstructor('\parbox[] OptionalUndigested OptionalUndigested {Dimension} VBox
beforeDigest => sub {
reenterTextMode(1); # actually vertical mode!
AssignRegister('\hsize' => $_[4]);
Let('\\\\', '\lx@parboxnewline'); });
Let('\\\\', '\lx@newline'); });
DefMacroI('\@parboxrestore', undef, Tokens());

DefConditional('\if@minipage');
Expand All @@ -4870,7 +4867,6 @@ DefEnvironment('{minipage}[][][]{Dimension}', sub {
my ($document, $attachment, $b, $c, $width, %props) = @_;
my $vattach = translateAttachment($attachment);
insertBlock($document, $props{body},
para => 1,
width => $width,
vattach => $vattach,
class => 'ltx_minipage');
Expand All @@ -4884,8 +4880,8 @@ DefEnvironment('{minipage}[][][]{Dimension}', sub {
reenterTextMode(1); # actually vertical mode!
Digest(T_CS('\@minipagetrue'));
AssignRegister('\hsize' => $_[4]);
# this conflicts (& not needed?) with insertBlock
Let('\\\\', '\lx@parboxnewline'); });
Let('\\\\', '\lx@newline');
});

DefConstructor('\rule[Dimension]{Dimension}{Dimension}',
"<ltx:rule ?#offset(yoffset='#offset') width='#width' height='#height'/>",
Expand Down
Loading
Loading