Beibehalten von Querverweisen in einer extrahierten PDF-Datei

Beibehalten von Querverweisen in einer extrahierten PDF-Datei

Wenn ich meine Vorlesungen schreibe, schreibe ich sie in ein Dokument wie dieses mwe

% document name : main.tex
\documentclass{scrbook}
\usepackage{etoc}
\newcommand{\chaptertoc}[1][Contenu du chapitre]{%
    %\etocsettocstyle{\addsec*{#1}}{}%
    \etocsettocstyle{\addsec*{#1\\\rule{\textwidth}{0.4pt}} \small }{}
    \localtableofcontents%
}

\usepackage{hyperref}

\usepackage[]{blindtext}

\begin{document}
\tableofcontents
\chapter{Chapter One}
\chaptertoc{}
\section{section one of chapter one}
\Blindtext
\section{section two of chapter one}
\Blindtext
\chapter{Chapter Two}
\chaptertoc{}
\section{section one of chapter two}
\Blindtext
\section{section two of chapter two}
\Blindtext
\section{section three of chapter two}
\Blindtext
\end{document}

Ich ändere und erweitere dieses main.tex-Dokument ständig und teile den Inhalt je nach Fortgang der Vorlesung mit meinen Studenten, normalerweise Kapitel für Kapitel. Also erstelle ich ein neues Dokument, das ungefähr dieses mwe enthält:

% document name: pdf_chapter1.tex
\documentclass{article}
\usepackage[]{pdfpages}
\usepackage{hyperref}
\begin{document}
    \includepdf[pages={3-5}]{main}
\end{document}

Und teilen Sie das kompilierte Ergebnis. Der Arbeitsablauf war praktisch, da ich ihn schon seit vielen Jahren so mache, aber das Problem ist, dass ich alle Links mit Querverweisen der Kapitel, des Inhaltsverzeichnisses und der Gleichungen im Dokument verliere. Können Sie mir bei der Lösung dieses Problems helfen oder, falls das nicht möglich ist, einen anderen Arbeitsablauf vorschlagen?

Antwort1

Ich würde vorschlagen, \includeonlykleinere Teile des Dokuments zu kompilieren. Stellen Sie sicher, dass Sie zuerst das gesamte Dokument kompilieren, damit Seitenzahlen und Querverweise in den kleineren Teilen korrekt sind.

\documentclass{scrbook}
\usepackage{etoc}
\newcommand{\chaptertoc}[1][Contenu du chapitre]{%
    %\etocsettocstyle{\addsec*{#1}}{}%
    \etocsettocstyle{\addsec*{#1\\\rule{\textwidth}{0.4pt}} \small }{}
    \localtableofcontents%
}

\usepackage{hyperref}

\usepackage[]{blindtext}

\begin{filecontents*}[overwrite]{cap1.tex}
\chapter{Chapter One}
\chaptertoc{}
\section{section one of chapter one}
\Blindtext
\[
  E = mc^{2}\label{eq}
\]
\section{section two of chapter one}
\Blindtext
\end{filecontents*}

\begin{filecontents*}[overwrite]{cap2.tex}
\chapter{Chapter Two}
\chaptertoc{} 
\section{section one of chapter two}
\Blindtext
\section{section two of chapter two}
\Blindtext
\section{section three of chapter two}
\Blindtext
\ref{eq}
\end{filecontents*}

\includeonly{cap2}

\begin{document}
\tableofcontents

\include{cap1}
\include{cap2}

\end{document}

Antwort2

Ein Mechanismus ähnlich dem \include/ \includeonly-Mechanismus wäre wahrscheinlich nett.

Ein Mechanismus, der für den Fall, dass Dinge (Fileparts statt Dateien) nicht zum Satz verarbeitet werden, auch sog. Checkpoints mit Zählerwerten in Hilfsdateien schreibt.

Allerdings mit folgenden Unterschieden zum \include/ \includeonly-Mechanismus:

  1. Anstatt Dateien mit bestimmten Namen zu lesen, würden Teile einer LaTeX-Datei gelesen, die mit Namen versehen sind und die in der .tex-Eingabedatei zwischen einer Sequenz \Filepart{⟨name of filepart⟩}und einer Sequenz verschachtelt sind \EndOfFilepart.

  2. Analog zum Befehl \includeonly{⟨comma list with the names of the files that are to be read in⟩}müsste es einen Befehl geben \OnlyFileparts{⟨comma list with the names of those fileparts that are to be read in for typesetting⟩}.

  3. Wenn ein Dateiteil nicht zum Satz eingelesen werden soll, müsste LaTeX in den Verbatim-Modus wechseln und aus der Datei lesen, Zeichen-Token erstellen und diese verwerfen, bis die Folge der Zeichen-Token
    \EndOfFilepart
    gefunden ist.

  4. Für den Fall, dass der Inhalt eines Fileparts im aktuellen LaTeX-Lauf nicht gesetzt wird, die zugehörige Hilfsdatei, die die Daten von in diesem Filepart definierten Querverweislabels und dergleichen bereithält, aber trotzdem gelesen wird, müsste es ein optionales Argument geben, wo man, falls das Hyperref-Paket geladen wird, die URL zu einer anderen PDF-Datei angeben kann, die dieses Filepart enthält, damit beim Querverweis auf Querverweislabels, die im nicht gesetzten Filepart definiert wurden, statt eines internen Links ohne Ziel (und damit bei von der pdfTeX-Engine automatisch auf Seite 1 festgelegtem Ziel) ein externer Link zu dieser anderen PDF-Datei erscheint.

Mit dem folgenden minimalen Arbeitsbeispiel wird ein Mechanismus aus den folgenden zwei Komponenten zusammengebastelt:

\OnlyFilepart{⟨comma list with the names of those fileparts that are to be read in for typesetting⟩}

Und

\Filepart[⟨URL of pdf-file containing this part⟩]{⟨name of filepart⟩}...\EndOfFilepart
  • \OnlyFilepartskann nur in der Präambel der Haupt-.tex-Datei erscheinen.
  • Beim \include/ \includeonly-Mechanismus haben die Checkpoints Namen, die den Namen der Dateien entsprechen. Beim \Filepart... \EndOfFilepart/ \OnlyFileparts-Mechanismus werden die Checkpoints beginnend mit der Nummer 1 durchnummeriert und sie sowie die zugehörigen Hilfsdateien/.aux-Dateien haben Namen nach dem Schema Filepart⟨number of the checkpoint belonging to the filepart⟩. Auf diese Weise können mehrere Dateiteile, die auf jeden Fall gemeinsam eingelesen werden müssen, den gleichen Namen haben.
  • Der Teil des Mechanismus, der im Falle des Nichtsetzens eines Dateiteils diesen Dateiteil wörtlich liest und Zeichentoken erzeugt und wegwirft, bis die Sequenz \EndOfFilepartgefunden ist, liest nicht Zeile für Zeile, sondern Zeichen für Zeichen. Einerseits gehen auf diese Weise keine Zeichen in einer Zeile verloren. Andererseits ist der Mechanismus auf langsamen Computern langsam.
  • Verschachteln Sie keine Dateiteile in Dateiteilen.
  • \Filepartund die Übereinstimmung \EndOfFilepartmuss im selben Bereich/in derselben Gruppe liegen.
  • \Filepartund die Übereinstimmung \EndOfFilepartmuss in derselben .tex-Eingabedatei liegen.
  • \Filepart[⟨URL of pdf-file containing this part⟩]{⟨name of filepart⟩}...\EndOfFilepartdürfen weder in Makroargumenten noch in Ersetzungstexten von Makros vorkommen noch Bestandteil von Werten von Token-Registern o.ä. sein.
  • Der Code des folgenden minimalen Arbeitsbeispiels wurde auf einem Smartphone geschrieben, auf dem TeX Live 2020 installiert war. Es nutzt die von der Programmierumgebung expl3 bereitgestellten Möglichkeiten. Zum Testen wurde es mit pdflatex kompiliert [pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (vorinstalliertes Format=pdflatex), LaTeX2e <2020-10-01> Patchlevel 4, L3-Programmierschicht <2021-02-18>].
  • Bei neueren Versionen von LaTeX 2ε, in denen das neue Hook-System verfügbar ist, enthält der \include/ -Mechanismus einige Hooks, um bei jeder Einbindung einer Datei einige Token auszuführen. Beim ... / -Mechanismus sind keine Hooks implementiert bzw. das neue Hook-System von LaTeX 2ε wird nicht verwendet. Dies liegt daran, dass der Autor der ersten Version dieser Antwort noch nicht ausreichend an das neue Hook-System von LaTeX 2ε gewöhnt ist.\includeonly\Filepart\EndOfFilepart\OnlyFileparts
  • Der \include/ \includeonly-Mechanismus funktioniert nur, wenn vor der Aktivierung \includeonlydas gesamte Dokument mit allen enthaltenen Dateien so oft wie nötig kompiliert wurde, um das Dokument mit allen passenden Querverweisen usw. zu erhalten. Analog dazu funktioniert der \Filepart... \EndOfFilepart/ -Mechanismus nur, wenn vor der Aktivierung das gesamte Dokument mit allen enthaltenen Dateiteilen so oft wie nötig kompiliert wurde, um das Dokument mit allen passenden Querverweisen usw. zu erhalten.\OnlyFileparts\OnlyFileparts
  • Der Code wurde nicht intensiv getestet. Die Verwendung erfolgt auf eigene Gefahr.
\makeatletter
%----------------------------------------------------------------------------------------------------
% Infrastructure for switching to verbatim-mode and gobbling things until encountering 
% \EndDocumentPart
%----------------------------------------------------------------------------------------------------
\ExplSyntaxOn
\cs_new_eq:NN \UD@StringCase \str_case:nnTF 
\cs_new_eq:NN \UD@StringTail \str_tail:n
\cs_new_eq:NN \UD@IfEmpty \tl_if_empty:nTF
%\cs_new_eq:NN \UseName \use:c
%\cs_new:Npn \ExpandArgs #1
% {
% \cs_if_exist_use:cF { exp_args:N #1 }
% { \msg_expandable_error:nnn { kernel } { unknown-arg-expansion } {#1} }
% }
%\msg_new:nnn { kernel } { unknown-arg-expansion }
% { Unknown~arg~expansion~"#1" }
\ExplSyntaxOff
\newcommand\UD@SwitchToVerbatimAndGgobbleToEndOfFilepart[1]{%
  \begingroup
  \endlinechar=-1\relax
  \let\do\@makeother\dospecials\do\^^I\do\^^M% 
  \UD@GgobbleToEndOfFilepartLoop{#1}{}%
}%
\begingroup
\newcommand\UD@GgobbleToEndOfFilepartLoop[4]{%
  \if#4Z\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {%
    \endgroup
    \newcommand\UD@GgobbleToEndOfFilepartLoop[3]{%
      \UD@StringCase{##2##3}{#1{#3}{\endgroup##1}}{}{%
        \UD@IfEmpty{##2}%
          {\UD@GgobbleToEndOfFilepartLoop{##1}{##3}}%
          {\ExpandArgs{ne}\UD@GgobbleToEndOfFilepartLoop{##1}{\UD@StringTail{##2}}{##3}}%
      }%
    }%
  }{%
    \UD@GgobbleToEndOfFilepartLoop
    {#1#2}%
    {{#3#4}{\UD@GgobbleToEndOfFilepartLoop{##1}{##2##3}}}%
    {#3#4}%
  }%
}%
\@firstofone{%
  \let\do\@makeother\dospecials\do\^^I\do\^^M%
  \UD@GgobbleToEndOfFilepartLoop{}{}{}%
}\EndOfFilepartZ%
%----------------------------------------------------------------------------------------------------
% Infrastructure for patching/restoring \newlabel and \new@label@record:
%----------------------------------------------------------------------------------------------------
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\@ifdefinable\UD@Savednewlabel{}%
\@ifdefinable\UD@Savednew@label@record{}%
\newcommand*\UD@ResetNewlabelAndNew@label@record[1]{%
  \AtIfFilepartIncluded{#1}{}{%
    \csname @\ifx\csname ver@hyperref.\@pkgextension\endcsname\relax gobble\else firstofone\fi\endcsname
    {\let\newlabel\UD@Savednewlabel}%
    \let\new@label@record\UD@Savednew@label@record
  }%
}%
\newcommand\UD@SwitchNewlabelAndNew@label@record[2]{%
  \AtIfFilepartIncluded{#2}{}{%
    \csname @\ifx\csname ver@hyperref.\@pkgextension\endcsname\relax gobble\else firstofone\fi\endcsname
    {%
      \let\UD@Savednewlabel\newlabel
      \def\newlabel{\UD@Patchednewlabel{#1}}%
    }%
    \let\UD@Savednew@label@record\new@label@record
    \def\new@label@record{\UD@Patchednew@label@record{#1}}%
  }%
}%
\@ifdefinable\UD@Patchednewlabel@AddURL{%
  \long\def\UD@Patchednewlabel@AddURL#1#2#3#4#5#6\\{{#2}{#3}{#4}{#5}{#1}}%
}%
\newcommand\UD@Patchednewlabel[3]{%
  \expandafter\UD@PassFirstToSecond
  \expandafter{%
    \UD@Patchednewlabel@AddURL{#1}#3{}{}{}{}\\%
  }%
  {\UD@Savednewlabel{#2}}%
}%
\newcommand\UD@Patchednew@label@record[3]{%
  \UD@Savednew@label@record{#2}{#3{xr-url}{#1}}%
}%
%----------------------------------------------------------------------------------------------------
% Infrastructure for \Filepart and \EndOfFilepart
%----------------------------------------------------------------------------------------------------
\newwrite\UD@Filepartaux
\newcommand\UD@previous@auxout{}%
\newif\ifUD@FilepartSW\UD@FilepartSWfalse
\newcommand\UD@FilepartNesting{0}%
\newcommand\UD@FilepartList{}%
\newcounter{UD@FilepartCheckpoints}%
%----------------------------------------------------------------------------------------------------
\newcommand\OnlyFileparts[1]{%
  \UD@FilepartSWtrue
  \let\UD@FilepartList\@empty
  \@for\reserved@a:=#1\do
  {%
    \ifx\UD@FilepartList\@empty
      \expandafter\def\expandafter\UD@FilepartList\expandafter{\reserved@a}%
    \else
      \expandafter\expandafter\expandafter\def
      \expandafter\expandafter\expandafter\UD@FilepartList
      \expandafter\expandafter\expandafter{\expandafter\UD@FilepartList\expandafter,\reserved@a}%
    \fi
  }%
}%
\@onlypreamble\OnlyFileparts
%----------------------------------------------------------------------------------------------------
\NewDocumentCommand\Filepart{om}{%
  \relax
  \xdef\UD@FilepartNesting{\the\numexpr((\UD@FilepartNesting)+1)\relax}%
  \ifnum\UD@FilepartNesting>1 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {%
    \@latex@error{\string\Filepart\space cannot be nested}\@eha
    \UD@SwitchToVerbatimAndGgobbleToEndOfFilepart{\EndOfFilepart}%
  }%
  {%
    \clearpage
    \addtocounter{UD@FilepartCheckpoints}\@ne
    \if@filesw
      \IfNoValueF{#1}{%
        \immediate\write\@auxout{\string\UD@SwitchNewlabelAndNew@label@record{#1}{#2}}%
      }%
      \immediate\write\@auxout{\string\@input{Filepart\arabic{UD@FilepartCheckpoints}.aux}}%
      \IfNoValueF{#1}{%
        \immediate\write\@auxout{\string\UD@ResetNewlabelAndNew@label@record{#2}}%
      }%
    \fi
    \let\UD@previous@auxout\@auxout
    \@tempswatrue
    \AtIfFilepartIncluded{#2}%
    {%
      \let\@auxout\UD@Filepartaux
      \if@filesw
        \immediate\openout\UD@Filepartaux "Filepart\arabic{UD@FilepartCheckpoints}.aux"
        \immediate\write\UD@Filepartaux{\relax}%
      \fi
    }{%
      \UD@SwitchToVerbatimAndGgobbleToEndOfFilepart{%
        \deadcycles\z@
        \@nameuse{cp@Filepart\arabic{UD@FilepartCheckpoints}}%
        \let\@auxout\UD@previous@auxout
        \xdef\UD@FilepartNesting{\the\numexpr((\UD@FilepartNesting)-1)\relax}%
      }%
    }%
  }%
}%
%----------------------------------------------------------------------------------------------------
\newcommand\AtIfFilepartIncluded[1]{%
  \begingroup
  \@tempswatrue
  \ifUD@FilepartSW
    \@tempswafalse
    \def\reserved@b{#1}%
    \@for\reserved@a:=\UD@FilepartList\do{%
      \ifx\reserved@a\reserved@b\@tempswatrue\fi
    }%
  \fi
  \expandafter\endgroup
  \if@tempswa\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}%
%----------------------------------------------------------------------------------------------------
\newcommand*\EndOfFilepart{%
  \ifnum\UD@FilepartNesting=1 \expandafter\@firstofone\else\expandafter\@gobble\fi
  {%
    \clearpage
    \if@filesw
      \immediate\write\UD@Filepartaux{\string\@setckpt{Filepart\arabic{UD@FilepartCheckpoints}}\@charlb}%
      {\let\@elt\@wckdocumentptelt \cl@@ckpt}%
      \immediate\write\UD@Filepartaux{\@charrb}%
      \immediate\closeout\UD@Filepartaux
    \fi
    \let\@auxout\UD@previous@auxout
  }%
  \ifnum\UD@FilepartNesting<1 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\@latex@error{Unmatched \string\EndOfFilepart}\@eha}%
  {\xdef\UD@FilepartNesting{\the\numexpr((\UD@FilepartNesting)-1)\relax}}%
}%
\newcommand*\@wckdocumentptelt[1]{%
  \immediate\write\UD@Filepartaux{\string\setcounter{#1}{\the\@nameuse{c@#1}}}%
}%
%----------------------------------------------------------------------------------------------------
\makeatother

\documentclass{scrbook}
\usepackage{etoc}
\newcommand{\chaptertoc}[1][Contenu du chapitre]{%
    %\etocsettocstyle{\addsec*{#1}}{}%
    \etocsettocstyle{\addsec*{#1\\\rule{\textwidth}{0.4pt}}\small}{}%
    \localtableofcontents
}


%\OnlyFileparts{Lecture2}
%\OnlyFileparts{Lecture1}
%\OnlyFileparts{Lecture3,Lecture4}

\usepackage[pdfnewwindow=true]{hyperref}
\usepackage[]{blindtext}

\begin{document}
\Filepart{ToC}%
\tableofcontents
\EndOfFilepart
\Filepart[file:./Lecture1.pdf]{Lecture1}%
\chapter{Chapter One}
\chaptertoc{}
\section{section one of chapter one}
\Blindtext
\section{section two of chapter one}
\label{A label}%
\Blindtext
\EndOfFilepart
\Filepart{Lecture2}%
\chapter{Chapter Two}
\chaptertoc{}
\section{section one of chapter two}
\Blindtext
\section{section two of chapter two}
\Blindtext
\section{section three of chapter two}
\Blindtext
\EndOfFilepart
\Filepart{Lecture3}%
\chapter{Chapter Three}
\chaptertoc{}
\section{section one of chapter three}
\Blindtext
\ref{A label}%
%\expandafter\show\csname r@A label\endcsname
\section{section two of chapter three}
\Blindtext
\section{section three of chapter three}
\Blindtext
\EndOfFilepart
\Filepart{Lecture4}%
\chapter{Chapter Four}
\chaptertoc{}
\section{section one of chapter four}
\Blindtext
\section{section two of chapter four}
\Blindtext
\section{section three of chapter four}
\Blindtext
\EndOfFilepart
\Filepart{Lecture2}%
\chapter{Chapter Five - should always go together with Chapter Two}
\chaptertoc{}
Chapter Five should always go together with Chapter Two, 
thus\verb|\Filepart|-commands get the same name.
\section{section one of chapter five}
\Blindtext
\section{section two of chapter five}
\Blindtext
\section{section three of chapter five}
\Blindtext
\EndOfFilepart
\end{document}

verwandte Informationen