forked from dwoll/RExRepos
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdwKnit.r
More file actions
179 lines (155 loc) · 7.27 KB
/
dwKnit.r
File metadata and controls
179 lines (155 loc) · 7.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
## knit one input Rmd file to one output md file
dwKnit <- function(fIn, fOut,
markdEngine=c("kramdown", "redcarpet", "pandoc"),
siteGen=c("jekyll", "nanoc", "none")) {
markdEngine <- match.arg(markdEngine)
siteGen <- match.arg(siteGen)
require(knitr)
require(stringr)
## set some directories and get base file name
dirTmp <- "../tmp"
dirMd <- "../md"
dirR <- "../R"
fName <- basename(tools::file_path_sans_ext(fIn))
## configure knitr chunk options
knitr::opts_chunk$set(cache.path=file.path("../tmp/cache/"),
fig.path=file.path("../content/assets/figure/"),
tidy=FALSE, message=FALSE, warning=FALSE, comment=NA)
## configure hooks for different types of markdown output
knitr::render_markdown(strict=FALSE)
## for Jekyll + Redcarpet2, as well as for nanoc + pandoc,
## code blocks can start with knitr's default fenced code block ```r, otherwise:
if((siteGen == "jekyll") & (markdEngine == "kramdown")) {
## for Jekyll + kramdown, code blocks need to start with {% highlight r %}
knitr::render_jekyll()
} else if((siteGen == "nanoc") & (markdEngine == "kramdown")) {
## for nanoc + kramdown, fenced code blocks need to start with ~~~ r
hook.t <- function(x, options) stringr::str_c("\n\n~~~\n", x, "~~~\n\n")
hook.r <- function(x, options) {
stringr::str_c("\n\n~~~ ", tolower(options$engine), "\n", x, "~~~\n\n")
}
} else if((siteGen == "nanoc") & (markdEngine == "redcarpet")) {
## for nanoc + Redcarpet2, fenced code blocks need to start with ```language-r
hook.t <- function(x, options) stringr::str_c("\n\n```\n", x, "```\n\n")
hook.r <- function(x, options) {
stringr::str_c("\n\n```language-", tolower(options$engine), "\n", x, "```\n\n")
}
}
## apply newly defined hooks
if(exists("hook.t") && exists("hook.r")) {
knitr::knit_hooks$set(source=hook.r, output=hook.t, warning=hook.t,
error=hook.t, message=hook.t)
}
## add GitHub-Links, knit to markdown, post-process, and extract R code
gitHubLinks(fIn, paste(dirTmp, "/", fName, "Tmp.Rmd", sep=""))
knitr::knit( paste(dirTmp, "/", fName, "Tmp.Rmd", sep=""),
paste(dirMd, "/", fName, ".md", sep=""))
postProcess( paste(dirMd, "/", fName, ".md", sep=""), fOut,
markdEngine, siteGen)
knitr::purl(fIn, paste(dirR, "/", fName, ".R", sep=""))
}
## add GitHub links to the bottom of a post
gitHubLinks <- function(fIn, fOut) {
## determine names for files we link to on GitHub
fName <- basename(tools::file_path_sans_ext(fIn))
fRmd <- paste(fName, ".Rmd", sep="")
fMd <- paste(fName, ".md", sep="")
fR <- paste(fName, ".R", sep="")
ghURL <- "https://github.com/dwoll/RExRepos"
fCont <- readLines(fIn)
nLines <- length(fCont)
fCont[nLines + 1] <- ""
fCont[nLines + 2] <- "Get the article source from GitHub"
fCont[nLines + 3] <- "----------------------------------------------"
fCont[nLines + 4] <- ""
fCont[nLines + 5] <-
paste("[R markdown](", ghURL, "/raw/master/Rmd/", fRmd, ") - ",
"[markdown](", ghURL, "/raw/master/md/", fMd, ") - ",
"[R code](", ghURL, "/raw/master/R/", fR, ") - ",
"[all posts](", ghURL, "/)", sep="")
writeLines(fCont, fOut)
}
## necessary post-processing required for building the site with Jekyll or nanoc
## TODO: ensure presence of YAML front matter with relevant entries like in
## https://github.com/jjallaire/rcpp-gallery/blob/gh-pages/_scripts/knit.sh
postProcess <- function(fIn, fOutPre,
markdEngine=c("kramdown", "redcarpet", "pandoc"),
siteGen=c("jekyll", "nanoc", "none")) {
markdEngine <- match.arg(markdEngine)
siteGen <- match.arg(siteGen)
## determine names for new files
fName <- basename(tools::file_path_sans_ext(fIn))
fInTmp <- paste("../tmp/", fName, "Tmp.md", sep="")
tocRepl <- c("", "")
fCont <- sanitizeMath(fIn, markdEngine) ## replace math delimiters \( and \)
writeLines(fCont, fIn) ## overwrite original file with sanitized one
if(markdEngine == "kramdown") {
## kramdown needs a ToC placeholder -> add that later instead of title
tocRepl <- c("* ToC", "{:toc}")
## replace all remaining ``` with ~~~ for fenced code blocks
fCont <- gsub("```", "~~~", fCont)
}
## remove h1 title since it will be built from YAML title
tL <- grep("^========*\\s*$", fCont) - 1 ## line number with title
fCont[tL] <- tocRepl[1] ## old: title
fCont[tL+1] <- tocRepl[2] ## old: =====
if(siteGen == "jekyll") {
## set Jekyll's date prefix
datePrefix <- "2012-08-08"
## replace {{ and }} with { { and } } for Jekyll's template engine liquid
fCont <- gsub("\\{\\{", "{ {", fCont)
fCont <- gsub("\\}\\}", "} }", fCont)
## output filename with date-prefix notation
fOut <- paste(dirname(fOutPre), "/", datePrefix, "-", fName, ".md", sep="")
} else {
fOut <- paste(dirname(fOutPre), "/", fName, ".md", sep="")
}
writeLines(fCont, fOut)
}
## replace MathJax inline math \( and \)
## with $$ (for kramdown) or with $ (for Redcarpet2 and pandoc)
## R bug 15012 makes R eat all resources and lock up for the following regexp
## fCont <- gsub('\\\\)', "$$", fCont)
## -> use external sed instead
## sed for Windows: <http://gnuwin32.sourceforge.net/packages/sed.htm>
sanitizeMath <- function(fIn, markdEngine=c("kramdown", "redcarpet", "pandoc")) {
markdEngine <- match.arg(markdEngine)
## calling external sed differs between platforms
## -> find out where we are
if(.Platform$OS.type == "windows") {
winRelease <- Sys.info()[["release"]]
if(winRelease %in% c("7 x64", "7 x32")) {
if(markdEngine == "kramdown") {
sedCall <- paste('sed -e "s/\\\\(/\\$\\$/g" -e "s/\\\\)/\\$\\$/g" <', fIn)
} else {
sedCall <- paste('sed -e "s/\\\\(/\\$/g" -e "s/\\\\)/\\$/g" <', fIn)
}
} else if(winRelease == "XP") {
## TODO: this doesn't work on XP
if(markdEngine == "kramdown") {
sedCall <- paste('sed -e "s/\\\\\\(/\\\\$\\\\$/g" -e "s/\\\\\\)/\\\\$\\\\$/g" <', fIn)
} else {
sedCall <- paste('sed -e "s/\\\\\\(/\\\\$/g" -e "s/\\\\\\)/\\\\$/g" <', fIn)
}
}
shell(sedCall, intern=TRUE)
} else if(.Platform$OS.type == "unix") {
if(markdEngine == "kramdown") {
sedCall <- paste('sed -e "s/\\\\\\(/\\$\\$/g" -e "s/\\\\\\)/\\$\\$/g" <', fIn)
} else {
sedCall <- paste('sed -e "s/\\\\\\(/\\$/g" -e "s/\\\\\\)/\\$/g" <', fIn)
}
system(sedCall, intern=TRUE)
}
}
## get arguments and call knit
args <- commandArgs(TRUE)
## input Rmd file
inputFile <- args[1]
## output md file
outputFile <- args[2]
## which markdown engine wille be used?
markdEngine <- args[3]
## which static site generator will be used?
siteGen <- args[4]
dwKnit(inputFile, outputFile, markdEngine, siteGen)