Skip to content

Commit f6bf4a4

Browse files
committed
Merge pull request rstudio#537 from yihui/bugfix/native-encoding
Use native encoding internally
2 parents 89dc132 + af978a6 commit f6bf4a4

File tree

7 files changed

+74
-21
lines changed

7 files changed

+74
-21
lines changed

R/app.R

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ shinyAppDir <- function(appDir, options=list()) {
112112
# If not, then take the last expression that's returned from ui.R.
113113
.globals$ui <- NULL
114114
on.exit(.globals$ui <- NULL, add = FALSE)
115-
ui <- source(uiR,
116-
local = new.env(parent = globalenv()),
117-
keep.source = TRUE, encoding = 'UTF-8')$value
115+
ui <- sourceUTF8(uiR, local = new.env(parent = globalenv()))$value
118116
if (!is.null(.globals$ui)) {
119117
ui <- .globals$ui[[1]]
120118
}
@@ -137,11 +135,7 @@ shinyAppDir <- function(appDir, options=list()) {
137135
# server.R.
138136
.globals$server <- NULL
139137
on.exit(.globals$server <- NULL, add = TRUE)
140-
result <- source(
141-
serverR,
142-
local = new.env(parent = globalenv()),
143-
keep.source = TRUE, encoding = 'UTF-8'
144-
)$value
138+
result <- sourceUTF8(serverR, local = new.env(parent = globalenv()))$value
145139
if (!is.null(.globals$server)) {
146140
result <- .globals$server[[1]]
147141
}
@@ -169,8 +163,7 @@ shinyAppDir <- function(appDir, options=list()) {
169163
oldwd <<- getwd()
170164
setwd(appDir)
171165
if (file.exists(file.path.ci(appDir, "global.R")))
172-
source(file.path.ci(appDir, "global.R"), keep.source = TRUE,
173-
encoding = 'UTF-8')
166+
sourceUTF8(file.path.ci(appDir, "global.R"))
174167
}
175168
onEnd <- function() {
176169
setwd(oldwd)

R/server.R

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,11 @@ decodeMessage <- function(data) {
249249
packBits(rawToBits(data[pos:(pos+3)]), type='integer')
250250
}
251251

252-
if (readInt(1) != 0x01020202L)
253-
return(fromJSON(rawToChar(data), asText=TRUE, simplify=FALSE, encoding='UTF-8'))
252+
if (readInt(1) != 0x01020202L) {
253+
# use native encoding for the message
254+
nativeData <- iconv(rawToChar(data), 'UTF-8')
255+
return(fromJSON(nativeData, asText=TRUE, simplify=FALSE))
256+
}
254257

255258
i <- 5
256259
parts <- list()
@@ -634,7 +637,7 @@ runApp <- function(appDir=getwd(),
634637
if (is.character(appDir)) {
635638
desc <- file.path.ci(appDir, "DESCRIPTION")
636639
if (file.exists(desc)) {
637-
con <- file(desc, encoding = 'UTF-8')
640+
con <- file(desc, encoding = checkEncoding(desc))
638641
on.exit(close(con), add = TRUE)
639642
settings <- read.dcf(con)
640643
if ("DisplayMode" %in% colnames(settings)) {

R/shinyui.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ renderPage <- function(ui, connection, showcase=0) {
3333

3434
deps <- c(
3535
list(
36+
htmlDependency("json2", "2014.02.04", c(href="shared"), script = "json2-min.js"),
3637
htmlDependency("jquery", "1.11.0", c(href="shared"), script = "jquery.js"),
3738
htmlDependency("shiny", packageVersion("shiny"), c(href="shared"),
3839
script = "shiny.js", stylesheet = "shiny.css")

R/showcase.R

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ showcaseHead <- function() {
5050
href="shared/shiny-showcase.css"),
5151
if (file.exists(mdfile))
5252
script(type="text/markdown", id="showcase-markdown-content",
53-
paste(readLines(mdfile, warn = FALSE, encoding='UTF-8'), collapse="\n"))
53+
paste(readUTF8(mdfile), collapse="\n"))
5454
else ""
5555
))
5656

@@ -106,9 +106,7 @@ showcaseCodeTabs <- function(codeLicense) {
106106
# we need to prevent the indentation of <code> ... </code>
107107
HTML(format(tags$code(
108108
class="language-r",
109-
paste(readLines(file.path.ci(getwd(), rFile), warn=FALSE,
110-
encoding='UTF-8'),
111-
collapse="\n")
109+
paste(readUTF8(file.path.ci(getwd(), rFile)), collapse="\n")
112110
), indent = FALSE))))
113111
})),
114112
codeLicense))
@@ -122,7 +120,9 @@ showcaseAppInfo <- function() {
122120
readmemd <- file.path.ci(getwd(), "Readme.md")
123121
hasReadme <- file.exists(readmemd)
124122
if (hasDesc) {
125-
desc <- read.dcf(descfile)
123+
con <- textConnection(readUTF8(descfile))
124+
on.exit(close(con), add = TRUE)
125+
desc <- read.dcf(con)
126126
}
127127
with(tags,
128128
div(class="container-fluid shiny-code-container well",

R/tar.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ untar2 <- function(tarfile, files = NULL, list = FALSE, exdir = ".")
141141
warning(gettextf("failed to copy %s to %s", sQuote(name2), sQuote(name)), domain = NA)
142142
}
143143
} else {
144-
if(.Platform$OS.type == "windows") {
144+
if(isWindows()) {
145145
## this will not work for links to dirs
146146
from <- file.path(dirname(name), name2)
147147
if (!file.copy(from, name))

R/utils.R

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ resolve <- function(dir, relpath) {
185185
abs.path <- normalizePath(abs.path, winslash='/', mustWork=TRUE)
186186
dir <- normalizePath(dir, winslash='/', mustWork=TRUE)
187187
# trim the possible trailing slash under Windows (#306)
188-
if (.Platform$OS.type == 'windows') dir <- sub('/$', '', dir)
188+
if (isWindows()) dir <- sub('/$', '', dir)
189189
if (nchar(abs.path) <= nchar(dir) + 1)
190190
return(NULL)
191191
if (substr(abs.path, 1, nchar(dir)) != dir ||
@@ -195,6 +195,8 @@ resolve <- function(dir, relpath) {
195195
return(abs.path)
196196
}
197197

198+
isWindows <- function() .Platform$OS.type == 'windows'
199+
198200
# This is a wrapper for download.file and has the same interface.
199201
# The only difference is that, if the protocol is https, it changes the
200202
# download settings, depending on platform.
@@ -203,7 +205,7 @@ download <- function(url, ...) {
203205
if (grepl('^https?://', url)) {
204206

205207
# If Windows, call setInternet2, then use download.file with defaults.
206-
if (.Platform$OS.type == "windows") {
208+
if (isWindows()) {
207209
# If we directly use setInternet2, R CMD CHECK gives a Note on Mac/Linux
208210
mySI2 <- `::`(utils, 'setInternet2')
209211
# Store initial settings
@@ -916,3 +918,35 @@ setServerInfo <- function(...) {
916918
infoOld[names(infoNew)] <- infoNew
917919
.globals$serverInfo <- infoOld
918920
}
921+
922+
# see if the file can be read as UTF-8 on Windows, and converted from UTF-8 to
923+
# native encoding; if the conversion fails, it will produce NA's in the results
924+
checkEncoding <- function(file) {
925+
if (!isWindows()) return('UTF-8')
926+
927+
x <- readLines(file, encoding = 'UTF-8', warn = FALSE)
928+
isUTF8 <- !any(is.na(iconv(x, 'UTF-8')))
929+
if (isUTF8) return('UTF-8')
930+
931+
enc <- getOption('encoding')
932+
msg <- c(sprintf('The source file "%s" is not encoded in UTF-8. ', file),
933+
'Please convert its encoding to UTF-8 ',
934+
'(e.g. use the menu `File -> Save with Encoding` in RStudio).')
935+
if (enc == 'UTF-8') stop(msg)
936+
# if you publish the app to ShinyApps.io, you will be in trouble
937+
warning(c(msg, ' Falling back to the encoding "', enc, '".'))
938+
939+
enc
940+
}
941+
942+
# try to read a file using UTF-8 (fall back to getOption('encoding') in case of
943+
# failure, which defaults to native.enc, i.e. native encoding)
944+
readUTF8 <- function(file) {
945+
x <- readLines(file, encoding = checkEncoding(file), warn = FALSE)
946+
enc2native(x)
947+
}
948+
949+
# similarly, try to source() a file with UTF-8
950+
sourceUTF8 <- function(file, ...) {
951+
source(file, ..., keep.source = TRUE, encoding = checkEncoding(file))
952+
}

inst/www/shared/json2-min.js

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)