1
#' A wrapper for rst2pdf
2
#'
3
#' Convert reST to PDF using \command{rst2pdf} (which converts from rst to PDF
4
#' using the ReportLab open-source library).
5
#' @param input The input rst file.
6
#' @param command Character string giving the path of the
7
#'   \command{rst2pdf} program. If the program is not in your PATH, the full path has to be
8
#'   given here.
9
#' @param options Extra command line options, e.g. \code{'-v'}.
10
#' @author Alex Zvoleff and Yihui Xie
11
#' @return An input file \file{*.rst} will produce \file{*.pdf} and this output
12
#'   filename is returned if the conversion was successful.
13
#' @export
14
#' @seealso \code{\link{knit2pdf}}
15
#' @references \url{https://github.com/rst2pdf/rst2pdf}
16
rst2pdf = function(input, command = 'rst2pdf', options = '') {
17 0
  out = with_ext(input, 'pdf')
18 0
  system2(command, paste(shQuote(input), '-o', shQuote(out), options))
19 0
  if (file.exists(out)) out else stop('conversion by rst2pdf failed!')
20
}
21

22
#' Convert various input files to various output files using \code{knit()} and
23
#' Pandoc
24
#'
25
#' Knits the input file and compiles to an output format using Pandoc.
26
#' @inheritParams knit
27
#' @param to Character string giving the Pandoc output format to use.
28
#' @param pandoc_wrapper An R function used to call Pandoc. If \code{NULL} (the
29
#'   default), \code{rmarkdown::\link[rmarkdown]{pandoc_convert}()} will be used
30
#'   if \pkg{rmarkdown} is installed, otherwise \code{\link{pandoc}()}.
31
#' @param ... Options to be passed to the \code{pandoc_wrapper} function.
32
#' @param encoding Ignored (always assumes UTF-8).
33
#' @author Trevor L. Davis
34
#' @return Returns the output of the \code{pandoc_wrapper} function.
35
#' @export
36
knit2pandoc = function(
37
  input, output = NULL, tangle = FALSE, text = NULL, quiet = FALSE,
38
  envir = parent.frame(), to = 'html', pandoc_wrapper = NULL, ..., encoding = 'UTF-8'
39
) {
40 0
  knit_output = knit(input, output, tangle, text, quiet, envir)
41 0
  if (!is.null(pandoc_wrapper)) return(pandoc_wrapper(knit_output, to, ...))
42 0
  if (!has_package('rmarkdown')) return(pandoc(knit_output, to, ...))
43 0
  output = gsub(paste0(file_ext(knit_output), '$'), to, knit_output)
44 0
  rmarkdown::pandoc_convert(knit_output, to, output = output, ...)
45
}
46

47
#' Convert Rnw or Rrst files to PDF
48
#'
49
#' Knit the input Rnw or Rrst document, and compile to PDF using
50
#' \code{tinytex::\link[tinytex]{latexmk}()} or \code{\link{rst2pdf}()}.
51
#' @inheritParams knit
52
#' @param compiler A character string giving the LaTeX engine used to compile
53
#'   the tex document to PDF. For an Rrst file, setting \code{compiler} to
54
#'   \code{'rst2pdf'} will use \code{\link{rst2pdf}} to compile the rst file to
55
#'   PDF using the ReportLab open-source library.
56
#' @param ... Options to be passed to \code{tinytex::\link[tinytex]{latexmk}()}
57
#'   or \code{\link{rst2pdf}()}.
58
#' @author Ramnath Vaidyanathan, Alex Zvoleff and Yihui Xie
59
#' @return The filename of the PDF file.
60
#' @note The \code{output} argument specifies the output filename to be passed
61
#'   to the PDF compiler (e.g. a tex document) instead of the PDF filename.
62
#' @export
63
#' @examples #' compile with xelatex
64
#' ## knit2pdf(..., compiler = 'xelatex')
65
#'
66
#' #' compile a reST file with rst2pdf
67
#' ## knit2pdf(..., compiler = 'rst2pdf')
68
knit2pdf = function(
69
  input, output = NULL, compiler = NULL, envir = parent.frame(), quiet = FALSE, ...
70
) {
71 0
  out = knit(input, output = output, envir = envir, quiet = quiet)
72 0
  owd = setwd(dirname(out)); on.exit(setwd(owd))
73 0
  if (is.null(compiler)) {
74 0
    compiler = if (grepl('\\.rst$', out)) 'rst2pdf' else 'pdflatex'
75
  }
76 0
  if (identical(compiler, 'rst2pdf')) {
77 0
    if (tolower(file_ext(out)) != 'rst')
78 0
      stop('for rst2pdf compiler input must be a .rst file')
79 0
    rst2pdf(basename(out), ...)
80
  } else {
81 0
    tinytex::latexmk(basename(out), engine = compiler, ...)
82
  }
83 0
  with_ext(out, 'pdf')
84
}
85

