• 新鲜事
  • 漂亮的 LaTeX 书籍模版 ElegantBook

最近在 Github 上看到一个很漂亮的书籍模版 ElegantBook 谁有兴趣把它 bookdown 化?输出 PDF 和 Gitbook两种格式,我觉得可以作为下一届 bookdown 大赛的作品

比较难的地方应该是 CSS 样式定制,还有各种 block 定制

    Cloud2016 有人关于 bookdown 某个问题跟我联系过,其间涉及一个名叫 EleganBook 的模板,我还试图把它不可挡化,后来被我删掉了,然而现在我一点都想不起来更详细的前因后果,想不起来是不是同一个 ElegantBook,以及为啥我把它删掉了……搜历史邮件也搜不到……

    I dreamt I was old.

      dapengde 我也是同样的经历,这个模版我试图两次 bookdown 化,奈何都感觉自己 LaTeX 方面弱了,转的不太好,另外 CSS 定制各个block也不是我擅长的,做的自己不满意都删掉了,谁要是能达到我想要的样式,我向谢大推荐进下一届 bookdown 获奖名单

        Cloud2016 我看了半天也没见着一个样式示例,所以到底咋个优雅法嘛。这种涉及到视觉的作品应该多列举一些截屏啊。好不容易在 CTAN 上找到了文档可作为示例:https://ctan.org/pkg/elegantbook 看着还可以。

        要把它转入 bookdown,可以先不考虑 HTML 版本,只做 LaTeX 版本的,理论上应该只是个 Pandoc LaTeX 模板啊。

          yihui 我摆弄了一下 latex。一般格式还容易,比如加个 tightlist 支持啥的,就是那些定理示例环境需要转成 bookdown 支持的 block,而这个 我忘了怎么弄了,或者是压根儿就没学会过 刚刚温习了一下:<https://bookdown.org/yihui/bookdown/custom-blocks.html>。

          确实漂亮,不过距离惊艳还差那么一丢丢,我觉得。不知道为什么。

            Cloud2016 我的记忆找回了!

            大约两个月前,有个 bookdownplus 的用户发邮件给我,推荐了一个名叫 ElegantPaper 的 LaTeX 模板(这就是为啥我在邮件里搜 ElegantBook 搜不到)。它跟 ElegantBook 模板是同一家子。我把ElegantPaper 不可挡化之后弄进了 bookdownplus 的模板库里。诡异的是,我连 commit 都没写,就搁在那儿了……

            ElegantPaper 早就可以用 bookdownplus 安装使用了:

            bookdownplus('elegantpaper_zh')

            然而我从来没用过,于是就忘干净了。

            ElegantBook 可以慢慢变。目前我变了一个版本,可以直接安装:

            bookdownplus('elegantbook')

            没弄完,所以会出现编译错误的 pdf 文档,可以打开看。目前明面上的问题就是参考文献、交叉引用、页眉页码有错误,隐藏的问题是定理等环境没法用,说是 openbox 重复定义。然而眼下我没时间去逐个折腾,只能先放在那儿了。

              dapengde 那这样的话距离我想要的样子还很远,\openbox already defined. 原因是他们自定义的block有的和 bookdown 定义的block名称一样

              这是他们自定义的 definition

              \begin{definition}{可积性}{int}
              设 $ f(x)=\sum\limits_{i=1}^{k} a_i \chi_{A_i}(x)$ 是 $E$ 上的非负简单函数,其中 $\{A_1,A_2,\ldots,A_k\}$ 是 $E$ 上的一个可测分割,$a_1,a_2,\ldots,a_k$ 是非负实数。定义 $f$ 在 $E$ 上的积分为 $\int_{a}^b f(x)$
              \begin{equation}
                 \label{inter}
                 \int_{E} f dx = \sum_{i=1}^k a_i m(A_i) \pi \alpha\beta\sigma\gamma\nu\xi\epsilon\varepsilon. 
              \end{equation}
              一般情况下 $0 \leq \int_{E} f dx \leq \infty$。若 $\int_{E} f dx < \infty$,则称 $f$ 在 $E$ 上可积。
              \end{definition}

              这是 bookdown 对 definition 的定义

              ```{definition, name="可积性", label="int"}
              设 $ f(x)=\sum\limits_{i=1}^{k} a_i \chi_{A_i}(x)$ 是 $E$ 上的非负简单函数,其中 $\{A_1,A_2,\ldots,A_k\}$ 是 $E$ 上的一个可测分割,$a_1,a_2,\ldots,a_k$ 是非负实数。定义 $f$ 在 $E$ 上的积分为 $\int_{a}^b f(x)$
              \begin{equation}
                 \int_{E} f dx = \sum_{i=1}^k a_i m(A_i) \pi \alpha\beta\sigma\gamma\nu\xi\epsilon\varepsilon. 
                 (\#eq:inter)
              \end{equation}
              一般情况下 $0 \leq \int_{E} f dx \leq \infty$。若 $\int_{E} f dx < \infty$,则称 $f$ 在 $E$ 上可积。
              ```

              转化后的 LaTeX 代码

              \BeginKnitrBlock{definition}[可积性]
              \begin{definition}
              
              \protect\hypertarget{def:int}{}{\label{def:int} \iffalse (可积性) \fi{} }设 \$ f(x)=\sum\limits\emph{\{i=1\}\^{}\{k\} a\_i \chi}\{A\_i\}(x)\$ 是 <code class="katex-escape">\(E\)</code> 上的非负简单函数,其中 <code class="katex-escape">\(\{A_1,A_2,\ldots,A_k\}\)</code> 是 <code class="katex-escape">\(E\)</code> 上的一个可测分割,<code class="katex-escape">\(a_1,a_2,\ldots,a_k\)</code> 是非负实数。定义 <code class="katex-escape">\(f\)</code> 在 <code class="katex-escape">\(E\)</code> 上的积分为 <code class="katex-escape">\(\int_{a}^b f(x)\)</code>
              \begin{equation}
                 \int_{E} f dx = \sum_{i=1}^k a_i m(A_i) \pi \alpha\beta\sigma\gamma\nu\xi\epsilon\varepsilon. 
                 \label{eq:inter}
              \end{equation}
              一般情况下 <code class="katex-escape">\(0 \leq \int_{E} f dx \leq \infty\)</code>。若 <code class="katex-escape">\(\int_{E} f dx < \infty\)</code>,则称 <code class="katex-escape">\(f\)</code> 在 <code class="katex-escape">\(E\)</code> 上可积。
              
              \end{definition}
              \EndKnitrBlock{definition}

              yihui 我不太想动上游的 ElegantBook 的模版,这会增加维护成本,使用 bookdown 的内建 block 和自定义 block 会出现奇奇怪怪的现象,这个好理解,就是上游开发人员可能没想过要和 bookdown 的 block 定义风格保持一致,所以需要这种高度自定义又不依赖 bookdown ,只有 Pandoc 提供的 divs-and-spans 。这样做可以尽可能地不动他们的 LaTeX 模版,而只是用 Pandoc lua filter 做替换, 自定义block实现会复杂一些 但是可塑性会很强,最好的办法就是和他们商量一下,具有共同的 block 能不能和 bookdown 内建的block 保持一致

                Cloud2016 yihui LaTeX 自定义环境有没有可能像 css 那样,同一个设置,后出现的自动把原先的覆盖?

                除了用 pandoc lua filter 之外,bookdown 在编译时,有没有选项可以关闭自动往 tex 文档里添加的定理等环境的定义?这个问题以前我在把 LaTeX 模板转 bookdown 时好像遇到过好几次,不会弄,就放弃了好些。大部分模板,只需添加 tightlist,shaded,highlight 等几个环境,就可以在 bookdown 里用了。

                  1 个月 后
                  5 天 后

                  Cloud2016 看样子,ElegantBook 的模版中应该是调用了LaTeX tcolorbox 宏包. 该宏包可以设置各种漂亮个block 风格。比如背景颜色,边框颜色,titlebox的位置等等。不知道这个信息是否有用。

                  9 个月 后

                  Cloud2016 关于elegantbook的问题,LaTeX 编译不过,主要是因为,bookdown 会在preamble 最后自动添加amsthm的定理环境定义。这个仅靠模板似乎不能解决。一个解决办法是用bookdown.post.latex。具体来说就是在index.Rmd 开头家上下面的设置

                  ```{r remove_amsthm,  include=FALSE}
                  options(bookdown.post.latex = function(x) {
                      from <- grep("usepackage\\{amsthm\\}", x)
                      to <- grep("newtheorem\\*\\{solution", x)
                      x <- x[-c(from:to)]
                    })
                  ```

                  效果可以参看 agfun.netlify.com.

                    18 天 后

                    Fye 我把你仓库里的 bookdown.post.latex 抄进我的项目里了 https://github.com/XiangyunHuang/ElegantBookdown/blob/master/.Rprofile#L12

                    最近重构了一下,项目 ElegantBookdown 里比较得意的地方就是没有依赖自定义的 LaTeX 模版了,仅用 Pandoc 2.9.2 内建的模版,所以一下子感觉清爽了。 CSS 这块还没想好要什么风格的,以后有时间再搞一下

                    • Fye 回复了此帖
                    • Fye 觉得很赞

                      @yihui @Fye @dapengde 自 2019年4月开帖至今,刚好过去差不多一年的时间,终于把这事给告一段落了 🎉 LaTeX 部分已经完成,完全没有自定义 Pandoc LaTeX 模版,一来担心增加维护成本,二来现在的 Pandoc 内建的 LaTeX 模版功能很丰富,三来 ElegantBook 本身功能定义非常完整,所以最好不搞 patch。送两张截图

                      elegantbookdown-page-4

                      elegantbookdown-page-5

                      Cloud2016 我没有注意到,原来模板试不需要的。这样就更方便了。你要的几个css 块的LaTeX,我有。CSS我没有太在意,从@yihui 那里抄了几个,自己有改造了一下,花了些时间找自由版权的图片。🙂

                      \usepackage{tcolorbox}
                      
                      \tcbset{
                      	noparskip/.style={before={\pagebreak[0]\parskip=0pt\parindent=0pt}},
                      	before skip=-\baselineskip,
                          box align=top,
                          enhanced,
                          breakable,
                          left=0pt,
                          right=0pt,
                          top=2pt,
                          bottom=2pt,
                          opacityframe=0,
                          opacitybacktitle=0.5,
                          width=\dimexpr\textwidth\relax,
                          enlarge left by=0mm,
                      }
                      
                      \makeatletter
                      
                      \ifdefstring{\ELEGANT@lang}{cn}{
                      \newcommand{\rmdnotename}{注意}
                      \newcommand{\tipname}{提示}
                      \newcommand{\warnname}{警告}
                      \newcommand{\thinkname}{思考}
                      }{\relax}
                      
                      \ifdefstring{\ELEGANT@lang}{en}{
                        \setlength\parindent{2em}
                        \newcommand{\rmdnotename}{Note}
                        \newcommand{\tipname}{Tips}
                        \newcommand{\warnname}{Warning}
                        \newcommand{\thinkname}{Think}
                      }{\relax}
                      
                      \makeatother
                      
                      \newenvironment{rmdnote}{
                      	\vspace*{0.5\baselineskip}
                          \par\noindent
                          \makebox[-3pt][r]{\color{red!90}\size{8}{\textdbend}\,\,}
                          \begin{tcolorbox}[
                          title={\textbf{\color{second}\rmdnotename}},
                          title style={left color=blue!10!green!20!white,right color=yellow!20!blue!20!white},
                          colback=red!10!white,
                          ]
                          \itshape
                      }{
                          \end{tcolorbox}
                          \par\ignorespacesafterend
                      }
                      
                      \newenvironment{rmdtip}{
                      	\vspace*{0.5\baselineskip}
                      	\par\noindent
                      	\makebox[-3pt][r]{\color{red!90}\size{12}{\HandRight}\,\,}
                          \begin{tcolorbox}[
                          enhanced,
                          title={\textbf{\color{second}\tipname}},
                          title style={left color=blue!10!green!20!white,right color=yellow!20!blue!20!white},
                          colback=cyan!10!white,
                          ]
                          \sffamily
                      }{
                          \end{tcolorbox}
                          \par\ignorespacesafterend
                      }
                      
                      \newenvironment{rmdthink}{
                      	\vspace*{0.5\baselineskip}
                      	\par\noindent
                      	\makebox[-4pt][r]{\color{green!90}\size{12}{\faLightbulbO}\,\,}
                          \begin{tcolorbox}[
                          enhanced,
                          title={\textbf{\color{second}\thinkname}},
                          title style={left color=blue!10!green!20!white,right color=yellow!20!blue!20!white},
                          colback=green!20!white,
                          ]
                          \sffamily
                      }{
                          \end{tcolorbox}
                      	\par\ignorespacesafterend
                      }
                      .rmdnote, .rmdtip, .rmdthink{
                          padding: 1em 1em 1em 4em;
                          margin-bottom: 10px;
                      }
                      
                      .rmdnote {
                          background: #f5ead8 5px center/3em no-repeat;
                          background-image: url("../figs/note.png");
                      }
                      .rmdtip {
                          background: #88c1f0 5px center/3em no-repeat;
                          background-image: url("../figs/tip.png");
                      }
                      .rmdthink {
                          background: #96f5f8 5px center/3em no-repeat;
                          background-image: url("../figs/thinking.png");
                      }