추출된 PDF에서 상호 참조 링크 유지

추출된 PDF에서 상호 참조 링크 유지

저는 강의를 작성할 때 이 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}

나는 계속해서 이 main.tex 문서를 수정 및 확장하고 강의 진행 상황에 따라 일반적으로 장별로 콘텐츠를 학생들과 공유합니다. 그래서 나는 다음 mwe의 내용을 포함하는 새 문서를 만듭니다.

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

그리고 컴파일된 결과를 공유합니다. 워크플로(is)는 수년간 이렇게 해왔기 때문에 편리했지만, 문제는 문서의 장, 목차, 방정식의 상호 참조 링크가 모두 사라진다는 것입니다. 이 문제를 해결하는 데 도움을 주시겠습니까? 아니면 가능하지 않은 경우 다른 작업 흐름을 제안해 주시겠습니까?

답변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. 특정 이름을 가진 파일을 읽는 대신 LaTeX 파일의 일부를 읽어 이름이 지정되고 .tex-input-file에서 시퀀스 \Filepart{⟨name of filepart⟩}와 시퀀스 사이에 중첩됩니다 \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. \EndOfFilepart
    조판을 위해 파일 부분을 읽어서는 안 되는 경우 LaTeX는 축어 모드로 전환하여 파일에서 읽고 문자 토큰을 생성한 후 문자 토큰 시퀀스를 찾을 때까지 버려야 합니다 .

  4. 파일 부분의 내용이 현재 LaTeX 실행에서 조판되지 않았지만 이 파일 부분에 정의된 상호 참조 레이블 및 이와 유사한 데이터를 보유하는 관련 보조 파일을 여전히 읽는 경우, 선택적 인수. 하이퍼참조 패키지가 로드되는 경우 이 파일 부분을 포함하는 다른 PDF 파일에 대한 URL을 지정할 수 있으므로 비타입셋 파일 부분에 정의된 상호 참조 레이블을 상호 참조할 때 이 다른 PDF 파일에 대한 외부 링크는 대상이 없는 내부 링크 대신 나타납니다(따라서 pdfTeX 엔진 대상은 1페이지로 자동 고정됩니다).

다음과 같은 최소 작업 예제에서는 메커니즘이 다음 두 구성 요소와 함께 작동됩니다.

\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메커니즘이 파일을 포함할 때마다 일부 토큰을 수행하기 위한 몇 가지 후크와 함께 제공됩니다. \Filepart... \EndOfFilepart/ - 메커니즘을 사용하면 \OnlyFileparts후크가 구현되지 않으며 LaTeX 2ε의 새로운 후크 시스템이 사용되지 않습니다. 이는 이 답변의 초기 릴리스 작성자가 아직 LaTeX 2ε의 새로운 후크 시스템에 충분히 익숙하지 않기 때문입니다.
  • \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}

관련 정보