Compare commits

...

4 Commits

Author SHA1 Message Date
Carson
923c1b2450 Handle the non-bslib case; better comments 2021-06-14 16:55:39 -05:00
Carson
914dc71d67 Attach dependencies to render hook object; bump version 2021-06-14 16:55:39 -05:00
Carson
a13ca9fd3a bump htmltools requirement 2021-06-14 16:55:39 -05:00
Carson
b8b34370da Close #3401: bootstrapLib() now always sets state on render and cleans up post static render 2021-06-14 16:55:39 -05:00
2 changed files with 25 additions and 48 deletions

View File

@@ -1,7 +1,7 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 1.6.0.9021
Version: 1.6.0.9022
Authors@R: c(
person("Winston", "Chang", role = c("aut", "cre"), email = "winston@rstudio.com", comment = c(ORCID = "0000-0002-1576-2126")),
person("Joe", "Cheng", role = "aut", email = "joe@rstudio.com"),
@@ -79,7 +79,7 @@ Imports:
jsonlite (>= 0.9.16),
xtable,
fontawesome (>= 0.2.1),
htmltools (>= 0.5.1.9003),
htmltools (>= 0.5.1.9006),
R6 (>= 2.0),
sourcetools,
later (>= 1.0.0),

View File

@@ -50,7 +50,7 @@ bootstrapPage <- function(..., title = NULL, theme = NULL, lang = NULL) {
# the tagList() contents to avoid breaking user code that makes assumptions
# about the return value https://github.com/rstudio/shiny/issues/3235
if (is_bs_theme(theme)) {
args <- c(bootstrapLib(theme), args)
args <- list(bootstrapLib(theme), args)
ui <- do.call(tagList, args)
} else {
ui <- do.call(tagList, args)
@@ -82,53 +82,30 @@ getLang <- function(ui) {
#' @inheritParams bootstrapPage
#' @export
bootstrapLib <- function(theme = NULL) {
tagFunction(function() {
if (isRunning()) {
# In the non-bslib case, return static HTML dependencies
if (!is_bs_theme(theme)) {
return(bootstrapDependency(theme))
}
# To support static rendering of Bootstrap version dependent markup (e.g.,
# tabsetPanel()), setCurrentTheme() at the start of the render (since
# bootstrapLib() comes first in bootstrapPage(), all other UI should then know
# what version of Bootstrap is being used). Then restore state after render as
# long as shiny isn't running (in that case, since setCurrentTheme() uses
# shinyOptions(), state will be automatically be restored when the app exits)
oldTheme <- NULL
tagList(
.renderHook = function(x) {
oldTheme <<- getCurrentTheme()
setCurrentTheme(theme)
# For refreshing Bootstrap CSS when session$setCurrentTheme() happens
if (isRunning()) registerThemeDependency(bs_theme_deps)
attachDependencies(x, bslib::bs_theme_dependencies(theme))
},
.postRenderHook = function() {
if (!isRunning()) setCurrentTheme(oldTheme)
NULL
}
# If we're not compiling Bootstrap Sass (from bslib), return the
# static Bootstrap build.
if (!is_bs_theme(theme)) {
# We'll enter here if `theme` is the path to a .css file, like that
# provided by `shinythemes::shinytheme("darkly")`.
return(bootstrapDependency(theme))
}
# Make bootstrap Sass available so other tagFunction()s (e.g.,
# sliderInput() et al) can resolve their HTML dependencies at render time
# using getCurrentTheme(). Note that we're making an implicit assumption
# that this tagFunction() executes *before* all other tagFunction()s; but
# that should be fine considering that, DOM tree order is preorder,
# depth-first traversal, and at least in the bootstrapPage(theme) case, we
# have control over the relative ordering.
# https://dom.spec.whatwg.org/#concept-tree
# https://stackoverflow.com/a/16113998/1583084
#
# Note also that since this is shinyOptions() (and not options()), the
# option is automatically reset when the app (or session) exits
if (isRunning()) {
registerThemeDependency(bs_theme_deps)
} else {
# Technically, this a potential issue (someone trying to execute/render
# bootstrapLib outside of a Shiny app), but it seems that, in that case,
# you likely have other problems, since sliderInput() et al. already assume
# that Shiny is the one doing the rendering
#warning(
# "It appears `shiny::bootstrapLib()` was rendered outside of an Shiny ",
# "application context, likely by calling `as.tags()`, `as.character()`, ",
# "or `print()` directly on `bootstrapLib()` or UI components that may ",
# "depend on it (e.g., `fluidPage()`, etc). For 'themable' UI components ",
# "(e.g., `sliderInput()`, `selectInput()`, `dateInput()`, etc) to style ",
# "themselves based on the Bootstrap theme, make sure `bootstrapLib()` is ",
# "provided directly to the UI and that the UI is provided direction to ",
# "`shinyApp()` (or `runApp()`)", call. = FALSE
#)
}
bslib::bs_theme_dependencies(theme)
})
)
}
# This is defined outside of bootstrapLib() because registerThemeDependency()