Skip to content
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

Support posit-dev/r-shinylive #21

Merged
merged 4 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _extensions/quarto-ext/shinylive/_extension.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: shinylive
title: Embedded Shinylive applications
author: Winston Chang
version: 0.0.3
version: 0.0.4
quarto-required: ">=1.2.198"
contributes:
filters:
Expand Down
62 changes: 49 additions & 13 deletions _extensions/quarto-ext/shinylive/shinylive.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ local hasDoneShinyliveSetup = false
local codeblockScript = nil

-- Try calling `pandoc.pipe('shinylive', ...)` and if it fails, print a message
-- about installing shinylive package.
function callShinylive(args, input)
-- about installing shinylive python package.
function callPythonShinylive(args, input)
local res
local status, err = pcall(
function()
Expand All @@ -19,40 +19,72 @@ function callShinylive(args, input)
return res
end

-- Try calling `pandoc.pipe('Rscript', ...)` and if it fails, print a message
-- about installing shinylive R package.
function callRShinylive(args, input)
args = { "-e",
"shinylive::quarto_ext()",
table.unpack(args) }
local res
local status, err = pcall(
function()
res = pandoc.pipe("Rscript", args, input)
end
)

if not status then
print(err)
error(
"Error running 'Rscript' command. Perhaps you need to install the 'shinylive' R package?")
end

return res
end

function callShinylive(language, args, input)
-- print("Calling " .. language .. " shinylive with args: " .. table.concat(args, " "))
if language == "python" then
return callPythonShinylive(args, input)
elseif language == "r" then
return callRShinylive(args, input)
else
error("Unknown language: " .. language)
end
end

-- Do one-time setup when a Shinylive codeblock is encountered.
function ensureShinyliveSetup()
function ensureShinyliveSetup(language)
if hasDoneShinyliveSetup then
return
end
hasDoneShinyliveSetup = true

-- Find the path to codeblock-to-json.ts and save it for later use.
codeblockScript = callShinylive({ "codeblock-to-json-path" }, "")
codeblockScript = callShinylive(language, { "codeblock-to-json-path" }, "")
-- Remove trailing whitespace
codeblockScript = codeblockScript:gsub("%s+$", "")

local baseDeps = getShinyliveBaseDeps()
local baseDeps = getShinyliveBaseDeps(language)
for idx, dep in ipairs(baseDeps) do
quarto.doc.add_html_dependency(dep)
end

quarto.doc.add_html_dependency(
{
name = "shinylive-quarto-css",
stylesheets = {"resources/css/shinylive-quarto.css"}
stylesheets = { "resources/css/shinylive-quarto.css" }
}
)
end


function getShinyliveBaseDeps()
function getShinyliveBaseDeps(language)
-- Relative path from the current page to the root of the site. This is needed
-- to find out where shinylive-sw.js is, relative to the current page.
if quarto.project.offset == nil then
error("The shinylive extension must be used in a Quarto project directory (with a _quarto.yml file).")
end
local depJson = callShinylive(
language,
{ "base-deps", "--sw-dir", quarto.project.offset },
""
)
Expand All @@ -61,15 +93,18 @@ function getShinyliveBaseDeps()
return deps
end


return {
{
CodeBlock = function(el)
if el.attr and (
el.attr.classes:includes("{shinylive-python}")
or el.attr.classes:includes("{shinylive-r}")
) then
ensureShinyliveSetup()
el.attr.classes:includes("{shinylive-python}")
or el.attr.classes:includes("{shinylive-r}")
) then
local language = "python"
if el.attr.classes:includes("{shinylive-r}") then
language = "r"
end
schloerke marked this conversation as resolved.
Show resolved Hide resolved
ensureShinyliveSetup(language)

-- Convert code block to JSON string in the same format as app.json.
local parsedCodeblockJson = pandoc.pipe(
Expand All @@ -83,6 +118,7 @@ return {

-- Find Python package dependencies for the current app.
local appDepsJson = callShinylive(
language,
{ "package-deps" },
quarto.json.encode(parsedCodeblock["files"])
)
Expand Down