-
Notifications
You must be signed in to change notification settings - Fork 11
Description
I am building a static site generator to move from quarto to litedown.
I am using the mustache template language implemented in the whisker
package to translate individual rmd
and md
fragments into a HTML (found the litedown templating lacking, or at least being rather undocumented).
I would like to use fuse
for this, passing a rmd
fragment without yaml header, but then inject back the chunk and HTML option parameters.
Suggestion
Allow passing opts
for chunk options and options
for HTML options to fuse
.
This would imho improve the interface instead of setting it outside of fuse.
(although I am slowly beginning to realise that HTML options, such as toc
, seems to be ignored for fragments)
So far, I am trying to hack fuse
, but I must have broken something since cleanup no longer works.
fuse_fragment
I tried to simplify some code since I am too stupid and can't handle so many indirections.
Otherwise it is mostly fuse
with .fuse
without some complicated bits and with opts and options.
"%||%" = function(x, y){
if(is.null(x)) y else x
}
random_string = function(n){
paste0(sample(c(0:9, letters, LETTERS), n, replace = TRUE), collapse = "")
}
fuse_fragment = function(
x, base = random_string(10), dir = getwd(), format = c("md", "html"),
envir = parent.frame(), options = list(), opts = list()
){
format = match.arg(format)
blocks = litedown::crack(text = x)
dir = normalizePath(dir)
# Initialize chunk options and set cleanup
chunk_opts = litedown::reactor() # initialize default options
chunk_opts_original = as.list(chunk_opts)
on.exit(litedown::reactor(chunk_opts_original), add = TRUE)
chunk_opts = list2env(opts, envir = chunk_opts)
# Initialize global options and set cleanup
if(length(options) > 0){
options_original = options(setNames(options, paste0("litedown.html.", names(options))))
on.exit(options(options_original), add = TRUE)
}
# Initialite internal environment and set cleanup
env = litedown:::.env
env_original = as.list(env)
on.exit(litedown:::reset_env(env_original, env), add = TRUE)
# dunno what these do
chunk_opts$wd = dir
env$wd_out = dir
env$global = envir
# set default graphical device
if(is.null(chunk_opts$dev))
chunk_opts$dev = "png"
# set default fig.path and cache.path
if(is.null(chunk_opts[["fig.path"]]))
chunk_opts[["fig.path"]] = paste0(base, "__files")
if(is.null(chunk_opts[["cache.path"]]))
chunk_opts[["cache.path"]] = paste0(base, "__cache")
chunk_opts[["fig.path"]] = normalizePath(chunk_opts[["fig.path"]], mustWork = FALSE)
chunk_opts[["cache.path"]] = normalizePath(chunk_opts[["cache.path"]], mustWork = FALSE)
# preserve trailing "/", because both fig.path and cache.path are prefixes
chunk_opts[["fig.path"]] = sub("/*$", "/", chunk_opts[["fig.path"]])
chunk_opts[["fig.path"]] = sub("/*$", "/", chunk_opts[["fig.path"]])
on.exit(xfun::del_empty_dir(chunk_opts[["fig.path"]]), add = TRUE)
# dunno what these do
env$format = format
env$input = base
# translate blocks
n = length(blocks)
nms = vapply(blocks, function(x) x$options[['label']] %||% '', character(1))
names(blocks) = nms
k = 0 # when exiting, k should be n + 1
on_error = function() {
if (k > n) return() # blocks have been successfully fused
message("Quitting from ", litedown:::get_loc(nms[k]))
}
on.exit(on_error(), add = TRUE)
# the chunk option `order` determines the execution order of chunks
o = litedown:::block_order(blocks, n)
res = character(n)
for (i in seq_len(n)){
k = o[i];
b = blocks[[k]];
litedown:::save_pos(b$lines)
res[k] = if(b$type == 'code_chunk') {
res[k] = litedown:::one_string(litedown:::fuse_code(b, blocks))
} else {
res[k] = litedown:::one_string(litedown:::fuse_text(b), '')
}
k = n + 1
}
if(format == "html"){
litedown::mark(res, output = NA)
} else {
res
}
}