I finally managed to put together an approach which is working - I believe - perfectly, although it has some not-really-elegant solutions, and therefore there is very likely (a lot of) room for improvement.
The basic idea is to include margin notes, both in HTML and PDF, and then these margin notes are those that will be displayed in the presentation. So they serve two purpose: a quick summary of the paragraph (somewhat Tufte-style) and the basis for creating the presentation.
The presentation comes only in one format, there is no incremental version, where bullet points appear one-by-one. (Actually, there are no more bullet points at all, texts are simply displayed as sentences in different paragraphs.)
To achieve this, I used the custom block function of bookdown
:
Text
```{block, type="handout"}
Margin note
```
Text
Here are the details:
- When compiling to HTML, the custom block conveniently compiles into a
div
, with appropriate type
, so all we have to do is the format it in the CSS file:
p {
text-align: justify;
width: 80%;
margin-left: 0;
margin-right: 20%;
}
li:not(.chapter) {
text-align: justify;
width: 80%;
margin-left: 0;
margin-right: 20%;
}
.handout {
float: right;
clear: right;
width: 18%;
margin-top: 0.5rem;
margin-bottom: 1rem;
font-size: 1.1rem;
line-height: 1.3;
vertical-align: baseline;
position: relative;
}
.handout p {
font-size:100%;
line-height:1.3;
-webkit-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
}
- When compiling into PDF, we unfortunately get an environment, but we can use the
environ
package to turn it to a single - marginnote
- command:
\NewEnviron{handout}{\marginnote{\footnotesize \BODY}[0.23cm]}
When compiling to beamer
, things get a bit trickier. I found a similar solution which uses preprocessor. Instead of that, I've chosen to use Pandoc's filters. Luckily, we even have an example that is quite close to what we want! We will use a lua filter, however, a few things should be tuned...
First, documentclass
is set "globally" (in index.Rmd
) to book
which won't work with beamer. Thus, in both beamer formats, we have to reset it:
function Meta(m)
if FORMAT=="beamer" then m.documentclass="beamer" end
return m
end
- Next, we should crop out everything, except the marginnotes and the figures. The former is recognized by looking for
RawBlock
type with tex
format which contains the text handout
, the latter needs some tweaking. Albeit it is a completely unrelated issue, here are the details: the part of the filter that recognizes the Image part should also be modified to work with Rmarkdown generated files: (el.t == "Para" and el.c[1].t == "Image") or
. More importantly, even this won't work if we use fig.align
or something like that as it changes the generated markdown's format from ![]()
to direct LaTeX code. So we have to add another condition: (el.t == "RawBlock" and el.format == "tex" and string.match( el.text, "includegraphics" ) ) or
. Overall, here is the second part of the lua filter:
function Pandoc(doc)
if FORMAT=="beamer" then
local hblocks = {}
for i,el in pairs(doc.blocks) do
if (el.t == "Div" and el.classes[1] == "handout") or
(el.t == "BlockQuote") or
(el.t == "RawBlock" and el.format == "tex" and string.match( el.text, "includegraphics" ) ) or
(el.t == "RawBlock" and el.format == "tex" and string.match( el.text, "handout" ) ) or
(el.t == "OrderedList" and el.style == "Example") or
(el.t == "Para" and el.c[1].t == "Image") or
(el.t == "Header") then
table.insert(hblocks, el)
end
end
return pandoc.Pandoc(hblocks, doc.meta)
end
end
- The fact that we don't cut out the
handout
environment means that we have to do something with it, we simply translate it to text:
\NewEnviron{handout}{\BODY}
- We still have to be careful to break long slides. Luckily, there is an
allowframebreaks
option in beamer (which is considered evil, but I think here it is completely justified, or rather, we don't have any better solution); the only problem is that we can't add it to each slide, as we have no direct control on the LaTeX code for the frames. Luckily, there's a solution to modify the option in header to make it default, and we can easily do it in preamble.tex
. I combine this solution with a more elegant numbering scheme:
\let\oldframe\frame
\renewcommand\frame[1][allowframebreaks]{\oldframe[#1]}
\makeatletter
\defbeamertemplate*{frametitle continuation}{only if multiple}{%
\ifnum \numexpr \beamer@endpageofframe+1-\beamer@startpageofframe\relax > 1
\insertcontinuationcount.%
\fi
}
\makeatother
The most non-elegant part is that we can't include the beamer_presentation
output to twice, and with different names, or at least I don't know a solution for this so we have to manually compile it with bookdown::render_book
and don't forget to rename (and move) the resulting compiled file afterwards.
This also means that we have to give up using the Build Book
button, unfortunately. We rather have to create a script to do all what the button would (and I hope that I made no mistake, and it is indeed doing the same as the button...):
bookdown::render_book( "index.Rmd", "bookdown::pdf_book" )
bookdown::render_book( "index.Rmd", "bookdown::gitbook" )
bookdown::render_book( "index.Rmd", "bookdown::epub_book" )
bookdown::render_book( "index.Rmd", "beamer_presentation" )
file.rename( "FerenciTamas_ValszamEsStatAlapvonalai.pdf", "./docs/FerenciTamas_ValszamEsStatAlapvonalai_handout.pdf" )
Finally, we also need a custom Pandoc template, as for the presentation it is easily possible that we need a short title (which is not currently supported by Pandoc). So I changed \title{$title$$if(thanks)$\thanks{$thanks$}$endif$}
to \title[$if(short-title)$$short-title$$endif$]{$title$$if(thanks)$\thanks{$thanks$}$endif$}
(adding a short-title
element to index.Rmd
).
It's again an unrelated issue, but I also changed the \frame{\sectionpage}
line in \AtBeginSection
to
\begin{frame}{$toc-title$}
\tableofcontents[currentsection]
\end{frame}
which is of course mostly a matter of taste, but an objective reason is that it works in non-English languages as well (the original template would display "Section 1" even if non-English language is selected).
And that's it!
You can find everything put together, in a completely realized project here: https://github.com/tamas-ferenci/FerenciTamas_ValszamEsStatAlapvonalai.
Of course, I really welcome any feedback, criticism or suggestion on improvement.