Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
Merge branch 'main' of https://github.com/laderast/shinyowl into main

# Conflicts:
#	reactives/app-bindEvent.R
#	reactives/app_eventReactive.R
  • Loading branch information
laderast committed Jun 21, 2024
2 parents 293f91e + 3454c46 commit b3c1d99
Show file tree
Hide file tree
Showing 33 changed files with 762 additions and 4,346 deletions.
8 changes: 8 additions & 0 deletions _extensions/coatless-quarto/embedio/_extension.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: embedio
title: Embedded different kinds of files
author: James Joseph Balamuta
version: 0.0.2-dev.1
quarto-required: ">=1.4.549"
contributes:
shortcodes:
- embedio.lua
234 changes: 234 additions & 0 deletions _extensions/coatless-quarto/embedio/embedio.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
-- Check if variable missing or an empty string
local function isVariableEmpty(s)
return s == nil or s == ''
end

-- Check if variable is present
local function isVariablePopulated(s)
return not isVariableEmpty(s)
end

-- Check whether an argument is present in kwargs
-- If it is, return the value
local function tryOption(options, key)

-- Protect against an empty options
if not (options and options[key]) then
return nil
end

-- Retrieve the option
local option_value = pandoc.utils.stringify(options[key])
-- Verify the option's value exists, return value otherwise nil.
if isVariablePopulated(option_value) then
return option_value
else
return nil
end
end

-- Retrieve the option value or use the default value
local function getOption(options, key, default)
return tryOption(options, key) or default
end

-- Validate input file path is not empty
local function checkFile(input)
if input then
return true
else
quarto.log.error("Error: file path is required for the embedio shortcode.")
assert(false)
end
end

-- Avoid duplicate class definitions
local initializedSlideCSS = false

-- Load CSS into header once
local function ensureSlideCSSPresent()
if initializedSlideCSS then return end
initializedSlideCSS = true

-- Default CSS class
local slideCSS = [[
<style>
.slide-deck {
border: 3px solid #dee2e6;
width: 100%;
}
</style>
]]

-- Inject into the header
quarto.doc.include_text("in-header", slideCSS)
end

-- Define a function to generate HTML code for an iframe element
local function iframe_helper(file_name, height, full_screen_link, template, type)
-- Check if the file exists
checkFile(file_name)

-- Define a template for displaying a full-screen link
local template_full_screen = [[
<p><a href=%q target="_blank">View %s in full screen</a></p>
]]

-- Combine the template with file name and height to generate HTML code
local combined_str = string.format(
[[%s %s]],
-- Include full-screen link if specified
(full_screen_link == "true" and string.format(template_full_screen, file_name, type) or ""),
-- Insert the iframe template with file name and height
string.format(template, file_name, height)
)

-- Return the combined HTML as a pandoc RawBlock
return pandoc.RawBlock('html', combined_str)
end

-- Define the html() function for embedding HTML files
local function html(args, kwargs, meta, raw_args)
-- Check if the output format is HTML
if not quarto.doc.is_format("html") then return end

-- Get the HTML file name, height, and full-screen link option
local file_name = pandoc.utils.stringify(args[1] or kwargs["file"])
local height = getOption(kwargs, "height", "475px")
local full_screen_link = getOption(kwargs, "full-screen-link", "true")

-- Define the template for embedding HTML files
local template_html = [[
<div>
<iframe src=%q height=%q></iframe>
</div>
]]

-- Call the iframe_helper() function with the HTML template
return iframe_helper(file_name, height, full_screen_link, template_html, "webpage")
end

-- Define the revealjs() function for embedding Reveal.js slides
local function revealjs(args, kwargs, meta, raw_args)
-- Check if the output format is HTML
if not quarto.doc.is_format("html") then return end

-- Ensure that the Reveal.js CSS is present
ensureSlideCSSPresent()

-- Get the slide file name, height, and full-screen link option
local file_name = pandoc.utils.stringify(args[1] or kwargs["file"])
local height = getOption(kwargs, "height", "475px")
local full_screen_link = getOption(kwargs, "full-screen-link", "true")

-- Define the template for embedding Reveal.js slides
local template_revealjs = [[
<div>
<iframe class="slide-deck" src=%q height=%q></iframe>
</div>
]]

-- Call the iframe_helper() function with the Reveal.js template
return iframe_helper(file_name, height, full_screen_link, template_revealjs, "slides")
end

local function audio(args, kwargs, meta)

if not quarto.doc.is_format("html") then return end

-- Start of HTML tag
local htmlTable = {"<figure "}

-- Extracting caption, class, and download from kwargs
local caption = pandoc.utils.stringify(kwargs.caption)
local class = pandoc.utils.stringify(kwargs.class)
local download_link = getOption(kwargs, "download-link", "false")

-- Extracting input from args or kwargs
local input = pandoc.utils.stringify(args[1] or kwargs.file)
checkFile(input)

-- Add class attribute if provided
if class then
table.insert(htmlTable, 'class="' .. class .. '">')
end

-- Add download link if provided
if download_link == "true" then
table.insert(htmlTable, '<p><a href="' .. input ..'"> Download audio file</a></p><br />')
end

-- Start the audio tag
table.insert(htmlTable, "<audio controls")

-- Add source attribute with input file path
table.insert(htmlTable, ' src="' .. input .. '"')

-- Automatically detect file type from the file extension
local fileType = string.match(input, "%.([^%.]+)$")

if fileType then
table.insert(htmlTable, ' type="audio/' .. fileType .. '">')
else
quarto.log.error("Error: Unable to detect file type from the audio file path.")
assert(false)
end

-- Add source element for browsers that do not support the audio tag
table.insert(htmlTable, 'Your browser does not support the audio tag.')

-- Add closing audio tag
table.insert(htmlTable, "</audio>")

-- Add caption if provided
if caption then
table.insert(htmlTable, '<figcaption>' .. caption .. '</figcaption>')
end

-- Add closing figure tag
table.insert(htmlTable, "</figure>")

return pandoc.RawBlock('html', table.concat(htmlTable))
end


local function pdf(args, kwargs, meta)

if not quarto.doc.is_format("html") then return end

-- Supported options for now
local pdf_file_name = pandoc.utils.stringify(args[1] or kwargs["file"])
checkFile(pdf_file_name)

local height = getOption(kwargs, "height", "600px")
local width = getOption(kwargs, "width", "100%")
local download_link = getOption(kwargs, "download-link", "true")

-- HTML block
local template_pdf = [[
<object data=%q type="application/pdf" width=%q height=%q>
<p>Unable to display PDF file. <a href=%q>Download</a> instead.</p>
</object>
]]

local template_pdf_download_link = [[
<p><a href=%q target="_blank">Download PDF File</a></p>
]]

-- Obtain the combined template
local combined_str = string.format(
[[%s %s]],
(download_link == "true" and string.format(template_pdf_download_link, pdf_file_name) or ""),
string.format(template_pdf, pdf_file_name, width, height, pdf_file_name)
)

-- Return as HTML block
return pandoc.RawBlock('html', combined_str)
end

return {
['audio'] = audio,
['pdf'] = pdf,
['revealjs'] = revealjs,
['html'] = html
}
3 changes: 2 additions & 1 deletion _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ project:
- "modules/"
output-dir: docs
post-render:
- "cp -rnv reactives/reactivity.pdf docs/"
- "rm docs/reactives/reactivity.pdf"
- "cp -rnv reactives/reactivity.pdf docs/reactives/"

website:
title: "shinyowl"
Expand Down
Binary file added docs/bit.ly_45BDX9k.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 21 additions & 8 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@
<h2 id="toc-title">On this page</h2>

<ul>
<li><a href="#learning-objectives" id="toc-learning-objectives" class="nav-link active" data-scroll-target="#learning-objectives">Learning Objectives</a>
<li><a href="#httpsbit.lyshinyowl" id="toc-httpsbit.lyshinyowl" class="nav-link active" data-scroll-target="#httpsbit.lyshinyowl">https://bit.ly/shinyowl</a></li>
<li><a href="#learning-objectives" id="toc-learning-objectives" class="nav-link" data-scroll-target="#learning-objectives">Learning Objectives</a>
<ul class="collapse">
<li><a href="#agenda-roughly" id="toc-agenda-roughly" class="nav-link" data-scroll-target="#agenda-roughly">Agenda (roughly)</a></li>
</ul></li>
Expand Down Expand Up @@ -151,6 +152,10 @@ <h1 class="title">Intermediate shiny: drawing the owl</h1>
</header>


