5.1 Jekyll
Para los usuarios de Jekyll (https://jekyllrb.com)\index{Jekyll}, he preparado un ejemplo mínimo en el repositorio de GitHub yihui/blogdown-jekyll.. Si clona o descarga este repositorio y abre blogdown-jekyll.Rproj
en RStudio, puede usar todos los complementos mencionados en la sección 1.3, como “New Post”, " Serve Site" y “Update Metadata”, pero ahora es Jekyll en lugar de Hugo quien crea el sitio web tras bambalinas.
Supongo que está familiarizado con Jekyll, y no voy a presentar los conceptos básicos de Jekyll en esta sección. Por ejemplo, debe saber lo que significan los directorios _posts/
y _site/
.
Las piezas clave de este proyecto blogdown-jekyll son los archivos .Rprofile
, R/build.R
, y R/build_one.R
. He configurado algunas opciones en R globales para este proyecto en .Rprofile
:40
En primer lugar, el generador del sitio web se configuró en jekyll
con la opción blogdown.generator
, por lo que blogdown sabe que debe usar Jekyll para construir el sitio. En segundo lugar, el método de compilación blogdown.method
se configuró como custom
, por lo que podemos definir nuestro guión en R personalizado R/build.R
para compilar los archivos Rmd (explicaré el motivo más adelante). En tercer lugar, el subdirectorio predeterminado para las nuevas publicaciones se estableció en _posts
, que es la convención de Jekyll. Después de configurar esta opción, el complemento “New message” creará nuevas publicaciones en el directorio _posts/
.
Cuando la opción blogdown.method
es custom
, blogdown llamará al script R R/build.R
para construir el sitio. Tiene plena libertad para hacer lo que quiera en este script. A continuación hay un script de ejemplo:
build_one = function(io) {
# si la salida no es más antigua que la entrada, omita la compilación
if (!blogdown:::require_rebuild(io[2], io[1])) return()
message('* knitting ', io[1])
if (blogdown:::Rscript(shQuote(c('R/build_one.R', io))) != 0) {
unlink(io[2])
stop('Failed to compile ', io[1], ' to ', io[2])
}
}
# Los archivos Rmd bajo el directorio raiz
rmds = list.files('.', '[.]Rmd$', recursive = T, full.names = T)
files = cbind(rmds, xfun::with_ext(rmds, '.md'))
for (i in seq_len(nrow(files))) build_one(files[i, ])
system2('jekyll', 'build')
Básicamente contiene una función
build_one()
que toma un argumentoio
, que es un vector de caracteres de longitud 2. El primer elemento es el nombre de archivo de entrada (Rmd) y el segundo elemento es el nombre del archivo de salida.Luego buscamos todos los archivos Rmd bajo el directorio actual, preparamos los nombres de los archivos de salida sustituyendo las extensiones de archivo Rmd por
.md
, y compilamos los archivos Rmd uno por uno. Tenga en cuenta que hay un mecanismo de almacenamiento en caché enbuild_one()
que hace uso de una función interna de blogdownrequire_rebuild()
. Esta función devuelveFALSE
si el archivo de salida no es anterior al archivo de entrada en términos del tiempo de modificación. Esto puede ahorrarle algo de tiempo porque esos archivos Rmd que se han compilado anteriormente no se compilarán nuevamente cada vez. El paso clave enbuild_one()
es ejecutar el script en RR/build_one.R
, que explicaremos más adelante.Por último, creamos el sitio web a través de una llamada al sistema del comando
jekyll build
.
El script R/build_one.R
se ve así (he omitido algunas configuraciones no esenciales por simplicidad):
local({
# fall back on "/" if baseurl is not specified
baseurl = blogdown:::get_config2("baseurl", default = "/")
knitr::opts_knit$set(base.url = baseurl)
knitr::render_jekyll() # set output hooks
# input/output filenames as two arguments to Rscript
a = commandArgs(TRUE)
d = gsub("^_|[.][a-zA-Z]+$", "", a[1])
knitr::opts_chunk$set(
fig.path = sprintf("figure/%s/", d),
cache.path = sprintf("cache/%s/", d)
)
knitr::knit(
a[1], a[2], quiet = TRUE, encoding = "UTF-8",
envir = globalenv()
)
})
La secuencia de comandos se envuelve en
local()
para que un archivo Rmd se teja en un entorno global limpio, y las variables comobaseurl
,a
yd
no se crearán en el entorno global, es decir,globalenv()
utilizado porknitr::knit()
a continuación.La opción del paquete knitr
base.url
es una URL que se agregará previamente a las rutas de las figuras. Necesitamos configurar esta opción para asegurarnos de que las cifras generadas a partir de los fragmentos de código en R puedan encontrarse cuando se muestran en una página web. Una ruta de figura normal es a menudo comofigure/foo.png
, y puede no funcionar cuando la imagen se representa en un archivo HTML, porquefigure/foo.png
es una ruta relativa, y no hay garantía de que esto el archivo de imagen se copiará en el directorio del archivo HTML final. Por ejemplo, para un archivo fuente Rmd_posts/2015-07-23-hello.Rmd
que generafigure/foo.png
(en_posts/
), el archivo HTML final puede ser_site/2015/07/23/hello/index.html
. Jekyll sabe cómo renderizar un archivo HTML en esta ubicación, pero no entiende la dependencia de la imagen y no copiará el archivo de imagen en esta ubicación. Para resolver este problema, presentamos figuras en el directorio raíz/figure/
, que Jekyll copiará a_site/
. Para hacer referencia a una imagen en_site/figure/
, necesitamos la barra diagonal (baseurl
), por ejemplo,<img src="/figure/foo.png">
. Esta es una ruta absoluta, por lo que no importa dónde se represente el HTML, esta ruta siempre funciona.Lo que
knitr::render_jekyll()
hace es principalmente configurar algunos hooks de salida knitr para que el código fuente y la salida de texto de los fragmentos de código en R se envuelvan en las etiquetas liquid{% highlight %}
y{% end highlight %}
.Recuerde que en
build.R
, pasamos la variableio
a la llamada Rscriptblogdown:::Rscript
. Aquí enbuild_one.R
, podemos recibirlos desdecommandArgs(TRUE)
. La variablea
contiene una ruta de archivo.Rmd
y.md
. Eliminamos el posible guion bajo principal (^_
) y la extensión ([.] [a-zA-Z]$
en la ruta. A continuación, establecemos rutas de figura y caché utilizando esta cadena. Por ejemplo, para una publicación_posts/foo.Rmd
, sus figuras se escribirán enfigure/foo/
y sus bases de datos de caché (si las hay) se almacenarán bajocache/foo/
. Ambos directorios están bajo el directorio raíz del proyecto.Por último, llamamos a
knitr::knit()
para unir el archivo Rmd a un archivo de salida Markdown, que será procesado posteriormente por Jekyll.
Una pequeña advertencia es que, dado que tenemos los dos archivos .Rmd
y .md
, Jekyll tratará ambos tipos de archivos como archivos Markdown de forma predeterminada. Tiene que pedirle a Jekyll que ignore los archivos .Rmd
y que solo cree archivos .md
. Puede establecer la opción exclude
en _config.yml
:
Comparado con el soporte de Hugo en blogdown, este enfoque es limitado en algunos aspectos:
No es compatible con Pandoc, por lo que no puede usar el Markdown de Pandoc. Como usa el paquete knitr en lugar de rmarkdown, tampoco puede usar ninguna de las funciones de Markdown blogdown. Usted está a merced de los renderizadores de Markdown apoyados por Jekyll.
Sin rmarkdown, no puede usar widgets HTML. Básicamente, todo lo que puede tener es salida de texto dinámico y salida de gráficos en R a partir de fragmentos de código R. Pueden o no ser suficientes, dependiendo de sus casos de uso específicos.
Es posible que podamos eliminar estas limitaciones en una versión futura de blogdown, si hay suficientes usuarios felices de Jekyll en la comunidad R.
Si no está familiarizado con este archivo, lea la sección @ref(opciones globales).↩