第 5 章 话说Xaringan

5.1 Xaringan缘起:创建课程slide

5.1.1 从前有座山

现在对(本科)教学工作的要求,已经发生了很大的改变:教学的内容变得更加专业化和细分化(学生就业市场的倒逼);教学过程/流程需要标准化(一切变得透明公开);教学活动应该能够便于复制并规模化运行(课程最好能以公开课/慕课方式运作);个性化教学和灵活性调整被反复强调(对学生多元考核、“一人一套试卷”);其他方面。

教师在讲台上的台前“艺术化”魅力(仪态、表情、音色等)已经不再如曾经那么重要;教师在台后的“技术性”设计(内容、互动、展示等)上升到了无与伦比的地位。

尤其是对于哪些技术性课程,如计量经济学(Econometrics)和统计学(Statistics),“技术性”设计必须要赶上这些教学新要求的呼声。(当你发现一位大学教师还在“坚持”使用Office2007,你一点都不要惊讶——经管现在已经是2019年了。)

5.1.2 逃离PowerPoint,拥抱HTML5?

为什么要逃离PowerPoint,拥抱HTML形式的slide?下面分别来说一说。

5.1.2.1 PowerPoint的“断、舍、离”

  • office版本太过分散,ppt可能会上演各种“变形记”。(现在国内有很多学生,已经不能区分WPS和Office了。学生的毕业论文或作业提交,那酸爽,真是谁看谁知道。)

  • ppt维护和更新的各种“梗”。最让我纠结的就是mathtype公式,神一般地会一夜之间“变砖”(倒腾几下,公式变图片,或者干脆显示不了),更不要说公式的重复使用和编辑修改。如果使用一些新技巧、新字体,那一定会让你记住“凡走过的都是一个一个的巨坑”。

  • 难以逾越数据、图形和模型分析的“天堑”。表格数据加总等分析基本等于不可能(事实上也可以关联excel,但是“关联越多,等价于羁绊越多”!);数据图形化,你只能老老实实拷贝统计软件里的做好的图吧(泪奔!);建模分析结果的调用,就更别提了(反复在多个软件窗口中切换和敲键盘,眼花缭乱的“骚操作”不说,最担心的还是手一抖怕敲错了结果啊!)。

5.1.2.2 HTML形式slide的“前世今生”

  • 一个浏览器就够了。HTML是互联网世界最广泛使用的交流形式。每台电脑都会安装浏览器(chrome、firefox、IE…),但不是都会安装Microsoft office全家桶(365家庭版那可是每年500RMB啊,心疼一下下!)。

  • 一份文本多种输出形态的终极需求。就像KTV里嗨唱切歌,老师们常常要在word、pdf、html、ppt、png等格式中不断切换啊。一个逗号或减号,在word里改了,那还得改ppt啊,就问你蛋疼不蛋疼。所以,仅维护一份文本,随时获得各种输出(html、word、ppt、slide…)简直就是人类共同的梦想啊。

  • “纯文本”就是你的最底层“话语”。一切的文字、代码、图形、格式、排版…,统统汇集于一份“纯文本”中!Plain Text,正如其名,平铺直叙,朴素而不简单,包含了你所需的一切,你想说和想呈现的一切。

5.1.3 优势和不足

5.1.3.1 优势

  • R语言和RMarkdown的应用就是它最大的优势。这赋予了教学准备工作更强的“生产力”:代码可重复利用、统计处理和分析报告完美整合。

  • Xaringan Slide可以高度灵活的定制化。本质上形式的呈现,完全依赖于CSS技术,这与PowerPoint中的模板使用是完全不同的体验,效率上完全秒掉后者。

  • Xaringan Slide可以完美转成pdf格式的slide。其实直接用Chrome浏览器打开HTML Slide不就完了嘛,这种格式转换的操作本来就是多此一举!总之,你说,世界需要pdf;于是Xaringan便说,给你pdf!

  • 与GitHub版本控制技术融合。我想说的是,这是一种全新的师生交互和反馈机制!

5.1.3.2 不足

  • 对行内公式支持不是很友好。比如\(\beta\)的实现代码$\beta$必须要保持独立一行!一段话要是有很多这样的inline equation,那么xaringan::moon_reader文档就显得很破碎了。

  • 风格调整CSS技术的学习还是有一定成本的。换言之,制作一份自己喜欢的“专属”模板,还需要花费一些时间。

  • 强迫症的一些小细节。使用knitr::kable()制表,转pdf时表格无法显示,替代办法就是用DT::datatable()的表格风格,而它往往不是真正的Table风格!另外,就是windows环境下,不支持Rstudio面板Viewer中预览slide,只能在浏览器中预览。

5.2 Xaringan发布:blogdown网站中的展示

本节介绍如何把Xaringan 演示Slides以静态网页(static webpage)形式载入个人网站。

主要参考资料和实现办法可参看:

以上都有比较系统的说明,可以直接参照。

需求和问题列表:

静态网页方式损失了效率。

静态网页,正如其名,只能相对“固定”地加载封装好的.html文件或.pdf文件之类。显然,交互性和动态性就暂时难以获得。因为我们写作Slide是在另一个repo文件夹下(repo如course-econometrics文件夹下,并使用Xaringan包),然后确认没问题后才能把渲染好的.html形式的Slide文件(一般是如02-simple-reg-basic-slide.html)拷贝到网站repo文件夹指定目录下(repo如netlify,特定目录为\netlify\static\slides-course)。同时,如果html文件不是完全自容的(self-container),那你还必须把使用到的图片数据等文件夹也一同拷贝过去(这就非常糟糕了!因为你的slide制作可能会经常变动或更新)。那么要如何自动关联Xaringan(实现slide)和blogdown(实现website)呢?

当然动态性和关联性也是有成本的。如果Xaring里的文件需要渲染很久(比如ggplot作图很多,数据分析很多),那么blogsite会负担比较大。

知识版权的保护问题。slide上传到website后,文字和图片等都可以任意拷贝下载。对于开源项目,这完全没毛病。但是,对于一些重视原创知识保护的人,这就是很大的“命门”了。

5.3 Xaringan效率:底层与简洁

一般而言,保持project下的文件夹结构稳定和简洁,能够大大避免工作的低效率性。Xaringan包用于制作多个系列slide幻灯片,也会难免带来文件数量和类型的逐渐增加和膨胀。那么在Xaringan框架下,如何管理和组织文件夹结构,以提升工作效率和代码稳定性?

5.3.1 底层逻辑

5.3.1.1 渲染方式

Xaringan slide的渲染方式主要有两类

  1. 静态渲染方式:Rstudio菜单knit

  2. 实时渲染有两种方式(live preview)

    • Rstudio里插件 “Infinite Moon Reader”
    • console里调用xaringan::xaringan::inf_mr()

5.3.1.2 共用文件夹的情形

mycss:假定课程里全部slide都使用同样的css风格。

pic:假定课程slide里的本地图片都放在pic文件夹下。

若干可能的文件体系结构及面临的主要问题

  1. 体系1“全部一起堆放”:随着Rmd文件数的增加,一级目录下会有很多文件!chn-chpt01.Rmd; chn-chpt02.Rmd;……;eng-chpt01.Rmd; eng-chpt02.Rmd;……

  2. 体系2“分模块堆放”:比较合理。但是在实时渲染时,将面临如何管理css和pic等问题。子文件夹1:Slide-chn:chn-chpt01.Rmd; chn-chpt02.Rmd;……;子文件夹2:Slide-eng:eng-chpt01.Rmd; eng-chpt02.Rmd;……

5.3.1.3 测试和发现

测试:比较合理的体系2“分模块对方”下,进行实时渲染

css问题:xaringan包已经解决此问题。只要确保css文件和Rmd文件在同一个work directory下即可。

pic问题:假定pic文件夹与模块文件夹(slide-chn; slide-eng)并列

  • 静态渲染方式下,图片引用可以使用“相对路径”("../pic/a.png")或“绝对路径”(here::here("pic", "a.png"))引用的任何一种来实现正常显示。

  • 实时渲染方式下,图片引用只能使用“相对路径”(“../pic/a.png”)来实现正常显示。

5.3.2 效率方法

5.3.2.1 减少系统复杂性

Yongfu的博客文章Tips to Reduce the Complexity of Slide Making with Xaringan,比较详细地介绍了如何减少xaringan制作复杂性的一些方法。

5.3.2.2 提高代码复用性

  • 引用代码块。前后slide如果要多次(2次及以上)用到同样的代码块,则可以使用代码块标签索引(see rmarkdown cookbook: reference labels)。具体有两种操作情形:

    • 简单重复引用代码块。先定义label,然后直接使用相同标签的代码块头即可。
    • 组合引用多个代码块。先定义label,然后设定ref.label=参数进行引用即可。
# 简单重复引用代码块
`` `{r, chunk-one, eval=TRUE} # def

some long content balabala 

`` `{r, chunk-one, eval=TRUE} # use


# 组合引用多个代码块

`` `{r chunk-a} # def1

some long content balabala 

`` `{r chunk-b} # def2

some long content balabala 

`` `{r chunk-a, ref.label=c('chunk-c', 'chunk-b')} # use

5.3.2.3 修改预览实时化

remotes::install_github('yihui/xaringan', upgrade = TRUE)
  • 而且是Windows用户的又一个福音啊。前面刚说Rstudio里不能Viewer预览,但是更新Xaringan包后发现Chrome浏览器竟然可以“实时”同步预览了!yoo!

定制自己的字体大小:

<style type="text/css">
.remark-slide-content {
    font-size: 30px;
    padding: 1em 4em 1em 4em;
}
</style>

5.3.2.4 选用一个好模板

  • 比如我使用的杜克大学模板:Slide Template for Duke University

  • 初学者最好先不要删除模板的内容,里面的示例说明可以很好地参考。

5.3.2.5 定制个性化模板

5.3.2.6 小结

xaringan实时渲染方式,会调用servr package来搭建本地网页服务参看官方文档

因此实时渲染下:本地服务会寻找一个根目录(root directory),从而会引发上述的图片渲染问题。libs文件夹总是会和.Rmd文件并列

总之,使用相对路径引用图片是比较保险的方式。具体的地方包括

  • remark.js背景图:background-image: url("../pic/a.png")

  • R函数正文图:include_graphics("../pic/a.png")

  • markdown行内图:![]("../pic/a.png")

其次,css的yaml设置

css: 
      - default
      - default-fonts
      - duke-blue
      - hygge-duke
      - ../mycss/my-custom.css

5.4 Xaringan美化:CSS功夫

本节内容总结了CSS的学习架构和逻辑体系,并专门针对Xaringan slide制作技术进行了探索和应用。

5.4.1 再谈Xaringan的本质

Xaringan背后是基于remark.js的。remark.js后台基本工作流程,就是采用JavaScript语言把markdown文档,映射到html上,并形成独特的slide幻灯片样式。因此,还是很有必要了解一下remark.js的说明文档(见Wiki页面)。那么Xaringan包又起到了什么作用呢?根据yihui的说法:它扩展支持了Rmarkdown语法以及R代码的直接运行!

Xaringan本质上是以html形态呈现,并使用css样式进行style视觉美化。Xaringan的技术讨论和细节见其wiki页面

归结起来这是对slide工具的一种选择,而且是选择了”未来感”的html呈现形态!那么CSS知识这是绕不过去的学习壁垒。html和css的学习至少也是需要在”三姑学院”(W3school)的汪洋里过水”捞一遍”(通读一遍)。

5.4.2 头衬和底衬(header and footer)

调整header和footer视觉效果,主要是从某个slide开始里设定layout: true,并按html语法设置header和footer样式。其完整的语法如下:

<!---slide area with layout--->
---
layout: true

<div class="my-header-h2"></div>

<div class="watermark1"></div>

<div class="watermark2"></div>

<div class="watermark3"></div>

<div class="my-footer"><span>huhuaping@  &emsp;&emsp; <a href="#chapter01"> 第01章 导论</a>
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
<a href="#sec-process">1.3 计量经济学分析过程</a> </span></div> 
---

具体样式细节包括:

  • heading文本居中设定。需要注意叠放层级参数z-index的设置。
.remark-slide-content h2, h3,h4,h5{
  position: relative;
  top: 0px;
  margin: 15px 0px 50px;
  width: 99%;
  text-shadow: 0px 0px;
  text-align: center;
  z-index: 5;
}
  • header背景色和渐变方式。
div.my-header-h2 {
    background-color: #FFFFFF;
    background: -webkit-gradient(linear, left top, right top, color-stop(0%,#f77a00), color-stop(0%,#f77a00), color-stop(10%,red), color-stop(74%,#fbd0ac), color-stop(83%,#fbd0ac), color-stop(100%,#fddfc8));
    position: fixed;
    top: 0px;
    left: 0px;
    height: 86.92913px;
    width: 100%;
}
  • footer导航样式。
div.my-footer {
    background-color: #272822;
    position: absolute;
    bottom: 0px;
    left: 0px;
    height: 20px;
    width: 100%;
}

div.my-footer span {
    font-size: 10pt;
    color: #F7F8FA;
    position: absolute;
    left: 15px;
    bottom: 2px;
}
  • footer的导航链接功能。先在css里设定链接文本的颜色,然后在slide里设定layout: true(见前面完整语句块),并按html语法设定链接定位#a-specify-id
/* link text color*/
div.my-footer a {
  color: white;
  background-color: transparent;
  text-decoration: none;
}

5.4.3 添加水印图片(watermark)

水印图片的个性化设定。首先需要设定css,然后在slide里设定layout: true(见前面完整语句块),并按html语法依次设定三个水印图片,其中之一如<div class="watermark1"></div>

/* water remark image */

.watermark1::after {
  content: "";
  display: block;
  width: 30%;
  height: 20%;
  position: absolute;
  top: 150px;
  left: 100px;
  background-image: url("vlog-nwsuaf.jpg");
  background-size: 80%;
  background-position: 0px 20px;
  background-repeat: no-repeat;
  opacity: 0.04;  
  /* Rotate div */
 -ms-transform: rotate(-45deg); /* IE 9 */
 -moz-transform: rotate(-45deg); /* firefox */
 -webkit-transform: rotate(-45deg); /* Chrome, Safari, Opera */
 transform: rotate(-45deg);
}

为了保证水印图片(<div class='watermark'>)总是显示在最下层,则需要使用css样式z-index: 1来调节页面各个元素(<p><ul>等)的层次关系。需要注意的是css样式z-index:要发挥作用,则要求这些元素的共同parent node(<div class = 'remark-slide-content'>)必须满足css样式position: relative。相关资料可以参看队长问答(Position one element relative to another in CSS)。

5.4.4 添加logo图片

方案1:手工添加logo。可以参看:a. xaringan Tip: Add A Logo to All of Your Slides。以及“队长论坛”贴文“Can I add a logo to every slide of a xaringan template using css?”。

方案2:包函数添加logoxaringanExtra::use_logo(能很好地处理logo图片,可以灵活使用class:hide_logo来指定特定slide不显示logo图片。具体请参看官方说明

xaringanExtra::use_logo(
  image_url = "https://raw.githubusercontent.com/rstudio/hex-stickers/master/PNG/xaringan.png",
  link_url = "http://slides.yihui.name/xaringan",
  position = xaringanExtra::css_position(top = "1em", right = "1em")
)

5.4.5 各类窗框(notes box)

在多个写作场景下(如xaringanblogdownrmarkdown),可能会用到各类提示窗框(notes box)。可以利用css设定获得个性化的提示窗框效果,具体可参看desirée de leon的博文1

基本要点:

  • 背后要用到html的div语块

  • 可以借用R包bookdownblocks代码块,进行快捷应用。

第一步:css文件(/my-css/notes-tips.css)设定如下:

/* -----------div tips------------- */

div.puzzle, div.fyi, div.demo, div.notes {
    padding: 0.5em;
    margin: 0.5em 0;
    padding-left: 100px;
    background-size: 70px;
    background-repeat: no-repeat;
    background-position: 15px center;
    min-height: 100px;
    color: #1f5386;
    background-color: #bed3ec;
    border: solid 5px #dfedff;
}

div.notes {
  background-image: url("notes-light-bulb-ff5500.png");
}

注意:需要自己手动下载背景图片,免费的图片icon下载网站有:

  • iconfinder。需要账号登陆。
  • fontawesome.com。图标可以先编辑,在下载。正文里还可使用R函数fontawesome::fa('slideshare')。例如slide图标
  • aiconica.net。搜索功能比较弱。

第二步:在.Rmd文件的yaml区域引用上面的css文件路径。

css: 
  - ../mycss/notes-tips.css

第三步:在.Rmd文件下进行写作,并引用对应的css样式:

` ``{block, type='notes', echo=T}

待完成:找到新数据,绘制一张条形图,但其不适合制作柱状图。

` ``

Xaringan slide下对div css的调用(以div.notes为例):

.notes[

here is your point.

]

bookdown或大部分html输出的Rmd下对div css的调用(以div.notes为例):

:::notes

here is your point.

:::

5.4.6 序贯图片的动画效果

幻灯片动画效果(animation)的背后,基本有两类思路:

第一类:小部件(partial elements)动画效果。常见的设计工具如pptx,在一张slide里面,对动画小部件(窗体、文本、箭头等)进行时序上(timeline)的安排设计,从而实现动画效果。比较适合于那些只需要利用“标准化”小部件组合形成动画的幻灯片。其优点也是显而易见的:一块幕布,持续添加小部件,比较符合动画的内容本质和视觉直觉。难点在于需要大量操作来给小部件定位(position)以及修饰小部件。

第二类,图片放映动画效果。利用人眼的视觉时间差特点,把事先设计好的系列序贯图片,连续反映展示,从而实现动画效果。比较适合于那些“手工绘制”多张序贯图片形成动画的幻灯片。其优点是:强调视觉定格(帧)关系,不太关注细节的严格一致。难点在于需要“手工绘制”,以及认为确定图片帧,小部件的细节可能会被认为并不太重要。

目前为止,直接在xaringan(或reveal.js)slide上进行第一类小部件动画制作的工具,基本上没有看到相关便利性的工具包或解决方案。xaringan(或reveal.js)slide上的动画主要是基于第二类,图片放映动画效果。例如,一个R相关会议报告做了题为Reproducible Data Workflows,就给出了“反映”型“流程图”(其实并不是流程)的动画效果,其背后就是利用序贯图片帧,不断反映,从而表现出“动画”效果。具体代码可参看其Rstudio cloud project

总体而言,在xaringan(或reveal.js)slide上主要采用“放映”型动画效果,因为动画实现(多帧图片)和动画控制(方向键)都相对简单。然而,多帧图片的设计和获得则成了其中最大难题。这样就需要依赖R之外的“绘图”工具,而且它最好还要能够自动保存序贯图片帧(反映时序中的中间环节图片)。不过很遗憾,这样的外部“绘图”工具(不管是否支持小部件)目前我是暂时没有发现(起码放狗搜了一大圈是无所得)。

不过还是找到了一个可以实现的“笨办法”。

第一阶段:绘制图片阶段。用到的主要外部工具有Powerpoint(用于绘图) 和Snagit(用于截图)。工作流程基本上是:

  1. 利用Powerpoint绘图,设计好动画。在动画窗口中控制小部件的出现先后顺序。

  2. 播放Powerpoint动画,再利用Snagit进行截图,获得图片帧,按要求进行图片自动命名(这一步很重要,方便后面调用)。需要注意在Snagit设置里,把截图质量设定为较高(File \(\Rrightarrow\) Capture perference \(\Rrightarrow\) Capture \(\Rrightarrow\) Videa Quality)

第二阶段:xaringan代码实现阶段。有了上述序贯图片,Xaringan里主要就是进行图片调用和css控制。

  1. 图片调用。因为涉及到调用系列图片(已经有规则地命名),因此可以将slide代码编程化,尽量减少代码数量,让文档结构更清晰。具体而言,需要用到的函数包括:

    • base::dir()函数调用图片路径。
    • glue:glue()函数组装slide语法要素。
    • base::cat()函数输出代码结果。
  2. CSS控制。图片相对位置等的控制,可以启用tachyons的CSS样式,具体要用到xaringanExtra包的xaringanExtra::use_tachyons()函数。

注意

  • glue::glue()函数的使用有两个坑:一是它对方括号{your parameter}敏感(默认为parameter),因此需要用双方括号嵌套,才能正确编写并识别latex代码\frac{{your code}};二是它需要双斜线\来escape特定latex语法(如)。

  • R code chunk参数一定要记得设定{r results=“asis”},这样才能实现正确代码输出(cat()函数)。

  • Rmarkdown图片调用一般而言有两种途径,一是使用html标记语言;二是使用knitr::include_graphics()。但是在序贯图片效果的图片调用中,目前只能使用第一种方法。因为knitr::include_graphics()是一种顶级表达方式(top-level R expressions。具体 参看:yihui;以及贴文。)

下面是Xaringan中的代码演示:

# 启用tachyons的CSS样式
xaringanExtra::use_tachyons()
# 调用图片位置
proj_slides <-sort(dir("pic/sequence/", pattern = "quatile-min-upper-.+png$", full.names = T),decreasing = T)
# 组装slide代码要素
proj_slides_txt <- glue::glue("
## (演示)分位数计算:较小制上限插值公式(推导)

.fl.w-60[
![]({proj_slides})
]

.fl.w-40[

- 
$f_i$表示各组所对应的频次,其中
$i \\in 1,2,\\cdots,5$。
$f_{{Q_j}}$表示分位数组的频次。
$p_j$表示1/4或3/4分割位置,其中:
$p_1=\\frac{{\\sum{{f_i}}}}{{4}}$,
$p_3=\\frac{{3\\sum{{f_i}}}}{{4}}$。
]

---

")
# 输出代码结果
cat(proj_slides_txt, sep = "")

下面的代码将对比说明图片调用的两种用法:方法1(可行)![]()(序贯动画效果可 参看),以及方法2(不可行)knitr::include_graphics()

r ''````{r, results='asis'}

# 方法1(可行)`![]()`

cat(
  paste0(
    c("### 内生自变量情形1:遗漏变量(演示2)"), 
    "\n\n",
    "具体地,遗漏变量引发内生自变量问题的直观演示如下:\n",
    "\n",
    paste0("![](pic/chpt11-endogeneity-ommit-seqence/chpt11-ommit-sequence-part-0",5:1,".png)"),
    "\n\n",
    "---\n\n",
  sep = ""),
sep = "")

```
r ''````{r, results='asis'}

# 方法2(不可行)`knitr::include_graphics()`

