抽出された PDF 内の相互参照リンクの保持

抽出された PDF 内の相互参照リンクの保持

私は講義を書くときは、このmweのような1つの文書に書きます。

% 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}

私は、この main.tex ドキュメントを継続的に修正および拡張し、講義の進行に応じて、通常は章ごとにコンテンツを学生と共有します。そこで、次の mwe に沿った内容を含む新しいドキュメントを作成します。

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

そして、コンパイルした結果を共有します。このワークフローは、長年この方法で実行してきたため便利でしたが、問題は、ドキュメント内の章、目次、および方程式の相互参照のリンクがすべて失われることです。この問題を解決するのを手伝っていただけますか。または、不可能な場合は、別のワークフローを提案してください。

答え1

\includeonlyドキュメントの小さな部分をコンパイルするには、 を使用することをお勧めします。小さな部分のページ番号と相互参照が正確になるように、まずドキュメント全体をコンパイルしてください。

\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}

答え2

\includeおそらく、 /メカニズムに似たメカニズムが\includeonly良いかもしれません。

物事 (ファイルではなくファイルパーツ) がタイプセットのために処理されない場合に、カウンター値を含むいわゆるチェックポイントを補助ファイルに書き込むメカニズム。

\includeただし、 /メカニズムとは次のような違いがあります\includeonly

  1. \Filepart{⟨name of filepart⟩}特定の名前を持つファイルを読み取る代わりに、名前が付けられ、.tex-input-file 内でシーケンスとシーケンスの間にネストされている LaTeX ファイルの部分が読み取られます\EndOfFilepart

  2. コマンド と同様に\includeonly{⟨comma list with the names of the files that are to be read in⟩}、 コマンド も存在するはずです\OnlyFileparts{⟨comma list with the names of those fileparts that are to be read in for typesetting⟩}

  3. ファイルパーツをタイプセット用に読み込む必要がない場合、LaTeX は逐語モードに切り替えてファイルから読み取り、文字トークンを作成し、文字トークンのシーケンスが
    \EndOfFilepart
    見つかるまでそれらを破棄する必要があります。

  4. ファイル部分の内容が現在の LaTeX 実行でタイプセットされていないが、このファイル部分で定義されている相互参照ラベルなどのデータを保持する関連補助ファイルがまだ読み取られる場合は、オプションの引数が必要になります。この引数では、hyperref パッケージがロードされている場合に、このファイル部分を含む別の PDF ファイルへの URL を指定できます。これにより、タイプセットされていないファイル部分で定義された相互参照ラベルを相互参照するときに、宛先のない内部リンク (したがって、pdfTeX エンジンの宛先はページ 1 に自動的に固定されます) の代わりに、この別の PDF ファイルへの外部リンクが表示されます。

次の最小限の動作例では、メカニズムは次の 2 つのコンポーネントを組み合わせて調整されています。

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

そして

\Filepart[⟨URL of pdf-file containing this part⟩]{⟨name of filepart⟩}...\EndOfFilepart
  • \OnlyFilepartsメインの .tex ファイルのプリアンブルにのみ出現できます。
  • \include/メカニズムでは\includeonly、チェックポイントの名前はファイル名に対応します。\Filepart... \EndOfFilepart/\OnlyFilepartsメカニズムでは、チェックポイントは 1 から始まる連続番号が付けられ、チェックポイントと関連する補助ファイル/.aux ファイルの名前はスキームに従って付けられますFilepart⟨number of the checkpoint belonging to the filepart⟩。このようにして、いずれにしても一緒に読み込む必要がある複数のファイル部分に同じ名前を付けることができます。
  • ファイルパートがタイプセットされていない場合に、そのファイルパートを逐語的に読み取り、文字トークンを作成し、シーケンスが\EndOfFilepart見つかるまでそれらを破棄するメカニズムの部分は、行ごとにではなく、文字ごとに読み取ります。一方で、この方法では行内の文字が失われることはありません。他方、このメカニズムは低速のコンピューターでは低速です。
  • ファイルパーツ内にファイルパーツをネストしないでください。
  • \Filepart一致は\EndOfFilepart同じスコープ/グループ内にある必要があります。
  • \Filepart一致するものは\EndOfFilepart同じ .tex 入力ファイル内にある必要があります。
  • \Filepart[⟨URL of pdf-file containing this part⟩]{⟨name of filepart⟩}...\EndOfFilepartマクロ引数やマクロの置換テキストには出現してはならず、トークンレジスタなどの値の構成要素にもなってはなりません。
  • 次の最小限の動作例のコードは、TeX Live 2020 がインストールされたスマートフォンで作成されました。expl3 プログラミング環境が提供する機能を使用しています。テストのために、pdflatex [pdfTeX、バージョン 3.14159265-2.6-1.40.21 (TeX Live 2020) (プリロードされた形式 = pdflatex)、LaTeX2e <2020-10-01> パッチ レベル 4、L3 プログラミング レイヤー <2021-02-18>] でコンパイルされました。
  • 新しいフック システムが利用できる最近の LaTeX 2ε リリースでは、\include/メカニズムに、ファイルのインクルードが行わ\includeonlyれるたびにいくつかのトークンを実行するためのフックがいくつか付属しています。... /メカニズムではフックは実装されておらず、LaTeX 2ε の新しいフック システムは使用されていません。これは、この回答の最初のリリースの作成者がまだ LaTeX 2ε の新しいフック システムに十分慣れていないためです。\Filepart\EndOfFilepart\OnlyFileparts
  • \include/メカニズムは、\includeonlyアクティブ化する前に\includeonly、すべての相互参照などが一致するドキュメントを取得するのに必要な回数だけすべてのファイルがインクルードされてドキュメント全体がコンパイルされた場合にのみ機能します。同様に、\Filepart... \EndOfFilepart/\OnlyFilepartsメカニズムは、アクティブ化する前に\OnlyFileparts、すべての相互参照などが一致するドキュメントを取得するのに必要な回数だけすべてのファイルパーツがインクルードされてドキュメント全体がコンパイルされた場合にのみ機能します。
  • コードは徹底的にテストされていません。自己責任で使用してください。
\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}

関連情報