Compare commits

..

7 Commits

Author SHA1 Message Date
Barret Schloerke
890957495b Remove debug branch name 2021-08-02 22:33:01 -04:00
Barret Schloerke
877ad18bb9 remove debug step 2021-08-02 22:31:53 -04:00
Barret Schloerke
a1cf9b40f0 fix master spacing 2021-08-02 22:31:42 -04:00
Barret Schloerke
5361c61faa use same branch 2021-08-02 22:30:00 -04:00
Barret Schloerke
b386e2b550 use same branch 2021-08-02 22:29:48 -04:00
Barret Schloerke
52499e4bc0 add space 2021-08-02 22:29:25 -04:00
Barret Schloerke
6fae374b11 debug 2021-08-02 22:28:10 -04:00
213 changed files with 11188 additions and 4588 deletions

View File

@@ -1,12 +0,0 @@
#!/bin/bash -e
. ./tools/documentation/checkDocsCurrent.sh
echo "Updating package.json version to match DESCRIPTION Version"
Rscript ./tools/updatePackageJsonVersion.R
if [ -n "$(git status --porcelain package.json)" ]
then
yarn build
git add ./inst package.json && git commit -m 'Sync package version (GitHub Actions)' || echo "No package version to commit"
else
echo "No package version difference detected; package.json is current."
fi

View File

@@ -1,23 +1,150 @@
# Workflow derived from https://github.com/rstudio/shiny-workflows
#
# NOTE: This Shiny team GHA workflow is overkill for most R packages.
# For most R packages it is better to use https://github.com/r-lib/actions
name: R-CMD-check
on:
push:
branches: [main, rc-**]
branches:
- master
pull_request:
branches: [main]
schedule:
- cron: '0 5 * * 1' # every monday
branches:
- master
name: Package checks
jobs:
website:
uses: rstudio/shiny-workflows/.github/workflows/website.yaml@v1
routine:
uses: rstudio/shiny-workflows/.github/workflows/routine.yaml@v1
with:
node-version: "14.x"
R-CMD-check:
uses: rstudio/shiny-workflows/.github/workflows/R-CMD-check.yaml@v1
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
strategy:
fail-fast: false
matrix:
config:
- {os: macOS-latest, r: 'devel'}
- {os: macOS-latest, r: '4.0'}
- {os: windows-latest, r: '4.0'}
- {os: ubuntu-16.04, r: '4.0', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.6', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.5', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.4', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.3', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
env:
_R_CHECK_FORCE_SUGGESTS_: false
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
RSPM: ${{ matrix.config.rspm }}
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
# https://github.com/actions/checkout/issues/135
- name: Set git to use LF
if: runner.os == 'Windows'
run: |
git config --system core.autocrlf false
git config --system core.eol lf
- uses: actions/checkout@v2
- uses: r-lib/actions/setup-r@master
id: install-r
with:
r-version: ${{ matrix.config.r }}
- uses: r-lib/actions/setup-pandoc@master
- name: Install pak and query dependencies
shell: Rscript {0}
run: |
install.packages("pak", repos = "https://r-lib.github.io/p/pak/dev/")
saveRDS(pak::pkg_deps_tree("local::.", dependencies = TRUE), ".github/r-depends.rds")
- name: Cache R packages
uses: actions/cache@v2
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-${{ hashFiles('.github/r-depends.rds') }}
restore-keys: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-
- name: Install system dependencies
if: runner.os == 'Linux'
shell: Rscript {0}
run: |
pak::local_system_requirements(execute = TRUE)
# https://stackoverflow.com/a/66568545/591574
#> fatal error: 'X11/Intrinsic.h' file not found
- name: Install Cairo macOS R devel dependency
if: runner.os == 'macOS' && matrix.config.r == 'devel'
run: |
brew install libxt
# xquartz and cairo are needed for Cairo package.
# harfbuzz and fribidi are needed for textshaping package.
- name: Mac systemdeps
if: runner.os == 'macOS'
run: |
brew install --cask xquartz
brew install cairo
brew install harfbuzz fribidi
# Use a shorter temp directory for pak installations, due to filename
# length issues on Windows. https://github.com/r-lib/pak/issues/252
- name: Windows temp dir
if: runner.os == 'Windows'
run: |
New-Item -Path "C:\" -Name "tmp" -ItemType Directory
echo "TMPDIR=c:\tmp" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Install dependencies
run: |
pak::local_install_dev_deps(upgrade = TRUE)
pak::pkg_install("rcmdcheck")
shell: Rscript {0}
- name: Find PhantomJS path
id: phantomjs
run: |
echo "::set-output name=path::$(Rscript -e 'cat(shinytest:::phantom_paths()[[1]])')"
- name: Cache PhantomJS
uses: actions/cache@v2
with:
path: ${{ steps.phantomjs.outputs.path }}
key: ${{ matrix.config.os }}-phantomjs
restore-keys: ${{ matrix.config.os }}-phantomjs
- name: Install PhantomJS
run: >
Rscript
-e "if (!shinytest::dependenciesInstalled()) shinytest::installDependencies()"
- name: Session info
run: |
options(width = 100)
pkgs <- installed.packages()[, "Package"]
sessioninfo::session_info(pkgs, include_base = TRUE)
shell: Rscript {0}
- name: Check
env:
_R_CHECK_CRAN_INCOMING_: false
_R_CHECK_FORCE_SUGGESTS_: ${{ matrix.config.r != 'devel' }}
run: rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
shell: Rscript {0}
- name: Show testthat output
if: always()
run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true
shell: bash
- name: Upload check results
if: failure()
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.config.os }}-r${{ matrix.config.r }}-results
path: check
- name: Fix path for Windows caching
if: runner.os == 'Windows'
# This is needed because if you use the default tar at this stage,
# C:/Rtools/bin/tar.exe, it will say that it can't find gzip.exe. So
# we'll just set the path so that the original tar that would be
# found, will be found.
run: echo "C:/Program Files/Git/usr/bin" >> $GITHUB_PATH

172
.github/workflows/rituals.yaml vendored Normal file
View File

@@ -0,0 +1,172 @@
on:
push:
branches:
- master
- ghactions
pull_request:
branches:
- master
name: Rituals
jobs:
rituals:
name: Rituals
# if: false
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- { os: ubuntu-16.04, r: '4.0', node: "14.x", rspm: "https://packagemanager.rstudio.com/all/__linux__/xenial/latest"}
env:
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
RSPM: ${{ matrix.config.rspm }}
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v1
- uses: r-lib/actions/pr-fetch@master
name: Git Pull (PR)
if: github.event_name == 'pull_request'
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: r-lib/actions/setup-r@master
id: install-r
with:
r-version: ${{ matrix.config.r }}
- uses: r-lib/actions/setup-pandoc@master
- name: Git Config
run: |
git config user.name "${GITHUB_ACTOR}"
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
- name: Install pak and query dependencies
shell: Rscript {0}
run: |
install.packages("pak", repos = "https://r-lib.github.io/p/pak/dev/")
saveRDS(pak::pkg_deps_tree("local::.", dependencies = TRUE), ".github/r-depends.rds")
- name: Cache R packages
uses: actions/cache@v2
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-${{ hashFiles('.github/r-depends.rds') }}
restore-keys: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-
- name: Install system dependencies
# if: runner.os == 'Linux'
shell: Rscript {0}
run: |
pak::local_system_requirements(execute = TRUE)
- name: Install dependencies
shell: Rscript {0}
run: |
pak::local_install_dev_deps(upgrade = TRUE)
- name: Session info
shell: Rscript {0}
run: |
options(width = 100)
pak::pkg_install("sessioninfo")
pkgs <- installed.packages()[, "Package"]
sessioninfo::session_info(pkgs, include_base = TRUE)
- name: Url redirects
# only perform if in an RC branch (`rc-vX.Y.Z`)
if: ${{ github.event_name == 'push' && contains(github.ref, '/rc-v') }}
run: |
Rscript -e 'pak::pkg_install("r-lib/urlchecker"); urlchecker::url_update()'
# throw an error if man files were updated
if [ -n "$(git status --porcelain man)" ]
then
git status --porcelain
>&2 echo "Updated links found in files above"
>&2 echo 'Run `urlchecker::url_update()` to fix links locally'
exit 1
fi
# Add locally changed urls
git add .
git commit -m 'Update links (GitHub Actions)' || echo "No link changes to commit"
- name: Document
run: |
Rscript -e 'pak::pkg_install("devtools")'
Rscript -e 'devtools::document()'
git add man/\* NAMESPACE
git commit -m 'Document (GitHub Actions)' || echo "No documentation changes to commit"
- name: Check documentation
run: |
./tools/documentation/checkDocsCurrent.sh
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.config.node }}
# https://github.com/actions/cache/blame/ccf96194800dbb7b7094edcd5a7cf3ec3c270f10/examples.md#L185-L200
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: yarn cache
uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ matrix.config.os }}-${{ matrix.config.node }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ matrix.config.os }}-${{ matrix.config.node }}-yarn-
- name: Sync DESCRIPTION and package.json versions
run: |
Rscript -e 'pak::pkg_install("jsonlite")'
Rscript -e 'pkg <- jsonlite::read_json("package.json", simplifyVector = TRUE)' \
-e 'version <- as.list(read.dcf("DESCRIPTION")[1,])$Version' \
-e 'pkg$version <- gsub("^(\\d+).(\\d+).(\\d+).(.+)$", "\\1.\\2.\\3-alpha.\\4", version)' \
-e 'pkg$files <- as.list(pkg$files)' \
-e 'jsonlite::write_json(pkg, path = "package.json", pretty = TRUE, auto_unbox = TRUE)'
git add package.json && git commit -m 'sync package version (GitHub Actions)' || echo "No version changes to commit"
- name: Build JS
run: |
tree srcts
rm -r srcts/types
yarn install --immutable && yarn build
git add ./srcts/src && git commit -m 'yarn lint (GitHub Actions)' || echo "No yarn lint changes to commit"
git add ./srcts/types && git commit -m 'yarn tsc (GitHub Actions)' || echo "No type definition changes to commit"
git add ./inst && git commit -m 'yarn build (GitHub Actions)' || echo "No yarn build changes to commit"
if [ -n "$(git status --porcelain)" ]
then
git status --porcelain
>&2 echo "The above files changed when we built the JavaScript assets."
exit 1
else
echo "No difference detected; TypeScript build is current."
fi
- name: Git Push (PR)
uses: r-lib/actions/pr-push@master
if: github.event_name == 'pull_request'
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Verify no un-pushed commits (MASTER)
if: github.event_name == 'push'
run: |
# Can't push to a protected branch
if [ -n "`git cherry origin/master`" ]; then
echo "Un-pushed commits:"
git cherry -v origin/master
echo "\nCan not push to a protected branch. Exiting"
exit 1
fi
# Execute after pushing, as no updated files will be produced
- name: Test TypeScript code
run: |
yarn test

2
.gitignore vendored
View File

@@ -12,7 +12,7 @@ README.html
tools/yarn-error.log
# TypeScript / yarn
/node_modules/
node_modules/
.cache
.yarn/*
!.yarn/releases

3
.prettierrc.yml Normal file
View File

@@ -0,0 +1,3 @@
trailingComma: "es5"
arrowParens: always
endOfLine: lf

16
.vscode/settings.json vendored
View File

@@ -1,18 +1,10 @@
{
"typescript.tsdk": ".yarn/sdks/typescript/lib",
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
},
"prettier.prettierPath": "./node_modules/prettier",
"typescript.enablePromptUseWorkspaceTsdk": true,
"[r]": {
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
},
"eslint.nodePath": ".yarn/sdks",
"prettier.prettierPath": ".yarn/sdks/prettier/index.js",
"typescript.enablePromptUseWorkspaceTsdk": true
}

View File

@@ -1,7 +1,7 @@
Package: shiny
Type: Package
Title: Web Application Framework for R
Version: 1.7.1.9003
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.2),
htmltools (>= 0.5.1.9003),
R6 (>= 2.0),
sourcetools,
later (>= 1.0.0),
@@ -91,7 +91,7 @@ Imports:
withr,
commonmark (>= 1.7),
glue (>= 1.3.2),
bslib (>= 0.3.0),
bslib (>= 0.2.5.9002),
cachem,
ellipsis,
lifecycle (>= 0.2.0)
@@ -105,12 +105,17 @@ Suggests:
ggplot2,
reactlog (>= 1.0.0),
magrittr,
shinytest (>= 1.4.0.9003),
yaml,
future,
dygraphs,
ragg,
showtext,
sass
Remotes:
r-lib/rlang,
rstudio/bslib,
rstudio/htmltools
URL: https://shiny.rstudio.com/
BugReports: https://github.com/rstudio/shiny/issues
Collate:
@@ -188,7 +193,6 @@ Collate:
'shinywrappers.R'
'showcase.R'
'snapshot.R'
'staticimports.R'
'tar.R'
'test-export.R'
'test-server.R'
@@ -201,10 +205,8 @@ Collate:
'version_selectize.R'
'version_strftime.R'
'viewer.R'
RoxygenNote: 7.2.0
RoxygenNote: 7.1.1
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RdMacros: lifecycle
Config/testthat/edition: 3
Config/Needs/check:
rstudio/shinytest2

76
NEWS.md
View File

@@ -1,72 +1,10 @@
shiny development
shiny 1.6.0.9000
================
## Full changelog
### Breaking changes
* Closed #3626: `renderPlot()` (and `plotPNG()`) now uses `ragg::agg_png()` by default when the [`{ragg}` package](https://github.com/r-lib/ragg) is installed. To restore the previous behavior, set `options(shiny.useragg = FALSE)`. (#3654)
### Minor new features and improvements
* Shiny's internal HTML dependencies are now mounted dynamically instead of statically. (#3537)
* HTML dependencies that are sent to dynamic UI now have better type checking, and no longer require a `dep.src.href` field. (#3537)
* Default for `ref` input in `runGithub()` changed from `"master"` to `"HEAD"`. (#3346)
* When taking a test snapshot, the sort order of the json keys of the `input`, `output`, and `export` fields is currently sorted using the locale of the machine. This can lead to inconsistent test snapshot results. To opt-in to a consistent ordering of snapshot fields with `{shinytest}`, please set the global option `options(shiny.snapshotsortc = TRUE)`. `{shinytest2}` users do not need to set this value. (#3515)
* The auto-reload feature (`options(shiny.autoreload=TRUE)`) was not being activated by `devmode(TRUE)`, despite a console message asserting that it was. (#3620)
* Add `shiny.mathjax.url` and `shiny.mathjax.config` options for configuring the MathJax URL used by `withMathJax`. Thanks, @Neutron3529! (#3639)
### Bug fixes
* Closed #3657: `throttle.ts` and the `Throttler` typescript objects it provides now function as intended.
* Closed tidyverse/dplyr#5552: Compatibility of dplyr 1.0 (and rlang chained errors in general) with `req()`, `validate()`, and friends.
* Closed #1545: `insertUI()` now executes `<script>` tags. (#3630)
* Closed #2955: Input and output bindings previously attempted to use `el['data-input-id']`, but that never worked. They now use `el.getAttribute('data-input-id')` instead. (#3538)
* Closed tidyverse/dplyr#6154: Values from an `actionButton()` had S3 classes in the incorrect order.
* Fixed a bug where updating an input value without a corresponding Input binding element did not trigger a JavaScript `shiny:inputchanged` event. Now, if no Input binding element is found, the `shiny:inputchanged` event is triggered on `window.document`. (#3584)
* Restored the previous behavior of automatically guessing the `Content-Type` header for `downloadHandler` functions when no explicit `contentType` argument is supplied. (#3393)
* Closed #3619: In R 4.2, `splitLayout()` raised warnings about incorrect length in an `if` statement. (Thanks to @dmenne, #3625)
* Closed #2297: If an error occurred in parsing a value in a bookmark query string, an error would be thrown and nothing would be restored. Now a message is displayed and that value is ignored. (Thanks to @daattali, #3385)
* `fileInput()` can set the `capture` attribute to facilitates user access to a device's media capture mechanism, such as a camera, or microphone, from within a file upload control ([W3C HTML Media Capture](https://www.w3.org/TR/html-media-capture/)). (Thanks to khaled-alshamaa, #3481)
* Closed rstudio/shinytest2#222: When restoring a context (i.e., bookmarking) from a URL, Shiny now better handles a trailing `=` after `_inputs_` and `_values_`. (#3648)
* Closed #3581: Errors in throttled/debounced reactive expressions no longer cause the session to exit. (#3624)
* Closed #3250:`{rlang}`/`{tidyeval}` conditions (i.e., warnings and errors) are no longer filtered from stack traces. (#3602)
shiny 1.7.1
===========
## Bug Fixes
* Closed #3516: Fix regression in repeated calls to `appendTab()` when `navbarMenu()` is already present within a `tabsetPanel()`/`navbarPage()`. (#3518)
* Re-arranged conditions for testthat 1.0.0 compatibility. (#3512)
shiny 1.7.0
===========
## Full changelog
### Breaking changes
* The `format` and `locale` arguments to `sliderInput()` have been removed. They have been deprecated since 0.10.2.2 (released on 2014-12-08).
* Closed #3403: `insertTab()`'s `position` parameter now defaults to `"after"` instead of `"before"`. This has the benefit of allowing us to fix a bug in positioning when `target = NULL`, but has the drawback of changing the default behavior when `target` is not `NULL`. (#3404)
@@ -80,7 +18,7 @@ shiny 1.7.0
* All uses of `list(...)` have been replaced with `rlang::list2(...)`. This means that you can use trailing `,` without error and use rlang's `!!!` operator to "splice" a list of argument values into `...`. We think this'll be particularly useful for passing a list of `tabPanel()` to their consumers (i.e., `tabsetPanel()`, `navbarPage()`, etc). For example, `tabs <- list(tabPanel("A", "a"), tabPanel("B", "b")); navbarPage(!!!tabs)`. (#3315 and #3328)
* `installExprFunction()` and `exprToFunction()` are now able to handle quosures when `quoted = TRUE`. So `render`-functions which call these functions (such as with `htmlwidgets`) can now understand quosures. Users can also use `rlang::inject()` to unquote a quosure for evaluation. This also means that `render` function no longer need `env` and `quoted` parameters; that information can be embedded into a quosure which is then passed to the `render` function. Better documentation was added for how to create `render` functions. (#3472)
* `installExprFunction()` and `exprToFunction()` are now able to handle quosures, so `render`-functions which call these functions can now understand quosures, when they are called using `rlang::inject()`. This also means that `render` function no longer need `env` and `quoted` parameters; that information can be embedded into a quosure which is then passed to the `render` function. Additionally, the `getQuosure()` function was added, which makes it easier for developers to create `render` functions which understand quosures. Better documentation was added for how to create `render` functions. (#3462, #3466)
* `icon(lib="fontawesome")` is now powered by the `{fontawesome}` package, which will make it easier to use the latest FA icons in the future (by updating the `{fontawesome}` package). (#3302)
@@ -92,7 +30,7 @@ shiny 1.7.0
### Other improvements
* Shiny's core JavaScript code was converted to TypeScript. For the latest development information, please see the [README.md in `./srcts`](https://github.com/rstudio/shiny/tree/v1.7.0/srcts). (#3296)
* Shiny's core JavaScript code was converted to TypeScript. For the latest development information, please see the [README.md in `./srcts`](https://github.com/rstudio/shiny/tree/master/srcts). (#3296)
* Switched from `digest::digest()` to `rlang::hash()` for hashing. (#3264)
@@ -106,12 +44,10 @@ shiny 1.7.0
* Fixed [#2666](https://github.com/rstudio/shiny/issues/2666) and [#2670](https://github.com/rstudio/shiny/issues/2670): `nearPoints()` and `brushedPoints()` weren't properly account for missing values (#2666 was introduced in v1.4.0). ([#2668](https://github.com/rstudio/shiny/pull/2668))
* Closed #3374: `quoToFunction()` now works correctly with nested quosures; and as a result, quasi-quotation with rendering function (e.g., `renderPrint()`, `renderPlot()`, etc) now works as expected with nested quosures. (#3373)
* Closed #3374: `quoToFunction()` now works correctly with nested quosures; and as a result, quasi-quotation with rendering function (e.g., `renderPrint()`, `renderPlot()`, etc) now works as expected with nested quosures. (#3373)
* Exported `register_devmode_option()`. This method was described in the documentation for `devmode()` but was never exported. See `?devmode()` for more details on how to register Shiny Developer options using `register_devmode_option()`. (#3364)
* Closed #3484: In the RStudio IDE on Mac 11.5, selected checkboxes and radio buttons were not visible. (#3485)
### Library updates
* Closed #3286: Updated to Font-Awesome 5.15.2. (#3288)
@@ -125,7 +61,7 @@ This release focuses on improvements in three main areas:
1. Better theming (and Bootstrap 4) support:
* The `theme` argument of `fluidPage()`, `navbarPage()`, and `bootstrapPage()` all now understand `bslib::bs_theme()` objects, which can be used to opt-into Bootstrap 4, use any Bootswatch theme, and/or implement custom themes without writing any CSS.
* The `session` object now includes `$setCurrentTheme()` and `$getCurrentTheme()` methods to dynamically update (or obtain) the page's `theme` after initial load, which is useful for things such as [adding a dark mode switch to an app](https://rstudio.github.io/bslib/articles/bslib.html#dynamic) or some other "real-time" theming tool like `bslib::bs_themer()`.
* The `session` object now includes `$setCurrentTheme()` and `$getCurrentTheme()` methods to dynamically update (or obtain) the page's `theme` after initial load, which is useful for things such as [adding a dark mode switch to an app](https://rstudio.github.io/bslib/articles/theming.html#dynamic-shiny) or some other "real-time" theming tool like `bslib::bs_themer()`.
* For more details, see [`{bslib}`'s website](https://rstudio.github.io/bslib/)
2. Caching of `reactive()` and `render*()` (e.g. `renderText()`, `renderTable()`, etc) expressions.
@@ -247,7 +183,7 @@ shiny 1.5.0
* The new `moduleServer` function provides a simpler interface for creating and using modules. (#2773)
* Resolved #2732: `markdown()` is a new function for writing Markdown with Github extensions directly in Shiny UIs. Markdown rendering is performed by the [commonmark](https://github.com/r-lib/commonmark) package. (#2737)
* Resolved #2732: `markdown()` is a new function for writing Markdown with Github extensions directly in Shiny UIs. Markdown rendering is performed by the [commonmark](https://github.com/jeroen/commonmark) package. (#2737)
* The `getCurrentOutputInfo()` function can now return the background color (`bg`), foreground color (`fg`), `accent` (i.e., hyperlink) color, and `font` information of the output's HTML container. This information is reported by `plotOutput()`, `imageOutput()`, and any other output bindings containing a class of `.shiny-report-theme`. This feature allows developers to style an output's contents based on the container's CSS styling. (#2740)

View File

@@ -10,7 +10,8 @@
#' 2: app.R : Main application file
#' 3: R/example.R : Helper file with R code
#' 4: R/example-module.R : Example module
#' 5: tests/testthat/ : Tests using the testthat and shinytest2 package
#' 5: tests/shinytest/ : Tests using the shinytest package
#' 6: tests/testthat/ : Tests using the testthat package
#' ```
#'
#' If option 1 is selected, the full example application including the
@@ -23,11 +24,13 @@
#' | |- example-module.R
#' | `- example.R
#' `- tests
#' |- shinytest.R
#' |- shinytest
#' | `- mytest.R
#' |- testthat.R
#' `- testthat
#' |- test-examplemodule.R
#' |- test-server.R
#' |- test-shinytest2.R
#' `- test-sort.R
#' ```
#'
@@ -42,20 +45,20 @@
#' * `tests/` contains various tests for the application. You may
#' choose to use or remove any of them. They can be executed by the
#' [runTests()] function.
#' * `tests/shinytest.R` is a test runner for test files in the
#' `tests/shinytest/` directory.
#' * `tests/shinytest/mytest.R` is a test that uses the
#' [shinytest](https://rstudio.github.io/shinytest/) package to do
#' snapshot-based testing.
#' * `tests/testthat.R` is a test runner for test files in the
#' `tests/testthat/` directory using the
#' [shinytest2](https://rstudio.github.io/shinytest2/reference/test_app.html)
#' package.
#' `tests/testthat/` directory using the [testthat](https://testthat.r-lib.org/) package.
#' * `tests/testthat/test-examplemodule.R` is a test for an application's module server function.
#' * `tests/testthat/test-server.R` is a test for the application's server code
#' * `tests/testthat/test-shinytest2.R` is a test that uses the
#' [shinytest2](https://rstudio.github.io/shinytest2/) package to do
#' snapshot-based testing.
#' * `tests/testthat/test-sort.R` is a test for a supporting function in the `R/` directory.
#'
#' @param path Path to create new shiny application template.
#' @param examples Either one of "default", "ask", "all", or any combination of
#' "app", "rdir", "module", and "tests". In an
#' "app", "rdir", "module", "shinytest", and "testthat". In an
#' interactive session, "default" falls back to "ask"; in a non-interactive
#' session, "default" falls back to "all". With "ask", this function will
#' prompt the user to select which template items will be added to the new app
@@ -76,19 +79,15 @@ shinyAppTemplate <- function(path = NULL, examples = "default", dryrun = FALSE)
# =======================================================
choices <- c(
app = "app.R : Main application file",
rdir = "R/example.R : Helper file with R code",
module = "R/example-module.R : Example module",
tests = "tests/testthat/ : Tests using {testthat} and {shinytest2}"
app = "app.R : Main application file",
rdir = "R/example.R : Helper file with R code",
module = "R/example-module.R : Example module",
shinytest = "tests/shinytest/ : Tests using the shinytest package",
testthat = "tests/testthat/ : Tests using the testthat package"
)
# Support legacy value
examples[examples == "shinytest"] <- "tests"
examples[examples == "testthat"] <- "tests"
examples <- unique(examples)
if (identical(examples, "default")) {
if (rlang::is_interactive()) {
if (interactive()) {
examples <- "ask"
} else {
examples <- "all"
@@ -125,8 +124,18 @@ shinyAppTemplate <- function(path = NULL, examples = "default", dryrun = FALSE)
return(invisible())
}
if ("tests" %in% examples) {
rlang::check_installed("shinytest2", "for {testthat} tests to work as expected")
if ("shinytest" %in% examples) {
if (!is_available("shinytest", "1.4.0"))
{
message(
"The tests/shinytest directory needs shinytest 1.4.0 or later to work properly."
)
if (is_available("shinytest")) {
message("You currently have shinytest ",
utils::packageVersion("shinytest"), " installed.")
}
}
}
# =======================================================
@@ -143,7 +152,7 @@ shinyAppTemplate <- function(path = NULL, examples = "default", dryrun = FALSE)
# Helper to resolve paths relative to our template
template_path <- function(...) {
system_file("app_template", ..., package = "shiny")
system.file("app_template", ..., package = "shiny")
}
# Resolve path relative to destination
@@ -199,13 +208,16 @@ shinyAppTemplate <- function(path = NULL, examples = "default", dryrun = FALSE)
}
# Copy the files for a tests/ subdirectory
copy_test_dir <- function() {
copy_test_dir <- function(name) {
files <- dir(template_path("tests"), recursive = TRUE)
# Note: This is not the same as using dir(pattern = "^shinytest"), since
# that will not match files inside of shinytest/.
files <- files[grepl(paste0("^", name), files)]
# Filter out files that are not module files in the R directory.
if (! "rdir" %in% examples) {
# find all files in the testthat folder that are not module or server files
is_r_folder_file <- !grepl("module|server|shinytest2|testthat", basename(files))
is_r_folder_file <- (!grepl("module|server", basename(files))) & (dirname(files) == "testthat")
files <- files[!is_r_folder_file]
}
@@ -270,10 +282,12 @@ shinyAppTemplate <- function(path = NULL, examples = "default", dryrun = FALSE)
copy_file(file.path("R", module_files))
}
# tests/testthat dir
if ("tests" %in% examples) {
copy_test_dir()
# tests/ dir
if ("shinytest" %in% examples) {
copy_test_dir("shinytest")
}
if ("testthat" %in% examples) {
copy_test_dir("testthat")
}
invisible()
}

View File

@@ -255,7 +255,7 @@ utils::globalVariables(".GenericCallEnv", add = TRUE)
#' the cache.
#'
#' You may need to provide a `cacheHint` to [createRenderFunction()] (or
#' `htmlwidgets::shinyRenderWidget()`, if you've authored an htmlwidget) in
#' [htmlwidgets::shinyRenderWidget()], if you've authored an htmlwidget) in
#' order for `bindCache()` to correctly compute a cache key.
#'
#' The potential problem is a cache collision. Consider the following:

View File

@@ -321,38 +321,34 @@ RestoreContext <- R6Class("RestoreContext",
if (substr(queryString, 1, 1) == '?')
queryString <- substr(queryString, 2, nchar(queryString))
# The "=" after "_inputs_" is optional. Shiny doesn't generate URLs with
# "=", but httr always adds "=".
inputs_reg <- "(^|&)_inputs_=?(&|$)"
values_reg <- "(^|&)_values_=?(&|$)"
# Error if multiple '_inputs_' or '_values_'. This is needed because
# strsplit won't add an entry if the search pattern is at the end of a
# string.
if (length(gregexpr(inputs_reg, queryString)[[1]]) > 1)
if (length(gregexpr("(^|&)_inputs_(&|$)", queryString)[[1]]) > 1)
stop("Invalid state string: more than one '_inputs_' found")
if (length(gregexpr(values_reg, queryString)[[1]]) > 1)
if (length(gregexpr("(^|&)_values_(&|$)", queryString)[[1]]) > 1)
stop("Invalid state string: more than one '_values_' found")
# Look for _inputs_ and store following content in inputStr
splitStr <- strsplit(queryString, inputs_reg)[[1]]
splitStr <- strsplit(queryString, "(^|&)_inputs_(&|$)")[[1]]
if (length(splitStr) == 2) {
inputStr <- splitStr[2]
# Remove any _values_ (and content after _values_) that may come after
# _inputs_
inputStr <- strsplit(inputStr, values_reg)[[1]][1]
inputStr <- strsplit(inputStr, "(^|&)_values_(&|$)")[[1]][1]
} else {
inputStr <- ""
}
# Look for _values_ and store following content in valueStr
splitStr <- strsplit(queryString, values_reg)[[1]]
splitStr <- strsplit(queryString, "(^|&)_values_(&|$)")[[1]]
if (length(splitStr) == 2) {
valueStr <- splitStr[2]
# Remove any _inputs_ (and content after _inputs_) that may come after
# _values_
valueStr <- strsplit(valueStr, inputs_reg)[[1]][1]
valueStr <- strsplit(valueStr, "(^|&)_inputs_(&|$)")[[1]][1]
} else {
valueStr <- ""
@@ -363,20 +359,16 @@ RestoreContext <- R6Class("RestoreContext",
values <- parseQueryString(valueStr, nested = TRUE)
valuesFromJSON <- function(vals) {
varsUnparsed <- c()
valsParsed <- mapply(names(vals), vals, SIMPLIFY = FALSE,
mapply(names(vals), vals, SIMPLIFY = FALSE,
FUN = function(name, value) {
tryCatch(
safeFromJSON(value),
error = function(e) {
varsUnparsed <<- c(varsUnparsed, name)
warning("Failed to parse URL parameter \"", name, "\"")
stop("Failed to parse URL parameter \"", name, "\"")
}
)
}
)
valsParsed[varsUnparsed] <- NULL
valsParsed
}
inputs <- valuesFromJSON(inputs)

View File

@@ -6,7 +6,7 @@
#' @param sidebarPanel The [sidebarPanel] containing input controls
#' @param mainPanel The [mainPanel] containing outputs
#' @keywords internal
#' @return A UI definition that can be passed to the [shinyUI] function
#' @return A UI defintion that can be passed to the [shinyUI] function
#' @export
pageWithSidebar <- function(headerPanel,
sidebarPanel,

View File

@@ -13,7 +13,7 @@
#' Can also be set as a side effect of the [titlePanel()] function.
#' @inheritParams bootstrapPage
#'
#' @return A UI definition that can be passed to the [shinyUI] function.
#' @return A UI defintion that can be passed to the [shinyUI] function.
#'
#' @details To create a fluid page use the `fluidPage` function and include
#' instances of `fluidRow` and [column()] within it. As an
@@ -111,7 +111,7 @@ fluidRow <- function(...) {
#' @param title The browser window title (defaults to the host URL of the page)
#' @inheritParams bootstrapPage
#'
#' @return A UI definition that can be passed to the [shinyUI] function.
#' @return A UI defintion that can be passed to the [shinyUI] function.
#'
#' @details To create a fixed page use the `fixedPage` function and include
#' instances of `fixedRow` and [column()] within it. Note that
@@ -516,7 +516,7 @@ splitLayout <- function(..., cellWidths = NULL, cellArgs = list()) {
children <- children[childIdx]
count <- length(children)
if (length(cellWidths) == 0 || isTRUE(is.na(cellWidths))) {
if (length(cellWidths) == 0 || is.na(cellWidths)) {
cellWidths <- sprintf("%.3f%%", 100 / count)
}
cellWidths <- rep(cellWidths, length.out = count)

View File

@@ -24,7 +24,7 @@ NULL
#' This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="en">}.
#' The default (NULL) results in an empty string.
#'
#' @return A UI definition that can be passed to the [shinyUI] function.
#' @return A UI defintion that can be passed to the [shinyUI] function.
#'
#' @note The `basicPage` function is deprecated, you should use the
#' [fluidPage()] function instead.
@@ -138,7 +138,8 @@ bs_theme_deps <- function(theme) {
}
is_bs_theme <- function(x) {
bslib::is_bs_theme(x)
is_available("bslib", "0.2.0.9000") &&
bslib::is_bs_theme(x)
}
#' Obtain Shiny's Bootstrap Sass theme
@@ -214,10 +215,11 @@ registerThemeDependency <- function(func) {
bootstrapDependency <- function(theme) {
htmlDependency(
"bootstrap",
bootstrapVersion,
src = "www/shared/bootstrap",
package = "shiny",
"bootstrap", bootstrapVersion,
c(
href = "shared/bootstrap",
file = system.file("www/shared/bootstrap", package = "shiny")
),
script = c(
"js/bootstrap.min.js",
# Safely adding accessibility plugin for screen readers and keyboard users; no break for sighted aspects (see https://github.com/paypal/bootstrap-accessibility-plugin)
@@ -385,7 +387,7 @@ collapseSizes <- function(padding) {
#' @inheritParams bootstrapPage
#' @param icon Optional icon to appear on a `navbarMenu` tab.
#'
#' @return A UI definition that can be passed to the [shinyUI] function.
#' @return A UI defintion that can be passed to the [shinyUI] function.
#'
#' @details The `navbarMenu` function can be used to create an embedded
#' menu within the navbar that in turns includes additional tabPanels (see
@@ -1107,17 +1109,11 @@ tableOutput <- function(outputId) {
dataTableDependency <- list(
htmlDependency(
"datatables",
"1.10.5",
src = "www/shared/datatables",
package = "shiny",
"datatables", "1.10.5", c(href = "shared/datatables"),
script = "js/jquery.dataTables.min.js"
),
htmlDependency(
"datatables-bootstrap",
"1.10.5",
src = "www/shared/datatables",
package = "shiny",
"datatables-bootstrap", "1.10.5", c(href = "shared/datatables"),
stylesheet = c("css/dataTables.bootstrap.css", "css/dataTables.extra.css"),
script = "js/dataTables.bootstrap.js"
)
@@ -1157,7 +1153,7 @@ dataTableOutput <- function(outputId) {
htmlOutput <- function(outputId, inline = FALSE,
container = if (inline) span else div, ...)
{
if (any_unnamed(list(...))) {
if (anyUnnamed(list(...))) {
warning("Unnamed elements in ... will be replaced with dynamic UI.")
}
container(id = outputId, class="shiny-html-output", ...)

View File

@@ -228,9 +228,7 @@ withLogErrors <- function(expr,
if (promises::is.promise(result)) {
result <- promises::catch(result, function(cond) {
# Don't print shiny.silent.error (i.e. validation errors)
if (cnd_inherits(cond, "shiny.silent.error")) {
return()
}
if (inherits(cond, "shiny.silent.error")) return()
if (isTRUE(getOption("show.error.messages"))) {
printError(cond, full = full, offset = offset)
}
@@ -241,7 +239,7 @@ withLogErrors <- function(expr,
},
error = function(cond) {
# Don't print shiny.silent.error (i.e. validation errors)
if (cnd_inherits(cond, "shiny.silent.error")) return()
if (inherits(cond, "shiny.silent.error")) return()
if (isTRUE(getOption("show.error.messages"))) {
printError(cond, full = full, offset = offset)
}
@@ -421,17 +419,8 @@ pruneStackTrace <- function(parents) {
# Loop over the parent indices. Anything that is not parented by current_node
# (a.k.a. last-known-good node), or is a dupe, can be discarded. Anything that
# is kept becomes the new current_node.
#
# jcheng 2022-03-18: Two more reasons a node can be kept:
# 1. parent is 0
# 2. parent is i
# Not sure why either of these situations happen, but they're common when
# interacting with rlang/dplyr errors. See issue rstudio/shiny#3250 for repro
# cases.
include <- vapply(seq_along(parents), function(i) {
if ((!is_dupe[[i]] && parents[[i]] == current_node) ||
parents[[i]] == 0 ||
parents[[i]] == i) {
if (!is_dupe[[i]] && parents[[i]] == current_node) {
current_node <<- i
TRUE
} else {

View File

@@ -1,6 +1,55 @@
# A scope where we can put mutable global state
.globals <- new.env(parent = emptyenv())
register_s3_method <- function(pkg, generic, class, fun = NULL) {
stopifnot(is.character(pkg), length(pkg) == 1)
stopifnot(is.character(generic), length(generic) == 1)
stopifnot(is.character(class), length(class) == 1)
if (is.null(fun)) {
fun <- get(paste0(generic, ".", class), envir = parent.frame())
} else {
stopifnot(is.function(fun))
}
if (pkg %in% loadedNamespaces()) {
registerS3method(generic, class, fun, envir = asNamespace(pkg))
}
# Always register hook in case pkg is loaded at some
# point the future (or, potentially, but less commonly,
# unloaded & reloaded)
setHook(
packageEvent(pkg, "onLoad"),
function(...) {
registerS3method(generic, class, fun, envir = asNamespace(pkg))
}
)
}
register_upgrade_message <- function(pkg, version) {
msg <- sprintf(
"This version of Shiny is designed to work with '%s' >= %s.
Please upgrade via install.packages('%s').",
pkg, version, pkg
)
if (pkg %in% loadedNamespaces() && !is_available(pkg, version)) {
packageStartupMessage(msg)
}
# Always register hook in case pkg is loaded at some
# point the future (or, potentially, but less commonly,
# unloaded & reloaded)
setHook(
packageEvent(pkg, "onLoad"),
function(...) {
if (!is_available(pkg, version)) packageStartupMessage(msg)
}
)
}
.onLoad <- function(libname, pkgname) {
# R's lazy-loading package scheme causes the private seed to be cached in the
# package itself, making our PRNG completely deterministic. This line resets
@@ -13,9 +62,9 @@
# Make sure these methods are available to knitr if shiny is loaded but not
# attached.
s3_register("knitr::knit_print", "reactive")
s3_register("knitr::knit_print", "shiny.appobj")
s3_register("knitr::knit_print", "shiny.render.function")
register_s3_method("knitr", "knit_print", "reactive")
register_s3_method("knitr", "knit_print", "shiny.appobj")
register_s3_method("knitr", "knit_print", "shiny.render.function")
# Shiny 1.4.0 bumps jQuery 1.x to 3.x, which caused a problem
# with static-rendering of htmlwidgets, and htmlwidgets 1.5

View File

@@ -4,7 +4,7 @@
# @param version The version of the package
check_suggested <- function(package, version = NULL) {
if (is_installed(package, version)) {
if (is_available(package, version)) {
return()
}
@@ -115,28 +115,22 @@ check_reactlog <- function() {
}
# read reactlog version from description file
# prevents version mismatch in code and description file
reactlog_version <- local({
version <- NULL
function() {
if (!is.null(version)) return(version)
reactlog_version <- function() {
desc <- read.dcf(system.file("DESCRIPTION", package = "shiny", mustWork = TRUE))
suggests <- desc[1,"Suggests"][[1]]
suggests_pkgs <- strsplit(suggests, "\n")[[1]]
desc <- read.dcf(system_file("DESCRIPTION", package = "shiny"))
suggests <- desc[1,"Suggests"][[1]]
suggests_pkgs <- strsplit(suggests, "\n")[[1]]
reactlog_info <- suggests_pkgs[grepl("reactlog", suggests_pkgs)]
if (length(reactlog_info) == 0) {
stop("reactlog can not be found in shiny DESCRIPTION file")
}
reactlog_info <- sub("^[^\\(]*\\(", "", reactlog_info)
reactlog_info <- sub("\\)[^\\)]*$", "", reactlog_info)
reactlog_info <- sub("^[>= ]*", "", reactlog_info)
version <<- package_version(reactlog_info)
version
reactlog_info <- suggests_pkgs[grepl("reactlog", suggests_pkgs)]
if (length(reactlog_info) == 0) {
stop("reactlog can not be found in shiny DESCRIPTION file")
}
})
reactlog_info <- sub("^[^\\(]*\\(", "", reactlog_info)
reactlog_info <- sub("\\)[^\\)]*$", "", reactlog_info)
reactlog_info <- sub("^[>= ]*", "", reactlog_info)
package_version(reactlog_info)
}
RLog <- R6Class(

View File

@@ -1,14 +1,19 @@
startPNG <- function(filename, width, height, res, ...) {
pngfun <- if ((getOption('shiny.useragg') %||% TRUE) && is_installed("ragg")) {
ragg::agg_png
# shiny.useragg is an experimental option that isn't officially supported or
# documented. It's here in the off chance that someone really wants
# to use ragg (say, instead of showtext, for custom font rendering).
# In the next shiny release, this option will likely be superseded in
# favor of a fully customizable graphics device option
if ((getOption('shiny.useragg') %||% FALSE) && is_available("ragg")) {
pngfun <- ragg::agg_png
} else if (capabilities("aqua")) {
# i.e., png(type = 'quartz')
grDevices::png
} else if ((getOption('shiny.usecairo') %||% TRUE) && is_installed("Cairo")) {
Cairo::CairoPNG
pngfun <- grDevices::png
} else if ((getOption('shiny.usecairo') %||% TRUE) && is_available("Cairo")) {
pngfun <- Cairo::CairoPNG
} else {
# i.e., png(type = 'cairo')
grDevices::png
pngfun <- grDevices::png
}
args <- rlang::list2(filename=filename, width=width, height=height, res=res, ...)
@@ -52,31 +57,33 @@ startPNG <- function(filename, width, height, res, ...) {
grDevices::dev.cur()
}
#' Capture a plot as a PNG file.
#' Run a plotting function and save the output as a PNG
#'
#' The PNG graphics device used is determined in the following order:
#' * If the ragg package is installed (and the `shiny.useragg` is not
#' set to `FALSE`), then use [ragg::agg_png()].
#' * If a quartz device is available (i.e., `capabilities("aqua")` is
#' `TRUE`), then use `png(type = "quartz")`.
#' * If the Cairo package is installed (and the `shiny.usecairo` option
#' is not set to `FALSE`), then use [Cairo::CairoPNG()].
#' * Otherwise, use [grDevices::png()]. In this case, Linux and Windows
#' may not antialias some point shapes, resulting in poor quality output.
#' This function returns the name of the PNG file that it generates. In
#' essence, it calls `png()`, then `func()`, then `dev.off()`.
#' So `func` must be a function that will generate a plot when used this
#' way.
#'
#' For output, it will try to use the following devices, in this order:
#' quartz (via [grDevices::png()]), then [Cairo::CairoPNG()],
#' and finally [grDevices::png()]. This is in order of quality of
#' output. Notably, plain `png` output on Linux and Windows may not
#' antialias some point shapes, resulting in poor quality output.
#'
#' In some cases, `Cairo()` provides output that looks worse than
#' `png()`. To disable Cairo output for an app, use
#' `options(shiny.usecairo=FALSE)`.
#'
#' @param func A function that generates a plot.
#' @param filename The name of the output file. Defaults to a temp file with
#' extension `.png`.
#' @param width Width in pixels.
#' @param height Height in pixels.
#' @param res Resolution in pixels per inch. This value is passed to the
#' graphics device. Note that this affects the resolution of PNG rendering in
#' @param res Resolution in pixels per inch. This value is passed to
#' [grDevices::png()]. Note that this affects the resolution of PNG rendering in
#' R; it won't change the actual ppi of the browser.
#' @param ... Arguments to be passed through to the graphics device. These can
#' be used to set the width, height, background color, etc.
#'
#' @return A path to the newly generated PNG file.
#'
#' @param ... Arguments to be passed through to [grDevices::png()].
#' These can be used to set the width, height, background color, etc.
#' @export
plotPNG <- function(func, filename=tempfile(fileext='.png'),
width=400, height=400, res=72, ...) {

View File

@@ -138,8 +138,7 @@ datePickerDependency <- function(theme) {
htmlDependency(
name = "bootstrap-datepicker-js",
version = version_bs_date_picker,
src = "www/shared/datepicker",
package = "shiny",
src = c(href = "shared/datepicker"),
script = if (getOption("shiny.minified", TRUE)) "js/bootstrap-datepicker.min.js"
else "js/bootstrap-datepicker.js",
# Need to enable noConflict mode. See #1346.
@@ -158,19 +157,18 @@ datePickerCSS <- function(theme) {
return(htmlDependency(
name = "bootstrap-datepicker-css",
version = version_bs_date_picker,
src = "www/shared/datepicker",
package = "shiny",
src = c(href = "shared/datepicker"),
stylesheet = "css/bootstrap-datepicker3.min.css"
))
}
scss_file <- system_file(package = "shiny", "www/shared/datepicker/scss/build3.scss")
scss_file <- system.file(package = "shiny", "www/shared/datepicker/scss/build3.scss")
bslib::bs_dependency(
input = sass::sass_file(scss_file),
theme = theme,
name = "bootstrap-datepicker",
version = version_bs_date_picker,
cache_key_extra = get_package_version("shiny")
cache_key_extra = shinyPackageVersion()
)
}

View File

@@ -23,18 +23,7 @@
#' @param buttonLabel The label used on the button. Can be text or an HTML tag
#' object.
#' @param placeholder The text to show before a file has been uploaded.
#' @param capture What source to use for capturing image, audio or video data.
#' This attribute facilitates user access to a device's media capture
#' mechanism, such as a camera, or microphone, from within a file upload
#' control.
#'
#' A value of `user` indicates that the user-facing camera and/or microphone
#' should be used. A value of `environment` specifies that the outward-facing
#' camera and/or microphone should be used.
#'
#' By default on most phones, this will accept still photos or video. For
#' still photos only, also use `accept="image/*"`. For video only, use
#' `accept="video/*"`.
#' @examples
#' ## Only run examples in interactive R sessions
#' if (interactive()) {
@@ -84,8 +73,7 @@
#'
#' @export
fileInput <- function(inputId, label, multiple = FALSE, accept = NULL,
width = NULL, buttonLabel = "Browse...", placeholder = "No file selected",
capture = NULL) {
width = NULL, buttonLabel = "Browse...", placeholder = "No file selected") {
restoredValue <- restoreInput(id = inputId, default = NULL)
@@ -113,9 +101,6 @@ fileInput <- function(inputId, label, multiple = FALSE, accept = NULL,
if (length(accept) > 0)
inputTag$attribs$accept <- paste(accept, collapse=',')
if (!is.null(capture)) {
inputTag$attribs$capture <- capture
}
div(class = "form-group shiny-input-container",
style = css(width = validateCssUnit(width)),

View File

@@ -213,7 +213,14 @@ selectizeIt <- function(inputId, select, options, nonempty = FALSE) {
deps <- list(selectizeDependency())
if ('drag_drop' %in% options$plugins) {
deps[[length(deps) + 1]] <- jqueryuiDependency()
deps <- c(
deps,
list(htmlDependency(
'jqueryui', '1.12.1',
c(href = 'shared/jqueryui'),
script = 'jquery-ui.min.js'
))
)
}
# Insert script on same level as <select> tag
@@ -240,7 +247,7 @@ selectizeDependencyFunc <- function(theme) {
return(selectizeStaticDependency(version_selectize))
}
selectizeDir <- system_file(package = "shiny", "www/shared/selectize/")
selectizeDir <- system.file(package = "shiny", "www/shared/selectize/")
bs_version <- bslib::theme_version(theme)
stylesheet <- file.path(
selectizeDir, "scss", paste0("selectize.bootstrap", bs_version, ".scss")
@@ -260,17 +267,15 @@ selectizeDependencyFunc <- function(theme) {
theme = theme,
name = "selectize",
version = version_selectize,
cache_key_extra = get_package_version("shiny"),
cache_key_extra = shinyPackageVersion(),
.dep_args = list(script = script)
)
}
selectizeStaticDependency <- function(version) {
htmlDependency(
"selectize",
version,
src = "www/shared/selectize",
package = "shiny",
"selectize", version,
src = c(href = "shared/selectize"),
stylesheet = "css/selectize.bootstrap3.css",
script = c(
"js/selectize.min.js",

View File

@@ -205,17 +205,13 @@ ionRangeSliderDependency <- function() {
list(
# ion.rangeSlider also needs normalize.css, which is already included in Bootstrap.
htmlDependency(
"ionrangeslider-javascript",
version_ion_range_slider,
src = "www/shared/ionrangeslider",
package = "shiny",
"ionrangeslider-javascript", version_ion_range_slider,
src = c(href = "shared/ionrangeslider"),
script = "js/ion.rangeSlider.min.js"
),
htmlDependency(
"strftime",
version_strftime,
src = "www/shared/strftime",
package = "shiny",
"strftime", version_strftime,
src = c(href = "shared/strftime"),
script = "strftime-min.js"
),
bslib::bs_dependency_defer(ionRangeSliderDependencyCSS)
@@ -227,8 +223,7 @@ ionRangeSliderDependencyCSS <- function(theme) {
return(htmlDependency(
"ionrangeslider-css",
version_ion_range_slider,
src = "www/shared/ionrangeslider",
package = "shiny",
src = c(href = "shared/ionrangeslider"),
stylesheet = "css/ion.rangeSlider.css"
))
}
@@ -237,13 +232,13 @@ ionRangeSliderDependencyCSS <- function(theme) {
input = list(
list(accent = "$component-active-bg"),
sass::sass_file(
system_file(package = "shiny", "www/shared/ionrangeslider/scss/shiny.scss")
system.file(package = "shiny", "www/shared/ionrangeslider/scss/shiny.scss")
)
),
theme = theme,
name = "ionRangeSlider",
version = version_ion_range_slider,
cache_key_extra = get_package_version("shiny")
cache_key_extra = shinyPackageVersion()
)
}

View File

@@ -41,7 +41,7 @@ normalizeChoicesArgs <- function(choices, choiceNames, choiceValues,
if (length(choiceNames) != length(choiceValues)) {
stop("`choiceNames` and `choiceValues` must have the same length.")
}
if (any_named(choiceNames) || any_named(choiceValues)) {
if (anyNamed(choiceNames) || anyNamed(choiceValues)) {
stop("`choiceNames` and `choiceValues` must not be named.")
}
} else {

View File

@@ -79,8 +79,8 @@ absolutePanel <- function(...,
if (isTRUE(draggable)) {
divTag <- tagAppendAttributes(divTag, class='draggable')
return(tagList(
singleton(tags$head(tags$script(src='shared/jqueryui/jquery-ui.min.js'))),
divTag,
jqueryuiDependency(),
tags$script('$(".draggable").draggable();')
))
} else {
@@ -99,14 +99,3 @@ fixedPanel <- function(...,
width=width, height=height, draggable=draggable, cursor=match.arg(cursor),
fixed=TRUE)
}
jqueryuiDependency <- function() {
htmlDependency(
'jqueryui',
'1.12.1',
src = 'www/shared/jqueryui',
package = 'shiny',
script = 'jquery-ui.min.js'
)
}

View File

@@ -63,7 +63,7 @@ knit_print.shiny.appobj <- function(x, ...) {
#' @param inline Whether the object is printed inline.
knit_print.shiny.render.function <- function(x, ..., inline = FALSE) {
x <- htmltools::as.tags(x, inline = inline)
output <- knitr::knit_print(tagList(x), ..., inline = inline)
output <- knitr::knit_print(tagList(x))
attr(output, "knit_cacheable") <- FALSE
attr(output, "knit_meta") <- append(attr(output, "knit_meta"),
shiny_rmd_warning())
@@ -77,5 +77,5 @@ knit_print.reactive <- function(x, ..., inline = FALSE) {
renderFunc <- if (inline) renderText else renderPrint
knitr::knit_print(renderFunc({
x()
}), ..., inline = inline)
}), inline = inline)
}

View File

@@ -348,7 +348,7 @@ HandlerManager <- R6Class("HandlerManager",
httpResponse(status = 500L,
content_type = "text/html; charset=UTF-8",
content = as.character(htmltools::htmlTemplate(
system_file("template", "error.html", package = "shiny"),
system.file("template", "error.html", package = "shiny"),
message = conditionMessage(err)
))
)

View File

@@ -1,5 +1,5 @@
# Promise helpers taken from:
# https://github.com/rstudio/promises/blob/main/tests/testthat/common.R
# https://github.com/rstudio/promises/blob/master/tests/testthat/common.R
# Block until all pending later tasks have executed
wait_for_it <- function() {
while (!later::loop_empty()) {

View File

@@ -1203,7 +1203,7 @@ Observer <- R6Class(
# validation = function(e) NULL,
# shiny.output.cancel = function(e) NULL
if (cnd_inherits(e, "shiny.silent.error")) {
if (inherits(e, "shiny.silent.error")) {
return()
}
@@ -2472,11 +2472,11 @@ debounce <- function(r, millis, priority = 100, domain = getDefaultReactiveDomai
# Ensure r() is called only after setting firstRun to FALSE since r()
# may throw an error
try(r(), silent = TRUE)
r()
return()
}
# This ensures r() is still tracked after firstRun
try(r(), silent = TRUE)
r()
# The value (or possibly millis) changed. Start or reset the timer.
v$when <- getDomainTimeMs(domain) + millis()
@@ -2509,7 +2509,7 @@ debounce <- function(r, millis, priority = 100, domain = getDefaultReactiveDomai
# commenting it out and studying the unit test failure that results.
primer <- observe({
primer$destroy()
try(er(), silent = TRUE)
er()
}, label = "debounce primer", domain = domain, priority = priority)
er
@@ -2551,7 +2551,7 @@ throttle <- function(r, millis, priority = 100, domain = getDefaultReactiveDomai
}
# Responsible for tracking when f() changes.
observeEvent(try(r(), silent = TRUE), {
observeEvent(r(), {
if (v$pending) {
# In a blackout period and someone already scheduled; do nothing
} else if (blackoutMillisLeft() > 0) {

View File

@@ -1,6 +1,6 @@
####
# Generated by `./tools/documentation/updateReexports.R`: do not edit by hand
# Please call `source('tools/documentation/updateReexports.R')` from the root folder to update`
# Generated by `./tools/updateReexports.R`: do not edit by hand
# Please call `source('tools/updateReexports.R') from the root folder to update`
####
@@ -90,20 +90,17 @@ htmltools::em
#' @export
htmltools::hr
# htmltools tag.Rd -------------------------------------------------------------
#' @importFrom htmltools tag
#' @export
htmltools::tag
# htmltools tagList.Rd ---------------------------------------------------------
#' @importFrom htmltools tagList
#' @export
htmltools::tagList
# htmltools tagAppendAttributes.Rd ---------------------------------------------
#' @importFrom htmltools tagAppendAttributes
#' @export
htmltools::tagAppendAttributes
@@ -116,9 +113,6 @@ htmltools::tagHasAttribute
#' @export
htmltools::tagGetAttribute
# htmltools tagAppendChild.Rd --------------------------------------------------
#' @importFrom htmltools tagAppendChild
#' @export
htmltools::tagAppendChild

View File

@@ -181,7 +181,7 @@
#' # At the top of app.R, this set the application-scoped cache to be a disk
#' # cache that can be shared among multiple concurrent R processes, and is
#' # deleted when the system reboots.
#' shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache")))
#' shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache"))
#'
#' # At the top of app.R, this set the application-scoped cache to be a disk
#' # cache that can be shared among multiple concurrent R processes, and

View File

@@ -34,7 +34,7 @@
#' When rendering an inline plot, you must provide numeric values (in pixels)
#' to both \code{width} and \code{height}.
#' @param res Resolution of resulting plot, in pixels per inch. This value is
#' passed to [plotPNG()]. Note that this affects the resolution of PNG
#' passed to [grDevices::png()]. Note that this affects the resolution of PNG
#' rendering in R; it won't change the actual ppi of the browser.
#' @param alt Alternate text for the HTML `<img>` tag if it cannot be displayed
#' or viewed (i.e., the user uses a screen reader). In addition to a character
@@ -44,7 +44,7 @@
#' ggplot objects; for other plots, `NA` results in alt text of "Plot object".
#' `NULL` or `""` is not recommended because those should be limited to
#' decorative images.
#' @param ... Arguments to be passed through to [plotPNG()].
#' @param ... Arguments to be passed through to [grDevices::png()].
#' These can be used to set the width, height, background color, etc.
#' @inheritParams renderUI
#' @param execOnResize If `FALSE` (the default), then when a plot is
@@ -612,7 +612,7 @@ getGgplotCoordmap <- function(p, width, height, res) {
find_panel_info <- function(b) {
# Structure of ggplot objects changed after 2.1.0. After 2.2.1, there was a
# an API for extracting the necessary information.
ggplot_ver <- get_package_version("ggplot2")
ggplot_ver <- utils::packageVersion("ggplot2")
if (ggplot_ver > "2.2.1") {
find_panel_info_api(b)

View File

@@ -23,10 +23,10 @@
#' @examples
#' ## Only run this example in interactive R sessions
#' if (interactive()) {
#' runUrl('https://github.com/rstudio/shiny_example/archive/main.tar.gz')
#' runUrl('https://github.com/rstudio/shiny_example/archive/master.tar.gz')
#'
#' # Can run an app from a subdirectory in the archive
#' runUrl("https://github.com/rstudio/shiny_example/archive/main.zip",
#' runUrl("https://github.com/rstudio/shiny_example/archive/master.zip",
#' subdir = "inst/shinyapp/")
#' }
runUrl <- function(url, filetype = NULL, subdir = NULL, destdir = NULL, ...) {
@@ -121,8 +121,7 @@ runGist <- function(gist, destdir = NULL, ...) {
#' @param username GitHub username. If `repo` is of the form
#' `"username/repo"`, `username` will be taken from `repo`.
#' @param ref Desired git reference. Could be a commit, tag, or branch name.
#' Defaults to `"HEAD"`, which means the default branch on GitHub, typically
#' `"main"` or `"master"`.
#' Defaults to `"master"`.
#' @export
#' @examples
#' ## Only run this example in interactive R sessions
@@ -134,7 +133,7 @@ runGist <- function(gist, destdir = NULL, ...) {
#' runGitHub("shiny_example", "rstudio", subdir = "inst/shinyapp/")
#' }
runGitHub <- function(repo, username = getOption("github.user"),
ref = "HEAD", subdir = NULL, destdir = NULL, ...) {
ref = "master", subdir = NULL, destdir = NULL, ...) {
if (grepl('/', repo)) {
res <- strsplit(repo, '/')[[1]]

View File

@@ -28,7 +28,7 @@
#' ports will be tried.
#' @param launch.browser If true, the system's default web browser will be
#' launched automatically after the app is started. Defaults to true in
#' interactive sessions only. The value of this parameter can also be a
#' interactive sessions only. This value of this parameter can also be a
#' function to call with the application's URL.
#' @param host The IPv4 address that the application should listen on. Defaults
#' to the `shiny.host` option, if set, or `"127.0.0.1"` if not. See
@@ -467,7 +467,7 @@ runExample <- function(example=NA,
launch.browser = getOption('shiny.launch.browser', interactive()),
host=getOption('shiny.host', '127.0.0.1'),
display.mode=c("auto", "normal", "showcase")) {
examplesDir <- system_file('examples', package='shiny')
examplesDir <- system.file('examples', package='shiny')
dir <- resolve(examplesDir, example)
if (is.null(dir)) {
if (is.na(example)) {

View File

@@ -41,9 +41,9 @@ inputHandlers <- Map$new()
#' })
#'
#' ## On the Javascript side, the associated input binding must have a corresponding getType method:
#' # getType: function(el) {
#' # return "mypackage.validint";
#' # }
#' getType: function(el) {
#' return "mypackage.validint";
#' }
#'
#' }
#' @seealso [removeInputHandler()] [applyInputHandlers()]
@@ -181,7 +181,7 @@ registerInputHandler("shiny.datetime", function(val, ...){
registerInputHandler("shiny.action", function(val, shinysession, name) {
# mark up the action button value with a special class so we can recognize it later
class(val) <- c("shinyActionButtonValue", class(val))
class(val) <- c(class(val), "shinyActionButtonValue")
val
})

View File

@@ -128,7 +128,7 @@ createAppHandlers <- function(httpHandlers, serverFuncSource) {
appvars <- new.env()
appvars$server <- NULL
sys.www.root <- system_file('www', package='shiny')
sys.www.root <- system.file('www', package='shiny')
# This value, if non-NULL, must be present on all HTTP and WebSocket
# requests as the Shiny-Shared-Secret header or else access will be
@@ -385,7 +385,7 @@ startApp <- function(appObj, port, host, quiet) {
list(
# Always handle /session URLs dynamically, even if / is a static path.
"session" = excludeStaticPath(),
"shared" = system_file(package = "shiny", "www", "shared")
"shared" = system.file(package = "shiny", "www", "shared")
),
.globals$resourcePaths
)

View File

@@ -94,10 +94,6 @@ getShinyOption <- function(name, default = NULL) {
#' numbers to JSON format to send to the client web browser.}
#' \item{shiny.launch.browser (defaults to `interactive()`)}{A boolean which controls the default behavior
#' when an app is run. See [runApp()] for more information.}
#' \item{shiny.mathjax.url (defaults to `"https://mathjax.rstudio.com/latest/MathJax.js"`)}{
#' The URL that should be used to load MathJax, via [withMathJax()].}
#' \item{shiny.mathjax.config (defaults to `"config=TeX-AMS-MML_HTMLorMML"`)}{The querystring
#' used to load MathJax, via [withMathJax()].}
#' \item{shiny.maxRequestSize (defaults to 5MB)}{This is a number which specifies the maximum
#' web request size, which serves as a size limit for file uploads.}
#' \item{shiny.minified (defaults to `TRUE`)}{By default
@@ -129,9 +125,6 @@ getShinyOption <- function(name, default = NULL) {
#' console.}
#' \item{shiny.testmode (defaults to `FALSE`)}{If `TRUE`, then various features for testing Shiny
#' applications are enabled.}
#' \item{shiny.snapshotsortc (defaults to `FALSE`)}{If `TRUE`, test snapshot keys
#' for \pkg{shinytest} will be sorted consistently using the C locale. Snapshots
#' retrieved by \pkg{shinytest2} will always sort using the C locale.}
#' \item{shiny.trace (defaults to `FALSE`)}{Print messages sent between the R server and the web
#' browser client to the R console. This is useful for debugging. Possible
#' values are `"send"` (only print messages sent to the client),
@@ -140,10 +133,9 @@ getShinyOption <- function(name, default = NULL) {
#' messages).}
#' \item{shiny.autoload.r (defaults to `TRUE`)}{If `TRUE`, then the R/
#' of a shiny app will automatically be sourced.}
#' \item{shiny.useragg (defaults to `TRUE`)}{Set to `FALSE` to prevent PNG rendering via the
#' ragg package. See [plotPNG()] for more information.}
#' \item{shiny.usecairo (defaults to `TRUE`)}{Set to `FALSE` to prevent PNG rendering via the
#' Cairo package. See [plotPNG()] for more information.}
#' \item{shiny.usecairo (defaults to `TRUE`)}{This is used to disable graphical rendering by the
#' Cairo package, if it is installed. See [plotPNG()] for more
#' information.}
#' \item{shiny.devmode (defaults to `NULL`)}{Option to enable Shiny Developer Mode. When set,
#' different default `getOption(key)` values will be returned. See [devmode()] for more details.}
### Not documenting as 'shiny.devmode.verbose' is for niche use only

View File

@@ -403,7 +403,7 @@ ShinySession <- R6Class(
sendMessage = function(...) {
# This function is a wrapper for $write
msg <- list(...)
if (any_unnamed(msg)) {
if (anyUnnamed(msg)) {
stop("All arguments to sendMessage must be named.")
}
private$write(toJSON(msg))
@@ -478,35 +478,6 @@ ShinySession <- R6Class(
# "json" unless requested otherwise. The only other valid value is
# "rds".
format <- params$format %||% "json"
# Machines can test their snapshot under different locales.
# R CMD check runs under the `C` locale.
# However, before this parameter, existing snapshots were most likely not
# under the `C` locale is would cause failures. This parameter allows
# users to opt-in to the `C` locale.
# From ?sort:
# However, there are some caveats with the radix sort:
# If x is a character vector, all elements must share the
# same encoding. Only UTF-8 (including ASCII) and Latin-1
# encodings are supported. Collation always follows the "C"
# locale.
# {shinytest2} will always set `sortC=1`
# {shinytest} does not have `sortC` functionality.
# Users should set `options(shiny.snapshotsortc = TRUE)` within their app.
# The sortingMethod should always be `radix` going forward.
sortMethod <-
if (!is.null(params$sortC)) {
if (params$sortC != "1") {
stop("The `sortC` parameter can only be `1` or not supplied")
}
"radix"
} else {
# Allow users to set an option for {shinytest2}.
if (isTRUE(getShinyOption("snapshotsortc", default = FALSE))) {
"radix"
} else {
"auto"
}
}
values <- list()
@@ -549,7 +520,7 @@ ShinySession <- R6Class(
}
)
values$input <- sortByName(values$input, method = sortMethod)
values$input <- sortByName(values$input)
}
if (!is.null(params$output)) {
@@ -577,7 +548,7 @@ ShinySession <- R6Class(
}
)
values$output <- sortByName(values$output, method = sortMethod)
values$output <- sortByName(values$output)
}
if (!is.null(params$export)) {
@@ -598,7 +569,7 @@ ShinySession <- R6Class(
)
}
values$export <- sortByName(values$export, method = sortMethod)
values$export <- sortByName(values$export)
}
# Make sure input, output, and export are all named lists (at this
@@ -854,7 +825,7 @@ ShinySession <- R6Class(
dots <- eval(substitute(alist(...)))
}
if (any_unnamed(dots))
if (anyUnnamed(dots))
stop("exportTestValues: all arguments must be named.")
names(dots) <- ns(names(dots))
@@ -942,7 +913,7 @@ ShinySession <- R6Class(
# Copy `values` from scopeState to state, adding namespace
if (length(scopeState$values) != 0) {
if (any_unnamed(scopeState$values)) {
if (anyUnnamed(scopeState$values)) {
stop("All scope values in must be named.")
}
@@ -1143,12 +1114,7 @@ ShinySession <- R6Class(
structure(list(), class = "try-error", condition = cond)
} else if (inherits(cond, "shiny.output.cancel")) {
structure(list(), class = "cancel-output")
} else if (cnd_inherits(cond, "shiny.silent.error")) {
# The error condition might have been chained by
# foreign code, e.g. dplyr. Find the original error.
while (!inherits(cond, "shiny.silent.error")) {
cond <- cond$parent
}
} else if (inherits(cond, "shiny.silent.error")) {
# Don't let shiny.silent.error go through the normal stop
# path of try, because we don't want it to print. But we
# do want to try to return the same looking result so that
@@ -1735,7 +1701,7 @@ ShinySession <- R6Class(
dots <- eval(substitute(alist(...)))
}
if (any_unnamed(dots))
if (anyUnnamed(dots))
stop("exportTestValues: all arguments must be named.")
# Create a named list where each item is a list with an expression and
@@ -1748,7 +1714,7 @@ ShinySession <- R6Class(
},
getTestSnapshotUrl = function(input = TRUE, output = TRUE, export = TRUE,
format = "json", sortC = FALSE) {
format = "json") {
reqString <- function(group, value) {
if (isTRUE(value))
paste0(group, "=1")
@@ -1762,7 +1728,6 @@ ShinySession <- R6Class(
reqString("input", input),
reqString("output", output),
reqString("export", export),
reqString("sortC", sortC),
paste0("format=", format),
sep = "&"
)

View File

@@ -193,7 +193,7 @@ shinyAppDir_serverR <- function(appDir, options=list()) {
staticPaths <- list()
}
fallbackWWWDir <- system_file("www-dir", package = "shiny")
fallbackWWWDir <- system.file("www-dir", package = "shiny")
serverSource <- cachedFuncWithFile(appDir, "server.R", case.sensitive = FALSE,
function(serverR) {
@@ -286,7 +286,7 @@ shinyAppDir_serverR <- function(appDir, options=list()) {
#
# The return value is a function that halts monitoring when called.
initAutoReloadMonitor <- function(dir) {
if (!get_devmode_option("shiny.autoreload", FALSE)) {
if (!getOption("shiny.autoreload", FALSE)) {
return(function(){})
}
@@ -339,7 +339,7 @@ initAutoReloadMonitor <- function(dir) {
#' @param appDir The application directory. If `appDir` is `NULL` or
#' not supplied, the nearest enclosing directory that is a Shiny app, starting
#' with the current directory, is used.
#' @param renv The environment in which the files in the `R/` directory should
#' @param renv The environmeny in which the files in the `R/` directory should
#' be evaluated.
#' @param globalrenv The environment in which `global.R` should be evaluated. If
#' `NULL`, `global.R` will not be evaluated at all.
@@ -455,7 +455,7 @@ shinyAppDir_appR <- function(fileName, appDir, options=list())
staticPaths <- list()
}
fallbackWWWDir <- system_file("www-dir", package = "shiny")
fallbackWWWDir <- system.file("www-dir", package = "shiny")
oldwd <- NULL
monitorHandle <- NULL

View File

@@ -14,11 +14,7 @@ NULL
#' # now we can just write "static" content without withMathJax()
#' div("more math here $$\\sqrt{2}$$")
withMathJax <- function(...) {
path <- paste0(
getOption("shiny.mathjax.url", "https://mathjax.rstudio.com/latest/MathJax.js"),
"?",
getOption("shiny.mathjax.config", "config=TeX-AMS-MML_HTMLorMML")
)
path <- 'https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'
tagList(
tags$head(
singleton(tags$script(src = path, type = 'text/javascript'))
@@ -43,7 +39,7 @@ renderPage <- function(ui, showcase=0, testMode=FALSE) {
# Put the body into the default template
ui <- htmlTemplate(
system_file("template", "default.html", package = "shiny"),
system.file("template", "default.html", package = "shiny"),
lang = lang,
body = ui,
# this template is a complete HTML document
@@ -59,14 +55,8 @@ renderPage <- function(ui, showcase=0, testMode=FALSE) {
if (testMode) {
# Add code injection listener if in test mode
shiny_deps[[length(shiny_deps) + 1]] <-
htmlDependency(
"shiny-testmode",
get_package_version("shiny"),
src = "www/shared",
package = "shiny",
script = "shiny-testmode.js",
all_files = FALSE
)
htmlDependency("shiny-testmode", shinyPackageVersion(),
c(href="shared"), script = "shiny-testmode.js")
}
html <- renderDocument(ui, shiny_deps, processDep = createWebDependency)
@@ -78,19 +68,23 @@ jqueryDependency <- function() {
if (version == 3) {
return(htmlDependency(
"jquery", version_jquery,
src = "www/shared",
src = c(
href = "shared",
file = "www/shared"
),
package = "shiny",
script = "jquery.min.js",
all_files = FALSE
script = "jquery.min.js"
))
}
if (version == 1) {
return(htmlDependency(
"jquery", "1.12.4",
src = "www/shared/legacy",
src = c(
href = "shared/legacy",
file = "www/shared/legacy"
),
package = "shiny",
script = "jquery.min.js",
all_files = FALSE
script = "jquery.min.js"
))
}
stop("Unsupported version of jQuery: ", version)
@@ -101,9 +95,8 @@ shinyDependencies <- function() {
bslib::bs_dependency_defer(shinyDependencyCSS),
htmlDependency(
name = "shiny-javascript",
version = get_package_version("shiny"),
src = "www/shared",
package = "shiny",
version = shinyPackageVersion(),
src = c(href = "shared"),
script =
if (isTRUE(
get_devmode_option(
@@ -113,27 +106,24 @@ shinyDependencies <- function() {
))
"shiny.min.js"
else
"shiny.js",
all_files = FALSE
"shiny.js"
)
)
}
shinyDependencyCSS <- function(theme) {
version <- get_package_version("shiny")
version <- shinyPackageVersion()
if (!is_bs_theme(theme)) {
return(htmlDependency(
name = "shiny-css",
version = version,
src = "www/shared",
package = "shiny",
stylesheet = "shiny.min.css",
all_files = FALSE
src = c(href = "shared"),
stylesheet = "shiny.min.css"
))
}
scss_home <- system_file("www/shared/shiny_scss", package = "shiny")
scss_home <- system.file("www/shared/shiny_scss", package = "shiny")
scss_files <- file.path(scss_home, c("bootstrap.scss", "shiny.scss"))
scss_files <- lapply(scss_files, sass::sass_file)

View File

@@ -778,9 +778,9 @@ renderUI <- function(expr, env = parent.frame(), quoted = FALSE,
#' function.)
#' @param contentType A string of the download's
#' [content type](https://en.wikipedia.org/wiki/Internet_media_type), for
#' example `"text/csv"` or `"image/png"`. If `NULL`, the content type
#' will be guessed based on the filename extension, or
#' `application/octet-stream` if the extension is unknown.
#' example `"text/csv"` or `"image/png"`. If `NULL` or
#' `NA`, the content type will be guessed based on the filename
#' extension, or `application/octet-stream` if the extension is unknown.
#' @param outputArgs A list of arguments to be passed through to the implicit
#' call to [downloadButton()] when `downloadHandler` is used
#' in an interactive R Markdown document.
@@ -810,7 +810,7 @@ renderUI <- function(expr, env = parent.frame(), quoted = FALSE,
#' shinyApp(ui, server)
#' }
#' @export
downloadHandler <- function(filename, content, contentType=NULL, outputArgs=list()) {
downloadHandler <- function(filename, content, contentType=NA, outputArgs=list()) {
renderFunc <- function(shinysession, name, ...) {
shinysession$registerDownload(name, filename, contentType, content)
}
@@ -822,9 +822,7 @@ downloadHandler <- function(filename, content, contentType=NULL, outputArgs=list
#' Table output with the JavaScript DataTables library
#'
#' @description
#' `r lifecycle::badge("superseded")` Please use
#' \href{https://rstudio.github.io/DT/shiny.html}{\code{DT::renderDataTable()}}.
#' (Shiny 0.11.1)
#' `r lifecycle::badge("superseded")` Please use [`DT::renderDataTable()`]. (Shiny 0.11.1)
#'
#' Makes a reactive version of the given function that returns a data frame (or
#' matrix), which will be rendered with the [DataTables](https://datatables.net)
@@ -953,7 +951,7 @@ renderDataTable <- function(expr, options = NULL, searchDelay = 500,
DT10Names <- function() {
rbind(
utils::read.table(
system_file('www/shared/datatables/upgrade1.10.txt', package = 'shiny'),
system.file('www/shared/datatables/upgrade1.10.txt', package = 'shiny'),
stringsAsFactors = FALSE
),
c('aoColumns', 'Removed') # looks like an omission on the upgrade guide

View File

@@ -32,40 +32,26 @@ licenseLink <- function(licenseName) {
showcaseHead <- function() {
deps <- list(
jqueryuiDependency(),
htmlDependency(
"showdown",
"0.3.1",
src = "www/shared/showdown/compressed",
package="shiny",
script = "showdown.js"
),
htmlDependency(
"highlight.js",
"6.2",
src = "www/shared/highlight",
package="shiny",
script = "highlight.pack.js",
stylesheet = "rstudio.css"
),
htmlDependency(
"showcase",
"0.1.0",
src = "www/shared",
package = "shiny",
script = "shiny-showcase.js",
stylesheet = "shiny-showcase.css",
all_files = FALSE
)
htmlDependency("jqueryui", "1.12.1", c(href="shared/jqueryui"),
script = "jquery-ui.min.js"),
htmlDependency("showdown", "0.3.1", c(href="shared/showdown/compressed"),
script = "showdown.js"),
htmlDependency("highlight.js", "6.2", c(href="shared/highlight"),
script = "highlight.pack.js")
)
mdfile <- file.path.ci(getwd(), 'Readme.md')
html <- tagList(
html <- with(tags, tagList(
script(src="shared/shiny-showcase.js"),
link(rel="stylesheet", type="text/css",
href="shared/highlight/rstudio.css"),
link(rel="stylesheet", type="text/css",
href="shared/shiny-showcase.css"),
if (file.exists(mdfile))
tags$script(type="text/markdown", id="showcase-markdown-content",
script(type="text/markdown", id="showcase-markdown-content",
paste(readUTF8(mdfile), collapse="\n"))
else ""
)
))
return(attachDependencies(html, deps))
}

View File

@@ -1,216 +0,0 @@
# Generated by staticimports; do not edit by hand.
# ======================================================================
# Imported from pkg:staticimports
# ======================================================================
# Given a vector, return TRUE if any elements are named, FALSE otherwise.
# For zero-length vectors, always return FALSE.
any_named <- function(x) {
if (length(x) == 0) return(FALSE)
nms <- names(x)
!is.null(nms) && any(nzchar(nms))
}
# Given a vector, return TRUE if any elements are unnamed, FALSE otherwise.
# For zero-length vectors, always return FALSE.
any_unnamed <- function(x) {
if (length(x) == 0) return(FALSE)
nms <- names(x)
is.null(nms) || !all(nzchar(nms))
}
# Borrowed from pkgload:::dev_meta, with some modifications.
# Returns TRUE if `pkg` was loaded with `devtools::load_all()`.
devtools_loaded <- function(pkg) {
ns <- .getNamespace(pkg)
if (is.null(ns) || is.null(ns$.__DEVTOOLS__)) {
return(FALSE)
}
TRUE
}
get_package_version <- function(pkg) {
# `utils::packageVersion()` can be slow, so first try the fast path of
# checking if the package is already loaded.
ns <- .getNamespace(pkg)
if (is.null(ns)) {
utils::packageVersion(pkg)
} else {
as.package_version(ns$.__NAMESPACE__.$spec[["version"]])
}
}
is_installed <- function(pkg, version = NULL) {
installed <- isNamespaceLoaded(pkg) || nzchar(system_file_cached(package = pkg))
if (is.null(version)) {
return(installed)
}
installed && isTRUE(get_package_version(pkg) >= version)
}
register_upgrade_message <- function(pkg, version, error = FALSE) {
msg <- sprintf(
"This version of '%s' is designed to work with '%s' >= %s.
Please upgrade via install.packages('%s').",
environmentName(environment(register_upgrade_message)),
pkg, version, pkg
)
cond <- if (error) stop else packageStartupMessage
if (pkg %in% loadedNamespaces() && !is_installed(pkg, version)) {
cond(msg)
}
# Always register hook in case pkg is loaded at some
# point the future (or, potentially, but less commonly,
# unloaded & reloaded)
setHook(
packageEvent(pkg, "onLoad"),
function(...) {
if (!is_installed(pkg, version)) cond(msg)
}
)
}
# Simplified version rlang:::s3_register() that just uses
# warning() instead of rlang::warn() when registration fails
# https://github.com/r-lib/rlang/blob/main/R/compat-s3-register.R
s3_register <- function(generic, class, method = NULL) {
stopifnot(is.character(generic), length(generic) == 1)
stopifnot(is.character(class), length(class) == 1)
pieces <- strsplit(generic, "::")[[1]]
stopifnot(length(pieces) == 2)
package <- pieces[[1]]
generic <- pieces[[2]]
caller <- parent.frame()
get_method_env <- function() {
top <- topenv(caller)
if (isNamespace(top)) {
asNamespace(environmentName(top))
} else {
caller
}
}
get_method <- function(method, env) {
if (is.null(method)) {
get(paste0(generic, ".", class), envir = get_method_env())
} else {
method
}
}
register <- function(...) {
envir <- asNamespace(package)
# Refresh the method each time, it might have been updated by
# `devtools::load_all()`
method_fn <- get_method(method)
stopifnot(is.function(method_fn))
# Only register if generic can be accessed
if (exists(generic, envir)) {
registerS3method(generic, class, method_fn, envir = envir)
} else {
warning(
"Can't find generic `", generic, "` in package ", package,
" register S3 method. Do you need to update ", package,
" to the latest version?", call. = FALSE
)
}
}
# Always register hook in case package is later unloaded & reloaded
setHook(packageEvent(package, "onLoad"), function(...) {
register()
})
# Avoid registration failures during loading (pkgload or regular).
# Check that environment is locked because the registering package
# might be a dependency of the package that exports the generic. In
# that case, the exports (and the generic) might not be populated
# yet (#1225).
if (isNamespaceLoaded(package) && environmentIsLocked(asNamespace(package))) {
register()
}
invisible()
}
# Borrowed from pkgload::shim_system.file, with some modifications. This behaves
# like `system.file()`, except that (1) for packages loaded with
# `devtools::load_all()`, it will return the path to files in the package's
# inst/ directory, and (2) for other packages, the directory lookup is cached.
# Also, to keep the implementation simple, it doesn't support specification of
# lib.loc or mustWork.
system_file <- function(..., package = "base") {
if (!devtools_loaded(package)) {
return(system_file_cached(..., package = package))
}
if (!is.null(names(list(...)))) {
stop("All arguments other than `package` must be unnamed.")
}
# If package was loaded with devtools (the package loaded with load_all),
# also search for files under inst/, and don't cache the results (it seems
# more likely that the package path will change during the development
# process)
pkg_path <- find.package(package)
# First look in inst/
files_inst <- file.path(pkg_path, "inst", ...)
present_inst <- file.exists(files_inst)
# For any files that weren't present in inst/, look in the base path
files_top <- file.path(pkg_path, ...)
present_top <- file.exists(files_top)
# Merge them together. Here are the different possible conditions, and the
# desired result. NULL means to drop that element from the result.
#
# files_inst: /inst/A /inst/B /inst/C /inst/D
# present_inst: T T F F
# files_top: /A /B /C /D
# present_top: T F T F
# result: /inst/A /inst/B /C NULL
#
files <- files_top
files[present_inst] <- files_inst[present_inst]
# Drop cases where not present in either location
files <- files[present_inst | present_top]
if (length(files) == 0) {
return("")
}
# Make sure backslashes are replaced with slashes on Windows
normalizePath(files, winslash = "/")
}
# A wrapper for `system.file()`, which caches the results, because
# `system.file()` can be slow. Note that because of caching, if
# `system_file_cached()` is called on a package that isn't installed, then the
# package is installed, and then `system_file_cached()` is called again, it will
# still return "".
system_file_cached <- local({
pkg_dir_cache <- character()
function(..., package = "base") {
if (!is.null(names(list(...)))) {
stop("All arguments other than `package` must be unnamed.")
}
not_cached <- is.na(match(package, names(pkg_dir_cache)))
if (not_cached) {
pkg_dir <- system.file(package = package)
pkg_dir_cache[[package]] <<- pkg_dir
} else {
pkg_dir <- pkg_dir_cache[[package]]
}
file.path(pkg_dir, ...)
}
})

View File

@@ -2,11 +2,6 @@
#' @include map.R
NULL
# @staticimports pkg:staticimports
# is_installed get_package_version system_file
# s3_register register_upgrade_message
# any_named any_unnamed
#' Make a random number generator repeatable
#'
#' Given a function that generates random data, returns a wrapped version of
@@ -131,6 +126,34 @@ dropNullsOrEmpty <- function(x) {
x[!vapply(x, nullOrEmpty, FUN.VALUE=logical(1))]
}
# Given a vector/list, return TRUE if any elements are named, FALSE otherwise.
anyNamed <- function(x) {
# Zero-length vector
if (length(x) == 0) return(FALSE)
nms <- names(x)
# List with no name attribute
if (is.null(nms)) return(FALSE)
# List with name attribute; check for any ""
any(nzchar(nms))
}
# Given a vector/list, return TRUE if any elements are unnamed, FALSE otherwise.
anyUnnamed <- function(x) {
# Zero-length vector
if (length(x) == 0) return(FALSE)
nms <- names(x)
# List with no name attribute
if (is.null(nms)) return(TRUE)
# List with name attribute; check for any ""
any(!nzchar(nms))
}
# Given a vector/list, returns a named vector/list (the labels will be blank).
asNamed <- function(x) {
@@ -150,7 +173,7 @@ empty_named_list <- function() {
# name as elements in a, the element in a is dropped. Also, if there are any
# duplicated names in a or b, only the last one with that name is kept.
mergeVectors <- function(a, b) {
if (any_unnamed(a) || any_unnamed(b)) {
if (anyUnnamed(a) || anyUnnamed(b)) {
stop("Vectors must be either NULL or have names for all elements")
}
@@ -162,27 +185,15 @@ mergeVectors <- function(a, b) {
# Sort a vector by the names of items. If there are multiple items with the
# same name, preserve the original order of those items. For empty
# vectors/lists/NULL, return the original value.
sortByName <- function(x, method = "auto") {
if (any_unnamed(x))
sortByName <- function(x) {
if (anyUnnamed(x))
stop("All items must be named")
# Special case for empty vectors/lists, and NULL
if (length(x) == 0)
return(x)
# Must provide consistent sort order
# https://github.com/rstudio/shinytest/issues/409
# Using a flag in the snapshot url to determine the method
# `method="radix"` uses `C` locale, which is consistent across platforms
# Even if two platforms share `en_us.UTF-8`, they may not sort consistently
# https://blog.zhimingwang.org/macos-lc_collate-hunt
# (macOS) $ LC_ALL=en_US.UTF-8 sort <<<$'python-dev\npython3-dev'
# python-dev
# python3-dev
# (Linux) $ LC_ALL=en_US.UTF-8 sort <<<$'python-dev\npython3-dev'
# python3-dev
# python-dev
x[order(names(x), method = method)]
x[order(names(x))]
}
# Sort a vector. If a character vector, sort using C locale, which is consistent
@@ -484,7 +495,7 @@ shinyCallingHandlers <- function(expr) {
withCallingHandlers(captureStackTraces(expr),
error = function(e) {
# Don't intercept shiny.silent.error (i.e. validation errors)
if (cnd_inherits(e, "shiny.silent.error"))
if (inherits(e, "shiny.silent.error"))
return()
handle <- getOption('shiny.error')
@@ -1705,20 +1716,24 @@ findEnclosingApp <- function(path = ".") {
}
}
# Until `rlang::cnd_inherits()` is on CRAN
cnd_inherits <- function(cnd, class) {
cnd_some(cnd, ~ inherits(.x, class))
}
cnd_some <- function(.cnd, .p, ...) {
.p <- rlang::as_function(.p)
while (rlang::is_condition(.cnd)) {
if (.p(.cnd, ...)) {
return(TRUE)
}
.cnd <- .cnd$parent
# Check if a package is installed, and if version is specified,
# that we have at least that version
is_available <- function(package, version = NULL) {
installed <- nzchar(system.file(package = package))
if (is.null(version)) {
return(installed)
}
FALSE
installed && isTRUE(utils::packageVersion(package) >= version)
}
# cached version of utils::packageVersion("shiny")
shinyPackageVersion <- local({
version <- NULL
function() {
if (is.null(version)) {
version <<- utils::packageVersion("shiny")
}
version
}
})

View File

@@ -2,7 +2,7 @@
<!-- badges: start -->
[![CRAN](https://www.r-pkg.org/badges/version/shiny)](https://CRAN.R-project.org/package=shiny)
[![R build status](https://github.com/rstudio/shiny/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/rstudio/shiny/actions)
[![R build status](https://github.com/rstudio/shiny/workflows/R-CMD-check/badge.svg)](https://github.com/rstudio/shiny/actions)
[![RStudio community](https://img.shields.io/badge/community-shiny-blue?style=social&logo=rstudio&logoColor=75AADB)](https://community.rstudio.com/new-topic?category=shiny&tags=shiny)
<!-- badges: end -->
@@ -47,13 +47,13 @@ For help with learning fundamental Shiny programming concepts, check out the [Ma
## Getting Help
To ask a question about Shiny, please use the [RStudio Community website](https://community.rstudio.com/new-topic?category=shiny&tags=shiny).
To ask a question about Shiny, please use the [RStudio Community website](https://community.rstudio.com/new-topic?category=shiny&tags=shiny).
For bug reports, please use the [issue tracker](https://github.com/rstudio/shiny/issues) and also keep in mind that by [writing a good bug report](https://github.com/rstudio/shiny/wiki/Writing-Good-Bug-Reports), you're more likely to get help with your problem.
For bug reports, please use the [issue tracker](https://github.com/rstudio/shiny/issues) and also keep in mind that by [writing a good bug report](https://github.com/rstudio/shiny/wiki/Writing-Good-Bug-Reports), you're more likely to get help with your problem.
## Contributing
We welcome contributions to the **shiny** package. Please see our [CONTRIBUTING.md](https://github.com/rstudio/shiny/blob/main/.github/CONTRIBUTING.md) file for detailed guidelines of how to contribute.
We welcome contributions to the **shiny** package. Please see our [CONTRIBUTING.md](https://github.com/rstudio/shiny/blob/master/.github/CONTRIBUTING.md) file for detailed guidelines of how to contribute.
## License

View File

@@ -0,0 +1,2 @@
library(shinytest)
expect_pass(testApp("../", suffix = osName()))

View File

@@ -0,0 +1,12 @@
app <- ShinyDriver$new("../../")
app$snapshotInit("mytest")
app$snapshot()
{{
if (isTRUE(module)) {
'
app$setInputs(`examplemodule1-button` = "click")
app$setInputs(`examplemodule1-button` = "click")
app$snapshot()'
}
}}

View File

@@ -1 +1,9 @@
shinytest2::test_app()
library(testthat)
test_dir(
"./testthat",
# Run in the app's environment containing all support methods.
env = shiny::loadSupport(),
# Display the regular progress output and throw an error if any test error is found
reporter = c("progress", "fail")
)

View File

@@ -14,4 +14,5 @@ if (isTRUE(rdir)) {
expect_equal(output$sequence, "1 2 3 4 5 6 7 8 9 10 11 12")
'
}
}}})
}}
})

View File

@@ -1,18 +0,0 @@
library(shinytest2)
test_that("Initial snapshot values are consistent", {
app <- AppDriver$new(name = "init")
app$expect_values()
}){{
if (isTRUE(module)) {
HTML('
test_that("Module values are consistent", {
app <- AppDriver$new(name = "mod")
app$click("examplemodule1-button")
app$click("examplemodule1-button")
app$expect_values()
})')
}
}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.6.0.9022 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
#showcase-well{border-radius:0}.shiny-code{background-color:#fff;margin-bottom:0}.shiny-code code{font-family:Menlo,Consolas,"Courier New",monospace}.shiny-code-container{margin-top:20px;clear:both}.shiny-code-container h3{display:inline;margin-right:15px}.showcase-header{font-size:16px;font-weight:normal}.showcase-code-link{text-align:right;padding:15px}#showcase-app-container{vertical-align:top}#showcase-code-tabs{margin-right:15px}#showcase-code-tabs pre{border:none;line-height:1em}#showcase-code-tabs .nav{margin-bottom:0}#showcase-code-tabs ul{margin-bottom:0}#showcase-code-tabs .tab-content{border-style:solid;border-color:#e5e5e5;border-width:0px 1px 1px 1px;overflow:auto;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#showcase-app-code{width:100%}#showcase-code-position-toggle{float:right}#showcase-sxs-code{padding-top:20px;vertical-align:top}.showcase-code-license{display:block;text-align:right}#showcase-code-content pre{background-color:#fff}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
/*! shiny 1.7.1.9003 | (c) 2012-2022 RStudio, PBC. | License: GPL-3 | file LICENSE */
/*! shiny 1.6.0.9022 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
(function(){var a=eval;window.addEventListener("message",function(i){var e=i.data;e.code&&a(e.code)});})();
//# sourceMappingURL=shiny-testmode.js.map
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvc3JjL3V0aWxzL2V2YWwudHMiLCAiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LXRlc3Rtb2RlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvL2VzYnVpbGQuZ2l0aHViLmlvL2NvbnRlbnQtdHlwZXMvI2RpcmVjdC1ldmFsXG4vL3RsL2RyO1xuLy8gKiBEaXJlY3QgdXNhZ2Ugb2YgYGV2YWwoXCJ4XCIpYCBpcyBiYWQgd2l0aCBidW5kbGVkIGNvZGUuXG4vLyAqIEluc3RlYWQsIHVzZSBpbmRpcmVjdCBjYWxscyB0byBgZXZhbGAgc3VjaCBhcyBgaW5kaXJlY3RFdmFsKFwieFwiKWBcbi8vICAgKiBFdmVuIGp1c3QgcmVuYW1pbmcgdGhlIGZ1bmN0aW9uIHdvcmtzIHdlbGwgZW5vdWdoLlxuLy8gPiBUaGlzIGlzIGtub3duIGFzIFwiaW5kaXJlY3QgZXZhbFwiIGJlY2F1c2UgZXZhbCBpcyBub3QgYmVpbmcgY2FsbGVkIGRpcmVjdGx5LCBhbmQgc28gZG9lcyBub3QgdHJpZ2dlciB0aGUgZ3JhbW1hdGljYWwgc3BlY2lhbCBjYXNlIGZvciBkaXJlY3QgZXZhbCBpbiB0aGUgSmF2YVNjcmlwdCBWTS4gWW91IGNhbiBjYWxsIGluZGlyZWN0IGV2YWwgdXNpbmcgYW55IHN5bnRheCBhdCBhbGwgZXhjZXB0IGZvciBhbiBleHByZXNzaW9uIG9mIHRoZSBleGFjdCBmb3JtIGV2YWwoJ3gnKS4gRm9yIGV4YW1wbGUsIHZhciBldmFsMiA9IGV2YWw7IGV2YWwyKCd4JykgYW5kIFtldmFsXVswXSgneCcpIGFuZCB3aW5kb3cuZXZhbCgneCcpIGFyZSBhbGwgaW5kaXJlY3QgZXZhbCBjYWxscy5cbi8vID4gV2hlbiB5b3UgdXNlIGluZGlyZWN0IGV2YWwsIHRoZSBjb2RlIGlzIGV2YWx1YXRlZCBpbiB0aGUgZ2xvYmFsIHNjb3BlIGluc3RlYWQgb2YgaW4gdGhlIGlubGluZSBzY29wZSBvZiB0aGUgY2FsbGVyLlxudmFyIGluZGlyZWN0RXZhbCA9IGV2YWw7XG5leHBvcnQgeyBpbmRpcmVjdEV2YWwgfTsiLCAiLyogZXNsaW50LWRpc2FibGUgdW5pY29ybi9maWxlbmFtZS1jYXNlICovXG5pbXBvcnQgeyBpbmRpcmVjdEV2YWwgfSBmcm9tIFwiLi4vc3JjL3V0aWxzL2V2YWxcIjsgLy8gTGlzdGVuIGZvciBtZXNzYWdlcyBmcm9tIHBhcmVudCBmcmFtZS4gVGhpcyBmaWxlIGlzIG9ubHkgYWRkZWQgd2hlbiB0aGVcbi8vIHNoaW55LnRlc3Rtb2RlIG9wdGlvbiBpcyBUUlVFLlxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHtcbiAgdmFyIG1lc3NhZ2UgPSBlLmRhdGE7XG4gIGlmIChtZXNzYWdlLmNvZGUpIGluZGlyZWN0RXZhbChtZXNzYWdlLmNvZGUpO1xufSk7Il0sCiAgIm1hcHBpbmdzIjogIjtZQU9BLEdBQUksR0FBZSxLQ0huQixPQUFPLGlCQUFpQixVQUFXLFNBQVUsRUFBRyxDQUM5QyxHQUFJLEdBQVUsRUFBRSxLQUNoQixBQUFJLEVBQVEsTUFBTSxFQUFhLEVBQVEiLAogICJuYW1lcyI6IFtdCn0K

View File

@@ -1,7 +0,0 @@
{
"version": 3,
"sources": ["../../../srcts/src/utils/eval.ts", "../../../srcts/extras/shiny-testmode.ts"],
"sourcesContent": ["//esbuild.github.io/content-types/#direct-eval\n//tl/dr;\n// * Direct usage of `eval(\"x\")` is bad with bundled code.\n// * Instead, use indirect calls to `eval` such as `indirectEval(\"x\")`\n// * Even just renaming the function works well enough.\n// > This is known as \"indirect eval\" because eval is not being called directly, and so does not trigger the grammatical special case for direct eval in the JavaScript VM. You can call indirect eval using any syntax at all except for an expression of the exact form eval('x'). For example, var eval2 = eval; eval2('x') and [eval][0]('x') and window.eval('x') are all indirect eval calls.\n// > When you use indirect eval, the code is evaluated in the global scope instead of in the inline scope of the caller.\nvar indirectEval = eval;\nexport { indirectEval };", "/* eslint-disable unicorn/filename-case */\nimport { indirectEval } from \"../src/utils/eval\"; // Listen for messages from parent frame. This file is only added when the\n// shiny.testmode option is TRUE.\n\nwindow.addEventListener(\"message\", function (e) {\n var message = e.data;\n if (message.code) indirectEval(message.code);\n});"],
"mappings": ";YAOA,GAAI,GAAe,KCHnB,OAAO,iBAAiB,UAAW,SAAU,EAAG,CAC9C,GAAI,GAAU,EAAE,KAChB,AAAI,EAAQ,MAAM,EAAa,EAAQ",
"names": []
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -295,15 +295,6 @@ pre.shiny-text-output {
margin-top: 0px;
}
/* Workaround for radio buttons and checkboxes not showing on Qt on Mac.
This occurs in the RStudio IDE on macOS 11.5.
https://github.com/rstudio/shiny/issues/3484
*/
.qtmac input[type="radio"],
.qtmac input[type="checkbox"] {
zoom: 1.0000001;
}
/* consistency with bootstrap.css for selectize.js */
.selectize-control {
margin-bottom: 10px;

View File

@@ -85,40 +85,40 @@ user. Always \code{NULL} for a \code{MockShinySesion}.}
\section{Methods}{
\subsection{Public methods}{
\itemize{
\item \href{#method-MockShinySession-new}{\code{MockShinySession$new()}}
\item \href{#method-MockShinySession-onFlush}{\code{MockShinySession$onFlush()}}
\item \href{#method-MockShinySession-onFlushed}{\code{MockShinySession$onFlushed()}}
\item \href{#method-MockShinySession-onEnded}{\code{MockShinySession$onEnded()}}
\item \href{#method-MockShinySession-isEnded}{\code{MockShinySession$isEnded()}}
\item \href{#method-MockShinySession-isClosed}{\code{MockShinySession$isClosed()}}
\item \href{#method-MockShinySession-close}{\code{MockShinySession$close()}}
\item \href{#method-MockShinySession-cycleStartAction}{\code{MockShinySession$cycleStartAction()}}
\item \href{#method-MockShinySession-fileUrl}{\code{MockShinySession$fileUrl()}}
\item \href{#method-MockShinySession-setInputs}{\code{MockShinySession$setInputs()}}
\item \href{#method-MockShinySession-.scheduleTask}{\code{MockShinySession$.scheduleTask()}}
\item \href{#method-MockShinySession-elapse}{\code{MockShinySession$elapse()}}
\item \href{#method-MockShinySession-.now}{\code{MockShinySession$.now()}}
\item \href{#method-MockShinySession-defineOutput}{\code{MockShinySession$defineOutput()}}
\item \href{#method-MockShinySession-getOutput}{\code{MockShinySession$getOutput()}}
\item \href{#method-MockShinySession-ns}{\code{MockShinySession$ns()}}
\item \href{#method-MockShinySession-flushReact}{\code{MockShinySession$flushReact()}}
\item \href{#method-MockShinySession-makeScope}{\code{MockShinySession$makeScope()}}
\item \href{#method-MockShinySession-setEnv}{\code{MockShinySession$setEnv()}}
\item \href{#method-MockShinySession-setReturned}{\code{MockShinySession$setReturned()}}
\item \href{#method-MockShinySession-getReturned}{\code{MockShinySession$getReturned()}}
\item \href{#method-MockShinySession-genId}{\code{MockShinySession$genId()}}
\item \href{#method-MockShinySession-rootScope}{\code{MockShinySession$rootScope()}}
\item \href{#method-MockShinySession-unhandledError}{\code{MockShinySession$unhandledError()}}
\item \href{#method-MockShinySession-freezeValue}{\code{MockShinySession$freezeValue()}}
\item \href{#method-MockShinySession-onSessionEnded}{\code{MockShinySession$onSessionEnded()}}
\item \href{#method-MockShinySession-registerDownload}{\code{MockShinySession$registerDownload()}}
\item \href{#method-MockShinySession-getCurrentOutputInfo}{\code{MockShinySession$getCurrentOutputInfo()}}
\item \href{#method-MockShinySession-clone}{\code{MockShinySession$clone()}}
\item \href{#method-new}{\code{MockShinySession$new()}}
\item \href{#method-onFlush}{\code{MockShinySession$onFlush()}}
\item \href{#method-onFlushed}{\code{MockShinySession$onFlushed()}}
\item \href{#method-onEnded}{\code{MockShinySession$onEnded()}}
\item \href{#method-isEnded}{\code{MockShinySession$isEnded()}}
\item \href{#method-isClosed}{\code{MockShinySession$isClosed()}}
\item \href{#method-close}{\code{MockShinySession$close()}}
\item \href{#method-cycleStartAction}{\code{MockShinySession$cycleStartAction()}}
\item \href{#method-fileUrl}{\code{MockShinySession$fileUrl()}}
\item \href{#method-setInputs}{\code{MockShinySession$setInputs()}}
\item \href{#method-.scheduleTask}{\code{MockShinySession$.scheduleTask()}}
\item \href{#method-elapse}{\code{MockShinySession$elapse()}}
\item \href{#method-.now}{\code{MockShinySession$.now()}}
\item \href{#method-defineOutput}{\code{MockShinySession$defineOutput()}}
\item \href{#method-getOutput}{\code{MockShinySession$getOutput()}}
\item \href{#method-ns}{\code{MockShinySession$ns()}}
\item \href{#method-flushReact}{\code{MockShinySession$flushReact()}}
\item \href{#method-makeScope}{\code{MockShinySession$makeScope()}}
\item \href{#method-setEnv}{\code{MockShinySession$setEnv()}}
\item \href{#method-setReturned}{\code{MockShinySession$setReturned()}}
\item \href{#method-getReturned}{\code{MockShinySession$getReturned()}}
\item \href{#method-genId}{\code{MockShinySession$genId()}}
\item \href{#method-rootScope}{\code{MockShinySession$rootScope()}}
\item \href{#method-unhandledError}{\code{MockShinySession$unhandledError()}}
\item \href{#method-freezeValue}{\code{MockShinySession$freezeValue()}}
\item \href{#method-onSessionEnded}{\code{MockShinySession$onSessionEnded()}}
\item \href{#method-registerDownload}{\code{MockShinySession$registerDownload()}}
\item \href{#method-getCurrentOutputInfo}{\code{MockShinySession$getCurrentOutputInfo()}}
\item \href{#method-clone}{\code{MockShinySession$clone()}}
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-new"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-new}{}}}
\if{html}{\out{<a id="method-new"></a>}}
\if{latex}{\out{\hypertarget{method-new}{}}}
\subsection{Method \code{new()}}{
Create a new MockShinySession.
\subsection{Usage}{
@@ -127,8 +127,8 @@ Create a new MockShinySession.
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-onFlush"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-onFlush}{}}}
\if{html}{\out{<a id="method-onFlush"></a>}}
\if{latex}{\out{\hypertarget{method-onFlush}{}}}
\subsection{Method \code{onFlush()}}{
Define a callback to be invoked before a reactive flush
\subsection{Usage}{
@@ -146,8 +146,8 @@ Define a callback to be invoked before a reactive flush
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-onFlushed"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-onFlushed}{}}}
\if{html}{\out{<a id="method-onFlushed"></a>}}
\if{latex}{\out{\hypertarget{method-onFlushed}{}}}
\subsection{Method \code{onFlushed()}}{
Define a callback to be invoked after a reactive flush
\subsection{Usage}{
@@ -165,8 +165,8 @@ Define a callback to be invoked after a reactive flush
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-onEnded"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-onEnded}{}}}
\if{html}{\out{<a id="method-onEnded"></a>}}
\if{latex}{\out{\hypertarget{method-onEnded}{}}}
\subsection{Method \code{onEnded()}}{
Define a callback to be invoked when the session ends
\subsection{Usage}{
@@ -182,8 +182,8 @@ Define a callback to be invoked when the session ends
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-isEnded"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-isEnded}{}}}
\if{html}{\out{<a id="method-isEnded"></a>}}
\if{latex}{\out{\hypertarget{method-isEnded}{}}}
\subsection{Method \code{isEnded()}}{
Returns \code{FALSE} if the session has not yet been closed
\subsection{Usage}{
@@ -192,8 +192,8 @@ Returns \code{FALSE} if the session has not yet been closed
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-isClosed"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-isClosed}{}}}
\if{html}{\out{<a id="method-isClosed"></a>}}
\if{latex}{\out{\hypertarget{method-isClosed}{}}}
\subsection{Method \code{isClosed()}}{
Returns \code{FALSE} if the session has not yet been closed
\subsection{Usage}{
@@ -202,8 +202,8 @@ Returns \code{FALSE} if the session has not yet been closed
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-close"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-close}{}}}
\if{html}{\out{<a id="method-close"></a>}}
\if{latex}{\out{\hypertarget{method-close}{}}}
\subsection{Method \code{close()}}{
Closes the session
\subsection{Usage}{
@@ -212,8 +212,8 @@ Closes the session
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-cycleStartAction"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-cycleStartAction}{}}}
\if{html}{\out{<a id="method-cycleStartAction"></a>}}
\if{latex}{\out{\hypertarget{method-cycleStartAction}{}}}
\subsection{Method \code{cycleStartAction()}}{
Unsophisticated mock implementation that merely invokes
\subsection{Usage}{
@@ -229,8 +229,8 @@ Unsophisticated mock implementation that merely invokes
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-fileUrl"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-fileUrl}{}}}
\if{html}{\out{<a id="method-fileUrl"></a>}}
\if{latex}{\out{\hypertarget{method-fileUrl}{}}}
\subsection{Method \code{fileUrl()}}{
Base64-encode the given file. Needed for image rendering.
\subsection{Usage}{
@@ -250,8 +250,8 @@ Base64-encode the given file. Needed for image rendering.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-setInputs"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-setInputs}{}}}
\if{html}{\out{<a id="method-setInputs"></a>}}
\if{latex}{\out{\hypertarget{method-setInputs}{}}}
\subsection{Method \code{setInputs()}}{
Sets reactive values associated with the \code{session$inputs}
object and flushes the reactives.
@@ -280,8 +280,8 @@ session$setInputs(x=1, y=2)
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-.scheduleTask"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-.scheduleTask}{}}}
\if{html}{\out{<a id="method-.scheduleTask"></a>}}
\if{latex}{\out{\hypertarget{method-.scheduleTask}{}}}
\subsection{Method \code{.scheduleTask()}}{
An internal method which shouldn't be used by others.
Schedules \code{callback} for execution after some number of \code{millis}
@@ -301,8 +301,8 @@ milliseconds.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-elapse"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-elapse}{}}}
\if{html}{\out{<a id="method-elapse"></a>}}
\if{latex}{\out{\hypertarget{method-elapse}{}}}
\subsection{Method \code{elapse()}}{
Simulate the passing of time by the given number of milliseconds.
\subsection{Usage}{
@@ -318,8 +318,8 @@ Simulate the passing of time by the given number of milliseconds.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-.now"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-.now}{}}}
\if{html}{\out{<a id="method-.now"></a>}}
\if{latex}{\out{\hypertarget{method-.now}{}}}
\subsection{Method \code{.now()}}{
An internal method which shouldn't be used by others.
\subsection{Usage}{
@@ -331,8 +331,8 @@ Elapsed time in milliseconds.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-defineOutput"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-defineOutput}{}}}
\if{html}{\out{<a id="method-defineOutput"></a>}}
\if{latex}{\out{\hypertarget{method-defineOutput}{}}}
\subsection{Method \code{defineOutput()}}{
An internal method which shouldn't be used by others.
Defines an output in a way that sets private$currentOutputName
@@ -354,8 +354,8 @@ appropriately.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-getOutput"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-getOutput}{}}}
\if{html}{\out{<a id="method-getOutput"></a>}}
\if{latex}{\out{\hypertarget{method-getOutput}{}}}
\subsection{Method \code{getOutput()}}{
An internal method which shouldn't be used by others. Forces
evaluation of any reactive dependencies of the output function.
@@ -376,8 +376,8 @@ output.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-ns"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-ns}{}}}
\if{html}{\out{<a id="method-ns"></a>}}
\if{latex}{\out{\hypertarget{method-ns}{}}}
\subsection{Method \code{ns()}}{
Returns the given id prefixed by this namespace's id.
\subsection{Usage}{
@@ -396,8 +396,8 @@ The id with a namespace prefix.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-flushReact"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-flushReact}{}}}
\if{html}{\out{<a id="method-flushReact"></a>}}
\if{latex}{\out{\hypertarget{method-flushReact}{}}}
\subsection{Method \code{flushReact()}}{
Trigger a reactive flush right now.
\subsection{Usage}{
@@ -406,8 +406,8 @@ Trigger a reactive flush right now.
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-makeScope"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-makeScope}{}}}
\if{html}{\out{<a id="method-makeScope"></a>}}
\if{latex}{\out{\hypertarget{method-makeScope}{}}}
\subsection{Method \code{makeScope()}}{
Create and return a namespace-specific session proxy.
\subsection{Usage}{
@@ -426,8 +426,8 @@ A new session proxy.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-setEnv"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-setEnv}{}}}
\if{html}{\out{<a id="method-setEnv"></a>}}
\if{latex}{\out{\hypertarget{method-setEnv}{}}}
\subsection{Method \code{setEnv()}}{
Set the environment associated with a testServer() call, but
only if it has not previously been set. This ensures that only the
@@ -449,8 +449,8 @@ The provided \code{env}.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-setReturned"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-setReturned}{}}}
\if{html}{\out{<a id="method-setReturned"></a>}}
\if{latex}{\out{\hypertarget{method-setReturned}{}}}
\subsection{Method \code{setReturned()}}{
Set the value returned by the module call and proactively
flush. Note that this method may be called multiple times if modules
@@ -472,8 +472,8 @@ The provided \code{value}.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-getReturned"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-getReturned}{}}}
\if{html}{\out{<a id="method-getReturned"></a>}}
\if{latex}{\out{\hypertarget{method-getReturned}{}}}
\subsection{Method \code{getReturned()}}{
Get the value returned by the module call.
\subsection{Usage}{
@@ -485,8 +485,8 @@ The value returned by the module call
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-genId"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-genId}{}}}
\if{html}{\out{<a id="method-genId"></a>}}
\if{latex}{\out{\hypertarget{method-genId}{}}}
\subsection{Method \code{genId()}}{
Generate a distinct character identifier for use as a proxy
namespace.
@@ -499,8 +499,8 @@ A character identifier unique to the current session.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-rootScope"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-rootScope}{}}}
\if{html}{\out{<a id="method-rootScope"></a>}}
\if{latex}{\out{\hypertarget{method-rootScope}{}}}
\subsection{Method \code{rootScope()}}{
Provides a way to access the root \code{MockShinySession} from
any descendant proxy.
@@ -513,8 +513,8 @@ The root \code{MockShinySession}.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-unhandledError"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-unhandledError}{}}}
\if{html}{\out{<a id="method-unhandledError"></a>}}
\if{latex}{\out{\hypertarget{method-unhandledError}{}}}
\subsection{Method \code{unhandledError()}}{
Called by observers when a reactive expression errors.
\subsection{Usage}{
@@ -530,8 +530,8 @@ Called by observers when a reactive expression errors.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-freezeValue"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-freezeValue}{}}}
\if{html}{\out{<a id="method-freezeValue"></a>}}
\if{latex}{\out{\hypertarget{method-freezeValue}{}}}
\subsection{Method \code{freezeValue()}}{
Freeze a value until the flush cycle completes.
\subsection{Usage}{
@@ -549,8 +549,8 @@ Freeze a value until the flush cycle completes.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-onSessionEnded"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-onSessionEnded}{}}}
\if{html}{\out{<a id="method-onSessionEnded"></a>}}
\if{latex}{\out{\hypertarget{method-onSessionEnded}{}}}
\subsection{Method \code{onSessionEnded()}}{
Registers the given callback to be invoked when the session
is closed (i.e. the connection to the client has been severed). The
@@ -570,8 +570,8 @@ guaranteed.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-registerDownload"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-registerDownload}{}}}
\if{html}{\out{<a id="method-registerDownload"></a>}}
\if{latex}{\out{\hypertarget{method-registerDownload}{}}}
\subsection{Method \code{registerDownload()}}{
Associated a downloadable file with the session.
\subsection{Usage}{
@@ -598,8 +598,8 @@ function.)}
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-getCurrentOutputInfo"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-getCurrentOutputInfo}{}}}
\if{html}{\out{<a id="method-getCurrentOutputInfo"></a>}}
\if{latex}{\out{\hypertarget{method-getCurrentOutputInfo}{}}}
\subsection{Method \code{getCurrentOutputInfo()}}{
Get information about the output that is currently being
executed.
@@ -614,8 +614,8 @@ output, or \code{NULL} if no output is currently executing.
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-MockShinySession-clone"></a>}}
\if{latex}{\out{\hypertarget{method-MockShinySession-clone}{}}}
\if{html}{\out{<a id="method-clone"></a>}}
\if{latex}{\out{\hypertarget{method-clone}{}}}
\subsection{Method \code{clone()}}{
The objects of this class are cloneable with this method.
\subsection{Usage}{

View File

@@ -62,19 +62,19 @@ shinyApp(ui, server)
\section{Methods}{
\subsection{Public methods}{
\itemize{
\item \href{#method-Progress-new}{\code{Progress$new()}}
\item \href{#method-Progress-set}{\code{Progress$set()}}
\item \href{#method-Progress-inc}{\code{Progress$inc()}}
\item \href{#method-Progress-getMin}{\code{Progress$getMin()}}
\item \href{#method-Progress-getMax}{\code{Progress$getMax()}}
\item \href{#method-Progress-getValue}{\code{Progress$getValue()}}
\item \href{#method-Progress-close}{\code{Progress$close()}}
\item \href{#method-Progress-clone}{\code{Progress$clone()}}
\item \href{#method-new}{\code{Progress$new()}}
\item \href{#method-set}{\code{Progress$set()}}
\item \href{#method-inc}{\code{Progress$inc()}}
\item \href{#method-getMin}{\code{Progress$getMin()}}
\item \href{#method-getMax}{\code{Progress$getMax()}}
\item \href{#method-getValue}{\code{Progress$getValue()}}
\item \href{#method-close}{\code{Progress$close()}}
\item \href{#method-clone}{\code{Progress$clone()}}
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-new"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-new}{}}}
\if{html}{\out{<a id="method-new"></a>}}
\if{latex}{\out{\hypertarget{method-new}{}}}
\subsection{Method \code{new()}}{
Creates a new progress panel (but does not display it).
\subsection{Usage}{
@@ -107,8 +107,8 @@ is for backward-compatibility).}
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-set"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-set}{}}}
\if{html}{\out{<a id="method-set"></a>}}
\if{latex}{\out{\hypertarget{method-set}{}}}
\subsection{Method \code{set()}}{
Updates the progress panel. When called the first time, the
progress panel is displayed.
@@ -135,8 +135,8 @@ relative to \code{message}.}
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-inc"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-inc}{}}}
\if{html}{\out{<a id="method-inc"></a>}}
\if{latex}{\out{\hypertarget{method-inc}{}}}
\subsection{Method \code{inc()}}{
Like \code{set}, this updates the progress panel. The difference
is that \code{inc} increases the progress bar by \code{amount}, instead of
@@ -163,8 +163,8 @@ relative to \code{message}.}
}
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-getMin"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-getMin}{}}}
\if{html}{\out{<a id="method-getMin"></a>}}
\if{latex}{\out{\hypertarget{method-getMin}{}}}
\subsection{Method \code{getMin()}}{
Returns the minimum value.
\subsection{Usage}{
@@ -173,8 +173,8 @@ Returns the minimum value.
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-getMax"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-getMax}{}}}
\if{html}{\out{<a id="method-getMax"></a>}}
\if{latex}{\out{\hypertarget{method-getMax}{}}}
\subsection{Method \code{getMax()}}{
Returns the maximum value.
\subsection{Usage}{
@@ -183,8 +183,8 @@ Returns the maximum value.
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-getValue"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-getValue}{}}}
\if{html}{\out{<a id="method-getValue"></a>}}
\if{latex}{\out{\hypertarget{method-getValue}{}}}
\subsection{Method \code{getValue()}}{
Returns the current value.
\subsection{Usage}{
@@ -193,8 +193,8 @@ Returns the current value.
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-close"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-close}{}}}
\if{html}{\out{<a id="method-close"></a>}}
\if{latex}{\out{\hypertarget{method-close}{}}}
\subsection{Method \code{close()}}{
Removes the progress panel. Future calls to \code{set} and
\code{close} will be ignored.
@@ -204,8 +204,8 @@ Removes the progress panel. Future calls to \code{set} and
}
\if{html}{\out{<hr>}}
\if{html}{\out{<a id="method-Progress-clone"></a>}}
\if{latex}{\out{\hypertarget{method-Progress-clone}{}}}
\if{html}{\out{<a id="method-clone"></a>}}
\if{latex}{\out{\hypertarget{method-clone}{}}}
\subsection{Method \code{clone()}}{
The objects of this class are cloneable with this method.
\subsection{Usage}{

View File

@@ -40,9 +40,7 @@ sense, namely:
In the example here, the \code{bindCache()} key consists of \code{input$x} and
\code{input$y} combined, and the value is \code{input$x * input$y}. In this simple
example, for any given key, there is only one possible returned value.
\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- reactive(\{ input$x * input$y \}) \%>\%
example, for any given key, there is only one possible returned value.\if{html}{\out{<div class="NA">}}\preformatted{r <- reactive(\{ input$x * input$y \}) \%>\%
bindCache(input$x, input$y)
}\if{html}{\out{</div>}}
@@ -65,9 +63,7 @@ to do some sort of reduction on the data that still captures information
about whether a value can be retrieved from the cache. For example, if you
have a large data set with timestamps, it might make sense to extract the
most recent timestamp and return that. Then, instead of hashing the entire
data object, the cached reactive only needs to hash the timestamp.
\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- reactive(\{ compute(bigdata()) \} \%>\%
data object, the cached reactive only needs to hash the timestamp.\if{html}{\out{<div class="NA">}}\preformatted{r <- reactive(\{ compute(bigdata()) \} \%>\%
bindCache(\{ extract_most_recent_time(bigdata()) \})
}\if{html}{\out{</div>}}
@@ -109,9 +105,7 @@ cache key is not too expensive.
Remember that the key is \emph{reactive}, so it is not re-executed every single
time that someone accesses the cached reactive. It is only re-executed if
it has been invalidated by one of the reactives it depends on. For
example, suppose we have this cached reactive:
\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- reactive(\{ input$x * input$y \}) \%>\%
example, suppose we have this cached reactive:\if{html}{\out{<div class="NA">}}\preformatted{r <- reactive(\{ input$x * input$y \}) \%>\%
bindCache(input$x, input$y)
}\if{html}{\out{</div>}}
@@ -160,30 +154,24 @@ persists beyond the current R session.
To use different settings for an application-scoped cache, you can call
\code{\link[=shinyOptions]{shinyOptions()}} at the top of your app.R, server.R, or
global.R. For example, this will create a cache with 500 MB of space
instead of the default 200 MB:
\if{html}{\out{<div class="sourceCode">}}\preformatted{shinyOptions(cache = cachem::cache_mem(max_size = 500e6))
}\if{html}{\out{</div>}}
instead of the default 200 MB:\preformatted{shinyOptions(cache = cachem::cache_mem(max_size = 500e6))
}
To use different settings for a session-scoped cache, you can set
\code{self$cache} at the top of your server function. By default, it will create
a 200 MB memory cache for each session, but you can replace it with
something different. To use the session-scoped cache, you must also call
\code{bindCache()} with \code{cache="session"}. This will create a 100 MB cache for
the session:
\if{html}{\out{<div class="sourceCode">}}\preformatted{function(input, output, session) \{
the session:\preformatted{function(input, output, session) \{
session$cache <- cachem::cache_mem(max_size = 100e6)
...
\}
}\if{html}{\out{</div>}}
}
If you want to use a cache that is shared across multiple R processes, you
can use a \code{\link[cachem:cache_disk]{cachem::cache_disk()}}. You can create a application-level shared
cache by putting this at the top of your app.R, server.R, or global.R:
\if{html}{\out{<div class="sourceCode">}}\preformatted{shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache"))
}\if{html}{\out{</div>}}
cache by putting this at the top of your app.R, server.R, or global.R:\preformatted{shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache"))
}
This will create a subdirectory in your system temp directory named
\code{myapp-cache} (replace \code{myapp-cache} with a unique name of
@@ -193,10 +181,8 @@ stops of the R process, as long as you do not reboot.
To have the cache persist even across multiple reboots, you can create the
cache in a location outside of the temp directory. For example, it could
be a subdirectory of the application:
\if{html}{\out{<div class="sourceCode">}}\preformatted{shinyOptions(cache = cachem::cache_disk("./myapp-cache"))
}\if{html}{\out{</div>}}
be a subdirectory of the application:\preformatted{shinyOptions(cache = cachem::cache_disk("./myapp-cache"))
}
In this case, resetting the cache will have to be done manually, by deleting
the directory.
@@ -258,14 +244,12 @@ cache collisions, dealing with internal state that may be set by the,
the cache.
You may need to provide a \code{cacheHint} to \code{\link[=createRenderFunction]{createRenderFunction()}} (or
\code{htmlwidgets::shinyRenderWidget()}, if you've authored an htmlwidget) in
\code{\link[htmlwidgets:htmlwidgets-shiny]{htmlwidgets::shinyRenderWidget()}}, if you've authored an htmlwidget) in
order for \code{bindCache()} to correctly compute a cache key.
The potential problem is a cache collision. Consider the following:
\if{html}{\out{<div class="sourceCode">}}\preformatted{output$x1 <- renderText(\{ input$x \}) \%>\% bindCache(input$x)
The potential problem is a cache collision. Consider the following:\preformatted{output$x1 <- renderText(\{ input$x \}) \%>\% bindCache(input$x)
output$x2 <- renderText(\{ input$x * 2 \}) \%>\% bindCache(input$x)
}\if{html}{\out{</div>}}
}
Both \code{output$x1} and \code{output$x2} use \code{input$x} as part of their cache key,
but if it were the only thing used in the cache key, then the two outputs
@@ -274,9 +258,7 @@ this, a \emph{cache hint} is automatically added when \code{\link[=renderText]{r
\code{\link[=createRenderFunction]{createRenderFunction()}}. The cache hint is used as part of the actual
cache key, in addition to the one passed to \code{bindCache()} by the user. The
cache hint can be viewed by calling the internal Shiny function
\code{extractCacheHint()}:
\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- renderText(\{ input$x \})
\code{extractCacheHint()}:\if{html}{\out{<div class="NA">}}\preformatted{r <- renderText(\{ input$x \})
shiny:::extractCacheHint(r)
}\if{html}{\out{</div>}}
@@ -307,9 +289,7 @@ that may influence the final value.
For \pkg{htmlwidgets}, it will try to automatically infer a cache hint;
again, you can inspect the cache hint with \code{shiny:::extractCacheHint()} and
also test it in an application. If you do need to explicitly provide a
cache hint, pass it to \code{shinyRenderWidget}. For example:
\if{html}{\out{<div class="sourceCode">}}\preformatted{renderMyWidget <- function(expr) \{
cache hint, pass it to \code{shinyRenderWidget}. For example:\preformatted{renderMyWidget <- function(expr) \{
q <- rlang::enquo0(expr)
htmlwidgets::shinyRenderWidget(
@@ -319,7 +299,7 @@ cache hint, pass it to \code{shinyRenderWidget}. For example:
cacheHint = list(label = "myWidget", userQuo = q)
)
\}
}\if{html}{\out{</div>}}
}
If your \code{render} function sets any internal state, you may find it useful
in your call to \code{\link[=createRenderFunction]{createRenderFunction()}} to use
@@ -350,10 +330,8 @@ For developers of such code, they should call \code{\link[=createRenderFunction]
When \code{bindCache()} is used with \code{renderPlot()}, the \code{height} and \code{width}
passed to the original \code{renderPlot()} are ignored. They are superseded by
\code{sizePolicy} argument passed to `bindCache. The default is:
\if{html}{\out{<div class="sourceCode">}}\preformatted{sizePolicy = sizeGrowthRatio(width = 400, height = 400, growthRate = 1.2)
}\if{html}{\out{</div>}}
\code{sizePolicy} argument passed to `bindCache. The default is:\preformatted{sizePolicy = sizeGrowthRatio(width = 400, height = 400, growthRate = 1.2)
}
\code{sizePolicy} must be a function that takes a two-element numeric vector as
input, representing the width and height of the \verb{<img>} element in the

View File

@@ -171,9 +171,7 @@ user sets both \code{x} and \code{y}, and then clicks on an \link{actionButton}
\code{go}.
To use both caching and events, the object should first be passed to
\code{bindCache()}, then \code{bindEvent()}. For example:
\if{html}{\out{<div class="sourceCode NA">}}\preformatted{r <- reactive(\{
\code{bindCache()}, then \code{bindEvent()}. For example:\if{html}{\out{<div class="NA">}}\preformatted{r <- reactive(\{
Sys.sleep(2) # Pretend this is an expensive computation
input$x * input$y
\}) \%>\%

View File

@@ -28,7 +28,7 @@ This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="
The default (NULL) results in an empty string.}
}
\value{
A UI definition that can be passed to the \link{shinyUI} function.
A UI defintion that can be passed to the \link{shinyUI} function.
}
\description{
Create a Shiny UI page that loads the CSS and JavaScript for

View File

@@ -101,9 +101,7 @@ displays a message once every 8 hrs (by default)
value and Developer message. This registration method allows package
authors to write one message in a single location.
For example, the following Shiny Developer Mode options are registered:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{# Reload the Shiny app when a sourced R file changes
For example, the following Shiny Developer Mode options are registered:\if{html}{\out{<div class="r">}}\preformatted{# Reload the Shiny app when a sourced R file changes
register_devmode_option(
"shiny.autoreload",
"Turning on shiny autoreload. To disable, call `options(shiny.autoreload = FALSE)`",
@@ -128,9 +126,7 @@ register_devmode_option(
Other known, non-Shiny Developer Mode options:
\itemize{
\item Sass:
}
\if{html}{\out{<div class="sourceCode r">}}\preformatted{# Display the full stack trace when errors occur during Shiny app execution
}\if{html}{\out{<div class="r">}}\preformatted{# Display the full stack trace when errors occur during Shiny app execution
register_devmode_option(
"sass.cache",
"Turning off sass cache. To use default caching, call `options(sass.cache = TRUE)`",
@@ -169,9 +165,7 @@ re-implementing these two functions:
This function should return \code{TRUE} if \code{getOption("shiny.devmode")} is set.
In addition, we strongly recommend that it also checks to make sure
\code{testthat} is not testing.
\if{html}{\out{<div class="sourceCode r">}}\preformatted{in_devmode <- function() \{
\code{testthat} is not testing.\if{html}{\out{<div class="r">}}\preformatted{in_devmode <- function() \{
isTRUE(getOption("shiny.devmode", FALSE)) &&
!identical(Sys.getenv("TESTTHAT"), "true")
\}
@@ -207,9 +201,7 @@ recommend displaying a message (\code{devmode_message}) to \code{stderr()} once
hours using \code{\link[rlang:abort]{rlang::inform()}}. This will keep the author up to date as to
which Dev Mode options are being altered. To allow developers a chance to
disable Dev Mode messages, the message should be skipped if
\code{getOption("shiny.devmode.verbose", TRUE)} is not \code{TRUE}.
\if{html}{\out{<div class="sourceCode r">}}\preformatted{get_devmode_option <- function(name, default = NULL, devmode_default, devmode_message) \{
\code{getOption("shiny.devmode.verbose", TRUE)} is not \code{TRUE}.\if{html}{\out{<div class="r">}}\preformatted{get_devmode_option <- function(name, default = NULL, devmode_default, devmode_message) \{
if (!in_devmode()) \{
# Dev Mode disabled, act like `getOption()`
return(getOption(name, default = default))

View File

@@ -40,7 +40,7 @@ deleted from disk. If \code{FALSE} (the default), it will do nothing when
finalized.}
\item{missing}{A value to return when \code{get(key)} is called but the key is not
present in the cache. The default is a \code{\link[cachem:key_missing]{key_missing()}} object. It is
present in the cache. The default is a \code{\link[cachem:reexports]{key_missing()}} object. It is
actually an expression that is evaluated each time there is a cache miss.
See section Missing keys for more information.}

View File

@@ -4,7 +4,7 @@
\alias{downloadHandler}
\title{File Downloads}
\usage{
downloadHandler(filename, content, contentType = NULL, outputArgs = list())
downloadHandler(filename, content, contentType = NA, outputArgs = list())
}
\arguments{
\item{filename}{A string of the filename, including extension, that the
@@ -19,9 +19,9 @@ function.)}
\item{contentType}{A string of the download's
\href{https://en.wikipedia.org/wiki/Internet_media_type}{content type}, for
example \code{"text/csv"} or \code{"image/png"}. If \code{NULL}, the content type
will be guessed based on the filename extension, or
\code{application/octet-stream} if the extension is unknown.}
example \code{"text/csv"} or \code{"image/png"}. If \code{NULL} or
\code{NA}, the content type will be guessed based on the filename
extension, or \code{application/octet-stream} if the extension is unknown.}
\item{outputArgs}{A list of arguments to be passed through to the implicit
call to \code{\link[=downloadButton]{downloadButton()}} when \code{downloadHandler} is used

View File

@@ -11,8 +11,7 @@ fileInput(
accept = NULL,
width = NULL,
buttonLabel = "Browse...",
placeholder = "No file selected",
capture = NULL
placeholder = "No file selected"
)
}
\arguments{
@@ -43,19 +42,6 @@ see \code{\link[=validateCssUnit]{validateCssUnit()}}.}
object.}
\item{placeholder}{The text to show before a file has been uploaded.}
\item{capture}{What source to use for capturing image, audio or video data.
This attribute facilitates user access to a device's media capture
mechanism, such as a camera, or microphone, from within a file upload
control.
A value of \code{user} indicates that the user-facing camera and/or microphone
should be used. A value of \code{environment} specifies that the outward-facing
camera and/or microphone should be used.
By default on most phones, this will accept still photos or video. For
still photos only, also use \code{accept="image/*"}. For video only, use
\code{accept="video/*"}.}
}
\description{
Create a file upload control that can be used to upload one or more files.

View File

@@ -28,7 +28,7 @@ This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="
The default (NULL) results in an empty string.}
}
\value{
A UI definition that can be passed to the \link{shinyUI} function.
A UI defintion that can be passed to the \link{shinyUI} function.
}
\description{
Functions for creating fixed page layouts. A fixed page layout consists of

View File

@@ -29,7 +29,7 @@ This will be used as the lang in the \code{<html>} tag, as in \code{<html lang="
The default (NULL) results in an empty string.}
}
\value{
A UI definition that can be passed to the \link{shinyUI} function.
A UI defintion that can be passed to the \link{shinyUI} function.
}
\description{
Functions for creating fluid page layouts. A fluid page layout consists of

View File

@@ -15,7 +15,7 @@ loadSupport(
not supplied, the nearest enclosing directory that is a Shiny app, starting
with the current directory, is used.}
\item{renv}{The environment in which the files in the \verb{R/} directory should
\item{renv}{The environmeny in which the files in the \verb{R/} directory should
be evaluated.}
\item{globalrenv}{The environment in which \code{global.R} should be evaluated. If

View File

@@ -30,7 +30,7 @@ value of \code{evict}. Use \code{Inf} for no limit of number of items.}
when a cache pruning occurs. Currently, \code{"lru"} and \code{"fifo"} are supported.}
\item{missing}{A value to return when \code{get(key)} is called but the key is not
present in the cache. The default is a \code{\link[cachem:key_missing]{key_missing()}} object. It is
present in the cache. The default is a \code{\link[cachem:reexports]{key_missing()}} object. It is
actually an expression that is evaluated each time there is a cache miss.
See section Missing keys for more information.}

View File

@@ -89,7 +89,7 @@ is needed if you want to insert/remove or show/hide an entire
\item{icon}{Optional icon to appear on a \code{navbarMenu} tab.}
}
\value{
A UI definition that can be passed to the \link{shinyUI} function.
A UI defintion that can be passed to the \link{shinyUI} function.
}
\description{
Create a page that contains a top level navigation bar that can be used to

View File

@@ -14,7 +14,7 @@ pageWithSidebar(headerPanel, sidebarPanel, mainPanel)
\item{mainPanel}{The \link{mainPanel} containing outputs}
}
\value{
A UI definition that can be passed to the \link{shinyUI} function
A UI defintion that can be passed to the \link{shinyUI} function
}
\description{
\strong{DEPRECATED}: use \code{\link[=fluidPage]{fluidPage()}} and \code{\link[=sidebarLayout]{sidebarLayout()}} instead.

View File

@@ -2,7 +2,7 @@
% Please edit documentation in R/imageutils.R
\name{plotPNG}
\alias{plotPNG}
\title{Capture a plot as a PNG file.}
\title{Run a plotting function and save the output as a PNG}
\usage{
plotPNG(
func,
@@ -23,26 +23,27 @@ extension \code{.png}.}
\item{height}{Height in pixels.}
\item{res}{Resolution in pixels per inch. This value is passed to the
graphics device. Note that this affects the resolution of PNG rendering in
\item{res}{Resolution in pixels per inch. This value is passed to
\code{\link[grDevices:png]{grDevices::png()}}. Note that this affects the resolution of PNG rendering in
R; it won't change the actual ppi of the browser.}
\item{...}{Arguments to be passed through to the graphics device. These can
be used to set the width, height, background color, etc.}
}
\value{
A path to the newly generated PNG file.
\item{...}{Arguments to be passed through to \code{\link[grDevices:png]{grDevices::png()}}.
These can be used to set the width, height, background color, etc.}
}
\description{
The PNG graphics device used is determined in the following order:
\itemize{
\item If the ragg package is installed (and the \code{shiny.useragg} is not
set to \code{FALSE}), then use \code{\link[ragg:agg_png]{ragg::agg_png()}}.
\item If a quartz device is available (i.e., \code{capabilities("aqua")} is
\code{TRUE}), then use \code{png(type = "quartz")}.
\item If the Cairo package is installed (and the \code{shiny.usecairo} option
is not set to \code{FALSE}), then use \code{\link[Cairo:Cairo]{Cairo::CairoPNG()}}.
\item Otherwise, use \code{\link[grDevices:png]{grDevices::png()}}. In this case, Linux and Windows
may not antialias some point shapes, resulting in poor quality output.
This function returns the name of the PNG file that it generates. In
essence, it calls \code{png()}, then \code{func()}, then \code{dev.off()}.
So \code{func} must be a function that will generate a plot when used this
way.
}
\details{
For output, it will try to use the following devices, in this order:
quartz (via \code{\link[grDevices:png]{grDevices::png()}}), then \code{\link[Cairo:Cairo]{Cairo::CairoPNG()}},
and finally \code{\link[grDevices:png]{grDevices::png()}}. This is in order of quality of
output. Notably, plain \code{png} output on Linux and Windows may not
antialias some point shapes, resulting in poor quality output.
In some cases, \code{Cairo()} provides output that looks worse than
\code{png()}. To disable Cairo output for an app, use
\code{options(shiny.usecairo=FALSE)}.
}

View File

@@ -52,6 +52,6 @@ below to see their documentation.
\describe{
\item{fastmap}{\code{\link[fastmap:key_missing]{is.key_missing}}, \code{\link[fastmap]{key_missing}}}
\item{htmltools}{\code{\link[htmltools:builder]{a}}, \code{\link[htmltools:builder]{br}}, \code{\link[htmltools:builder]{code}}, \code{\link[htmltools:builder]{div}}, \code{\link[htmltools:builder]{em}}, \code{\link[htmltools:builder]{h1}}, \code{\link[htmltools:builder]{h2}}, \code{\link[htmltools:builder]{h3}}, \code{\link[htmltools:builder]{h4}}, \code{\link[htmltools:builder]{h5}}, \code{\link[htmltools:builder]{h6}}, \code{\link[htmltools:builder]{hr}}, \code{\link[htmltools]{HTML}}, \code{\link[htmltools]{htmlTemplate}}, \code{\link[htmltools:builder]{img}}, \code{\link[htmltools:include]{includeCSS}}, \code{\link[htmltools:include]{includeHTML}}, \code{\link[htmltools:include]{includeMarkdown}}, \code{\link[htmltools:include]{includeScript}}, \code{\link[htmltools:include]{includeText}}, \code{\link[htmltools:singleton]{is.singleton}}, \code{\link[htmltools:builder]{p}}, \code{\link[htmltools:builder]{pre}}, \code{\link[htmltools]{singleton}}, \code{\link[htmltools:builder]{span}}, \code{\link[htmltools:builder]{strong}}, \code{\link[htmltools]{suppressDependencies}}, \code{\link[htmltools:builder]{tag}}, \code{\link[htmltools]{tagAppendAttributes}}, \code{\link[htmltools]{tagAppendChild}}, \code{\link[htmltools:tagAppendChild]{tagAppendChildren}}, \code{\link[htmltools:tagAppendAttributes]{tagGetAttribute}}, \code{\link[htmltools:tagAppendAttributes]{tagHasAttribute}}, \code{\link[htmltools]{tagList}}, \code{\link[htmltools:builder]{tags}}, \code{\link[htmltools:tagAppendChild]{tagSetChildren}}, \code{\link[htmltools]{validateCssUnit}}, \code{\link[htmltools]{withTags}}}
\item{htmltools}{\code{\link[htmltools]{HTML}}, \code{\link[htmltools:builder]{a}}, \code{\link[htmltools:builder]{br}}, \code{\link[htmltools:builder]{code}}, \code{\link[htmltools:builder]{div}}, \code{\link[htmltools:builder]{em}}, \code{\link[htmltools:builder]{h1}}, \code{\link[htmltools:builder]{h2}}, \code{\link[htmltools:builder]{h3}}, \code{\link[htmltools:builder]{h4}}, \code{\link[htmltools:builder]{h5}}, \code{\link[htmltools:builder]{h6}}, \code{\link[htmltools:builder]{hr}}, \code{\link[htmltools]{htmlTemplate}}, \code{\link[htmltools:builder]{img}}, \code{\link[htmltools:include]{includeCSS}}, \code{\link[htmltools:include]{includeHTML}}, \code{\link[htmltools:include]{includeMarkdown}}, \code{\link[htmltools:include]{includeScript}}, \code{\link[htmltools:include]{includeText}}, \code{\link[htmltools:singleton]{is.singleton}}, \code{\link[htmltools:builder]{p}}, \code{\link[htmltools:builder]{pre}}, \code{\link[htmltools]{singleton}}, \code{\link[htmltools:builder]{span}}, \code{\link[htmltools:builder]{strong}}, \code{\link[htmltools]{suppressDependencies}}, \code{\link[htmltools:builder]{tag}}, \code{\link[htmltools]{tagAppendAttributes}}, \code{\link[htmltools]{tagAppendChild}}, \code{\link[htmltools:tagAppendChild]{tagAppendChildren}}, \code{\link[htmltools:tagAppendAttributes]{tagGetAttribute}}, \code{\link[htmltools:tagAppendAttributes]{tagHasAttribute}}, \code{\link[htmltools]{tagList}}, \code{\link[htmltools:tagAppendChild]{tagSetChildren}}, \code{\link[htmltools:builder]{tags}}, \code{\link[htmltools]{validateCssUnit}}, \code{\link[htmltools]{withTags}}}
}}

View File

@@ -51,9 +51,9 @@ registerInputHandler("mypackage.validint", function(x, shinysession, name) {
})
## On the Javascript side, the associated input binding must have a corresponding getType method:
# getType: function(el) {
# return "mypackage.validint";
# }
getType: function(el) {
return "mypackage.validint";
}
}
}

View File

@@ -37,7 +37,7 @@ information on the default sizing policy.}
(the default), \code{"session"}, or a cache object like a
\code{\link[cachem:cache_disk]{cachem::cache_disk()}}. See the Cache Scoping section for more information.}
\item{...}{Arguments to be passed through to \code{\link[=plotPNG]{plotPNG()}}.
\item{...}{Arguments to be passed through to \code{\link[grDevices:png]{grDevices::png()}}.
These can be used to set the width, height, background color, etc.}
\item{alt}{Alternate text for the HTML \verb{<img>} tag if it cannot be displayed
@@ -219,7 +219,7 @@ shinyOptions(cache = cachem::cache_mem(max_size = 20e6, max_age = 3600))
# At the top of app.R, this set the application-scoped cache to be a disk
# cache that can be shared among multiple concurrent R processes, and is
# deleted when the system reboots.
shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache")))
shinyOptions(cache = cachem::cache_disk(file.path(dirname(tempdir()), "myapp-cache"))
# At the top of app.R, this set the application-scoped cache to be a disk
# cache that can be shared among multiple concurrent R processes, and

View File

@@ -63,9 +63,7 @@ call to \code{dataTableOutput()} when \code{renderDataTable()} is used
in an interactive R Markdown document.}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} Please use
\href{https://rstudio.github.io/DT/shiny.html}{\code{DT::renderDataTable()}}.
(Shiny 0.11.1)
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} Please use \code{\link[DT:renderDataTable]{DT::renderDataTable()}}. (Shiny 0.11.1)
Makes a reactive version of the given function that returns a data frame (or
matrix), which will be rendered with the \href{https://datatables.net}{DataTables}

View File

@@ -35,10 +35,10 @@ When rendering an inline plot, you must provide numeric values (in pixels)
to both \code{width} and \code{height}.}
\item{res}{Resolution of resulting plot, in pixels per inch. This value is
passed to \code{\link[=plotPNG]{plotPNG()}}. Note that this affects the resolution of PNG
passed to \code{\link[grDevices:png]{grDevices::png()}}. Note that this affects the resolution of PNG
rendering in R; it won't change the actual ppi of the browser.}
\item{...}{Arguments to be passed through to \code{\link[=plotPNG]{plotPNG()}}.
\item{...}{Arguments to be passed through to \code{\link[grDevices:png]{grDevices::png()}}.
These can be used to set the width, height, background color, etc.}
\item{alt}{Alternate text for the HTML \verb{<img>} tag if it cannot be displayed

View File

@@ -25,30 +25,26 @@ nor displayed in the Shiny app's UI).
\details{
The \code{req} function was designed to be used in one of two ways. The first
is to call it like a statement (ignoring its return value) before attempting
operations using the required values:
\if{html}{\out{<div class="sourceCode">}}\preformatted{rv <- reactiveValues(state = FALSE)
operations using the required values:\preformatted{rv <- reactiveValues(state = FALSE)
r <- reactive(\{
req(input$a, input$b, rv$state)
# Code that uses input$a, input$b, and/or rv$state...
\})
}\if{html}{\out{</div>}}
}
In this example, if \code{r()} is called and any of \code{input$a},
\code{input$b}, and \code{rv$state} are \code{NULL}, \code{FALSE}, \code{""},
etc., then the \code{req} call will trigger an error that propagates all the
way up to whatever render block or observer is executing.
The second is to use it to wrap an expression that must be truthy:
\if{html}{\out{<div class="sourceCode">}}\preformatted{output$plot <- renderPlot(\{
The second is to use it to wrap an expression that must be truthy:\preformatted{output$plot <- renderPlot(\{
if (req(input$plotType) == "histogram") \{
hist(dataset())
\} else if (input$plotType == "scatter") \{
qplot(dataset(), aes(x = x, y = y))
\}
\})
}\if{html}{\out{</div>}}
}
In this example, \code{req(input$plotType)} first checks that
\code{input$plotType} is truthy, and if so, returns it. This is a convenient

View File

@@ -37,7 +37,7 @@ ports will be tried.}
\item{launch.browser}{If true, the system's default web browser will be
launched automatically after the app is started. Defaults to true in
interactive sessions only. The value of this parameter can also be a
interactive sessions only. This value of this parameter can also be a
function to call with the application's URL.}
\item{host}{The IPv4 address that the application should listen on. Defaults

View File

@@ -13,7 +13,7 @@ runGist(gist, destdir = NULL, ...)
runGitHub(
repo,
username = getOption("github.user"),
ref = "HEAD",
ref = "master",
subdir = NULL,
destdir = NULL,
...
@@ -47,8 +47,7 @@ all valid values.}
\code{"username/repo"}, \code{username} will be taken from \code{repo}.}
\item{ref}{Desired git reference. Could be a commit, tag, or branch name.
Defaults to \code{"HEAD"}, which means the default branch on GitHub, typically
\code{"main"} or \code{"master"}.}
Defaults to \code{"master"}.}
}
\description{
\code{runUrl()} downloads and launches a Shiny application that is hosted at
@@ -63,10 +62,10 @@ respectively.
\examples{
## Only run this example in interactive R sessions
if (interactive()) {
runUrl('https://github.com/rstudio/shiny_example/archive/main.tar.gz')
runUrl('https://github.com/rstudio/shiny_example/archive/master.tar.gz')
# Can run an app from a subdirectory in the archive
runUrl("https://github.com/rstudio/shiny_example/archive/main.zip",
runUrl("https://github.com/rstudio/shiny_example/archive/master.zip",
subdir = "inst/shinyapp/")
}
## Only run this example in interactive R sessions

View File

@@ -10,7 +10,7 @@ shinyAppTemplate(path = NULL, examples = "default", dryrun = FALSE)
\item{path}{Path to create new shiny application template.}
\item{examples}{Either one of "default", "ask", "all", or any combination of
"app", "rdir", "module", and "tests". In an
"app", "rdir", "module", "shinytest", and "testthat". In an
interactive session, "default" falls back to "ask"; in a non-interactive
session, "default" falls back to "all". With "ask", this function will
prompt the user to select which template items will be added to the new app
@@ -25,31 +25,30 @@ This function populates a directory with files for a Shiny application.
}
\details{
In an interactive R session, this function will, by default, prompt the user
to select which components to add to the application. Choices are
\if{html}{\out{<div class="sourceCode">}}\preformatted{1: All
to select which components to add to the application. Choices are\preformatted{1: All
2: app.R : Main application file
3: R/example.R : Helper file with R code
4: R/example-module.R : Example module
5: tests/testthat/ : Tests using the testthat and shinytest2 package
}\if{html}{\out{</div>}}
5: tests/shinytest/ : Tests using the shinytest package
6: tests/testthat/ : Tests using the testthat package
}
If option 1 is selected, the full example application including the
following files and directories is created:
\if{html}{\out{<div class="sourceCode">}}\preformatted{appdir/
following files and directories is created:\preformatted{appdir/
|- app.R
|- R
| |- example-module.R
| `- example.R
`- tests
|- shinytest.R
|- shinytest
| `- mytest.R
|- testthat.R
`- testthat
|- test-examplemodule.R
|- test-server.R
|- test-shinytest2.R
`- test-sort.R
}\if{html}{\out{</div>}}
}
Some notes about these files:
\itemize{
@@ -63,15 +62,15 @@ and the second contains code for module created by the
\item \verb{tests/} contains various tests for the application. You may
choose to use or remove any of them. They can be executed by the
\code{\link[=runTests]{runTests()}} function.
\item \code{tests/shinytest.R} is a test runner for test files in the
\verb{tests/shinytest/} directory.
\item \code{tests/shinytest/mytest.R} is a test that uses the
\href{https://rstudio.github.io/shinytest/}{shinytest} package to do
snapshot-based testing.
\item \code{tests/testthat.R} is a test runner for test files in the
\verb{tests/testthat/} directory using the
\href{https://rstudio.github.io/shinytest2/reference/test_app.html}{shinytest2}
package.
\verb{tests/testthat/} directory using the \href{https://testthat.r-lib.org/}{testthat} package.
\item \code{tests/testthat/test-examplemodule.R} is a test for an application's module server function.
\item \code{tests/testthat/test-server.R} is a test for the application's server code
\item \code{tests/testthat/test-shinytest2.R} is a test that uses the
\href{https://rstudio.github.io/shinytest2/}{shinytest2} package to do
snapshot-based testing.
\item \code{tests/testthat/test-sort.R} is a test for a supporting function in the \verb{R/} directory.
}
}

View File

@@ -73,10 +73,6 @@ then jQuery 3.6.0 is used.}
numbers to JSON format to send to the client web browser.}
\item{shiny.launch.browser (defaults to \code{interactive()})}{A boolean which controls the default behavior
when an app is run. See \code{\link[=runApp]{runApp()}} for more information.}
\item{shiny.mathjax.url (defaults to \code{"https://mathjax.rstudio.com/latest/MathJax.js"})}{
The URL that should be used to load MathJax, via \code{\link[=withMathJax]{withMathJax()}}.}
\item{shiny.mathjax.config (defaults to \code{"config=TeX-AMS-MML_HTMLorMML"})}{The querystring
used to load MathJax, via \code{\link[=withMathJax]{withMathJax()}}.}
\item{shiny.maxRequestSize (defaults to 5MB)}{This is a number which specifies the maximum
web request size, which serves as a size limit for file uploads.}
\item{shiny.minified (defaults to \code{TRUE})}{By default
@@ -108,9 +104,6 @@ should only be used for debugging or demonstrations of reactivity at the
console.}
\item{shiny.testmode (defaults to \code{FALSE})}{If \code{TRUE}, then various features for testing Shiny
applications are enabled.}
\item{shiny.snapshotsortc (defaults to \code{FALSE})}{If \code{TRUE}, test snapshot keys
for \pkg{shinytest} will be sorted consistently using the C locale. Snapshots
retrieved by \pkg{shinytest2} will always sort using the C locale.}
\item{shiny.trace (defaults to \code{FALSE})}{Print messages sent between the R server and the web
browser client to the R console. This is useful for debugging. Possible
values are \code{"send"} (only print messages sent to the client),
@@ -119,10 +112,9 @@ values are \code{"send"} (only print messages sent to the client),
messages).}
\item{shiny.autoload.r (defaults to \code{TRUE})}{If \code{TRUE}, then the R/
of a shiny app will automatically be sourced.}
\item{shiny.useragg (defaults to \code{TRUE})}{Set to \code{FALSE} to prevent PNG rendering via the
ragg package. See \code{\link[=plotPNG]{plotPNG()}} for more information.}
\item{shiny.usecairo (defaults to \code{TRUE})}{Set to \code{FALSE} to prevent PNG rendering via the
Cairo package. See \code{\link[=plotPNG]{plotPNG()}} for more information.}
\item{shiny.usecairo (defaults to \code{TRUE})}{This is used to disable graphical rendering by the
Cairo package, if it is installed. See \code{\link[=plotPNG]{plotPNG()}} for more
information.}
\item{shiny.devmode (defaults to \code{NULL})}{Option to enable Shiny Developer Mode. When set,
different default \code{getOption(key)} values will be returned. See \code{\link[=devmode]{devmode()}} for more details.}
}

View File

@@ -33,7 +33,17 @@ types (such as logicals and numbers) will be coerced to strings.}
\item{inline}{If \code{TRUE}, render the choices inline (i.e. horizontally)}
\item{choiceNames, choiceValues}{List of names and values, respectively,
\item{choiceNames}{List of names and values, respectively,
that are displayed to the user in the app and correspond to the each
choice (for this reason, \code{choiceNames} and \code{choiceValues}
must have the same length). If either of these arguments is
provided, then the other \emph{must} be provided and \code{choices}
\emph{must not} be provided. The advantage of using both of these over
a named list for \code{choices} is that \code{choiceNames} allows any
type of UI object to be passed through (tag objects, icons, HTML code,
...), instead of just simple text. See Examples.}
\item{choiceValues}{List of names and values, respectively,
that are displayed to the user in the app and correspond to the each
choice (for this reason, \code{choiceNames} and \code{choiceValues}
must have the same length). If either of these arguments is

View File

@@ -35,7 +35,16 @@ use \code{character(0)}.}
\item{inline}{If \code{TRUE}, render the choices inline (i.e. horizontally)}
\item{choiceNames, choiceValues}{List of names and values, respectively, that
\item{choiceNames}{List of names and values, respectively, that
are displayed to the user in the app and correspond to the each choice (for
this reason, \code{choiceNames} and \code{choiceValues} must have the same length).
If either of these arguments is provided, then the other \emph{must} be provided
and \code{choices} \emph{must not} be provided. The advantage of using both of these
over a named list for \code{choices} is that \code{choiceNames} allows any type of UI
object to be passed through (tag objects, icons, HTML code, ...), instead
of just simple text. See Examples.}
\item{choiceValues}{List of names and values, respectively, that
are displayed to the user in the app and correspond to the each choice (for
this reason, \code{choiceNames} and \code{choiceValues} must have the same length).
If either of these arguments is provided, then the other \emph{must} be provided

View File

@@ -29,7 +29,10 @@ updateSliderInput(
create a regular slider; a length two vector will create a double-ended
range slider. Must lie between \code{min} and \code{max}.}
\item{min, max}{The minimum and maximum values (inclusive) that can be
\item{min}{The minimum and maximum values (inclusive) that can be
selected.}
\item{max}{The minimum and maximum values (inclusive) that can be
selected.}
\item{step}{Specifies the interval between each selectable value on the

View File

@@ -55,12 +55,10 @@ can create your own validation test functions. A passing test should return
to display to the user, or if the failure should happen silently, \code{FALSE}.
Alternatively you can use \code{validate()} within an \code{if} statement, which is
particularly useful for more complex conditions:
\if{html}{\out{<div class="sourceCode">}}\preformatted{if (input$x < 0 && input$choice == "positive") \{
particularly useful for more complex conditions:\preformatted{if (input$x < 0 && input$choice == "positive") \{
validate("If choice is positive then x must be greater than 0")
\}
}\if{html}{\out{</div>}}
}
}
\examples{

View File

@@ -76,10 +76,10 @@ value when it is a single choice input and the empty string is not in the
The resulting server \code{input} value will be returned as:
\itemize{
\item A symbol if \code{multiple = FALSE}. The \code{input} value should be
used with rlang's \code{\link[rlang:injection-operator]{rlang::!!()}}. For example,
used with rlang's \code{\link[rlang:bang-bang]{rlang::!!()}}. For example,
\code{ggplot2::aes(!!input$variable)}.
\item A list of symbols if \code{multiple = TRUE}. The \code{input} value
should be used with rlang's \code{\link[rlang:splice-operator]{rlang::!!!()}} to expand
should be used with rlang's \code{\link[rlang:bang-bang]{rlang::!!!()}} to expand
the symbol list as individual arguments. For example,
\code{dplyr::select(mtcars, !!!input$variabls)} which is
equivalent to \code{dplyr::select(mtcars, !!input$variabls[[1]], !!input$variabls[[2]], ..., !!input$variabls[[length(input$variabls)]])}.

View File

@@ -3,7 +3,7 @@
"homepage": "https://shiny.rstudio.com",
"repository": "github:rstudio/shiny",
"name": "@types/rstudio-shiny",
"version": "1.7.1-alpha.9003",
"version": "1.6.0-alpha.9022",
"license": "GPL-3.0-only",
"main": "",
"browser": "",
@@ -46,8 +46,7 @@
"@typescript-eslint/parser": "^4.25.0",
"autoprefixer": "^10.2.6",
"bootstrap-datepicker": "1.9.0",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001312",
"browserslist": "^4.16.6",
"core-js": "^3.13.0",
"esbuild": "^0.12.4",
"esbuild-plugin-babel": "https://github.com/schloerke/esbuild-plugin-babel#patch-2",

View File

@@ -8,7 +8,7 @@ yarn add https://github.com/rstudio/shiny\#v1.7.0
, matching the GitHub tag to your current the Shiny CRAN release (ex: `v1.7.0`). If you are asked to select a version of `@types/jquery`, please select the closest matching version.
This will provide a global type definition of `Shiny`, let your IDE know that `window.Shiny` is of type `Shiny`, and declare a globally available variable `Shiny` within your project. You **should not** need to import anything. Similar to `jQuery`, it should _Just Work_<sup>TM</sup>.
This will provide a global type defintion of `Shiny`, let your IDE know that `window.Shiny` is of type `Shiny`, and declare a globally available variable `Shiny` within your project. You **should not** need to import anything. Similar to `jQuery`, it should _Just Work_<sup>TM</sup>.
When loading your compiled file, it should be loaded after `shiny.js` is loaded. If you are using an `htmlDependency()` to add your code to the page, your script will automatically be loaded after has been loaded.
@@ -192,11 +192,11 @@ Both JavaScript files will produce a sourcemap (`**.js.map`) that the browser wi
### Exported types
`./extras/globalShiny.ts` contains global declarations to define `window.Shiny`, a globally available `Shiny` variable, and a globally available `Shiny` type. This file is in a parallel folder to `./src` to avoid `Shiny` from being globally accessable within the source code. However, this file is the default type definition when the Type definitions are installed by external developers.
`./extras/globalShiny.ts` contains global declarations to define `window.Shiny`, a globally available `Shiny` variable, and a globally available `Shiny` type. This file is in a parallel folder to `./src` to avoid `Shiny` from being globally accessable within the source code. However, this file is the default type defintion when the Type definitions are installed by external developers.
### GitHub Actions
On push to the `main` branch or push to a Pull Request to the `main` branch, a GitHub Action will be run to make sure the bundled JavaScript code is up to date. If the source code does not compile to the exact same file, it will be committed an pushed back to the outdated branch. (This makes it so the full build tools are not necessary for small tweaks and comments. 🎉)
On push to the `master` branch or push to a Pull Request to the `master` branch, a GitHub Action will be run to make sure the bundled JavaScript code is up to date. If the source code does not compile to the exact same file, it will be committed an pushed back to the outdated branch. (This makes it so the full build tools are not necessary for small tweaks and comments. 🎉)
<!-- #### Auto build and browser refresh

View File

@@ -70,7 +70,6 @@ async function build(
incremental: incremental,
watch: watch,
target: "es5",
preserveSymlinks: true,
...opts,
}).then((x) => {
onRebuild();

View File

@@ -10,7 +10,7 @@ import babelPlugin from "esbuild-plugin-babel";
build({
bundle: true,
sourcemap: true,
sourcemap: "inline",
minify: true,
plugins: [babelPlugin()],
banner: banner,

View File

@@ -1,13 +1,14 @@
/* eslint-disable unicorn/filename-case */
const protocol = (window.location.protocol === "https:") ? "wss:" : "ws:";
// Add trailing slash to path, if necessary, before appending "autoreload"
const defaultPath = window.location.pathname.replace(/\/?$/, "/") + "autoreload/";
const defaultUrl = `${protocol}//${window.location.host}${defaultPath}`;
let protocol = "ws:";
// By default, use the defaultUrl. But if there's a data-ws-url attribute on our
// <script> tag, use that instead.
const wsUrl = document.currentScript.dataset.wsUrl || defaultUrl;
const ws = new WebSocket(wsUrl);
if (window.location.protocol === "https:") protocol = "wss:";
let defaultPath = window.location.pathname;
if (!/\/$/.test(defaultPath)) defaultPath += "/";
defaultPath += "autoreload/";
const ws = new WebSocket(protocol + "//" + window.location.host + defaultPath);
ws.onmessage = function (event) {
if (event.data === "autoreload") {

283
srcts/old/Gruntfile.js Normal file
View File

@@ -0,0 +1,283 @@
module.exports = function(grunt) {
var instdir = '../inst/';
var js_srcdir = '../srcjs/'
// Make sure all plattforms to use `\n` as eol char: https://stackoverflow.com/questions/29817511/grunt-issue-with-line-endings
grunt.util.linefeed = "\n";
gruntConfig = {
pkg: pkgInfo(),
clean: {
options: { force: true },
src: [
instdir + "www/shared/shiny.js",
instdir + "www/shared/shiny.js.map",
instdir + "www/shared/shiny.min.js",
instdir + "www/shared/shiny.min.js.map",
"./temp_concat/shiny.js",
"./temp_concat/shiny.js.map",
instdir + "www/shared/datepicker/js/bootstrap-datepicker.min.js",
instdir + "www/shared/ionrangeslider/js/ion.rangeSlider.min.js"
]
},
concat: {
options: {
process: function(src, filepath) {
return (
"//---------------------------------------------------------------------\n" +
"// Source file: " +
filepath +
"\n\n" +
src
);
},
sourceMap: true
},
shiny: {
src: [
js_srcdir + "_start.js",
js_srcdir + "utils.js",
js_srcdir + "browser.js",
js_srcdir + "input_rate.js",
js_srcdir + "shinyapp.js",
js_srcdir + "notifications.js",
js_srcdir + "modal.js",
js_srcdir + "file_processor.js",
js_srcdir + "binding_registry.js",
js_srcdir + "output_binding.js",
js_srcdir + "output_binding_text.js",
js_srcdir + "output_binding_image.js",
js_srcdir + "output_binding_html.js",
js_srcdir + "output_binding_downloadlink.js",
js_srcdir + "output_binding_datatable.js",
js_srcdir + "output_binding_adapter.js",
js_srcdir + "input_binding.js",
js_srcdir + "input_binding_text.js",
js_srcdir + "input_binding_textarea.js",
js_srcdir + "input_binding_password.js",
js_srcdir + "input_binding_number.js",
js_srcdir + "input_binding_checkbox.js",
js_srcdir + "input_binding_slider.js",
js_srcdir + "input_binding_date.js",
js_srcdir + "input_binding_daterange.js",
js_srcdir + "input_binding_select.js",
js_srcdir + "input_binding_radio.js",
js_srcdir + "input_binding_checkboxgroup.js",
js_srcdir + "input_binding_actionbutton.js",
js_srcdir + "input_binding_tabinput.js",
js_srcdir + "input_binding_fileinput.js",
js_srcdir + "init_shiny.js",
js_srcdir + "reactlog.js",
js_srcdir + "_end.js"
],
// The temp_concat/ directory would have gone under /srcjs/, but the
// Babel Grunt plugin has trouble finding presets if it operates on a
// file that's not under the current directory. So we'll put it under
// ./
dest: "./temp_concat/shiny.js",
nonull: true
}
},
"string-replace": {
version: {
files: {
"./temp_concat/shiny.js": "./temp_concat/shiny.js"
},
options: {
replacements: [
{
pattern: /{{\s*VERSION\s*}}/g,
replacement: pkgInfo().version
}
]
}
}
},
babel: {
options: {
sourceMap: true,
compact: false,
presets: ["@babel/preset-env"]
},
shiny: {
src: "./temp_concat/shiny.js",
dest: instdir + "/www/shared/shiny.js"
}
},
eslint: {
options: {
parser: "babel-eslint",
format: require("eslint-stylish-mapped"),
extends: "eslint:recommended",
rules: {
"consistent-return": 1,
"dot-location": [1, "property"],
eqeqeq: 1,
// "no-shadow": 1,
"no-implicit-globals": 1,
"no-restricted-globals": [
"error",
"name",
"length",
"top",
"location",
"parent",
"status"
],
"no-global-assign": 1,
"no-undef": 1,
"no-unused-vars": [1, { args: "none" }],
"guard-for-in": 1,
// "no-use-before-define": [1, {"functions": false}],
semi: [1, "always"]
},
envs: ["es6", "browser", "jquery"],
globals: ["strftime"]
},
shiny: ["./temp_concat/shiny.js"]
},
uglify: {
shiny: {
options: {
banner:
"/*! <%= pkg.name %> <%= pkg.version %> | " +
'(c) 2012-<%= grunt.template.today("yyyy") %> RStudio, Inc. | ' +
"License: <%= pkg.license %> */\n",
sourceMap: {
includeSources: true
},
// Base the .min.js sourcemap off of the .js sourcemap created by concat
sourceMapIn: instdir + "www/shared/shiny.js.map"
},
src: instdir + "www/shared/shiny.js",
dest: instdir + "www/shared/shiny.min.js"
},
datepicker: {
src: [
instdir + "www/shared/datepicker/js/bootstrap-datepicker.js",
instdir + "www/shared/datepicker/js/locales/bootstrap-datepicker.*.js"
],
dest: instdir + "www/shared/datepicker/js/bootstrap-datepicker.min.js"
},
ionrangeslider: {
src: instdir + "www/shared/ionrangeslider/js/ion.rangeSlider.js",
dest: instdir + "www/shared/ionrangeslider/js/ion.rangeSlider.min.js"
},
selectize: {
src: instdir + "www/shared/selectize/accessibility/js/selectize-plugin-a11y.js",
dest: instdir + "www/shared/selectize/accessibility/js/selectize-plugin-a11y.min.js"
}
},
watch: {
shiny: {
files: ["<%= concat.shiny.src %>", "../DESCRIPTION"],
tasks: ["default"]
},
datepicker: {
files: "<%= uglify.datepicker.src %>",
tasks: ["uglify:datepicker"]
}
},
newer: {
options: {
override: function(detail, include) {
// If DESCRIPTION is updated, we'll also need to re-minify shiny.js
// because the min.js file embeds the version number.
if (detail.task === "uglify" && detail.target === "shiny") {
include(isNewer("../DESCRIPTION", detail.time));
} else {
include(false);
}
}
}
}
};
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-string-replace');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-newer');
// Need this here so that babel reads in the source map file after it's
// generated. Without this task, it would read in the source map when Grunt
// runs, which is wrong, if the source map doesn't exist, or is change later.
grunt.task.registerTask("configureBabel", "configures babel options", function() {
gruntConfig.babel.options.inputSourceMap = grunt.file.readJSON('./temp_concat/shiny.js.map');
});
grunt.task.registerTask(
"validateStringReplace",
"tests to make sure the version value was replaced",
function() {
var shinyContent = require('fs').readFileSync('./temp_concat/shiny.js', 'utf8');
if (/{{\s*VERSION\s*}}/.test(shinyContent)) {
grunt.fail.fatal("{{ VERSION }} was not replaced in compiled shiny.js file!")
}
}
);
grunt.initConfig(gruntConfig);
grunt.registerTask('default', [
'concat',
'string-replace',
'validateStringReplace',
'eslint',
'configureBabel',
'babel',
'uglify'
]);
// ---------------------------------------------------------------------------
// Utility functions
// ---------------------------------------------------------------------------
// Return an object which merges information from package.json and the
// DESCRIPTION file.
function pkgInfo() {
var pkg = grunt.file.readJSON('package.json');
pkg.name = descKeyValue('Package');
pkg.version = descKeyValue('Version');
pkg.license = descKeyValue('License');
return pkg;
}
// From the DESCRIPTION file, get the value of a key. This presently only
// works if the value is on one line, the same line as the key.
function descKeyValue(key) {
var lines = require('fs').readFileSync('../DESCRIPTION', 'utf8').split(/\r?\n/);
var pattern = new RegExp('^' + key + ':');
var txt = lines.filter(function(line) {
return pattern.test(line);
});
txt = txt[0];
pattern = new RegExp(key + ': *');
txt = txt.replace(pattern, '');
return txt;
}
// Return true if file's mtime is newer than mtime; false otherwise.
function isNewer(file, mtime) {
return require('fs').statSync(file).mtime > mtime;
}
};

View File

@@ -0,0 +1,17 @@
(function() {
var protocol = 'ws:';
if (window.location.protocol === 'https:')
protocol = 'wss:';
var defaultPath = window.location.pathname;
if (!/\/$/.test(defaultPath))
defaultPath += '/';
defaultPath += 'autoreload/';
var ws = new WebSocket(protocol + '//' + window.location.host + defaultPath);
ws.onmessage = function(event) {
if (event.data === "autoreload") {
window.location.reload()
}
}
})();

Some files were not shown because too many files have changed in this diff Show More