Dans "knitr" comment puis-je tester si la sortie sera PDF ou word?

Je voudrais inclure un contenu spécifique basé sur le format en cours de création. Dans cet exemple spécifique, mes tables ont l'air terribles dans la sortie MS word, mais géniales dans HTML. Je voudrais ajouter un test pour laisser de côté la table en fonction de la sortie.

Voici un pseudocode:

output.format <- opts_chunk$get("output")

if(output.format != "MS word"){
print(table1)
}

Je suis sûr que ce n'est pas la bonne façon d'utiliser les opts_chunk, mais c'est la limite de ma compréhension de la façon dont knitr fonctionne sous le capot. Quelle serait la bonne façon de tester pour cela?

23
demandé sur Tom 2016-02-02 05:42:58

4 réponses

Réponse Courte

Dans la plupart des cas, opts_knit$get("rmarkdown.pandoc.to") fournit les informations requises.

Sinon, interrogez rmarkdown::all_output_formats(knitr::current_input()) et vérifiez si la valeur de retour contient word_document:

if ("word_document" %in% rmarkdown::all_output_formats(knitr::current_input()) {
  # Word output
}

Réponse Longue

Je suppose que le document source est RMD parce que c'est le format d'entrée habituel/le plus commun pour tricoter vers différents formats de sortie tels que MS Word, PDF et HTML.

Dans ce cas, les options knitr ne peuvent pas être utilisées pour déterminer le format de sortie final question du point de vue de knitr: pour tous les formats de sortie, le travail de knitr consiste à tricoter le fichier RMD d'entrée dans un fichier MD. La conversion du fichier MD au format de sortie spécifié dans L'en-tête YAML se fait à l'étape suivante, par pandoc.

Par conséquent, nous ne pouvons pas utiliser l'option de paquet knitr::opts_knit$get("out.format") pour en savoir plus sur le format de sortie final, mais nous devons analyser l'en-tête YAML à la place.

Jusqu'à présent, en théorie. la réalité est un peu différente. Le "tricot" de RStudio PDF" / "Knit HTML" bouton appelle {[14] } qui à son tour appelle knit. Avant que cela arrive, render définit a (non documenté?) option de paquet rmarkdown.pandoc.to au format de sortie réel. La valeur sera html, latex ou docx, respectivement, selon le format de sortie.

Par conséquent, si (et seulement si) le bouton "Knit PDF"/"Knit HTML" de RStudio est utilisé, knitr::opts_knit$get("rmarkdown.pandoc.to") peut être utilisé pour déterminer le format de sortie. Ceci est également décrit dans cette réponse et ce blog post .

Le problème reste non résolu pour le cas d'appeler knit directement car alors rmarkdown.pandoc.to n'est pas défini. Dans ce cas, nous pouvons exploiter la fonction (non exportée) parse_yaml_front_matter du paquet rmarkdown pour analyser l'en-tête YAML.

[mise à jour: à partir de rmarkdown 0.9.6, la fonction all_output_formats a été ajoutée (merci à Bill Denney pour l'avoir signalé). Il rend la fonction personnalisée développée ci-dessous obsolète - pour la production, utilisez rmarkdown::all_output_formats! Je laisse le reste de ceci réponse écrite à l'origine à des fins éducatives.]

---
output: html_document
---
```{r}
knitr::opts_knit$get("out.format") # Not informative.

knitr::opts_knit$get("rmarkdown.pandoc.to") # Works only if knit() is called via render(), i.e. when using the button in RStudio.

rmarkdown:::parse_yaml_front_matter(
    readLines(knitr::current_input())
    )$output
```

L'exemple ci-dessus démontre l'utilisation(lesness) de opts_knit$get("rmarkdown.pandoc.to") (opts_knit$get("out.format")), alors que la ligne employant parse_yaml_front_matter renvoie le format spécifié dans le champ" output " de L'en-tête YAML.

L'entrée de parse_yaml_front_matter est le fichier source en tant que vecteur de caractères, tel que renvoyé par readLines. Pour déterminer le nom du fichier en cours de tricotage, {[34] } Comme suggéré dans cette réponse est utilisée.

Avant parse_yaml_front_matter peut être utilisé dans une simple instruction if pour implémenter un comportement conditionnel au format de sortie, un petit raffinement est requis: L'instruction ci-dessus peut renvoyer une liste s'il existe des paramètres YAML supplémentaires pour la sortie comme dans cet exemple:

---
output: 
  html_document: 
    keep_md: yes
---

La fonction d'assistance suivante doit résoudre ce problème:

getOutputFormat <- function() {
  output <- rmarkdown:::parse_yaml_front_matter(
    readLines(knitr::current_input())
    )$output
  if (is.list(output)){
    return(names(output)[1])
  } else {
    return(output[1])
  }
}

, Il peut être utilisé dans des constructions telles que

if(getOutputFormat() == 'html_document') {
   # do something
}

Notez que getOutputFormat utilise uniquement le premier format de sortie spécifié, donc avec l'en-tête suivant uniquement html_document est retourné:

---
output:
  html_document: default
  pdf_document:
    keep_tex: yes
---

Cependant, ce n'est pas très restrictif. Lorsque le bouton "Knit HTML"/"Knit PDF" de RStudio est utilisé (avec le menu déroulant à côté pour sélectionner le type de sortie), RStudio réarrange l'en-tête YAML de sorte que le format de sortie sélectionné sera le premier format de la liste. Plusieurs formats de sortie ne sont (AFAIK) pertinents que lorsque vous utilisez rmarkdown::render avec output_format = "all". Et: Dans ces deux cas rmarkdown.pandoc.to peut être utilisé, ce qui est plus facile de toute façon.

36
répondu CL. 2017-05-23 11:47:19

Depuis knitr 1.18, vous pouvez utiliser les deux fonctions de

knitr::is_html_output()

Et

knitr::is_latex_output()
6
répondu David 2018-01-26 08:53:59

Un point supplémentaire: les réponses ci-dessus ne fonctionnent pas pour un html_notebook, puisque le code est exécuté directement là-bas et knitr::current_input() ne répond pas. Si vous connaissez le nom du document, vous pouvez appeler all_output_formats comme ci-dessus, en spécifiant explicitement le nom. Je ne sais pas s'il y a un autre moyen de le faire.

2
répondu 2017-03-17 16:30:05

Je veux juste ajouter un peu de clarification ici, puisque je rends souvent le même fichier Rmarkdown (*.Rmd) en plusieurs formats (*.HTML, *.PDF, *.docx), donc plutôt que de vouloir à savoir si le format d'intérêt est répertorié parmi ceux spécifiés dans les pages préliminaires yaml (c - "word_document" %in% rmarkdown::all_output_formats(knitr::current_input()), je veux savoir quel format doit être rendu. Pour ce faire, vous pouvez soit:

  1. Obtenez le premier élément des formats listés en première ligne: rmarkdown::all_output_formats(knitr::current_input()[1]; ou

  2. Obtenir le format de sortie par défaut nom: rmarkdown::default_output_format(knitr::current_input())$name

Par exemple...

---
title: "check format"
output:
  html_document: default
  pdf_document: default
  word_document: default
---

```{r}
rmarkdown::all_output_formats(knitr::current_input())[1]
```

```{r}
rmarkdown::default_output_format(knitr::current_input())$name
```

```{r}
fmt <- rmarkdown::default_output_format(knitr::current_input())$name

if (fmt == "pdf_document"){
  #...
}

if (fmt == "word_document"){
  #...
}
```
2
répondu Ben Best 2017-12-23 00:40:06