Skip to content

Improve support for fragments #89

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
J-Moravec opened this issue Apr 29, 2025 · 0 comments
Open

Improve support for fragments #89

J-Moravec opened this issue Apr 29, 2025 · 0 comments

Comments

@J-Moravec
Copy link

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
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant