mirror of
https://github.com/rstudio/shiny.git
synced 2026-01-12 00:19:06 -05:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71d20d3561 | ||
|
|
32ac62f2a3 | ||
|
|
d1e7e6c63a | ||
|
|
29b574bf94 | ||
|
|
7e4248bbca | ||
|
|
fee267dc2e | ||
|
|
9864130435 | ||
|
|
c9770cbd03 | ||
|
|
ed6a40ba41 | ||
|
|
3c22cdf90c | ||
|
|
e55749b897 | ||
|
|
88cd87a5f7 |
4
NEWS.md
4
NEWS.md
@@ -1,3 +1,7 @@
|
||||
Addresses #2521: Updated the list of TCP ports that will [be rejected](https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc)
|
||||
by default in runapp.R, adding 5060, 5061 and 6566. Added documentation describing the port range (3000:8000)
|
||||
and which ports are rejected.
|
||||
|
||||
shiny 1.6.0.9000
|
||||
================
|
||||
|
||||
|
||||
@@ -208,15 +208,6 @@ selectizeIt <- function(inputId, select, options, nonempty = FALSE) {
|
||||
options$plugins <- c(options$plugins, list('selectize-plugin-a11y'))
|
||||
}
|
||||
|
||||
# to prevent clipping of the selectize drop-down we set the dropdownParent
|
||||
# to "body". This might be necessary if e.g. overflow-x: scroll is set
|
||||
# on it's container, which forces overflow-y to 'auto' (as per
|
||||
# https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-y). Discussion
|
||||
# of usage here: https://github.com/selectize/selectize.js/issues/192
|
||||
if (is.null(options$dropdownParent)) {
|
||||
options$dropdownParent <- "body"
|
||||
}
|
||||
|
||||
res <- checkAsIs(options)
|
||||
|
||||
deps <- list(selectizeDependency())
|
||||
|
||||
@@ -178,14 +178,15 @@ modalDialog <- function(..., title = NULL, footer = modalButton("Dismiss"),
|
||||
if (!is.null(footer)) div(class = "modal-footer", footer)
|
||||
)
|
||||
),
|
||||
tags$script(
|
||||
"if (window.bootstrap) {
|
||||
# jQuery plugin doesn't work in Bootstrap 5, but vanilla JS doesn't work in Bootstrap 4 :sob:
|
||||
tags$script(HTML(
|
||||
"if (window.bootstrap && !window.bootstrap.Modal.VERSION.match(/^4\\./)) {
|
||||
var modal = new bootstrap.Modal(document.getElementById('shiny-modal'));
|
||||
modal.show();
|
||||
} else {
|
||||
$('#shiny-modal').modal().focus();
|
||||
}"
|
||||
)
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,10 @@
|
||||
#' @param port The TCP port that the application should listen on. If the
|
||||
#' `port` is not specified, and the `shiny.port` option is set (with
|
||||
#' `options(shiny.port = XX)`), then that port will be used. Otherwise,
|
||||
#' use a random port.
|
||||
#' use a random port between 3000:8000, excluding ports that are blocked
|
||||
#' by Google Chrome for being considered unsafe: 3659, 4045, 5060,
|
||||
#' 5061, 6000, 6566, 6665:6669 and 6697. Up to twenty random
|
||||
#' 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. This value of this parameter can also be a
|
||||
@@ -301,7 +304,8 @@ runApp <- function(appDir=getwd(),
|
||||
# Reject ports in this range that are considered unsafe by Chrome
|
||||
# http://superuser.com/questions/188058/which-ports-are-considered-unsafe-on-chrome
|
||||
# https://github.com/rstudio/shiny/issues/1784
|
||||
if (!port %in% c(3659, 4045, 6000, 6665:6669, 6697)) {
|
||||
# https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/port_util.cc
|
||||
if (!port %in% c(3659, 4045, 5060, 5061, 6000, 6566, 6665:6669, 6697)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
45
R/shiny.R
45
R/shiny.R
@@ -2126,6 +2126,51 @@ ShinySession <- R6Class(
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
getUrl = function() {
|
||||
req <- self$request
|
||||
|
||||
url <-
|
||||
# Connect
|
||||
req[["HTTP_X_RSC_REQUEST"]] %||%
|
||||
req[["HTTP_RSTUDIO_CONNECT_APP_BASE_URL"]] %||%
|
||||
# ShinyApps.io
|
||||
if (!is.null(req[["HTTP_X_REDX_FRONTEND_NAME"]])) {
|
||||
paste0("https://", req[["HTTP_X_REDX_FRONTEND_NAME"]])
|
||||
}
|
||||
|
||||
if (is.null(url)) {
|
||||
forwarded_host <- req[["HTTP_X_FORWARDED_HOST"]]
|
||||
forwarded_port <- req[["HTTP_X_FORWARDED_PORT"]]
|
||||
|
||||
host <- if (!is.null(forwarded_host) && !is.null(forwarded_port)) {
|
||||
paste0(forwarded_host, ":", forwarded_port)
|
||||
} else {
|
||||
req[["HTTP_HOST"]] %||% paste0(req[["SERVER_NAME"]], ":", req[["SERVER_PORT"]])
|
||||
}
|
||||
|
||||
proto <- req[["HTTP_X_FORWARDED_PROTO"]] %||% req[["rook.url_scheme"]]
|
||||
|
||||
if (tolower(proto) == "http") {
|
||||
host <- sub(":80$", "", host)
|
||||
} else if (tolower(proto) == "https") {
|
||||
host <- sub(":443$", "", host)
|
||||
}
|
||||
|
||||
url <- paste0(
|
||||
proto,
|
||||
"://",
|
||||
host,
|
||||
req[["SCRIPT_NAME"]],
|
||||
req[["PATH_INFO"]]
|
||||
)
|
||||
}
|
||||
|
||||
# Strip existing querystring, if any
|
||||
url <- sub("\\?.*", "", url)
|
||||
|
||||
url
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1159,7 +1159,7 @@ reactiveStop <- function(message = "", class = NULL) {
|
||||
#'
|
||||
#' ui <- fluidPage(
|
||||
#' checkboxGroupInput('in1', 'Check some letters', choices = head(LETTERS)),
|
||||
#' selectizeInput('in2', 'Select a state', choices = state.name),
|
||||
#' selectizeInput('in2', 'Select a state', choices = c("", state.name)),
|
||||
#' plotOutput('plot')
|
||||
#' )
|
||||
#'
|
||||
|
||||
@@ -58,3 +58,7 @@ We welcome contributions to the **shiny** package. Please see our [CONTRIBUTING.
|
||||
## License
|
||||
|
||||
The shiny package as a whole is licensed under the GPLv3. See the [LICENSE](LICENSE) file for more details.
|
||||
|
||||
## R version support
|
||||
|
||||
Shiny is supported on the latest release version of R, as well as the previous four minor release versions of R. For example, if the latest release R version is 4.1, then that version is supported, as well as 4.0, 3.6, 3.5, and 3.4.
|
||||
|
||||
@@ -13,6 +13,13 @@
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
/* https://github.com/rstudio/shiny/issues/3443 */
|
||||
/* https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.irs *, .irs *:before, .irs *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
.irs-line {
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
@include pos-r();
|
||||
-webkit-touch-callout: none;
|
||||
@include no-click();
|
||||
/* https://github.com/rstudio/shiny/issues/3443 */
|
||||
/* https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
|
||||
box-sizing: border-box;
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
&-line {
|
||||
@include pos-r();
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
/*! shiny 1.6.0.9021 | (c) 2012-2021 RStudio, PBC. | License: GPL-3 | file LICENSE */
|
||||
(function(){var t="ws:";window.location.protocol==="https:"&&(t="wss:");var o=window.location.pathname;/\/$/.test(o)||(o+="/");o+="autoreload/";var n=new WebSocket(t+"//"+window.location.host+o);n.onmessage=function(a){a.data==="autoreload"&&window.location.reload()};})();
|
||||
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LWF1dG9yZWxvYWQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbInZhciBwcm90b2NvbCA9IFwid3M6XCI7XG5pZiAod2luZG93LmxvY2F0aW9uLnByb3RvY29sID09PSBcImh0dHBzOlwiKSBwcm90b2NvbCA9IFwid3NzOlwiO1xudmFyIGRlZmF1bHRQYXRoID0gd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lO1xuaWYgKCEvXFwvJC8udGVzdChkZWZhdWx0UGF0aCkpIGRlZmF1bHRQYXRoICs9IFwiL1wiO1xuZGVmYXVsdFBhdGggKz0gXCJhdXRvcmVsb2FkL1wiO1xudmFyIHdzID0gbmV3IFdlYlNvY2tldChwcm90b2NvbCArIFwiLy9cIiArIHdpbmRvdy5sb2NhdGlvbi5ob3N0ICsgZGVmYXVsdFBhdGgpO1xuXG53cy5vbm1lc3NhZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgaWYgKGV2ZW50LmRhdGEgPT09IFwiYXV0b3JlbG9hZFwiKSB7XG4gICAgd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpO1xuICB9XG59O1xuXG5leHBvcnQge307Il0sCiAgIm1hcHBpbmdzIjogIjtZQUFBLEdBQUksR0FBVyxNQUNmLEFBQUksT0FBTyxTQUFTLFdBQWEsVUFBVSxHQUFXLFFBQ3RELEdBQUksR0FBYyxPQUFPLFNBQVMsU0FDbEMsQUFBSyxNQUFNLEtBQUssSUFBYyxJQUFlLEtBQzdDLEdBQWUsY0FDZixHQUFJLEdBQUssR0FBSSxXQUFVLEVBQVcsS0FBTyxPQUFPLFNBQVMsS0FBTyxHQUVoRSxFQUFHLFVBQVksU0FBVSxFQUFPLENBQzlCLEFBQUksRUFBTSxPQUFTLGNBQ2pCLE9BQU8sU0FBUyIsCiAgIm5hbWVzIjogW10KfQo=
|
||||
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LWF1dG9yZWxvYWQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qIGVzbGludC1kaXNhYmxlIHVuaWNvcm4vZmlsZW5hbWUtY2FzZSAqL1xudmFyIHByb3RvY29sID0gXCJ3czpcIjtcbmlmICh3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgPT09IFwiaHR0cHM6XCIpIHByb3RvY29sID0gXCJ3c3M6XCI7XG52YXIgZGVmYXVsdFBhdGggPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWU7XG5pZiAoIS9cXC8kLy50ZXN0KGRlZmF1bHRQYXRoKSkgZGVmYXVsdFBhdGggKz0gXCIvXCI7XG5kZWZhdWx0UGF0aCArPSBcImF1dG9yZWxvYWQvXCI7XG52YXIgd3MgPSBuZXcgV2ViU29ja2V0KHByb3RvY29sICsgXCIvL1wiICsgd2luZG93LmxvY2F0aW9uLmhvc3QgKyBkZWZhdWx0UGF0aCk7XG5cbndzLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICBpZiAoZXZlbnQuZGF0YSA9PT0gXCJhdXRvcmVsb2FkXCIpIHtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG4gIH1cbn07XG5cbmV4cG9ydCB7fTsiXSwKICAibWFwcGluZ3MiOiAiO1lBQ0EsR0FBSSxHQUFXLE1BQ2YsQUFBSSxPQUFPLFNBQVMsV0FBYSxVQUFVLEdBQVcsUUFDdEQsR0FBSSxHQUFjLE9BQU8sU0FBUyxTQUNsQyxBQUFLLE1BQU0sS0FBSyxJQUFjLElBQWUsS0FDN0MsR0FBZSxjQUNmLEdBQUksR0FBSyxHQUFJLFdBQVUsRUFBVyxLQUFPLE9BQU8sU0FBUyxLQUFPLEdBRWhFLEVBQUcsVUFBWSxTQUFVLEVBQU8sQ0FDOUIsQUFBSSxFQUFNLE9BQVMsY0FDakIsT0FBTyxTQUFTIiwKICAibmFtZXMiOiBbXQp9Cg==
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
|
||||
/*! shiny 1.6.0.9021 | (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=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvc3JjL3V0aWxzL2V2YWwudHMiLCAiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LXRlc3Rtb2RlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvL2VzYnVpbGQuZ2l0aHViLmlvL2NvbnRlbnQtdHlwZXMvI2RpcmVjdC1ldmFsXG4vL3RsL2RyO1xuLy8gKiBEaXJlY3QgdXNhZ2Ugb2YgYGV2YWwoXCJ4XCIpYCBpcyBiYWQgd2l0aCBidW5kbGVkIGNvZGUuXG4vLyAqIEluc3RlYWQsIHVzZSBpbmRpcmVjdCBjYWxscyB0byBgZXZhbGAgc3VjaCBhcyBgaW5kaXJlY3RFdmFsKFwieFwiKWBcbi8vICAgKiBFdmVuIGp1c3QgcmVuYW1pbmcgdGhlIGZ1bmN0aW9uIHdvcmtzIHdlbGwgZW5vdWdoLlxuLy8gPiBUaGlzIGlzIGtub3duIGFzIFwiaW5kaXJlY3QgZXZhbFwiIGJlY2F1c2UgZXZhbCBpcyBub3QgYmVpbmcgY2FsbGVkIGRpcmVjdGx5LCBhbmQgc28gZG9lcyBub3QgdHJpZ2dlciB0aGUgZ3JhbW1hdGljYWwgc3BlY2lhbCBjYXNlIGZvciBkaXJlY3QgZXZhbCBpbiB0aGUgSmF2YVNjcmlwdCBWTS4gWW91IGNhbiBjYWxsIGluZGlyZWN0IGV2YWwgdXNpbmcgYW55IHN5bnRheCBhdCBhbGwgZXhjZXB0IGZvciBhbiBleHByZXNzaW9uIG9mIHRoZSBleGFjdCBmb3JtIGV2YWwoJ3gnKS4gRm9yIGV4YW1wbGUsIHZhciBldmFsMiA9IGV2YWw7IGV2YWwyKCd4JykgYW5kIFtldmFsXVswXSgneCcpIGFuZCB3aW5kb3cuZXZhbCgneCcpIGFyZSBhbGwgaW5kaXJlY3QgZXZhbCBjYWxscy5cbi8vID4gV2hlbiB5b3UgdXNlIGluZGlyZWN0IGV2YWwsIHRoZSBjb2RlIGlzIGV2YWx1YXRlZCBpbiB0aGUgZ2xvYmFsIHNjb3BlIGluc3RlYWQgb2YgaW4gdGhlIGlubGluZSBzY29wZSBvZiB0aGUgY2FsbGVyLlxuXG4vKipcbiAqIEV2YWx1YXRlcyBKYXZhU2NyaXB0IGNvZGUgYW5kIGV4ZWN1dGVzIGl0IHZpYSBfSW5kaXJlY3QgRXZhbHVhdGlvbl9cbiAqIEBwYXJhbSB5IEEgU3RyaW5nIHZhbHVlIHRoYXQgY29udGFpbnMgdmFsaWQgSmF2YVNjcmlwdCBjb2RlLlxuICpcbiAqIEZyb20gW2VzYnVpbGRdKGVzYnVpbGQuZ2l0aHViLmlvL2NvbnRlbnQtdHlwZXMvI2RpcmVjdC1ldmFsKTogRGlyZWN0IHVzYWdlIG9mIGBldmFsKFwieFwiKWAgaXMgYmFkIHdpdGggYnVuZGxlZCBjb2RlLiBJbnN0ZWFkLCB1c2UgaW5kaXJlY3QgY2FsbHMgdG8gYGV2YWxgIHN1Y2ggYXMgYGluZGlyZWN0RXZhbChcInhcIilgLiBFdmVuIGp1c3QgcmVuYW1pbmcgdGhlIGZ1bmN0aW9uIHdvcmtzIHdlbGwgZW5vdWdoLlxuICpcbiAqID4gVGhpcyBpcyBrbm93biBhcyBcImluZGlyZWN0IGV2YWxcIiBiZWNhdXNlIGV2YWwgaXMgbm90IGJlaW5nIGNhbGxlZCBkaXJlY3RseSwgYW5kIHNvIGRvZXMgbm90IHRyaWdnZXIgdGhlIGdyYW1tYXRpY2FsIHNwZWNpYWwgY2FzZSBmb3IgZGlyZWN0IGV2YWwgaW4gdGhlIEphdmFTY3JpcHQgVk0uIFlvdSBjYW4gY2FsbCBpbmRpcmVjdCBldmFsIHVzaW5nIGFueSBzeW50YXggYXQgYWxsIGV4Y2VwdCBmb3IgYW4gZXhwcmVzc2lvbiBvZiB0aGUgZXhhY3QgZm9ybSBgZXZhbCgneCcpYC4gRm9yIGV4YW1wbGUsIGB2YXIgZXZhbDIgPSBldmFsOyBldmFsMigneCcpYCBhbmQgYFtldmFsXVswXSgneCcpYCBhbmQgd2luZG93LmBldmFsKCd4JylgIGFyZSBhbGwgaW5kaXJlY3QgZXZhbCBjYWxscy5cbiAqID4gV2hlbiB5b3UgdXNlIGluZGlyZWN0IGV2YWwsIHRoZSBjb2RlIGlzIGV2YWx1YXRlZCBpbiB0aGUgZ2xvYmFsIHNjb3BlIGluc3RlYWQgb2YgaW4gdGhlIGlubGluZSBzY29wZSBvZiB0aGUgY2FsbGVyLlxuICpcbiAqL1xudmFyIGluZGlyZWN0RXZhbCA9IGV2YWw7XG5leHBvcnQgeyBpbmRpcmVjdEV2YWwgfTsiLCAiaW1wb3J0IHsgaW5kaXJlY3RFdmFsIH0gZnJvbSBcIi4uL3NyYy91dGlscy9ldmFsXCI7IC8vIExpc3RlbiBmb3IgbWVzc2FnZXMgZnJvbSBwYXJlbnQgZnJhbWUuIFRoaXMgZmlsZSBpcyBvbmx5IGFkZGVkIHdoZW4gdGhlXG4vLyBzaGlueS50ZXN0bW9kZSBvcHRpb24gaXMgVFJVRS5cblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIGZ1bmN0aW9uIChlKSB7XG4gIHZhciBtZXNzYWdlID0gZS5kYXRhO1xuICBpZiAobWVzc2FnZS5jb2RlKSBpbmRpcmVjdEV2YWwobWVzc2FnZS5jb2RlKTtcbn0pOyJdLAogICJtYXBwaW5ncyI6ICI7WUFrQkEsR0FBSSxHQUFlLEtDZm5CLE9BQU8saUJBQWlCLFVBQVcsU0FBVSxFQUFHLENBQzlDLEdBQUksR0FBVSxFQUFFLEtBQ2hCLEFBQUksRUFBUSxNQUFNLEVBQWEsRUFBUSIsCiAgIm5hbWVzIjogW10KfQo=
|
||||
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjdHMvc3JjL3V0aWxzL2V2YWwudHMiLCAiLi4vLi4vLi4vc3JjdHMvZXh0cmFzL3NoaW55LXRlc3Rtb2RlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvL2VzYnVpbGQuZ2l0aHViLmlvL2NvbnRlbnQtdHlwZXMvI2RpcmVjdC1ldmFsXG4vL3RsL2RyO1xuLy8gKiBEaXJlY3QgdXNhZ2Ugb2YgYGV2YWwoXCJ4XCIpYCBpcyBiYWQgd2l0aCBidW5kbGVkIGNvZGUuXG4vLyAqIEluc3RlYWQsIHVzZSBpbmRpcmVjdCBjYWxscyB0byBgZXZhbGAgc3VjaCBhcyBgaW5kaXJlY3RFdmFsKFwieFwiKWBcbi8vICAgKiBFdmVuIGp1c3QgcmVuYW1pbmcgdGhlIGZ1bmN0aW9uIHdvcmtzIHdlbGwgZW5vdWdoLlxuLy8gPiBUaGlzIGlzIGtub3duIGFzIFwiaW5kaXJlY3QgZXZhbFwiIGJlY2F1c2UgZXZhbCBpcyBub3QgYmVpbmcgY2FsbGVkIGRpcmVjdGx5LCBhbmQgc28gZG9lcyBub3QgdHJpZ2dlciB0aGUgZ3JhbW1hdGljYWwgc3BlY2lhbCBjYXNlIGZvciBkaXJlY3QgZXZhbCBpbiB0aGUgSmF2YVNjcmlwdCBWTS4gWW91IGNhbiBjYWxsIGluZGlyZWN0IGV2YWwgdXNpbmcgYW55IHN5bnRheCBhdCBhbGwgZXhjZXB0IGZvciBhbiBleHByZXNzaW9uIG9mIHRoZSBleGFjdCBmb3JtIGV2YWwoJ3gnKS4gRm9yIGV4YW1wbGUsIHZhciBldmFsMiA9IGV2YWw7IGV2YWwyKCd4JykgYW5kIFtldmFsXVswXSgneCcpIGFuZCB3aW5kb3cuZXZhbCgneCcpIGFyZSBhbGwgaW5kaXJlY3QgZXZhbCBjYWxscy5cbi8vID4gV2hlbiB5b3UgdXNlIGluZGlyZWN0IGV2YWwsIHRoZSBjb2RlIGlzIGV2YWx1YXRlZCBpbiB0aGUgZ2xvYmFsIHNjb3BlIGluc3RlYWQgb2YgaW4gdGhlIGlubGluZSBzY29wZSBvZiB0aGUgY2FsbGVyLlxudmFyIGluZGlyZWN0RXZhbCA9IGV2YWw7XG5leHBvcnQgeyBpbmRpcmVjdEV2YWwgfTsiLCAiLyogZXNsaW50LWRpc2FibGUgdW5pY29ybi9maWxlbmFtZS1jYXNlICovXG5pbXBvcnQgeyBpbmRpcmVjdEV2YWwgfSBmcm9tIFwiLi4vc3JjL3V0aWxzL2V2YWxcIjsgLy8gTGlzdGVuIGZvciBtZXNzYWdlcyBmcm9tIHBhcmVudCBmcmFtZS4gVGhpcyBmaWxlIGlzIG9ubHkgYWRkZWQgd2hlbiB0aGVcbi8vIHNoaW55LnRlc3Rtb2RlIG9wdGlvbiBpcyBUUlVFLlxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgZnVuY3Rpb24gKGUpIHtcbiAgdmFyIG1lc3NhZ2UgPSBlLmRhdGE7XG4gIGlmIChtZXNzYWdlLmNvZGUpIGluZGlyZWN0RXZhbChtZXNzYWdlLmNvZGUpO1xufSk7Il0sCiAgIm1hcHBpbmdzIjogIjtZQU9BLEdBQUksR0FBZSxLQ0huQixPQUFPLGlCQUFpQixVQUFXLFNBQVUsRUFBRyxDQUM5QyxHQUFJLEdBQVUsRUFBRSxLQUNoQixBQUFJLEVBQVEsTUFBTSxFQUFhLEVBQVEiLAogICJuYW1lcyI6IFtdCn0K
|
||||
|
||||
@@ -9181,22 +9181,17 @@
|
||||
} else {
|
||||
link.attr("href", href2);
|
||||
link.attr("onload", function() {
|
||||
var dummyId = "dummy-" + Math.floor(Math.random() * 999999999);
|
||||
var cssString = "#" + dummyId + " { color: #a7c920 !important; transition: 0.1s all !important; visibility: hidden !important; position: absolute !important; top: -1000px !important; left: 0 !important; }";
|
||||
var base64CssString = "data:text/css;base64," + btoa(cssString);
|
||||
var $dummyLink = (0, import_jquery27.default)("<link rel='stylesheet' type='text/css' />");
|
||||
$dummyLink.attr("href", base64CssString);
|
||||
var $dummyEl = (0, import_jquery27.default)("<div id='" + dummyId + "'></div>");
|
||||
var $dummyEl = (0, import_jquery27.default)("<div>").css("transition", "0.1s all").css("position", "absolute").css("top", "-1000px").css("left", "0");
|
||||
$dummyEl.one("transitionend", function() {
|
||||
$dummyEl.remove();
|
||||
removeSheet(findSheet($dummyLink.attr("href")));
|
||||
removeSheet(oldSheet);
|
||||
sendImageSizeFns.transitioned();
|
||||
});
|
||||
(0, import_jquery27.default)(document.body).append($dummyEl);
|
||||
var color = "#" + Math.floor(Math.random() * 16777215).toString(16);
|
||||
setTimeout(function() {
|
||||
return $head.append($dummyLink);
|
||||
}, 0);
|
||||
return $dummyEl.css("color", color);
|
||||
}, 10);
|
||||
});
|
||||
$head.append(link);
|
||||
}
|
||||
@@ -12286,8 +12281,8 @@
|
||||
data: _this.$initialInput
|
||||
}));
|
||||
while (_this.$pendingMessages.length) {
|
||||
var _msg = _this.$pendingMessages.shift();
|
||||
socket.send(_msg);
|
||||
var msg = _this.$pendingMessages.shift();
|
||||
socket.send(msg);
|
||||
}
|
||||
};
|
||||
socket.onmessage = function(e) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
inst/www/shared/shiny.min.js
vendored
2
inst/www/shared/shiny.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -30,7 +30,10 @@ expression that produces a Shiny app object.
|
||||
\item{port}{The TCP port that the application should listen on. If the
|
||||
\code{port} is not specified, and the \code{shiny.port} option is set (with
|
||||
\code{options(shiny.port = XX)}), then that port will be used. Otherwise,
|
||||
use a random port.}
|
||||
use a random port between 3000:8000, excluding ports that are blocked
|
||||
by Google Chrome for being considered unsafe: 3659, 4045, 5060,
|
||||
5061, 6000, 6566, 6665:6669 and 6697. Up to twenty random
|
||||
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
|
||||
|
||||
@@ -19,7 +19,10 @@ list the available examples.}
|
||||
\item{port}{The TCP port that the application should listen on. If the
|
||||
\code{port} is not specified, and the \code{shiny.port} option is set (with
|
||||
\code{options(shiny.port = XX)}), then that port will be used. Otherwise,
|
||||
use a random port.}
|
||||
use a random port between 3000:8000, excluding ports that are blocked
|
||||
by Google Chrome for being considered unsafe: 3659, 4045, 5060,
|
||||
5061, 6000, 6566, 6665:6669 and 6697. Up to twenty random
|
||||
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
|
||||
|
||||
@@ -68,7 +68,7 @@ options(device.ask.default = FALSE)
|
||||
|
||||
ui <- fluidPage(
|
||||
checkboxGroupInput('in1', 'Check some letters', choices = head(LETTERS)),
|
||||
selectizeInput('in2', 'Select a state', choices = state.name),
|
||||
selectizeInput('in2', 'Select a state', choices = c("", state.name)),
|
||||
plotOutput('plot')
|
||||
)
|
||||
|
||||
|
||||
10
package.json
10
package.json
@@ -2,13 +2,16 @@
|
||||
"private": true,
|
||||
"homepage": "https://shiny.rstudio.com",
|
||||
"repository": "github:rstudio/shiny",
|
||||
"name": "@types/shiny",
|
||||
"name": "@types/rstudio-shiny",
|
||||
"version": "1.6.0-alpha.9021",
|
||||
"license": "GPL-3.0-only",
|
||||
"main": "",
|
||||
"browser": "",
|
||||
"types": "srcts/types/shiny/index.d.ts",
|
||||
"types": "srcts/types/extras/globalShiny.d.ts",
|
||||
"files": [
|
||||
"DESCRIPTION",
|
||||
"LICENSE",
|
||||
"NEWS.md",
|
||||
"srcts/types/**/*.d.ts"
|
||||
],
|
||||
"engines": {
|
||||
@@ -20,7 +23,7 @@
|
||||
"@types/bootstrap-datepicker": "0.0.14",
|
||||
"@types/datatables.net": "^1.10.19",
|
||||
"@types/ion-rangeslider": "2.3.0",
|
||||
"@types/jquery": "^3.5.5",
|
||||
"@types/jquery": "patch:@types/jquery@3.5.5#./srcts/patch/types-jquery.patch",
|
||||
"@types/selectize": "0.12.34"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -75,6 +78,7 @@
|
||||
"util-inspect": "https://github.com/deecewan/browser-util-inspect#c0b4350df4378ffd743e8c36dd3898ce3992823e"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "node --eval \"1+1; // help yarn users not install the whole repo; https://github.com/yarnpkg/yarn/issues/2822#issuecomment-847360267\"",
|
||||
"watch": "yarn run build_shiny --watch",
|
||||
"build": "yarn run build_shiny && yarn run bundle_extras && yarn run bundle_external_libs",
|
||||
"build_shiny": "yarn run checks && yarn run bundle_shiny",
|
||||
|
||||
@@ -173,6 +173,25 @@ yarn watch
|
||||
|
||||
Both JavaScript files will produce a sourcemap (`**.js.map`) that the browser will understand. This will help you debug Shiny's JavaScript code within the browser and point back to the original TypeScript files.
|
||||
|
||||
### 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 defintion when the Type definitions are installed by external developers.
|
||||
|
||||
#### External development
|
||||
|
||||
When developing TypeScript projects that leverage Shiny, we recommend installing the Shiny TypeScript definitions to your package. To install the definitions, call
|
||||
|
||||
```bash
|
||||
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 version.
|
||||
|
||||
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 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.
|
||||
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
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. 🎉)
|
||||
|
||||
@@ -92,16 +92,11 @@
|
||||
* √ Completely remove `parcel` from `./package.json` and only use `esbuild`
|
||||
* √ Delete 'shiny-es5' files
|
||||
* Delete 'old' folder
|
||||
* Maybe not. Might be good to keep for a cycle.
|
||||
* _Uglify_ js files (like in previous Gruntfile.js)
|
||||
* datepicker
|
||||
* ionrangeslider
|
||||
* selectize
|
||||
* Documentation
|
||||
* Check out
|
||||
* https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#this
|
||||
* https://github.com/gajus/eslint-plugin-jsdoc
|
||||
* Looks like it can handle markdown
|
||||
|
||||
|
||||
|
||||
# Eventual TODO
|
||||
|
||||
20
srcts/extras/globalShiny.ts
Normal file
20
srcts/extras/globalShiny.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// Type definitions for @types-rstudio/shiny
|
||||
// Project: Shiny <https://shiny.rstudio.com/>
|
||||
// Definitions by: RStudio <https://www.rstudio.com/>
|
||||
|
||||
import type { Shiny as RStudioShiny } from "../src/shiny/index";
|
||||
|
||||
declare global {
|
||||
// Tell Shiny variable globally exists
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const Shiny: RStudioShiny;
|
||||
|
||||
// Tell window.Shiny exists
|
||||
interface Window {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
Shiny: RStudioShiny;
|
||||
}
|
||||
|
||||
// Make `Shiny` a globally available type definition. (No need to import the type)
|
||||
type Shiny = RStudioShiny;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable unicorn/filename-case */
|
||||
let protocol = "ws:";
|
||||
|
||||
if (window.location.protocol === "https:") protocol = "wss:";
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { Shiny } from "../src/shiny";
|
||||
/* eslint-disable unicorn/filename-case */
|
||||
import "./globalShiny";
|
||||
|
||||
type ShowcaseSrcMessage = {
|
||||
srcref: Array<number>;
|
||||
srcref: number[];
|
||||
srcfile: string;
|
||||
};
|
||||
|
||||
@@ -135,8 +136,8 @@ function highlightSrcref(
|
||||
// If this is the main Shiny window, wire up our custom message handler.
|
||||
// TODO-barret, this should work
|
||||
|
||||
if ((window as any).Shiny) {
|
||||
((window as any).Shiny as Shiny).addCustomMessageHandler(
|
||||
if (Shiny) {
|
||||
Shiny.addCustomMessageHandler(
|
||||
"showcase-src",
|
||||
function (message: ShowcaseSrcMessage) {
|
||||
if (message.srcref && message.srcfile) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable unicorn/filename-case */
|
||||
import { indirectEval } from "../src/utils/eval";
|
||||
|
||||
// Listen for messages from parent frame. This file is only added when the
|
||||
|
||||
@@ -525,11 +525,17 @@ function initDeferredIframes(): void {
|
||||
// TODO-barret; This method uses `window.Shiny`. Could be replaced with `fullShinyObj_.shinyapp?.isConnected()`,
|
||||
// but that would not use `window.Shiny`. Is it a problem???
|
||||
if (
|
||||
// @ts-expect-error; Do not want to define `window.Shiny` as a type to discourage usage of `window.Shiny`
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore; Do not want to define `window.Shiny` as a type to discourage usage of `window.Shiny`;
|
||||
// Can not expect error when combining with window available Shiny definition
|
||||
!window.Shiny ||
|
||||
// @ts-expect-error; Do not want to define `window.Shiny` as a type to discourage usage of `window.Shiny`
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore; Do not want to define `window.Shiny` as a type to discourage usage of `window.Shiny`;
|
||||
// Can not expect error when combining with window available Shiny definition
|
||||
!window.Shiny.shinyapp ||
|
||||
// @ts-expect-error; Do not want to define `window.Shiny` as a type to discourage usage of `window.Shiny`
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore; Do not want to define `window.Shiny` as a type to discourage usage of `window.Shiny`;
|
||||
// Can not expect error when combining with window available Shiny definition
|
||||
!window.Shiny.shinyapp.isConnected()
|
||||
) {
|
||||
// If somehow we accidentally call this before the server connection is
|
||||
|
||||
@@ -233,37 +233,26 @@ function renderDependency(dep: HtmlDep) {
|
||||
// the same plot being redrawn multiple times with different
|
||||
// styling.
|
||||
link.attr("onload", () => {
|
||||
const dummyId = "dummy-" + Math.floor(Math.random() * 999999999);
|
||||
const cssString =
|
||||
"#" +
|
||||
dummyId +
|
||||
" { " +
|
||||
"color: #a7c920 !important; " + // An arbitrary color for the transition
|
||||
"transition: 0.1s all !important; " +
|
||||
"visibility: hidden !important; " +
|
||||
"position: absolute !important; " +
|
||||
"top: -1000px !important; " +
|
||||
"left: 0 !important; }";
|
||||
const base64CssString = "data:text/css;base64," + btoa(cssString);
|
||||
|
||||
const $dummyLink = $("<link rel='stylesheet' type='text/css' />");
|
||||
|
||||
$dummyLink.attr("href", base64CssString);
|
||||
|
||||
const $dummyEl = $("<div id='" + dummyId + "'></div>");
|
||||
const $dummyEl = $("<div>")
|
||||
.css("transition", "0.1s all")
|
||||
.css("position", "absolute")
|
||||
.css("top", "-1000px")
|
||||
.css("left", "0");
|
||||
|
||||
$dummyEl.one("transitionend", () => {
|
||||
$dummyEl.remove();
|
||||
removeSheet(findSheet($dummyLink.attr("href")));
|
||||
removeSheet(oldSheet);
|
||||
sendImageSizeFns.transitioned();
|
||||
});
|
||||
$(document.body).append($dummyEl);
|
||||
|
||||
// Need to add the CSS with a setTimeout 0, to ensure that it
|
||||
// takes effect _after_ the DOM element has been added. This is
|
||||
// necessary to ensure that the transition actually occurs.
|
||||
setTimeout(() => $head.append($dummyLink), 0);
|
||||
// To ensure a transition actually happens, change the inline style _after_
|
||||
// the DOM element has been added, and also use a new random color each time
|
||||
// to prevent any potential caching done by the browser
|
||||
const color =
|
||||
"#" + Math.floor(Math.random() * 16777215).toString(16);
|
||||
|
||||
setTimeout(() => $dummyEl.css("color", color), 10);
|
||||
});
|
||||
|
||||
$head.append(link);
|
||||
|
||||
@@ -33,9 +33,7 @@ import type { WherePosition } from "./singletons";
|
||||
import type { UploadInitValue, UploadEndValue } from "../file/fileProcessor";
|
||||
|
||||
type ResponseValue = UploadEndValue | UploadInitValue;
|
||||
type Handler = (
|
||||
msg: unknown[] | boolean | string | { [key: string]: unknown }
|
||||
) => void;
|
||||
type Handler = (message: any) => void;
|
||||
|
||||
type ShinyWebSocket = WebSocket & {
|
||||
allowReconnect?: boolean;
|
||||
|
||||
@@ -6,16 +6,6 @@
|
||||
// > 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.
|
||||
// > When you use indirect eval, the code is evaluated in the global scope instead of in the inline scope of the caller.
|
||||
|
||||
/**
|
||||
* Evaluates JavaScript code and executes it via _Indirect Evaluation_
|
||||
* @param y A String value that contains valid JavaScript code.
|
||||
*
|
||||
* From [esbuild](esbuild.github.io/content-types/#direct-eval): Direct usage of `eval("x")` is bad with bundled code. Instead, use indirect calls to `eval` such as `indirectEval("x")`. Even just renaming the function works well enough.
|
||||
*
|
||||
* > 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.
|
||||
* > When you use indirect eval, the code is evaluated in the global scope instead of in the inline scope of the caller.
|
||||
*
|
||||
*/
|
||||
const indirectEval = eval;
|
||||
|
||||
export { indirectEval };
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/**
|
||||
* Wrapper around `Object.prototype.hasOwnProperty.call(x,y)`
|
||||
* @param x Object to inspect
|
||||
* @param y Key to inspect in `x`
|
||||
* @returns Whether object `x` actually has property `y`.
|
||||
* */
|
||||
function hasOwnProperty(x: { [key: string]: unknown }, y: string): boolean {
|
||||
return Object.prototype.hasOwnProperty.call(x, y);
|
||||
}
|
||||
|
||||
8
srcts/types/extras/globalShiny.d.ts
vendored
Normal file
8
srcts/types/extras/globalShiny.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { Shiny as RStudioShiny } from "../src/shiny/index";
|
||||
declare global {
|
||||
const Shiny: RStudioShiny;
|
||||
interface Window {
|
||||
Shiny: RStudioShiny;
|
||||
}
|
||||
type Shiny = RStudioShiny;
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
import type { OutputBindingAdapter } from "../bindings/outputAdapter";
|
||||
import type { UploadInitValue, UploadEndValue } from "../file/fileProcessor";
|
||||
declare type ResponseValue = UploadEndValue | UploadInitValue;
|
||||
declare type Handler = (msg: unknown[] | boolean | string | {
|
||||
[key: string]: unknown;
|
||||
}) => void;
|
||||
declare type Handler = (message: any) => void;
|
||||
declare type ShinyWebSocket = WebSocket & {
|
||||
allowReconnect?: boolean;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user