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
|
|
}
|