
Я верстаю документ, в котором цвет заголовков разделов периодически меняется. Я хочу также раскрасить записи разделов в toc в соответствии с цветами соответствующих разделов.
Чтобы сделать это, я использую \setkomafont{sectioning}
и "внедряю" команды цвета в toc. Это работает так, как и ожидалось, хотя у меня есть ощущение, что последнее является своего рода неправильным использованием записей toc. \setkomafont{sectionentry}
и \setkomafont{sectionentrypagenumber}
не работает, поскольку они окрашивают их всех одинаково (поскольку они, конечно, находятся в одном и том же разделе документа).
Проблема в следующем: когда я использую hyperref, я получаю эти Token not allowed in a PDF string
предупреждения, поскольку эти "инжектированные" команды попадают в оглавление файла PDF. Еще большей проблемой является то, что при переопределении hyperref \contentsline
цвет номера страницы исчезает. \DeclareTOCStyleEntry
не помогает в любом случае, поскольку он не знает номер раздела, который необходим для определения правильного цвета. Тем не менее, он нужен, чтобы сделать это правильно без hyperref.
Вот MWE:
\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{blindtext}
\usepackage{arrayjobx}
\usepackage{pgf}
\usepackage{hyperref}
\colorlet{myblue}{blue!60!green!90!black}
\colorlet{myred}{red!80!black}
\colorlet{mygreen}{green!40!black}
\colorlet{default}{black}
\newarray\structurecolors
\readarray{structurecolors}{mygreen&myblue&myred}
\makeatletter
\newcommand{\structurecolor}[1][\value{section}]{%
\pgfmathparse{int(mod(#1,\total@structurecolors) + 1)}%
\checkstructurecolors(\pgfmathresult)%
\color{\cachedata}%
\ifnum#1=0%
\color{black}
\fi
}
\makeatother
\setkomafont{sectioning}{\sffamily\bfseries\structurecolor}
\renewcommand{\addsectiontocentry}[2]{%
\IfArgIsEmpty{#1}{%
\addtocentrydefault{section}{}{#2}
}{%
\addtocentrydefault{section}{\structurecolor[#1]#1}{\protect\structurecolor[#1]#2}
}
}
\DeclareTOCStyleEntry[pagenumberformat={\sffamily\bfseries}]{default}{section}
\begin{document}
\tableofcontents
\Blinddocument
\Blinddocument
\end{document}
Следует отметить, что использование этого tocloft
пакета — лишь крайний вариант, поскольку koma-script не рекомендует использовать tocloft.
Раскомментируйте, \usepackage{hyperref}
чтобы увидеть желаемый результат. Спасибо за любую помощь или предложения.
решение1
ну, "токен не допускается" можно обойти, как всегда \texorpdfstring
, с помощью , например, что-то вроде \texorpdfstring{\protect\structurecolor[#1]#2}{#2}
. Относительно цвета: вы полагаетесь на то, что текст и номер страницы находятся в одной группе. Но hyperref, естественно, должен добавить скобки и группировку для ссылок. Сохраните цвет в какой-нибудь глобальной переменной, а затем повторите его в номере страницы:
\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{blindtext}
\usepackage{arrayjobx}
\usepackage{pgf}
\usepackage{hyperref}
\colorlet{myblue}{blue!60!green!90!black}
\colorlet{myred}{red!80!black}
\colorlet{mygreen}{green!40!black}
\colorlet{default}{black}
\newarray\structurecolors
\readarray{structurecolors}{mygreen&myblue&myred}
\makeatletter
\newcommand{\structurecolor}[1][\value{section}]{%
\pgfmathparse{int(mod(#1,\total@structurecolors) + 1)}%
\checkstructurecolors(\pgfmathresult)%
\color{\cachedata}%
\global\let\currentstructurecolor\cachedata
\ifnum#1=0%
\color{black}
\fi
}
\makeatother
\setkomafont{sectioning}{\sffamily\bfseries\structurecolor}
\renewcommand{\addsectiontocentry}[2]{%
\IfArgIsEmpty{#1}{%
\addtocentrydefault{section}{}{#2}
}{%
\addtocentrydefault{section}{\structurecolor[#1]#1}{\texorpdfstring{\protect\structurecolor[#1]#2}{#2}}
}
}
\DeclareTOCStyleEntry[pagenumberformat={\sffamily\bfseries\color{\currentstructurecolor}}]{default}{section}
\begin{document}
\showoutput
\tableofcontents
\section{a}
\section{b}
% \Blinddocument
% \Blinddocument
\end{document}
решение2
Если вы используете \addtocontents{toc}{}
внутри \renewcommand{\addsectiontocentry}{...}
него, это никак не влияет на pdf toc. Тогда вам не нужно вызывать \structurecolor[#1]
внутри \addtocentrydefault
. Используйте \begingroup ... \endgroup
для внесения изменений локально. Этот способ даже \DeclareTOCStyleEntry
больше не нужен.
\renewcommand{\addsectiontocentry}[2]{%
\IfArgIsEmpty{#1}{%
\addtocentrydefault{section}{}{#2}
}{%
\addtocontents{toc}{\begingroup\structurecolor[#1]}
\addtocentrydefault{section}{#1}{#2}
\addtocontents{toc}{\endgroup}
}
}
Полная МВЭ:
\documentclass{scrartcl}
\usepackage{xcolor}
\usepackage{blindtext}
\usepackage{arrayjobx}
\usepackage{pgf}
\usepackage{hyperref}
\colorlet{myblue}{blue!60!green!90!black}
\colorlet{myred}{red!80!black}
\colorlet{mygreen}{green!40!black}
\colorlet{default}{black}
\newarray\structurecolors
\readarray{structurecolors}{mygreen&myblue&myred}
\makeatletter
\newcommand{\structurecolor}[1][\value{section}]{%
\pgfmathparse{int(mod(#1,\total@structurecolors) + 1)}%
\checkstructurecolors(\pgfmathresult)%
\color{\cachedata}%
\ifnum#1=0%
\color{black}
\fi
}
\makeatother
\setkomafont{sectioning}{\sffamily\bfseries\structurecolor}
\setkomafont{sectionentry}{\sffamily\bfseries}
\renewcommand{\addsectiontocentry}[2]{%
\IfArgIsEmpty{#1}{%
\addtocentrydefault{section}{}{#2}
}{%
\addtocontents{toc}{\begingroup\structurecolor[#1]}
\addtocentrydefault{section}{#1}{#2}
\addtocontents{toc}{\endgroup}
}
}
\begin{document}
\tableofcontents
\section{a}
\section{b}
\end{document}