86
#' Convert markdown to HTML using knit() and markdownToHTML()
87
#'
88
#' This is a convenience function to knit the input markdown source and call
89
#' \code{markdown::\link{markdownToHTML}()} in the \pkg{markdown} package to
90
#' convert the result to HTML.
91
#' @inheritParams knit
92
#' @param ... Options passed to \code{markdown::\link{markdownToHTML}()}.
93
#' @param force_v1 Boolean; whether to force rendering the input document as an
94
#'   R Markdown v1 document, even if it is for v2.
95
#' @export
96
#' @seealso \code{\link{knit}}, \code{markdown::\link{markdownToHTML}}
97
#' @return If the argument \code{text} is NULL, a character string (HTML code)
98
#'   is returned; otherwise the result is written into a file and the filename
99
#'   is returned.
100
#' @note The \pkg{markdown} package is for R Markdown v1, which is much less
101
#'   powerful than R Markdown v2, i.e. the \pkg{rmarkdown} package
102
#'   (\url{https://rmarkdown.rstudio.com}). To render R Markdown v2 documents to
103
#'   HTML, please use \code{rmarkdown::render()} instead.
104
#' @examples # a minimal example
105
#' writeLines(c("# hello markdown", '```{r hello-random, echo=TRUE}', 'rnorm(5)', '```'), 'test.Rmd')
106
#' knit2html('test.Rmd')
107
#' if (interactive()) browseURL('test.html')
108
#'
109
#' unlink(c('test.Rmd', 'test.html', 'test.md'))
110
knit2html = function(input, output = NULL, ..., envir = parent.frame(), text = NULL,
111
                     quiet = FALSE, encoding = 'UTF-8', force_v1 = FALSE) {
112
  # packages containing vignettes using R Markdown v1 should declare dependency
113
  # on 'markdown' in DESCRIPTION (typically in Suggests)
114 0
  if (!is.na(pkg <- check_package_name()) && pkg != 'markdown') {
115 0
    info = packageDescription(pkg, fields = c('Depends', 'Imports', 'Suggests'))
116 0
    if (!'markdown' %in% unlist(strsplit(unlist(info), '[[:space:],]+'))) {
117 0
      if (is_CRAN_incoming()) stop2(
118 0
        "The 'markdown' package should be declared as a dependency of the '", pkg,
119 0
        "' package (e.g., in the  'Suggests' field of DESCRIPTION), because it ",
120 0
        "contains vignette(s) built with the 'markdown' package. Please see ",
121 0
        "https://github.com/yihui/knitr/issues/1864 for more information."
122
      )
123
    }
124
  }
125
  # TODO: remove the above hack in the future when no CRAN packages have the issue
126

127 0
  if (!force_v1 && is.null(text)) {
128 0
    signal = if (is_R_CMD_check()) warning2 else stop2
129 0
    if (length(grep('^---\\s*$', head(read_utf8(input), 1)))) signal(
130 0
      'It seems you should call rmarkdown::render() instead of knitr::knit2html() ',
131 0
      'because ', input, ' appears to be an R Markdown v2 document.'
132
    )
133
  }
134 0
  out = knit(input, text = text, envir = envir, quiet = quiet)
135 0
  if (is.null(text)) {
136 0
    output = with_ext(if (is.null(output) || is.na(output)) out else output, 'html')
137 0
    markdown::markdownToHTML(out, output, encoding = 'UTF-8', ...)
138 0
    invisible(output)
139 0
  } else markdown::markdownToHTML(text = out, ...)
140
}
141

142 0
knit2html_v1 = function(...) knit2html(..., force_v1 = TRUE)
143

