Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ inst/resources/gitbook/js/app.min.js.map
^_pkgdown\.yml$
^reference$
^pkgdown$
^tests/manual$
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: bookdown
Type: Package
Title: Authoring Books and Technical Documents with R Markdown
Version: 0.22.1
Version: 0.22.2
Authors@R: c(
person("Yihui", "Xie", role = c("aut", "cre"), email = "[email protected]", comment = c(ORCID = "0000-0003-0645-5666")),
person("JJ", "Allaire", role = "ctb"),
Expand Down Expand Up @@ -62,7 +62,7 @@ Description: Output formats and utilities for authoring books and technical docu
License: GPL-3
Imports:
htmltools (>= 0.3.6),
knitr (>= 1.22),
knitr (>= 1.31),
rmarkdown (>= 2.6),
xfun (>= 0.22),
tinytex (>= 0.12),
Expand Down
11 changes: 10 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# CHANGES IN bookdown VERSION 0.23


- [Theorem and Proof environment](https://bookdown.org/yihui/bookdown/markdown-extensions-by-bookdown.html#theorems) can now be used with `beamer_presentation2()` using fenced Div syntax like this
````markdown
::: {.theorem #label name="My Theorem"}
Content
:::
````

However, as _beamer_ defines its own LaTeX throem environments, **bookdown** won't add any definition in preamble as it is doing with `pdf_book()`. This means user will have to define the ones supported by **bookdown** and not yet defined by _beamer_. Special environment from _beamer_ (like `fact`) needs to be used with usual [Custom Blocks syntax](https://bookdown.org/yihui/rmarkdown-cookbook/custom-blocks.html). See related issues for examples in their discussions thread (thanks, @XiangyunHuang, #1143, #1145).
This change comes with several small improvements in `custom-enviromnent.lua` for `latex` and `beamer` format, including a new option `bookdown.theorem.preamble` to opt-out **bookdown** addition of theorems and proofs definitions in LaTeX preamble. Set it to `FALSE` if you have conflict with some specific format for example (like #1001).

# CHANGES IN bookdown VERSION 0.22

## NEW FEATURES
Expand Down
12 changes: 9 additions & 3 deletions R/latex.R
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,15 @@ add_toc_bib = function(x) {
restore_block2 = function(x, global = FALSE) {
i = grep('^\\\\begin\\{document\\}', x)[1]
if (is.na(i)) return(x)
# add the necessary definition in the preamble when block2 engine (\BeginKnitrBlock) or pandoc
# fenced div (\begin) is used
if (length(grep(sprintf('^\\\\(BeginKnitrBlock|begin)\\{(%s)\\}', paste(all_math_env, collapse = '|')), x)) &&
# add the necessary definition in the preamble when block2 engine
# (\BeginKnitrBlock) or pandoc fenced div (\begin) is used if not already
# define. But don't do it with beamer and it defines already amsthm
# environments.
# An options allow external format to skip this part
# (useful for rticles see rstudio/bookdown#1001)
if (getOption("bookdown.theorem.preamble", TRUE) &&
!knitr::pandoc_to("beamer") &&
length(grep(sprintf('^\\\\(BeginKnitrBlock|begin)\\{(%s)\\}', paste(all_math_env, collapse = '|')), x)) &&
length(grep('^\\s*\\\\newtheorem\\{theorem\\}', head(x, i))) == 0) {
theorem_label = vapply(theorem_abbr, function(a) {
label_prefix(a)()
Expand Down
87 changes: 53 additions & 34 deletions inst/rmarkdown/lua/custom-environment.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ local function print_debug(label,obj,iter)
label = "DEBUG (from custom-environment.lua): "..label
if (debug_mode) then
if not obj then
print(label)
print(label.." nil")
elseif (type(obj) == "string") then
print(label.." "..obj)
elseif type(obj) == "table" then
Expand All @@ -46,7 +46,7 @@ end
-- create a unique id for a div with none provided
local counter = 0
local function unlabeled_div()
counter = counter + 1
counter = counter + 1
return "unlabeled-div-"..(counter)
end

Expand All @@ -62,8 +62,16 @@ local function get_name(format, options)
return name
end

-- Create a label for referencing - only for theorem like env
local function create_label(env_type, id)
if (env_type.type ~= "theorem") then return nil end
label = string.format("%s:%s", theorem_abbr[env_type.env], id)
print_debug("label for reference -> ", label)
return label
end

-- Get metadata specific to bookdown for this filter
Meta = function(m)
Meta = function(m)
bookdownmeta = m.bookdown
if (bookdownmeta and bookdownmeta.language and bookdownmeta.language.label) then
-- For internationalization feature of bookdown
Expand All @@ -90,11 +98,11 @@ Div = function (div)
-- checking if the class is one of the supported custom environment
local env_type = {type = nil, env = nil}
for i,v in ipairs(classes) do
if (theorem_abbr[v] ~= nil) then
if (theorem_abbr[v] ~= nil) then
env_type.type = "theorem"
env_type.env = v
break
elseif (proof_label[v] ~= nil) then
elseif (proof_label[v] ~= nil) then
env_type.type = "proof"
env_type.env = v
break
Expand All @@ -109,47 +117,45 @@ Div = function (div)

-- get the id if it exists - it will we use to build label for reference
local id = div.identifier
-- if no id, one is generated so that bookdown labelling mechanism works
if #id == 0 then id = unlabeled_div() end
print_debug("id -> ", id)
-- remove unwanted identifier on the div, as it will be on the span
div.identifier = ""

-- get the attributes
local options = div.attributes
if (options["data-latex"] ~= nil) then
if (options["data-latex"] ~= nil or options["latex"] ~= nil) then
-- so that latex-divs.lua in rmarkdown does not activate
print("[WARNING] data-latex attribute can't be used with one of bookdown custom environment. It has been removed.")
options["data-latex"] = nil
options["latex"] = nil
end

-- create the custom environment
local label
-- Create a label for referencing - only for theorem like env
if (env_type.type == "theorem") then
label = string.format("%s:%s", theorem_abbr[env_type.env], id)
end
print_debug("label for reference -> ", label)

-- TODO: should we support beamer also ?
if (FORMAT:match 'latex') then
local label_part
if label then
label_part = string.format( "\n\\protect\\hypertarget{%s}{}\\label{%s}", label, label)
end
if (FORMAT:match 'latex' or FORMAT:match 'beamer') then
-- build the name
local name = get_name('latex', options)
table.insert(
div.content, 1,
pandoc.RawBlock('tex', string.format('\\begin{%s}%s%s', env_type.env, name, label_part or ""))
)
table.insert(
div.content,
pandoc.RawBlock('tex', string.format('\\end{%s}', env_type.env))
)
elseif (FORMAT:match 'html') then
local name = get_name('html', options)
-- build the label string for theorem env type
-- For LaTeX, only insert \label{} if an id as been provided explicitly
local label_part
if #id ~= 0 and env_type.type == "theorem" then
local label = create_label(env_type, id)
label_part = string.format("\\protect\\hypertarget{%s}{}\\label{%s}", label, label)
end
-- build the env string
local beginEnv = string.format('\\begin{%s}%s\n%s', env_type.env, name, label_part or "")
local endEnv = string.format('\\end{%s}', env_type.env)

-- if div is already processed by eng_theorem, it would also modify it.
-- similar to latex-div.lua in rmarkdown:
-- if the first and last div blocks are paragraphs then we can
-- bring the environment begin/end closer to the content
if div.content[1].t == "Para" and div.content[#div.content].t == "Para" then
table.insert(div.content[1].content, 1, pandoc.RawInline('tex', beginEnv))
table.insert(div.content[#div.content].content, pandoc.RawInline('tex', '\n' .. endEnv))
else
table.insert(div.content, 1, pandoc.RawBlock('tex', beginEnv))
table.insert(div.content, pandoc.RawInline('tex', endEnv))
end
elseif (FORMAT:match 'html') then
-- if div is already processed by eng_theorem, it would also modify it.
-- we can ignore knowing how eng_theorem modifies options$html.before2
-- It can be Plain or Para depending if a name was used or not.
-- MAYBE NOT VERY RELIABLE THOUGH
Expand All @@ -162,6 +168,13 @@ Div = function (div)
end
end

-- build the name
local name = get_name('html', options)
-- if no id, one is generated so that bookdown labelling mechanism works
if #id == 0 then id = unlabeled_div() end
-- build a label - only used to theorem type
local label = create_label(env_type, id)

-- inserted the correct span depending on the environment type
local span
if (env_type.type == "theorem") then
Expand All @@ -186,4 +199,10 @@ Div = function (div)
return div
end

return {{Meta = Meta}, {Div = Div}}
-- only run filter for supported format
if (FORMAT:match 'html' or FORMAT:match 'latex' or FORMAT:match 'beamer') then
return {{Meta = Meta}, {Div = Div}}
else
print_debug("Lua Filter skipped. Output format not supported:", FORMAT)
return {}
end
3 changes: 3 additions & 0 deletions tests/manual/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.pdf
*.tex
*.html
3 changes: 3 additions & 0 deletions tests/manual/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Manual tests

This folder contains Rmd files useful for visual inspecteion of some features
100 changes: 100 additions & 0 deletions tests/manual/theorem-proof-engine.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: "Theorem and Proof env using R engine"
documentclass: book
output:
bookdown::pdf_document2:
keep_tex: true
bookdown::html_document2: default
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

# Examples

```{definition}
The characteristic function of a random variable $X$ is defined by

$$\varphi _{X}(t)=\operatorname {E} \left[e^{itX}\right], \; t\in\mathcal{R}$$
```


```{example}
We derive the characteristic function of $X\sim U(0,1)$ with the probability density function $f(x)=\mathbf{1}_{x \in [0,1]}$.

\begin{equation*}
\begin{split}
\varphi _{X}(t) &= \operatorname {E} \left[e^{itX}\right]\\
& =\int e^{itx}f(x)dx\\
& =\int_{0}^{1}e^{itx}dx\\
& =\int_{0}^{1}\left(\cos(tx)+i\sin(tx)\right)dx\\
& =\left.\left(\frac{\sin(tx)}{t}-i\frac{\cos(tx)}{t}\right)\right|_{0}^{1}\\
& =\frac{\sin(t)}{t}-i\left(\frac{\cos(t)-1}{t}\right)\\
& =\frac{i\sin(t)}{it}+\frac{\cos(t)-1}{it}\\
& =\frac{e^{it}-1}{it}
\end{split}
\end{equation*}

Note that we used the fact $e^{ix}=\cos(x)+i\sin(x)$ twice.
```

```{lemma, chf-pdf}
For any two random variables $X_1$, $X_2$, they both have the same probability distribution if and only if

$$\varphi _{X_1}(t)=\varphi _{X_2}(t)$$
```

```{theorem, chf-sum}
If $X_1$, ..., $X_n$ are independent random variables, and $a_1$, ..., $a_n$ are some constants, then the characteristic function of the linear combination $S_n=\sum_{i=1}^na_iX_i$ is

$$\varphi _{S_{n}}(t)=\prod_{i=1}^n\varphi _{X_i}(a_{i}t)=\varphi _{X_{1}}(a_{1}t)\cdots \varphi _{X_{n}}(a_{n}t)$$
```

```{proposition}
The distribution of the sum of independent Poisson random variables $X_i \sim \mathrm{Pois}(\lambda_i),\: i=1,2,\cdots,n$ is $\mathrm{Pois}(\sum_{i=1}^n\lambda_i)$.
```

```{proof}
The characteristic function of $X\sim\mathrm{Pois}(\lambda)$ is $\varphi _{X}(t)=e^{\lambda (e^{it}-1)}$. Let $P_n=\sum_{i=1}^nX_i$. We know from Theorem \@ref(thm:chf-sum) that

\begin{equation*}
\begin{split}
\varphi _{P_{n}}(t) & =\prod_{i=1}^n\varphi _{X_i}(t) \\
& =\prod_{i=1}^n e^{\lambda_i (e^{it}-1)} \\
& = e^{\sum_{i=1}^n \lambda_i (e^{it}-1)}
\end{split}
\end{equation*}

This is the characteristic function of a Poisson random variable with the parameter $\lambda=\sum_{i=1}^n \lambda_i$. From Lemma \@ref(lem:chf-pdf), we know the distribution of $P_n$ is $\mathrm{Pois}(\sum_{i=1}^n\lambda_i)$.
```

```{remark}
In some cases, it is very convenient and easy to figure out the distribution of the sum of independent random variables using characteristic functions.
```

```{corollary}
The characteristic function of the sum of two independent random variables $X_1$ and $X_2$ is the product of characteristic functions of $X_1$ and $X_2$, i.e.,

$$\varphi _{X_1+X_2}(t)=\varphi _{X_1}(t) \varphi _{X_2}(t)$$
```

```{exercise, name="Characteristic Function of the Sample Mean"}
Let $\bar{X}=\sum_{i=1}^n \frac{1}{n} X_i$ be the sample mean of $n$ independent and identically distributed random variables, each with characteristic function $\varphi _{X}$. Compute the characteristic function of $\bar{X}$.
```

```{solution}
Applying Theorem \@ref(thm:chf-sum), we have

$$\varphi _{\bar{X}}(t)=\prod_{i=1}^n \varphi _{X_i}\left(\frac{t}{n}\right)=\left[\varphi _{X}\left(\frac{t}{n}\right)\right]^n.$$
```

```{hypothesis, name="Riemann hypothesis"}
The Riemann Zeta-function is defined as
$$\zeta(s) = \sum_{n=1}^{\infty} \frac{1}{n^s}$$
for complex values of $s$ and which converges when the real part of $s$ is greater than 1. The Riemann hypothesis is that the Riemann zeta function has its zeros only at the negative even integers and complex numbers with real part $1/2$.
```

# Referencing

You can see Theorem \@ref(thm:chf-sum) and Lemma \@ref(lem:chf-pdf)
Loading