cat(
  paste0(
    c("### 内生自变量情形1:遗漏变量(演示2)"), 
    "\n\n",
    "具体地,遗漏变量引发内生自变量问题的直观演示如下:\n\n",
    paste0("\`\`\`{r, fig.cap='animation-0",1:5,"'}"),
    "\n",
    paste0("knitr::include_graphics('pic/chpt11-endogeneity-ommit-seqence/chpt11-ommit-sequence-part-0",5:1,".png')"),
    "\n",
    c("\`\`\`"),
    "\n\n",
    "---",
    "\n\n",
  sep = ""),
sep = "")
```

5.4.7 灵活选用字体

解决字体灵活选用问题。工作量理论上不是很大,主要是受到中文字体适用性和加载速度等的限制。目前暂时还不想去碰它,大众字体就大众字体,先忍一忍。具体看yihui的相关思考和说明。如思源宋体楷体

在Xaringan中给slide内容设定不同的个性化字体,基本有两种方案(当然二者结合也是可行的):

  • 方案1:个性化手动设置。首先,需要编写个性化字体CSS。然后,在yaml区域来指定调用字体CSS文件。Xaringan包的官方wiki “Deploying Your Slides Online”给出了具体操作过程和办法。此外,还有一类是集成、友好性的css工具集,也可能更便捷地提供字体设定,例如Tachyons字体库管理方案

  • 方案2:R包函数化设置。具体要用到R包xaringanthemer,其字体设置及相关R函数可参看其官方说明

上述两种方案,其关键都在于可用“字体库”(font family)。因此需要弄明白如下几个问题:

  • Xaringan默认的字体库是什么?它存放在哪里?(对于方案2的R包xaringanthemer,我们也同样需要问这样的问题。)

Xaringan字体css文件位置在:“your-pkg-dir-fonts.css”

  • 操作系统(如Win 10 或Mac OS)的字体库(system font libraries)与Xaringan的字体库是什么关系?(后者能直接调用前者的字体库么?)

  • 电脑本地渲染的slide字体,与网站开发(如netlify)上的slide字体是什么关系?(后者可能需要设置netlify的后台相关字体控制参数)。

  • 怎么来使用网络开源的字体库?slide的字体加载能否成功,以及加载速度够快么?

下面提供一些可用的免费字体库:

下面再展示一下Xaringan slide个性化字体css文件(my-font.css)的代码设定(也可参看[说明]((https://github.com/yihui/xaringan/wiki/Deploy-Slides-Online)):

# my-font.css
@import url('https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap');

body { font-family:'Songti SC', serif, 'KaiTi', '楷体','Droid Serif', 'Palatino Linotype', 'Book Antiqua', Palatino, 'Microsoft YaHei' ; }

h1, h2, h3 {
  font-family: 'Ma Shan Zheng', cursive,'楷体';
  font-weight: normal;
}

注意

  • 字体使用有先后顺序。客户浏览器会根据操作系统字体情况,依次按顺序来加载字体。

  • 综合考虑不同平台和设备下的字体可用性。因此,往往需要设定字体库的“备胎计划”(fallback)。

此外,Xaringan中不同内容要素(elements)的字体应该考虑不同的设定,具体内容要素类别包括:

  • 标题(headings):h1,h2,h3,h4,...

  • 代码区域(code chunk)以及行内代码(inline code):.remark-code.remark-inline-code

  • 表格(table):表题(caption),表注(notation)。

  • 图片(figture):图题(caption),图注(notation)。

  • 数学公式符号(latex equation and symbol):

5.4.8 后续需要处理的CSS问题

5.4.8.1 储备炫酷技能

提前准备好各类丰富slide功能的css实现方法。具体明确的一些炫酷功能,相关slide和css样板可以参看:

5.4.8.2 图文混排

图文混排技巧。

  • remark.js自带光环的边栏效果(side bar).left-column[]或者.right-column[]

  • remark.js自带光环的两栏效果(two columns).pull-left[]或者.pull-right[]

5.4.8.3 Todo清单

  • 页面布局。页面紧凑度和宽松度灵活调整。例如remark-slide-content.roomy

  • 前导符设定。正文符号列表的前导符设定问题。

  • 播放动画效果。常见的进入或退出等动画效果。CSS可以参考相对比较成熟的Animate.css,可以直接拿来就用。

  • 窗格动画效果。大抵类似于PowerPoint的动画窗格设计,目前在Xaringan或remark.js里还没有看到。可以参看Earo Wang’s slide。以及另一个很不错的Xaringan slide报告题为Reproducible Data Workflows给出了绘制版流程图的动画效果,其背后的关键是连续的png部件是如何分解得到的(可参看其Rstudio cloud project)。有待进一步去找这样的draw工具,它应该能自动保存中间环节的png。

基于CSS的窗格动画Build your own universe。相关资源可以参看:Garrick Aden‑Buie的网站

5.4.9 Tachyons CSS

因为使用R包xaringanExtra的缘故,初次接触到Tachyons。简单地,Tachyons是一套创新的CSS架构理念和工具。

该CSS架构的可能最初设想,是来自前端开发员Adam Morse的一篇倡议性短文CSS and Scalability(他的个人首页)。然后经过实践探索和迭代坚持,诞生了目前的Tachyons工具集。具体的介绍可以参看 Learn Tachyons。如果要使用各种css元件和样式,也可以登陆快速检索入口:Cheat Sheet

这里主要说两个与本人项目相关的话题。

第一个话题是:为什么要尝试选择Tachyons的CSS架构理念。其实也就是Tachyons要解决的主要CSS痛点。个人认为最重要的优点有:1)坚持“所见即所得”。下面的图既是最好的说明。具体而言,它坚持明确的“语义化代码”,让CSS显性化,实现人类友好。2)坚持“乐高组装模块化”。基于最小颗粒的CSS原件和风格,可以进行无限可能的模块化组合,从而实现CSS代码可复用性和稳定性,以及维护的简单化。3)坚持“函数化CSS开发”。与R语言类似的函数化编程思维一致,可以通过参数进行灵活控制。例如其中提到的“尺度化”(scale)概念,运用于字体大小(fontsize)、宽度(width)等。个人感觉类似于ggplot2的数据化映射思路。

tachons
tachons
before
before

第二个话题是:如何将Tachyons的CSS架构运用于Xaringan的视觉输出设计中去?当然目前已经可以基于xaringanExtra包进行引入,但是里面也还有很多需要有效衔接的地方。

5.4.10 最后的若干思考和感受

这次对Xaringan 又一次发起冲锋,直接缘由是《计量经济学》双一流课程团队的视频录制。团队里其他人都不用R和Rmarkdown,更不要提Xaringan slide了。大家仍旧还是基于PowerPoint准备和制作授课幻灯片,有的老师甚至操作系统还是win7,office套件还是2010版!所以只能我事先用powerpoint设定好ppt模板,大家各自拿去制作自己的授课ppt(其实大部分团队老师甚至连ppt母版也不会用)。考虑到我自己的实际需求,我是希望能同时兼顾自己使用xaringan 和团队其他老师使用ppt的一致性——当然是不能奢求最后两者视觉效果的完全一样!目前在Xaringan上的设定调整,基本上达到了ppt模板类似效果的80%左右。

事实上,Xaringan和ppt二者效果一致性的达成,并不是最大的挑战。基本上基于html的Xaringan slide,可以使用css技巧实现ppt里的几乎所有功能。而况Xaringan还有很多ppt无法实现的”现代的”以及”未来的”诸多功能!真正的挑战在于团队协作,尤其是对于非常技术守旧的团队(并不指技术之外的其他方面)。到此,我的基本态度就是:最低限度地在技术方面与其他人协作,重点是把协作任务下自己事情做完、基本ok即可!

当然,这里面也还有一个在协作冲突中推动自己不断学习进步的问题。显然,如果没有这次的协作录制课程,我肯定还是会一如往常地坚持”最小化学习”策略:也即如无实际所需,绝不去茫然学习所谓的各种知识技能。这一次,我充分认识到了CSS对于Xaringan甚至对于Html的重要性,并且看到了一些文档协作、协作和输出的”未来”趋势和走向!

5.5 Xaringan增强:若干辅助R包及工具

Xaringan生态正在不断扩展,也将会大大方便slide制作,提升slide美观度,增加slide的更多新功能。本文将持续关注相关增强辅助包和定制函数,包括xaringanthemer、xaringanBuilder和metathis等正在开发和维护中的R包,还有一些定制化的R函数。

其中,博文Making Extra Great Slides做出了基本的梳理。本文在此基础上做了进一步测试、对比和总结。

5.5.1 增强包1:xaringanExtra

R包xaringanExtra确实是“包”如其名,提供了不少Xaringan功能增强,可以说是大大缓解了Xaingan用户的大部分痛点。

具体可以参看R包xaringanExtra说明文档,以及关注追踪其github repo

整体来看,个人认为比较有用的增强功能包括:

  • Scribble。slide可以涂鸦啦。一句话点评:手写墨迹的保存需要手动浏览器打印,有点费手。白板(键盘B)状态下无法手写涂鸦,槽点还有,距离好用总差那么一丢丢

  • Search。全域slide搜索功能。一句话点评:这个好,直接甩掉pptx几条街。

  • Clipboard。便于代码复制操作。一句话点评:码农一族的最爱,非码农表示不觉明厉。

  • Tile View。实现slide缩略图效果。一句话点评:pptx有的,咱也的有。

  • Editable。slide内容可编辑。一句话点评:必须指定可编辑内容域,功能实用性也不够明确。

其中,比较有意思的slide操作包括:

  • Animate.css。动画效果。一句话点评:类似pptx幻灯片动画效果(进入、退出),但不是部件(element)的动画效果。无论如何,聊胜于无。此外,尤其要注意css独立文件的依赖关系,上传个人站点(如netlify)需仔细考证。

  • Panelset。面板集效果。一句话点评:它有点类似于Xaringan自带的navigator导航效果(.right-column[]+.left-column)。区别在于:前者面板是水平罗列,且只需在一个slide页面下完成(一个---下);其优点是代码更少,结构更紧凑;最大的问题是pdf导出需要额外包来加持解决,其他不足还包括:slide页码下的代码特别多,不便于导航写内容;另外对math公式等支持还不完善(如裸的Rmarkdown数学表达式会无法显示,但是加上.small[]字体大小类css修饰则可以显示)。后者则是垂直罗列,且需要在多个slide页面下完成(多个---下);其优点是便于导航编写内容,且每个pannel天然就占一张slide,方便导出pdf;不足在于垂直罗列后,右侧展示空间被压缩。

  • Broadcast。你讲你的slide,观众可自动实时跟随slide翻页。一句话点评:很炫酷的功能,但是国内网速和访问可达性还有待测试。

  • FreezeFrame。定格gif,免得它一直动。一句话点评:功夫是好功夫,不过都摆开了大架势秀舞姿了(gif嗨起来),还管得了台下观众头昏眼花么?

  • Webcam。调用摄像头,实现图中画效果。一句话点评:颜值后生美女们,定会喜大普奔吧。

  • Tachyons。大概包括了多种支持Xaringan的Tachyons“小部件”(参看Tachyons官网),如文本窗框(text box)。一句话点评:似乎普通的css设定也可以实现,这个有空再去推敲推敲其中有啥玄妙。

5.5.2 增强包2:xaringanBuilder

R包xaringanBuildergithub repo)的目标是支持多种输出格式的Xaringan slide导出:

  • html

  • pdf

  • gif

  • pptx

  • mp4

  • png

  • social (png of first slide sized for sharing on social media)

xaringanBuilder包的安装命令为:remotes::install_github("jhelvy/xaringanBuilder")

优点

  • pdf和pptx两种格式导出是大多数人比较关心的。可以与其他导出方法比较,看哪一种方案的导出质量和速度更优。例如,pdf格式输出,感觉与后面提到的xaringan_to_pdf()过程和效果都很类似。

  • 同时支持多种格式输入和输出,还可以对“中间格式”进行处理。例如可以支持先导出为pdf,然后再进一步把pdf导出为pptx。

  • 支持复杂形式Xaringan slide的多格式输出。例如xaringanBuilder::build_pptx("03-slide-class/04-data-measuring.Rmd",complex_slides = T)就可以实现对计面板集(panelsets)类型slide的完美输出。这个功能也即实现后面要提到的xaringan_to_pdf()函数过程和效果,必须点赞!

槽点

  • 可能的多种包依赖关系。例如pptx格式需要依赖officer包。

  • “伪”pptx格式输出。xaringanBuilder::build_pptx("03-slide-class/04-data-measuring.Rmd",complex_slides = T)的结果,pptx的每张幻灯片都只是png格式的图片而已。不过,这个槽点应该是能够预料到的(大家猜猜是为什么?因为Xaringan slide和pptx幻灯片的血统完全不一样啊!)。

5.5.2.1 pdf输出时数学公式显示异常

问题描述:如果直接使用chrome浏览器打印pdf,数学公式显示都是正常的(如同html预览效果)。但是使用xaringanBuilder::build_pdf()函数进行pdf输出,则数学公式总是显示异常(非常小)。

尝试办法

  • 怀疑html转会效果更好,尝试.Rmd转pdf或者.html转pdf,问题都依旧。
# from html to pdf
xaringanBuilder::build_pdf("03-slide-class/04-data-measuring-test.html","public/04-data-measuring-test.pdf", complex_slides = T, delay = 3)
# from Rmd to pdf
xaringanBuilder::build_pdf("03-slide-class/04-data-measuring-test.Rmd", complex_slides = T, delay = 2)
  • 怀疑MathJax.js在线不稳定,尝试指定调用其他路径,问题依旧。

Rmarkdown的公式渲染主要有两种方式。 - 默认渲染:xaringan会自动调用MathJax.js(集成在Rstudio中)来渲染数学公式和符号。 - 本地渲染:需要在yaml区域指定本地路径下或其他网络地址的MathJax.js文件。

---
output:
  xaringan::moon_reader:
    chakra: libs/remark-latest.min.js
    mathjax: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML.js"
    self_contained: false
---

5.5.3 增强包3:xaringanthemer

R包xaringanthemer提供了很多Xaringan slide风格的模板,具体可以查看官方说明,以及github repo。实际上我个人基本上还没有使用上述任何style,因为目前有自己的定制化xaringan模板。

简单点评

  • 以满足个性化需求为首,切记千篇一律。style风格一事,不过是外貌形象而已,仁者见仁智者见智。大部分人的工作汇报场景应该是固定化、模式化的,因此自己设计和维护的个性化style反而会更加实用,细节操控自然也会心中有数,迭代更新相应也更加可靠。

  • 简单的就是最有力的。还是那句老话,越复杂的style、越多的新结构,也意味着更加难以控制。开源世界里采用或拥抱某些创新工具的基本法则应该是:简单可靠,步步为营。

5.5.3.1 输出pdf函数xaringan_to_pdf()

显然,对Xaringan进行功能增强以后,带来的直接后果就是slide的结构和形式开始变得复杂多样。

其中,使用xaringanExtra设计面板集(panelsets)类型的slide时,简单使用chrome浏览器导出为pdf文件会不满足用户需求:pdf只会保留面板集slide下的第一个panel页面。

为此,xaringanExtra包的开发者Garrick在博文”Printing xaringan slides with chromote“中,专门提到了这一用户需求和解决办法。他编写了一个输出pdf的R函数xaringan_to_pdf(),并且后续可能会直接添加到xaringanExtra包中去。xaringan_to_pdf()函数源代码下载链接github Gist

根据作者说明,xaringan_to_pdf()函数需要依赖如下工具和R包:

  • 本地浏览器Google Chrome

  • 依赖包chromote:安装remotes::install_github("rstudio/chromote")

  • 其他依赖包:安装install.packages(c("progress", "jsonlite", "pdftools", "digest"))

最后做一下简单点评

  • pdf输出速度不太理想。xaringan_to_pdf()函数的pdf输出速度相对较慢,经测试180页slide大概需要5-10分钟(当然,根据slide的复杂程度会有一定差异)。这显然是因为依赖包过多或者工作流workflow过长 。

  • 限制是对html文件格式的pdf输出。例如xaringan_to_pdf("03-slide-class/04-data-measuring.html"),不能直接针对.Rmd文件。相当于工作流workflow进一步被延长了。

  • 后续更新支持不确定。

5.5.4 增强工具1 :参考文献列表

温馨提示:目前R包RefManageR(version 1.1.0及以上)可以支持在Xaringan中实现我们提到的下述需求。不再需要后面的破解方法。

有些时候, presentation slide的最后需求列出幻灯片演讲中出现的参考文献列表。

问题在于Xaringan slide基于remark.js,而后者并不原生支持文献引用(bib citations)(参看yihui关于这一点的评论)。

下面将介绍两种破解思路和方法,但是其背后都基于如下过程:

  • 保存文献格式文件.bib(最简单的就是采用文献管理软件zetero自动化保存)

  • Rmarkdown文件中,使用特定R包(例如RefManageR::ReadBib())读取上述.bib文件,并渲染。

  • 根据需要开发定制函数,以实现特定显示效果(如列表太长时指定分页等)。

最新方法:使用RefManageR(version 1.1.0及以上),具体参看Xaringan Bibliography and citations’ wiki page

  • 步骤1:准备bib
```{r, load_refs, include=FALSE, cache=FALSE}
library(RefManageR)
BibOptions(check.entries = FALSE,
           bib.style = "authoryear",
           cite.style = "alphabetic",
           style = "markdown",
           hyperlink = FALSE,
           dashed = FALSE)
