Skip to content

Commit e5120f7

Browse files
committed
Improve timing of overriding marks; make \ref,\label connections between author/affiliation work via marks; improve trailing \\ removal from frontmatter
1 parent 743cae8 commit e5120f7

File tree

1 file changed

+63
-51
lines changed

1 file changed

+63
-51
lines changed

lib/LaTeXML/Engine/Base_Utility.pool.ltxml

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -229,24 +229,28 @@ DefPrimitive('\lx@clear@creators OptionalKeyVals:Frontmatter', sub {
229229
#DefMacro('\lx@clear@creators OptionalKeyVals:Frontmatter', '\lx@clear@frontmatter{ltx:creator)[#1]');
230230
DefMacro('\lx@clear@creators []', '\lx@clear@frontmatter{ltx:creator}[#1]');
231231

232-
# trailing \\ should disappear.
233-
# OR alternatively a Tag if <ltx:break/> is last element?
234-
DefMacro('\lx@ignored OptionalMatch:* [Glue]', sub {
235-
my ($gullet, $star, $dim) = @_;
236-
return ($gullet->peekToken ? Invocation(T_CS('\lx@newline'),$star, $dim) : ()); });
237-
238-
# Digest the content for a frontmatter item, disabling certain commands
232+
# Digest the content for a frontmatter item, disabling or masking certain commands
239233
# Note that we shouldn't be digesting any frontmatter until within document, so inPreamble unnec.
240-
# NOTE: shouldn't actually ignore \\, but trailing onces should be stripped!!!
234+
# See cleanTrailingBreak for cleanup of misused \\.
241235
sub digestFrontmatterItem {
242236
my ($stomach, $item) = @_;
243237
$stomach->bgroup;
244-
Let('\\\\', '\lx@ignored');
245238
Let('\label','\lx@set@contact@label');
246239
my $digested = DigestText($item);
247240
$stomach->egroup;
248241
return $digested; }
249242

243+
sub cleanTrailingBreak {
244+
my ($document, $node) = @_;
245+
while (my $last = $node->lastChild ) {
246+
my $tag = $document->getNodeQName($last);
247+
last unless (($tag eq '#PCDATA') && ($last->toString =~ /^\s*$/s))
248+
|| ($tag eq 'ltx:break');
249+
$node->removeChild($last); }
250+
return; }
251+
Tag('ltx:personname', afterClose => \&cleanTrailingBreak);
252+
Tag('ltx:contact', afterClose => \&cleanTrailingBreak);
253+
250254
# Add a new frontmatter item that will be enclosed in <$tag %attr>...</$tag>
251255
# The content is the result of digesting $tokens.
252256
# \@add@frontmatter[keys]{tag}[attributes]{content}
@@ -317,6 +321,7 @@ DefPrimitive('\lx@add@contact OptionalKeyVals:Frontmatter {}', sub {
317321
my ($stomach, $kv, $content) = @_;
318322
saveFrontMatter($stomach, 'ltx:contact', $kv, Invocation(T_CS('\lx@add@contact@now'), $kv, $content));
319323
return; });
324+
320325
DefPrimitive('\lx@add@contact@now OptionalKeyVals:Frontmatter {}', sub {
321326
##DefPrimitive('\lx@add@contact OptionalKeyVals:Frontmatter {}', sub {
322327
my ($stomach, $kv, $content) = @_;
@@ -330,7 +335,7 @@ DefPrimitive('\lx@add@contact@now OptionalKeyVals:Frontmatter {}', sub {
330335
AssignMapping('num_contacts', $role => $n);
331336
if (!$options{name} || ! scalar($options{name}->unlist)) {
332337
my $cs = T_CS('\lx@contact@' . $role . '@name');
333-
$options{name} = (LookupDefinition($cs) ? $cs : Tokens()); }
338+
$options{name} = DigestText($cs) if LookupDefinition($cs); }
334339
my @allcreators = @{ $$frontmatter{'ltx:creator'} || [] };
335340
my @creators = grep { ($$_[1]{role} || '') ne 'pending'; } @allcreators;
336341
my $ncreators = scalar(@creators);
@@ -343,16 +348,19 @@ DefPrimitive('\lx@add@contact@now OptionalKeyVals:Frontmatter {}', sub {
343348
Debug("ADD contact: [" .
344349
join(',', map { $_ . '=' . ToString($options{$_}); } sort keys %options)
345350
. "] " . ToString($content) . " (with $ncreators available)");
351+
# Tentatively create new entry in frontmatter, in case digestion changes marks!
352+
my $entry = ['ltx:creator', { role => 'pending', _marks => $marks }, 'place_keeper'];
353+
push(@{ $$frontmatter{'ltx:creator'} }, $entry);
354+
my $xcontent = digestFrontmatterItem($stomach, $content);
355+
$marks = $$entry[1]{_marks}; # Reset if changed!
356+
my $datum = LaTeXML::Core::Whatsit->new(LookupDefinition(T_CS('\lx@make@contact@@')),
357+
[$role,$marks,$options{name},$xcontent]);
346358
if ($marks || !$ncreators) { # deferred until we can compare marks
347-
my $entry = ['ltx:creator', { role => 'pending', _marks => $marks }, 'place_keeper'];
348-
push(@{ $$frontmatter{'ltx:creator'} }, $entry);
349-
# NOW, with that context saved, we can digest, THEN store the contact's content.
350359
Debug("... deferring to mark=$marks");
351-
## $$entry[2] = DigestText(Invocation(T_CS('\lx@make@contact@'),
352-
$$entry[2] = digestFrontmatterItem($stomach, Invocation(T_CS('\lx@make@contact@'),
353-
#### T_OTHER($role), T_OTHER($marks), $options{name} || Tokens(), $content)); }
354-
T_OTHER($role), T_OTHER($marks), $options{name}, $content)); }
360+
$$entry[2] = $datum; }
355361
else {
362+
$$frontmatter{'ltx:creator'} # Remove unneeded entry.
363+
= [grep { $_ ne $entry; } @{ $$frontmatter{'ltx:creator'} }];
356364
my ($nprev, $newonly) = (1, 0);
357365
my $attach = ToString($options{attach});
358366
if ((!defined $attach) || ($attach eq '')) { }
@@ -362,42 +370,57 @@ DefPrimitive('\lx@add@contact@now OptionalKeyVals:Frontmatter {}', sub {
362370
elsif ($attach eq 'new') { $nprev = $ncreators; $newonly = 1; }
363371
else { Info('unexpected', 'contact', $stomach, "Contact attach '$attach' unrecognized"); }
364372
Debug("...adding to $nprev previous" . ($newonly ? ' new' : ''));
365-
## my $datum = DigestText(Invocation(T_CS('\lx@make@contact@'),
366-
my $datum = digestFrontmatterItem($stomach, Invocation(T_CS('\lx@make@contact@'),
367-
#### T_OTHER($role), T_OTHER($marks), $options{name} || Tokens(), $content));
368-
T_OTHER($role), T_OTHER($marks), $options{name}, $content));
369373
while (my $creator = pop(@creators)) {
370374
push(@$creator, $datum);
371375
$$creator[1]{"_has$role"} = 1;
372376
last if (--$nprev <= 0) || ($newonly && $creators[-1][1]{"_has$role"}); } }
373377
return; });
374378

379+
DefConstructor('\lx@make@contact@@ Undigested Undigested {} Undigested',
380+
"^<ltx:contact role='#1'_mark='#2' name='#3'>#4</ltx:contact>");
381+
375382
sub show_frontmatter_entry {
376383
my ($entry) = @_;
377384
my ($tag, $attr, @content) = @$entry;
378385
return "[$tag {" .
379386
join(',', map { $_ . '=' . ToString($$attr{$_}); } sort keys %$attr) . "} "
380387
. join('', map { ToString($_); } @content) . "]"; }
381388

382-
# Add comma-separated marks to the current ltx:creator by which some other ltx:contact
383-
# data can be attached; expected to be embedded within the (eg) \author text.
384-
# Canonical example: \inst, typically \inst is let to \lx@add@creator@mark in classes.
385-
# If there are distinct kinds of marks, might want to prefix the mark
386-
# with some unique text?
387-
# NOTE: Could also treat \label & \ref as a mark pair?
388-
DefConstructor('\lx@add@creator@mark[]{}', sub {
389-
my ($document, $prefix, $mark) = @_;
390-
if (my $creator = $document->findnode('ancestor::ltx:creator', $document->getNode)) {
391-
my $marks = $creator->getAttribute('_marks') || '';
392-
$mark = join(',', cleanFrontmatterMarks($mark, $prefix));
393-
Debug("MARKS add: $mark");
394-
$creator->setAttribute(_marks => ($marks ? "$marks,$mark" : $mark)); } });
395-
DefConstructor('\lx@set@contact@label Semiverbatim', sub {
396-
my ($document, $mark) = @_;
397-
if (my $creator = $document->findnode('ancestor::ltx:contact', $document->getNode)) {
398-
$mark = join(',', cleanFrontmatterMarks($mark, 'LABEL'));
399-
Debug("MARKS set: $mark");
400-
$creator->setAttribute(_mark => $mark); } });
389+
# Find the entry for the ltx:creator/ltx:contact currently being digested.
390+
sub fetchPendingCreatorEntry {
391+
my $frontmatter = LookupValue('frontmatter');
392+
my @allcreators = @{ $$frontmatter{'ltx:creator'} || [] };
393+
if (my $last = $allcreators[-1]) {
394+
### if ((($$last[1]{role} || '') eq 'pending') && (($$last[2] || '') eq 'place_keeper')) {
395+
if (($$last[2] || '') eq 'place_keeper') {
396+
return $last; } }
397+
return; }
398+
399+
# These next two are primitives executing during digestion (BEFORE XML);
400+
# they add to or replace marks to be used when building the frontmatter plan.
401+
402+
# \lx@add@creator@mark adds comma separated marks to the currently digesting creator;
403+
# Typically would \let\inst to this, and used within creator's content
404+
# to identify contacts to include.
405+
# Can provide the prefix to distinguish different sets of marks
406+
DefPrimitive('\lx@add@creator@mark[]{}', sub {
407+
my ($document, $prefix, $mark) = @_;
408+
if (my $current = fetchPendingCreatorEntry()) {
409+
my $marks = $$current[1]{_marks};
410+
$mark = join(',', cleanFrontmatterMarks($mark, $prefix));
411+
$$current[1]{_marks} = ($marks ? "$marks,$mark" : $mark);
412+
Debug("MARKS add: $mark"); } });
413+
414+
# \lx@set@contact@label sets (replaces) the _marks on the currently digesting creator
415+
# which could be a stub (role=pending) for a to-be-inserted contact.
416+
# Typically would \let\label to this so that a \ref within a creator
417+
# will get a contact with corresponding \label will be attached.
418+
DefPrimitive('\lx@set@contact@label Semiverbatim', sub {
419+
my ($stomach, $label) = @_;
420+
if (my $current = fetchPendingCreatorEntry()) {
421+
$label = CleanLabel($label,'LABEL');
422+
$$current[1]{_marks} = $label;
423+
Debug("MARKS set: $label"); } });
401424

402425
# Append a piece of data to an existing frontmatter item that is contained in <$tag>
403426
# If $label is given, look for an item which has label=>$label,
@@ -452,22 +475,11 @@ DefMacro('\lx@add@authors{}',
452475
. '\lx@clear@frontmatter{ltx:contact}'
453476
# Note: must keep affiliations (after \\) embedded, to simplify clear@author removal
454477
. '\lx@splitting{\lx@author@and@affil}{\and,\And}{#1}');
455-
# NOTE: Dangling <ltx:break> in affiliation???
456478
DefMacro('\lx@author@and@affil{}', '\lx@author@and@affil@#1\\\\\done');
457479
DefMacro('\lx@author@and@affil@ Until:\\\\ Until:\\done',
458480
'\ifx.#2.\lx@add@creator[role=author]{#1}'
459481
. '\else\lx@add@creator[role=author]{#1\lx@add@contact[role=affiliation]{#2}}\fi');
460482

461-
# THIS SHOULD GO AWAY
462-
DefConstructor('\lx@contact@{}{}{}',
463-
"^<ltx:contact role='#1' _mark='#2'>#3</ltx:contact>");
464-
465-
DefConstructor('\lx@make@contact@ Undigested Undigested {} {}',
466-
"^<ltx:contact role='#role'_mark='#mark' name='#name'>#4</ltx:contact>",
467-
properties => sub {
468-
my ($stomach, $role, $mark, $name, $content) = @_;
469-
(role => $role, mark => $mark, name => $name); });
470-
471483
DefMacro('\lx@contact@affiliation@name', "Affiliation:~");
472484
DefMacro('\lx@contact@altaffiliation@name', "Alternate Affiliation:~");
473485
DefMacro('\lx@contact@address@name', "Address:~");

0 commit comments

Comments
 (0)