Rewriting the standard classes with xparse
The problem is that hyperref
redefines \@part
, essentially for doing what you do yourself with the spart
counter.
You don't need to use two macros, anyway. I wouldn't change the syntax of part: the optional argument should go before the mandatory one.
\documentclass{book}
\usepackage{xparse}
\usepackage{hyperref}
\makeatletter
\DeclareDocumentCommand{\part}{s O{#3} m}{%
\cleardoublepage\thispagestyle{plain}%
\if@twocolumn
\onecolumn
\@tempswatrue
\else
\@tempswafalse
\fi
\null\vfil
\IfBooleanTF{#1}
{% * version
\csname phantomsection\endcsname % for hyperref
\addcontentsline{toc}{part}{#2}%
}
{% standard version
\ifnum\c@secnumdepth >-2\relax
\refstepcounter{part}%
\addcontentsline{toc}{part}{\thepart\hspace{1em}#2}%
\else
\addcontentsline{toc}{part}{#2}%
\fi
}%
\markboth{}{}%
{% print the title
\centering \interlinepenalty\@M \normalfont
\IfBooleanF{#1}
{% standard version
\ifnum \c@secnumdepth >-2\relax
\huge\bfseries \partname~\thepart
\par
\vskip 20\p@
\fi
}%
\Huge \bfseries #2\par
}%
\@endpart
}
\makeatother
\begin{document}
\tableofcontents
\part{Teil 1}
\part[Ops 2]{Teil 2}
\part*{Teil 3}
\part*[Ops 4]{Teil 4}
\end{document}
Note that you need the most recent version of xparse
for this to work (release 2017/02/10 or later).
hyperref
does a redefinition of \addcontentsline
, \label
and of sectioning commands, adding functionality for hyperlinks etc.
If your definition should not interfere with hyperref
, it should grab the definition of \@part
etc. after hyperref
has done its job or redefine it after hyperref
.
Wrapping the redefinition in a \AtBeginDocument{...}
works.
I took the original version of the O.P. and wrapped in the \AtBeginDocument{...}
hook, in my opinion, there's no need to use the latest version of xparse
for this.
\documentclass{book}
\usepackage{xparse}
\newcounter{spart}% makes hyperref work
\usepackage{blindtext}
\usepackage{hyperref}
\makeatletter
\AtBeginDocument{%
\DeclareDocumentCommand{\part}{s m o}%
{\cleardoublepage\thispagestyle{plain}%
\if@twocolumn%
\onecolumn%
\@tempswatrue%
\else%
\@tempswafalse%
\fi%
\null\vfil%
\IfNoValueTF{#3}%
{\IfBooleanTF{#1}{\m@part*{#2}{#2}}{\m@part{#2}{#2}}}%
{\IfBooleanTF{#1}{\m@part*{#2}{#3}}{\m@part{#2}{#3}}}}
\DeclareDocumentCommand{\m@part}{s m m}%
{\IfBooleanTF{#1}{\refstepcounter{spart}% makes hyperref work
\addcontentsline{toc}{part}{#3}}%
{\ifnum \c@secnumdepth >-2\relax%
\refstepcounter{part}%
\addcontentsline{toc}{part}{\thepart\hspace{1em}#3}%
\else%
\addcontentsline{toc}{part}{#3}%
\fi}%
\markboth{}{}%
{\centering%
\interlinepenalty \@M%
\normalfont%
\IfBooleanF{#1}{\ifnum \c@secnumdepth >-2\relax%
\huge\bfseries \partname~\thepart%
\par%
\vskip 20\p@%
\fi}%
\Huge \bfseries #2\par}%
\@endpart}
}
\makeatother
\begin{document}
\tableofcontents
\part{Teil 1}
\Blinddocument
\part*{Teil 2}
\Blinddocument
\end{document}