LaTeXML

 view release on metacpan or  search on metacpan

lib/LaTeXML/Package/inst_support.sty.ltxml  view on Meta::CPAN

# | Released to the Public Domain                                       | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Package::Pool;
use strict;
use warnings;
use LaTeXML::Package;

# This bit of code supports the \inst style institution markup
# used by several document classes and styles
# [aa, llncs, sv]

# This supports single or multiple authors along with single or multiple affiliations.
# You put ALL authors in a SINGLE \author, POSSIBLY separated by \and.
# You put ALL institutions in a SINGLE \institute, POSSIBLY separated by \and.
# If there are multiple separated institutes, then you can use \inst{number} after an
# author (whether or not the authors separated by \and), to indicate the number-th institute.
# BUT you can leave off all \and and \inst to just have an amorphous line of authors
# and affiliations!

# In LaTeX, \inst generates a footnote mark, and \institution puts counters within the
# institution line.

# Our implementation strategy is similar, but we split the \institution into several
# ltx:note's. We check to see if there is an ltx:creator with a footnote mark
# with the same mark number, and copy the institute information into that creator element
# as an ltx:contact(with @role='institute').

# add optinal argument for OmniBus use
DefMacro('\author[]{}', sub {
    map { (T_CS('\lx@author'), T_BEGIN, @$_, T_END) } SplitTokens($_[2], T_CS('\and'), T_OTHER(',')); });

DefMacro('\@institutemark{}', '\lx@contact{institutemark}{#1}');

# \inst typically appears INSIDE \author, so @add@to@frontmatter doesn't sync them
DefConstructor('\@@@inst{}',
  "^<ltx:contact role='institutemark' _mark='#1'>#1</ltx:contact>"
    . "<ltx:contact role='emailmark' _mark='#1'>#1</ltx:contact>");
DefMacro('\@inst{}', '\@add@to@frontmatter{ltx:creator}{\@@@inst{#1}}');
DefMacro('\inst{}', sub {
    map { (T_CS('\@inst'), T_BEGIN, @$_, T_END) } SplitTokens($_[1], T_OTHER(',')); });

Let('\at',      '\and');    # Actually this is different than \and, but...
Let('\iand',    '\and');
Let('\nand',    '\and');
Let('\lastand', '\and');
Let('\AND',     '\and');

NewCounter('inst', 'document');
DefMacro('\institute{}',
  '\bgroup\setcounter{inst}{1}'
    . '\let\and\institute@and\let\iand\institute@and\let\nand\institute@and\let\lastand\institute@and'
    . '\let\at\institute@and'    # Actually something quite different...?
    . '\let\email\@in@inst@email\@new@institute#1\@end@institute\egroup');
DefMacro('\institute@and', '\@end@institute\stepcounter{inst}\@new@institute');
DefMacro('\@new@institute XUntil:\@end@institute', '\if.#1.\else\@add@institute{#1}\fi');
Let('\@end@institute', '\relax');

#should play similar game as with institute, relocate?
DefMacro('\emailname', 'E-mail');
DefConstructor('\@in@inst@email{}',
  "<ltx:note role='email' name='#name' mark='#mark'>#1</ltx:note>",
  properties => sub { (name => Digest(T_CS('\emailname')),
      mark => ToString(Expand(T_CS('\theinst')))); });

# This creates the note for each institute.
DefConstructor('\@add@institute {}',
  "<ltx:note role='institutetext' mark='#mark'>#1</ltx:note>",
  bounded    => 1, beforeDigest => sub { AssignValue(inPreamble => 0); },
  properties => sub { (mark => ToString(Expand(T_CS('\theinst')))); });

# Reconnecting the institute to the appropriate author:
# [Handling is similar to reconnecting footnotemark & footnotetext]
Tag('ltx:note', afterClose => \&relocateInstitute);

sub relocateInstitute {
  my ($document, $instnode) = @_;
  if (($instnode->getAttribute('role') || '') eq 'institutetext') {
    if (my $mark = $instnode->getAttribute('mark')) {
      # Find authors with same mark.
      my @authors;
      if (@authors = $document->findnodes(".//ltx:contact[\@role='institutemark'][\@_mark='$mark']")) {
        foreach my $author (@authors) {
          $document->appendClone($author, $instnode->childNodes);
          $author->setAttribute(role => 'institute');
          $author->removeAttribute('_mark'); }
        $instnode->parentNode->removeChild($instnode); }
      # Not sure if this is right; find authors WITHOUT a contact mark.
      elsif (@authors = $document->findnodes(".//ltx:creator[not(descendant::ltx:contact[\@role='institutemark'])]")) {
        foreach my $author (@authors) {
          $document->appendTree($author, ['ltx:contact', { role => 'institute' }, $instnode->childNodes]);
          $instnode->parentNode->removeChild($instnode); } }
  } }
  # Or relocate email
  if (($instnode->getAttribute('role') || '') eq 'email') {
    if (my $mark = $instnode->getAttribute('mark')) {
      # Find authors with same mark.
      my @authors;
      if (@authors = $document->findnodes(".//ltx:contact[\@role='emailmark'][\@_mark='$mark']")) {
        foreach my $author (@authors) {
          $document->appendClone($author, $instnode->childNodes);
          $author->setAttribute(role => 'email');
          $author->removeAttribute('_mark'); }
        $instnode->parentNode->removeChild($instnode); }
  } }
  return; }

1;



( run in 0.557 second using v1.01-cache-2.11-cpan-71847e10f99 )