144
#' Knit an R Markdown document and post it to WordPress
145
#'
146
#' This function is a wrapper around the \pkg{RWordPress} package. It compiles
147
#' an R Markdown document to HTML and post the results to WordPress. Please note
148
#' that \pkg{RWordPress} has not been updated for several years, which is
149
#' \href{https://github.com/yihui/knitr/issues/1866}{not a good sign}. For
150
#' blogging with R, you may want to try the \pkg{blogdown} package instead.
151
#' @param input Filename of the Rmd document.
152
#' @param title Title of the post.
153
#' @param ... Other meta information of the post, e.g. \code{categories = c('R',
154
#'   'Stats')} and \code{mt_keywords = c('knitr', 'wordpress')}, et cetera.
155
#' @param shortcode A length-2 logical vector: whether to use the shortcode
156
#'   \samp{[sourcecode lang='lang']}, which can be useful to WordPress.com users
157
#'   for syntax highlighting of source code and output. The first element
158
#'   applies to source code, and the second applies to text output. By default,
159
#'   both are \code{FALSE}.
160
#' @param action Whether to create a new post, update an existing post, or
161
#'   create a new page.
162
#' @param postid If \code{action} is \code{editPost}, the post id \code{postid}
163
#'   must be specified.
164
#' @param publish Boolean: publish the post immediately?
165
#' @inheritParams knit
166
#' @export
167
#' @references \url{https://yihui.org/knitr/demo/wordpress/}
168
#' @author William K. Morris, Yihui Xie, and Jared Lander
169
#' @note This function will convert the encoding of the post and the title to
170
#'   UTF-8 internally. If you have additional data to send to WordPress (e.g.
171
#'   keywords and categories), you may have to manually convert them to the
172
#'   UTF-8 encoding with the \code{\link{iconv}(x, to = 'UTF-8')} function
173
#'   (especially when using Windows).
174
#' @examples # see the reference
175
knit2wp = function(
176
  input, title = 'A post from knitr', ..., envir = parent.frame(), shortcode = FALSE,
177
  action = c('newPost', 'editPost', 'newPage'), postid, publish = TRUE
178
) {
179 0
  do.call('library', list(package = 'RWordPress', character.only = TRUE))
180 0
  xfun::do_once(
181 0
    warning2(
182 0
      'This function is based on the RWordPress package, which is no longer actively ',
183 0
      'maintained (https://github.com/yihui/knitr/issues/1866). For blogging with R, ',
184 0
      'you may try the blogdown package instead.'
185 0
    ), 'knitr.knit2wp.warning'
186
  )
187 0
  out = knit(input, envir = envir); on.exit(unlink(out))
188 0
  content = file_string(out)
189 0
  content = markdown::markdownToHTML(text = content, fragment.only = TRUE)
190 0
  shortcode = rep(shortcode, length.out = 2L)
191 0
  if (shortcode[1]) content = gsub(
192 0
    '<pre><code class="([[:alpha:]]+)">(.+?)</code></pre>',
193 0
    '[sourcecode language="\\1"]\\2[/sourcecode]', content
194
  )
195 0
  content = gsub(
196 0
    '<pre><code( class="no-highlight"|)>(.+?)</code></pre>',
197 0
    if (shortcode[2]) '[sourcecode]\\2[/sourcecode]' else '<pre>\\2</pre>', content
198
  )
199

200 0
  content = enc2utf8(content)
201 0
  title = enc2utf8(title)
202

203
  # figure out if we are making a newPost or overwriting an existing post
204 0
  action = match.arg(action)
205

206
  # build a list of arguments to be fed into either newPost or editPost
207
  # the first argument is the content, which itself is a list containing
208
  #     description
209
  #     title
210
  #     ...
211
  # then there is the publish argument
212 0
  WPargs = list(content = list(description = content, title = title, ...), publish = publish)
213

214
  # if we are editing the post, also include the argument for postid
215 0
  if (action == "editPost") WPargs = c(postid = postid, WPargs)
216

217 0
  do.call(action, args = WPargs)
218
}
219

220
#' Watch an input file continuously and knit it when it is updated
221
#'
222
#' Check the modification time of an input file continously in an infinite loop.
223
#' Whenever the time indicates the file has been modified, call a function to
224
#' recompile the input file.
225
#'
226
#' This is actually a general function not necessarily restricted to
227
#' applications in \pkg{knitr}. You may specify any \code{compile} function to
228
#' process the \code{input} file. To stop the infinite loop, press the
229
#' \samp{Escape} key or \samp{Ctrl + C} (depending on your editing environment
230
#' and operating system).
231
#' @param input An input file path, or a character vector of mutiple input file paths.
232
#' @param compile A function to compile the \code{input} file. This could be e.g.
233
#'   \code{\link{knit}} or \code{\link{knit2pdf}}, depending on the input file
234
#'   and the output you want.
235
#' @param interval A time interval to pause in each cycle of the infinite loop.
236
#' @param ... Other arguments to be passed to the \code{compile} function.
237
#' @export
238
#' @examples # knit_watch('foo.Rnw', knit2pdf)
239
#'
240
#' # knit_watch('foo.Rmd', rmarkdown::render)
241
knit_watch = function(input, compile = knit, interval = 1, ...) {
242 0
  mtime = function(...) file.info(...)[, 'mtime']
243 0
  last_time = mtime(input)
244 0
  updated = function() {
245 0
    this_time = mtime(input)
246 0
    on.exit(last_time <<- this_time, add = TRUE)
247 0
    this_time > last_time
248
  }
249 0
  for (f in input) compile(f, ...)
250 0
  while (TRUE) {
251 0
    for (f in input[updated()]) compile(f, ...)
252 0
    Sys.sleep(interval)
253
  }
254
}

Read our documentation on viewing source code .

Loading