myBib <- ReadBib("./myBib.bib", check = FALSE)
```
  • 步骤2:在正文引用,使用Citet(), Citep(), AutoCite()

  • 步骤3:参考文献列表(单页或分页)

# References

```{r all, echo=FALSE, results="asis"}
PrintBibliography(myBib)
```
# References

```{r split, echo=FALSE, results="asis"}
PrintBibliography(myBib, start = 1, end = 7)
```

破解方法1:适合参考文献条目较少的情形,直接读取.bib条目并渲染。此时,全部文献条目将显示在一页slide上(示例效果可参看)。

```{r,split=FALSE,echo=FALSE,results='asis'}
knitr::write_bib(c(.packages()), "assets/packages.bib")
BibOptions(check.entries = TRUE,     # style
           bib.style = "authoryear",
           sorting = "nty",
           style = "markdown",
           dashed = TRUE)
RefManageR::ReadBib("assets/packages.bib")
```

破解方法2:适合参考文献条目较多的情形,可以在多个slide上分页渲染文献条目(示例效果可参看jvcasillas的示例以及hhp的slide)。

如前所述,破解方法2需要设定一个定制函数以实现指定分页。github仓库jvcasillas/xaringan_bib参看)开发了这样的定制函数print_bib_rmd ()(原始函数请参看)。具体的函数使用方式为:

```{r}
source(here::here("helper.R"))
library(RefManageR)
BibOptions(check.entries = FALSE, 
           bib.style = "authoryear", 
           style = "markdown",
           dashed = TRUE)
file.name <- system.file(
  "Bib", 
  "biblatexExamples.bib",
  package = "RefManageR")
bib <- ReadBib(file.name)
```
显示第1页

```{r, results='asis', echo=FALSE, warning=FALSE}
print_bib_rmd(bib, start = 1, stop = 6)
```
显示第2页

```{r, results='asis', echo=FALSE, warning=FALSE}
print_bib_rmd(bib, start = 7, stop = 10)
```

5.6 Xaringan宏定制:remark.js Macros

5.6.1 定制宏:基本原理与使用方法

remark.js允许用户自定义宏。

自定义宏在markdown中的具体使用方法为:

  • ![:macroName arg1, arg2, ...]

  • 或者![:macroName arg1, arg2, ...](this)

例如,可以自定义一个名为scale的宏(在渲染remark之前,设定图片的缩放比例),其代码如下(具体参看):

remark.macros.scale = function (percentage) {
var url = this;
return '<img src="' + url + '" style="width: ' + percentage + '" />';
};

然后在Rmd文件的yaml区域调用这个宏:

output:
  xaringan::moon_reader:
    nature:
      beforeInit: "macros.js"

在Rmarkdown正文中使用方法为:

  • ![:scale 50%](image.jpg)

最终渲染结果的html格式为:

  • <img src="image.jpg" style="width: 50%" />

5.6.2 定制宏:多列或多行布局样式

github项目emilyriederer/xaringan_columns(见仓库)开发出了多列或多行布局样式,其xaringan slide效果可参看

注意:作者特意hack了多列或多行布局中,逗号,的使用技巧重点在于unicode 代码&#44的使用。

rstudio::conf(2022)中,演讲者Liz Roten的报告Oddly Satisfying - Find delight in the mundane就用到了这个宏包。具体可参看她的slide

5.7 Xaringan杂音:常见异常及bug

5.7.1 杂音1:css相对路径失效问题

经验法则:为了得到正确的相对路径关系,我们需要:a.更新rmarkdown包;b.尽量使用Xaringan插件渲染.Rmd文件(“Rstudio \(\rightarrow\) Addins \(\rightarrow\) Infinite Moon Reader”!

一般情况下,Xaringan创作者会把CSS文件放在一个独立文件夹下,而不是与.Rmd文件并行存放。这样处理的重要理由在于:CSS文件往往是可复用的。

例如,下面的文件管理方式:

library(data.tree)

path <- c(
    "master-SEM/mycss/my-custom-for-video-roomy.css", 
    "master-SEM/slide-chn-part1/part00-slide-intro.Rmd", 
    "master-SEM/slide-chn-part1/part00-slide-intro.html", 
    "master-SEM/slide-chn-part1/part00-slide-intro_files" )

(mytree <- data.tree::as.Node(data.frame(pathString = path)))
                              levelName
1 master-SEM                           
2  ¦--mycss                            
3  ¦   °--my-custom-for-video-roomy.css
4  °--slide-chn-part1                  
5      ¦--part00-slide-intro.Rmd       
6      ¦--part00-slide-intro.html      
7      °--part00-slide-intro_files     

同时,Xaringan slide最常见使用场景一般也有两个:

  • 项目内(项目A)将.Rmd代码文件渲染为.html演示文件,将项目上线(如github),然后分享演讲内容的链接。

  • 其他项目(项目B,如netlify静态建站项目),需要调用上述项目的.html演示文件。

然而对于后者而言,CSS文件夹或html文件夹的移动或复制(如netlify静态建站时需要拷贝到static/文件下)则会面临相对引用路径的问题。而且这也是一个Xaringan包已知的“旧疾隐患”(参看Relative paths to dir above root? see xaringan issue)。

好在最近Xaringan团队着手处理了这个“定时炸弹”。具体请参看:Relative CSS in parent folder are now added with an absolute path (see xaringan issue)。然而通过测试,也发现目前只是“部分地”解决了问题。

操作情形1:如果使用Rstudio菜单渲染.Rmd文件(“Rstudio \(\rightarrow\) knit \(\rightarrow\) knit to moon_reader”),输出的.html文件与css文件的路径关系结果显示不正常!使用chrome浏览器 \(\rightarrow\) 右键“查看”,具体关系如下:

<!---
scenario 1: knit button by 'knit to moon_reader'
html source element in chrome
--->
<head>
  <style>
    <link rel="stylesheet" href="D:/github/master-SEM/mycss/my-custom-for-video-roomy.css" type="text/css">
  </style>
</head>

然而href后面的css路径”D:/github/master-SEM/mycss/my-custom-for-video-roomy.css” ,仅仅只是“显示路径”。chrome浏览器下把鼠标悬置1秒在上述“显示路径”上,则可以看到css的“真实路径”为: “file:///D:/github/master-SEM/slide-chn-part1/D:/github/master-SEM/mycss/text-box.css”。显然这样的路径关系是“不正常”的!

操作情形2:如果使用Xaringan插件渲染.Rmd文件(“Rstudio \(\rightarrow\) Addins \(\rightarrow\) Infinite Moon Reader”),输出的.html文件与css文件的路径关系结果则显示正常。使用chrome浏览器 \(\rightarrow\) 右键“查看”,具体关系如下:

<!---
scenario 2: Addins by 'Infinite Moon Reader'
html source element in chrome
--->

<head>
  <style>
    <link rel="stylesheet" href="../mycss/my-custom-for-video-roomy.css" type="text/css">
  </style>
</head>

可以观察到href后面的css文件的“显示路径”为”../mycss/my-custom-for-video-roomy.css” 。进一步地,在chrome浏览器下把鼠标悬置1秒在上述“显示路径”上,则可以看到css的“真实路径”为:file:///D:/github/master-SEM/mycss/text-box.css。而这样的路径关系应该是“正常”的!

5.7.2 杂音2:count: false/true

经验法则:目前没有找到好的解决办法,建议只在幻灯片的首页设定”count: false”,第2页开始立刻设定为”count: true”。——免得夜长梦多!

先简单描述一下问题:多个幻灯片中设定了count: false/true,输出的.html一切如你所愿,然而当转换为pdf时(具体地,是使用pagedown::chrome_print("your-output-slide.html")进行pdf转换),部分设定为count: false的幻灯片会消失不见!

例如,.Rmd里的slide 代码如下。对输出的.html进行pdf转换(pagedown::chrome_print())后,pdf仅仅只有第3页,前两页会消失不见!

<!---
scenario:
1.multiple slides use class of "count: false/true"
2. convert .html to pdf by using pagedown::chrome_print("your-output-slide.html")
--->

---
count: true 
Content 1

---
count: false
Content 2

---
count: false
Content 3

参看资料:

  • Slides written in Rmd missing pages when converting from HTML to PDF see stackoverflow

5.7.3 杂音3:html/pdf转可编辑化的pptx

温馨提示:严格一致的可编辑性的pptx输出基本难以实现,无论是Bluebeam revu extreme软件手动导出,还是LibreOffice软件的CMD命令导出。

html格式的slide适合展示,但是学生可能更喜欢.pdf或者.pptx格式的slide。如果单纯只是获得图片格式的pptx,这个基本没有什么实现难度,例如pagedown。问题在于严格一致的可编辑性的pptx输出(文本、图片要素等可编辑或拉选移动),理论上基本是很难实现的。

具体地,实现可编辑ppt的方法至少有:

  • 利用Bluebeam revu extreme软件手动将pdf导出为pptx。

  • 利用LibreOffice软件将pdf导出为pptx(见下),这里可以使用CMD命令方法进行批量处理。

相关操作可参看:

  • html转pdf的一个选择DeckTape(支持reveal /remark等多种编译方法)。

  • LibreOffice是pdf转可编辑化的pptx的一个选择。可以参看博文:Automated Build and Publication of Slides with R Markdown, Reveal.js, DeckTape, and LibreOffice.

这里重点介绍LibreOffice软件的Linux命令操作:

  • 步骤1:安装LibreOffice软件

  • 步骤2:Windows 10系统设定LibreOffice的环境变量参看

  • 步骤3:CMD命令操作(参看说明1;以及说明2

# 在CMD中运行如下代码
soffice --infilter="impress_pdf_import" --convert-to pptx:"Impress MS PowerPoint 2007 XML" d:/opensource-getting-involved_2.pdf

# 同名的pptx转换文件会出现在 `c:/user/your/`路径下

已经完成的导出测试包括:

  • reveal格式输出pdf下的pptx导出。

  • remark格式输出pdf下的pptx导出。