3

I am extending a class to take Cornell styled notes. For this the class heavily relies on tcolorboxes. I want to add bookmarks to the resulting PDF for some of these tcolorboxes but no matter what I try the bookmarks jump to the wrong location.

Here is the class:

\ProvidesClass{cornell}
\LoadClass[a4paper]{article}
\usepackage{tcolorbox}
\tcbuselibrary{breakable,skins,xparse}

\usepackage[margin=2cm]{geometry} % Change geometry of pages

\usepackage{bookmark} % Add bookmarks to the resulting PDF
\usepackage{hyperref}
\hypersetup{
    colorlinks   = true, % Colour links instead of ugly boxes
    urlcolor     = blue, % Colour for external hyperlinks
    linkcolor    = blue, % Colour of internal links
    citecolor    = red   % Colour of citations
    bookmarks    = true
}

\date{}

\renewcommand{\maketitle}{%
    \vspace{-3em}
    \pdfbookmark[0]{\@title}{title}
    \begin{tcolorbox}[width=\textwidth,lowerbox=invisible]
        \Huge\sffamily \@title
    \end{tcolorbox}
%    \vspace{2em}
}

\NewDocumentEnvironment{extra}{m}
{
    \pdfbookmark[1]{#1}{extra}
    \begin{tcolorbox}[
        width=\textwidth,
        colframe=black,
        colupper=black,
        opacitybacktitle=1,
        opacitytext=1,
        segmentation style={black!55,solid,opacity=0,line width=3pt},
        fonttitle=\large\bfseries\sffamily,
        title=#1,
    ]
}
{
    \end{tcolorbox}
}

\NewDocumentEnvironment{note}{o}
{
    \IfNoValueT{#1} {
        \vspace{-1em}
    }{}
    \begin{tcolorbox}[
        enhanced,
        breakable,
        enlarge left by=.34\textwidth,
        width=.66\textwidth,
        overlay={
            \IfNoValueF{#1} {
                \pdfbookmark[1]{#1}{note}
                \node[anchor=north west, outer sep=0pt, inner sep=0pt] at ([xshift=-.34\textwidth]frame.north west) {\begin{tcolorbox}[width=.325\textwidth]#1\end{tcolorbox}};
            }{}
        }
    ]
}
{
    \end{tcolorbox}
}

\NewDocumentEnvironment{summary}{}
{
    \vfill
    \pdfbookmark[1]{Summary}{summary}
    \begin{tcolorbox}[
        floatplacement=!b,
        float,
        colframe=black,
        colupper=black,
        opacitybacktitle=1,
        opacitytext=1,
        segmentation style={black!55,solid,opacity=0,line width=3pt},
        fonttitle=\large\bfseries\sffamily,
        title=Summary,
    ]
}
{
    \end{tcolorbox}
}

And here is a sample:

\documentclass{cornell}

\usepackage{lipsum}

\title{A topic we're taking notes on}

\begin{document}
\maketitle

\begin{extra}{Introduction}
    This can be used to introduce what is about to come, like
    \begin{enumerate}
        \item{What's the first question this section will answer?}
        \item{What's the second question?}
    \end{enumerate}
\end{extra}

\begin{note}[Some key term]
    \begin{itemize}
        \item{A cool thing}
        \item{Another cool thing}
        \item{Not all things are cool}
    \end{itemize}

    That has another paragraph.
\end{note}


\begin{summary}
    A fabulous summary.
    \\\\
    With multiple paragraphs.
\end{summary}

\begin{extra}{Second introduction}
    This is another introduction to a related yet different section.
\end{extra}

\begin{note}[Another term]
    \lipsum[4]
\end{note}
\begin{note}
    \lipsum[5]
\end{note}
\begin{note}
    \lipsum[6-7]
\end{note}

\end{document}
5
  • As far as I can tell, the pdf bookmark of "Introduction" correctly points to the "Introduction" box, while the bookmark of "Second Introduction" points to "Introduction" instead. To overcome this, you could change the definition of the extra environment to \NewDocumentEnvironment{extra}{mm} { \pdfbookmark[1]{#1}{#2} \begin{tcolorbox}[.... and use it as follows: \begin{extra}{Second introduction}{secondintro}.
    – leandriis
    Jan 27, 2021 at 19:05
  • For some background info, you can take a look at the hyperref manual: pdfbookmark[level]{text}{name}, "As name for the internal anchor name is used (in conjunction with level). Therefore the name must be unique (similar to \label)."
    – leandriis
    Jan 27, 2021 at 19:06
  • @leandriis That seems to have fixed the issue for the extra environments but the bookmarks for the note environments do not work at all. Same for the only summary environment used.
    – L. Resch
    Jan 27, 2021 at 19:49
  • The issue with non-unique names of \pdfbookmark is also true for the note environments. You could adapt its definition correspondingly.
    – leandriis
    Jan 27, 2021 at 19:52
  • @leandriis That's what I did but compared to the extra environment it did not help.
    – L. Resch
    Jan 27, 2021 at 20:44

2 Answers 2

1

Unique destination names

Macro \pdfbookmark from package hyperref also defines an anchor that is used as destination for the bookmark. Destination names must be unique. The last argument of \pdfbookmark is to be used to provide unique names. Since the class cornell defines several entities (environment note, ...) that can be used more than once, a counter helps to ensure uniqueness.

  1. Counter declaration:

    \newcounter{BkmCornell}
    \renewcommand*{\theBkmCornell}{\the\value{BkmCornell}}
    

    Macro \theBkmCornell is redefined to expand to a plain ASCII number. (The default definition of \theBkmCornell uses \arabic that also works most of the time, but it might be redefined in some languages.)

  2. The counter is incremented right before \pdfbookmark, example for inside environment note:

    \stepcounter{BkmCornell}%
    \pdfbookmark[1]{#1}{note\theBkmCornell}%
    

    The percent sign avoids trouble with spaces by line ends.

Placement of the bookmark

The best place is the top left corner of the entity.

  • For example, the bookmark can be placed in vertical mode right before the box with the entity. Disadvantage is that care is needed to prevent a page break between the bookmark and the box with the entity. This can be tricky, if the entity is an environment that adds page break points at its beginning.

    For example, the bookmark should not be used before an environment that can float away (environments figure, table, or option float of environment tcolorbox). In this cases the bookmark must go into the environment, see next item.

  • Another way is to include the bookmark inside the entity box, but move it to the top left corner. Example for environment note:

    \begin{tcolorbox}[
        % ...,
        enhanced,
        overlay={%
            \stepcounter{BkmCornell}%
            \node[inner sep=0pt, outer sep=0pt] at (frame.north west)
            {\pdfbookmark[1]{#1}{note\theBkmCornell}};%
        },
    ]
    
1
  • I tried your solution but some of the created links do not work at all while other are now closer but still off. I found the solution though and will answer the question for others.
    – L. Resch
    Jan 28, 2021 at 8:48
1

I found the solution in the tcolorbox documentation. There is a bookmark option that can be given to a tcolorbox as long as the bookmarks package is loaded. It will add a pdfbookmark automatically.

I had to use the bookmark* option to be able to manually set the level of the bookmark.

As an example, here is the definition of the title:

\renewcommand{\maketitle}{%
    \vspace{-3em}
    \begin{tcolorbox}[
        width=\textwidth,
        lowerbox=invisible,
        bookmark*={level=0}{\@title}
    ]
        \Huge\sffamily \@title
    \end{tcolorbox}
}

It seems like the uniqueness of the bookmark label is handled by tcolorbox automatically.

2
  • 1
    If you are working with cornell.cls and reading tcolorbox documentation, I suggest to look at section "Library xparse". You'll find commands like \DeclareTColorBoxequivalent to \NewDocumentEnvironment and others. This way you can simplify cornell.cls code.
    – Ignasi
    Jan 28, 2021 at 18:39
  • Thanks for the suggestion. I did apply some of it. See gitlab.com/MLNW/cornell-notes-template for the current code.
    – L. Resch
    Jan 29, 2021 at 10:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .