Skip to content

Improve support for fragments #89

@J-Moravec

Description

@J-Moravec

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions