面包屑超链接标题

面包屑超链接标题

我希望面包屑导航每页的页眉均有超链接。单击每个部分、章节、节将带您到该部分/章节/节的开头。

我已经在使用hyperref它来链接目录。

答案1

如何在每个部分/章节/节自动插入标签?请注意此解决方案(仿照如何通过章节编号获取章节标题?) 要求您至少使用部分/章节/节各一次。


编辑3:仍在开发中,但尝试通过首先将面包屑作为数据按顺序保存,将内容与呈现分开来实现通用化。这种基本跟踪将为面包屑提供更多可扩展的功能和不同的外观。有兴趣的请继续关注GitHub了解更多信息。(这里没有显示堆栈代码,但可以浏览这里


编辑2:仍在开发中,但在 egreg 的帮助下已移至 LaTeX3 语法。正在研究上一个。前沿技术GitHub


编辑:仍处于 WIP 阶段,但现在面包屑的长度根据评论而变化。仍在努力通过挖掘来源来反转chapterpage、等的偏好顺序。我还希望页面开头的当前部分成为面包屑的一部分,除非页面开头sectionpagefancyhdr节标题。

bredcrmb.sty

% GOAL: introduce a \pagestyle "breadcrumb" that will place the breadcrumb as a header.
\RequirePackage{xparse}
\RequirePackage{everypage
\RequirePackage{atbegshi}
\RequirePackage{fancyhdr}

\let\myhook\AtBeginShipout % playing with the two to see if I can get the desired output

% All credit to egreg for the following generalization: (#122823)
% My only additions were the booleans and related stuff.
\ExplSyntaxOn
% Macro to insert labels at the end of other macros
\NewDocumentCommand{\labelize}{mm}
{
  \breadcrumbs_labelize:Nn #1 { #2 }
}
\myhook{\pagestyle{breadcrumb}}
\cs_new_protected:Npn \breadcrumbs_labelize:Nn #1 #2 {
  % LaTeX3-ify
  \bool_new:c { g_breadcrumbs_in_#2 }
  \myhook{
    \bool_gset_false:c { g_breadcrumbs_in_#2 }
  }

  \cs_set_eq:cN { original_ \cs_to_str:N #1 } #1
  \RenewDocumentCommand #1 { som }
  {
    % Put page style stuff here
    \bool_gset_true:c { g_breadcrumbs_in_#2 }
    \thispagestyle{#2:style}
    \IfBooleanTF{##1}
    {
      \use:c { original_ \cs_to_str:N #1 }*{##3}
    }
    {
      \IfNoValueTF{##2}
      {
        \use:c { original_ \cs_to_str:N #1 } {##3}
      }
      {
        \use:c { original_ \cs_to_str:N #1 } [##2]{##3}
      }
      \label{#2: \use:c{the\cs_to_str:N #1} }%
    }
  }
}
% Much nicer syntax.  Thanks, egreg!
\labelize {\part}    {breadcrumb:part}
\labelize {\chapter} {breadcrumb:chapter}
\labelize {\section} {breadcrumb:section}

\fancypagestyle{breadcrumb:part:style}{
  \fancyhf{}
}
\fancypagestyle{breadcrumb:chapter:style}{
  \fancyhf{}
  \chead{
    \nameref{breadcrumb:part:\thepart}
  }
}
\fancypagestyle{breadcrumb:section:style}{
  \fancyhf{}
  \chead{
    \nameref{breadcrumb:part:\thepart}~$\rightarrow$~
    \nameref{breadcrumb:chapter:\thechapter}
  }
}
\fancypagestyle{breadcrumb}{
  \fancyhf{}
  \chead{
    \nameref{breadcrumb:part:\thepart}~$\rightarrow$~
    \nameref{breadcrumb:chapter:\thechapter}~$\rightarrow$~
    \nameref{breadcrumb:section:\thesection}
  }
}
\ExplSyntaxOff

test.tex

\documentclass{memoir}

\let\footruleskip\relax

\usepackage{bredcrmb} % Moved code to style file
\usepackage{fancyhdr}
\usepackage[colorlinks]{hyperref}

\pagestyle{breadcrumb}

\usepackage{mwe}
\begin{document}

\part{Part the First}
\chapter{Chapter Primo}
\section{Section A}
\lipsum
\section{Section B}
\lipsum
\chapter{Chapter Secundo}
\section{Section A}
\lipsum
\section{Section B}
\lipsum
\part{Part the Second}
\chapter{Chapter Primo}
\section{Section A}
\lipsum
\section{Section B}
\lipsum
\chapter{Chapter Secundo}
\section{Section A}
\lipsum
\section{Section B}
\lipsum

\end{document}

在此处输入图片描述

答案2

以下示例利用了这样一个事实:在构建标题行之前,部分命令的锚点已设置并已知。这意味着,只要仔细计时,就可以避免在第二次运行 LaTeX 时出现引用系统。

示例使用类book,其中\chaptermark\sectionmark\subsectionmark被重新定义为包含\hyperlink当前锚点,该锚点在 via或\@currentHref之前定义,用于未编号的节命令。需要进行一些修补才能插入或支持带星号的节命令或命令。此外,使用 的命令(如)也需要进行修补才能获得。\refstepcounter\phantomsection\partmark\tableofcontents\@markboth\chaptermark

示例中的章节标题取自用户手册pgf以获得更接近真实文件的感觉。

\documentclass{book}

\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{ragged2e}

\usepackage{etoolbox}

\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyfoot{}
\fancyhead{}
\cfoot{\thepage}
\lhead{%
  \RaggedRight
%  \HeaderFont
  \hypersetup{linkcolor=blue}%
  \rightmark
}

\newcommand*{\HeaderFont}{%
  \usefont{T1}{qhv}{c}{n}%
  \small
}
\makeatletter

\DeclareRobustCommand*{\BreadSep}{%
  \,\textbf{\guilsinglright}\hspace{0pt}\,%
}
\newcount\breadnav@level
\breadnav@level=0 %

\newcommand*{\breadnav@starmark}[2]{%
  \begingroup
    \c@secnumdepth=-9 %
    #1{#2}%
  \endgroup
}

\patchcmd{\@part}{\markboth}{%
  \partmark{#1}\@gobbletwo
}{}{}
\patchcmd{\@spart}{\normalfont}{%
  \breadnav@starmark\partmark{#1}%
  \normalfont
}{}{}
\newcommand*{\partmark}[1]{%
  \protected@xdef\CurrentPart{%
    \protect\hyperlink{\@currentHref}{%
      \ifnum\value{secnumdepth}>-2 %
        \thepart\@~%
      \fi
      #1%
    }%
  }%
  \markright{%
    \CurrentPart
  }%
}
\newcommand*{\CurrentPart}{}

\patchcmd{\@schapterhead}{\normalfont}{%
  \breadnav@starmark\chaptermark{#1}%
  \normalfont
}{}{}
\patchcmd{\tableofcontents}{\@mkboth}{%
  \breadnav@starmark\chaptermark{\contentsname}%
  \@gobbletwo
}
\renewcommand*{\chaptermark}[1]{%
  \protected@xdef\CurrentChapter{%
    \protect\hyperlink{\@currentHref}{%
      \ifnum\value{secnumdepth}>-1 %
        \if@mainmatter
          %\@chapapp~
          \thechapter.\@~%
        \fi
      \fi
      #1%
    }%
  }%
  \markright{%
    \ifx\CurrentPart\@empty
    \else
      \CurrentPart\BreadSep
    \fi
    \CurrentChapter  
  }%
}
\newcommand*{\CurrentChapter}{}

\patchcmd{\@startsection}{\@ifstar}{%
  \edef\CurrentSectionType{#1}%
  \@ifstar
}{%
  \patchcmd{\@ssect}{\@tempskipa}{%
    \expandafter\breadnav@starmark
    \csname\CurrentSectionType mark\endcsname{#5}%
    \@tempskipa
  }{}{}%
}{}
\renewcommand*{\sectionmark}[1]{%
  \protected@xdef\CurrentSection{%
    \protect\hyperlink{%
      \@currentHref
    }{%
      \ifnum\value{secnumdepth}>0 %
        \thesection.\@~%
      \fi
      #1%
    }%
  }%
  \markright{%
    \ifx\CurrentPart\@empty
    \else
      \CurrentPart\BreadSep
    \fi
    \ifx\CurrentChapter\@empty
    \else
      \CurrentChapter\BreadSep
    \fi
    \CurrentSection
  }%
}
\newcommand*{\CurrentSection}{}

\renewcommand*{\subsectionmark}[1]{%
  \protected@xdef\CurrentSubsection{%
    \protect\hyperlink{\@currentHref}{%
      \ifnum\value{secnumdepth}>1 %
        \thesubsection.\@~%
      \fi
      #1%
    }%
  }%
  \markright{%
    \ifx\CurrentPart\@empty
    \else
      \CurrentPart\BreadSep
    \fi
    \ifx\CurrentChapter\@empty
    \else
      \CurrentChapter\BreadSep
    \fi
    \ifx\CurrentSection\@empty
    \else
      \CurrentSection\BreadSep
    \fi
    \CurrentSubsection
  }%
}
\newcommand*{\CurrentSubsection}{}

\let\ps@plain\ps@fancy
\makeatother

\usepackage[colorlinks]{hyperref}
\usepackage{bookmark}
\bookmarksetup{numbered,open}

\usepackage{lipsum}

\addtolength{\textheight}{\headheight}
\setlength{\headheight}{21pt}
\addtolength{\textheight}{-\headheight}

\begin{document}
\title{Test document}
\author{Me}
\date{\today}
\maketitle
\tableofcontents
\chapter{Introduction}
\lipsum
\section{Structure of the System}
\lipsum
\section{Comparison with Other Graphics Packages}
\lipsum
\section{Utility Packages}
\lipsum
\section{How to Read This Manual}
\lipsum
\section{Authors and Acknowledgements}
\lipsum
\section{Getting Help}
\lipsum
\part{Tutorials and Guidelines}
\chapter{Tutorial: A Picture for Karl's Students}
\lipsum
\section{Problem Statement}
\lipsum
\section{Setting up the Environment}
\lipsum
\subsection{Setting up the Environment in \LaTeX}
\lipsum
\subsection{Setting up the Environment in Plain \TeX}
\lipsum
\subsection{Setting up the Environment in Con\TeX t}
\lipsum
\section{Straigt Path Construction}
\lipsum
\section{Curved Path Construction}
\lipsum
\section{Circle Path Construction}
\lipsum
\section{Rectangle Path Construction}
\lipsum
\end{document}

结果,第 8 页:

结果

和第 25 页:

结果

讨论

我认为主要的问题是面包屑标题占用了太多空间,如第二张快照所示,其中标题已经需要三行。

可以通过以下方式减少位置:

  • 该示例使用较短的分隔符号,\guilsinglright而不是较大的分隔符号\rightarrow

  • 较小的字体大小(\small\footnotesize)。

  • 压缩字体。遗憾的是,这些字体通常不适用于所需的字体系列。

以下快照显示了在 中启用\small压缩字体 Tex Gyre Hermes 后的结果。这会将上面第二张屏幕截图中的三行缩减为两行:\HeaderFont\lhead

结果

变体

如果将级别显示在单独的行中并缩进,导航路径的排列会更加清晰。这可以通过以下定义来实现\BreadSep(不支持需要多行的过长标题):

\DeclareRobustCommand*{\BreadSep}{%
  \\%
  \advance\breadnav@level by 1 %
  \hspace*{\breadnav@level\dimexpr1em\relax}%
  \textbf{\guilsinglright}\,%
}

使用此定义的屏幕截图并\small使用\HeaderFont

结果

但是,这需要与支持的部分级别一样多的行数。

如果标题较小,可以将不需要的空间还给正文,那就太好了。但页面构建标题及其可用空间是已知的。请记住,标签中的标题大小会引发一个问题,即如果重新排列页面材料,标题可能会发生变化。与包装类似,varioref这会导致文档永远不稳定。

答案3

编辑1:从所需包中删除不需要的包,以防止控制台中出现烦人的警告(反正也没做任何事情)


我知道这几乎是一篇遗留帖子,但我还是会这样做,以防将来有人碰到它。


我根据以下特点定制了@SeanAllred 的代码(接受的答案),并觉得我应该分享该代码:

  • 它仅打印最低可用的部分级别。

    如果您当前处于 中\part,但尚未开始\chapter\section,那么它将打印Part Name在标题中而不是Part Name → ??? → ???

    如果您已启动\partand \chapter,但没有\section,那么它将打印Part Name → Chapter Name而不是Part Name → Chapter Name → ???

  • 它将打印页面当前可用的最低文档部分。

    如果您的页面以 开头\chapter,那么它将Part Name → Chapter Name在开始时打印,而不是像以前的版本那样什么都不打印*。

  • 使得更改面包屑分隔符变得稍微容易一些。

  • 应用面包屑之前不重置页脚。

    以前它会重置页眉和页脚,现在它只会重置页眉。

由于我的代码远非完美,因此在使用时应注意以下几点:

* 目前,这将打印页面上的最后一部分。因此,如果您的页面有两个部分,则打印的是页面结束前的最后一部分。这可能是您想要的,也可能是不需要的,具体取决于您想要什么。如果您\section在一页上有多个 s,请记住这一点。

此外,页面样式会自动应用于全部 \part\chapter\section命令。(只要它们没有星号,例如\chapter*{Some Chapter})如果您只希望将其应用于某些分段命令,那么您将必须修改此代码。

最后,当调用其中一个分节命令(\part\chapter\section)时,它将为所有后续页面设置页面样式。如果您希望之后将页面样式恢复为其他样式,则必须调用该\pagestyle宏。

这是breadcrumb.sty

%! suppress = EscapeHashOutsideCommand
%! Package = breadcrumb
%! Author = vermiculus (Sean Allred), egreg, solonovamax, Heiko Oberdiek
%! Date = 2021-04-06

% Credits:
%  - vermiculus: Put things together & made shit work
%  - egreg: Contributed logic improvements
%  - solonovamax: added some minor tweaks + doc comments. All comments by solonovamax are signed with ``-s'' at the end.
%  - Heiko Oberdiek: stole their code for the seperator from their SO answer, since I [solonovamax] think it looks nicer.

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{breadcrumb}[2021/04/05]

\RequirePackage{xparse}
\RequirePackage{atbegshi}
\RequirePackage{fancyhdr}

% If you want to change the header style, use this:
%\DeclareRobustCommand*{\BreadSep}{%
%    ~\ensuremath{\rightarrow}~%
%}
% -s
\DeclareRobustCommand*{\BreadSep}{      % This seperator is stolen from Heiko Oberdiek.
    \,{\LARGE\textbf{\guilsinglright}}\hspace{0pt}\,%
}

\let\myhook\AtBeginShipout % playing with the two to see if I can get the desired output
\myhook{\pagestyle{breadcrumb}}

% All credit to egreg for the following generalization: (#122823)
% My [vermiculus's] only additions were the booleans and related stuff.
\ExplSyntaxOn
% Defines macro that allows you to hack the document sectioning commands. -s
\NewDocumentCommand{\labelize}{mm}{\breadcrumbs_labelize:Nn#1{#2}}

\cs_new_protected:Npn\breadcrumbs_labelize:Nn#1#2{
    % LaTeX3-ify
    \bool_new:c{g_breadcrumbs_in_#2}
    \myhook{
        \bool_gset_false:c{g_breadcrumbs_in_#2}
    }
    \cs_set_eq:cN{original_\cs_to_str:N#1}#1
    \RenewDocumentCommand#1{som}{% Put page style stuff here
        \bool_gset_true:c{g_breadcrumbs_in_#2}
%        \thispagestyle{#2:style} % This is redundant now, but didn't do much before, anyways.
%          (It only affected the \section command, since \part and \section print a new page at the start of the macro.)
%          -s
        \IfBooleanTF{##1}{
            \use:c{original_\cs_to_str:N#1}*{##3}
        }{
            \IfNoValueTF{##2}
            {\use:c{original_\cs_to_str:N#1}{##3}}
            {\use:c{original_\cs_to_str:N#1}[##2]{##3}}
%
            \label{#2:\use:c{the\cs_to_str:N#1}}%
            \thispagestyle{#2:style}% Set the style of this page, because SOME things (looking at you, \chapter) reset the style. -s
            \pagestyle{#2:style}% Set the style of all future pages. -s
        %  This means:
        %  All future pages will have the right level
        %  BUT this affects the entire document.
        %  -s
        }

    }
}

% Much nicer syntax.  Thanks, egreg!
% page styles are defined in the syntax: ``breadcrumb:[style name]:style''. You can copy & paste to define any new ones. -s
\fancypagestyle{breadcrumb:part:style}{
    \fancyhead{} % reset header -s
    \chead{\large\nameref{breadcrumb:part:\thepart}}
}%
\fancypagestyle{breadcrumb:chapter:style}{
    \fancyhead{} % reset header -s
    \chead{\large\nameref{breadcrumb:part:\thepart}\BreadSep\nameref{breadcrumb:chapter:\thechapter}}
}%
\fancypagestyle{breadcrumb:section:style}{
    \fancyhead{} % reset header -s
    \chead{\large\nameref{breadcrumb:part:\thepart}\BreadSep\nameref{breadcrumb:chapter:\thechapter}\BreadSep\nameref{breadcrumb:section:\thesection}}
}

\fancypagestyle{breadcrumb}{
    \fancyhead{} % reset header -s
    \chead{\large\nameref{breadcrumb:part:\thepart}\BreadSep\nameref{breadcrumb:chapter:\thechapter}\BreadSep\nameref{breadcrumb:section:\thesection}}
}

% This hacks the \part, \chapter, and \section commands. If you want more levels, define the new page styles and then labelize them.
\labelize{\part}    {breadcrumb:part}
\labelize{\chapter} {breadcrumb:chapter}
\labelize{\section} {breadcrumb:section}

\ExplSyntaxOff

要使用它,只需包括

\usepackage{breadcrumb}

在您的文档序言中。它将完成其他所有工作。

根据对原始答案的编辑,可以在 GH 上找到 SO 上发布的代码的更新版本,但无论我尝试什么,我都无法让 GH 上的代码正常工作,所以我只是坚持使用原始修改后的版本。

相关内容