<section id="httpsbit.lyshinyowl" class="level1">
<h1><a href="https://bit.ly/shinyowl" class="uri">https://bit.ly/shinyowl</a></h1>
<p><img src="bit.ly_45BDX9k.png" class="img-fluid" width="400"></p>
</section>
<section id="learning-objectives" class="level1">
<h1>Learning Objectives</h1>
<p>This workshop aims to get you over the hill to faster, better looking, and dynamic Shiny Apps.</p>
Expand All @@ -165,33 +170,40 @@ <h2 class="anchored" data-anchor-id="agenda-roughly">Agenda (roughly)</h2>
<thead>
<tr class="header">
<th>Section</th>
<th>Time</th>
<th>Begin</th>
<th>End</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Welcome/Get Started</td>
<td>9:00-9:10</td>
<td>9:00</td>
<td>9:10</td>
</tr>
<tr class="even">
<td>Dashboards</td>
<td>9:10-9:55</td>
<td>9:10</td>
<td>9:55</td>
</tr>
<tr class="odd">
<td>Break</td>
<td>9:55-10</td>
<td>9:55</td>
<td>10</td>
</tr>
<tr class="even">
<td>Reactivity</td>
<td>10-10:55</td>
<td>10</td>
<td>10:55</td>
</tr>
<tr class="odd">
<td>Break</td>
<td>10:55-11</td>
<td>10:55</td>
<td>11</td>
</tr>
<tr class="even">
<td>Modules/Wrap-up</td>
<td>11-12</td>
<td>11</td>
<td>12</td>
</tr>
</tbody>
</table>
Expand All @@ -202,6 +214,7 @@ <h1>Posit.cloud project</h1>
<ol type="1">
<li>Please create a free user account at posit.cloud</li>
<li>Invite yourself to the workspace <a href="https://posit.cloud/spaces/525494/join?access_code=N0vloDrDMCVvlXLIhXHISNdrWjHe4SOlhPm_9abK">here</a></li>
<li></li>
</ol>
</section>
<section id="reminders" class="level1">
Expand Down
1 change: 1 addition & 0 deletions docs/reactives/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ <h3 class="anchored" data-anchor-id="exercise-2">Exercise 2</h3>
</section>
<section id="exercise-3" class="level3">
<h3 class="anchored" data-anchor-id="exercise-3">Exercise 3</h3>
<p>Try and understand this app using <code>{reactlog}</code></p>
<div class="sourceCode" id="cb3"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">runApp</span>(<span class="st">"reactives/app_ExtendedTaskSingle.R"</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>


Expand Down
8 changes: 4 additions & 4 deletions docs/search.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,21 @@
"href": "reactives/index.html",
"title": "Exploring Reactivity",
"section": "",
"text": "Slides\n Download PDF File\n \n Unable to display PDF file. Download instead.\n \n \n\nExercise 1\nCompare the two apps with a partner. Look at the reactive graph. Are they any different?\nrunApp(\"reactives/app_reactive.R\")\nrunApp(\"reactives/app_isolate.R\")\n\n\nExercise 2\nCompare the two apps with a partner. Look at the reactive graph. Are they any different?\nrunApp(\"reactives/app_eventReactive.R\")\nrunApp(\"reactives/app_observeEvent.R\")\n\n\nExercise 3\nrunApp(\"reactives/app_ExtendedTaskSingle.R\")"
"text": "Slides\n Download PDF File\n \n Unable to display PDF file. Download instead.\n \n \n\nExercise 1\nCompare the two apps with a partner. Look at the reactive graph. Are they any different?\nrunApp(\"reactives/app_reactive.R\")\nrunApp(\"reactives/app_isolate.R\")\n\n\nExercise 2\nCompare the two apps with a partner. Look at the reactive graph. Are they any different?\nrunApp(\"reactives/app_eventReactive.R\")\nrunApp(\"reactives/app_observeEvent.R\")\n\n\nExercise 3\nTry and understand this app using {reactlog}\nrunApp(\"reactives/app_ExtendedTaskSingle.R\")"
},
{
"objectID": "index.html",
"href": "index.html",
"title": "Intermediate shiny: drawing the owl",
"section": "",
"text": "This workshop aims to get you over the hill to faster, better looking, and dynamic Shiny Apps.\n\nCustomize dashboards with {bslib} and {thematic}\nExplain fundamentals of Reactive Programming\nUtilize Shiny modules in your projects\n\n\n\n\n\n\nSection\nTime\n\n\n\n\nWelcome/Get Started\n9:00-9:10\n\n\nDashboards\n9:10-9:55\n\n\nBreak\n9:55-10\n\n\nReactivity\n10-10:55\n\n\nBreak\n10:55-11\n\n\nModules/Wrap-up\n11-12"
"text": "{width = 400}"
},
{
"objectID": "index.html#agenda-roughly",
"href": "index.html#agenda-roughly",
"title": "Intermediate shiny: drawing the owl",
"section": "",
"text": "Section\nTime\n\n\n\n\nWelcome/Get Started\n9:00-9:10\n\n\nDashboards\n9:10-9:55\n\n\nBreak\n9:55-10\n\n\nReactivity\n10-10:55\n\n\nBreak\n10:55-11\n\n\nModules/Wrap-up\n11-12"
"section": "Agenda (roughly)",
"text": "Agenda (roughly)\n\n\n\nSection\nBegin\nEnd\n\n\n\n\nWelcome/Get Started\n9:00\n9:10\n\n\nDashboards\n9:10\n9:55\n\n\nBreak\n9:55\n10\n\n\nReactivity\n10\n10:55\n\n\nBreak\n10:55\n11\n\n\nModules/Wrap-up\n11\n12"
},
{
"objectID": "layouts/slides.html#learning-objectives",
Expand Down
Loading

0 comments on commit b3c1d99

Please sign in to comment.