Last active
March 9, 2024 07:14
-
-
Save helgasoft/819035e853d9889ba02cb69ecc587f34 to your computer and use it in GitHub Desktop.
Echarty Translate Assistant - JavaScript data to R
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(shiny) | |
library(stringr) | |
library(echarty) | |
library(rclipboard) # for clipboard Copy button | |
library(formatR) | |
if (FALSE) { # notes | |
#' problem plot with Chinese chars: | |
#' text='<U+6F0F><U+6597><U+56FE>' > Sys.getlocale() | |
#' Sys.setlocale(category = "LC_ALL", locale = "") | |
#' Sys.setlocale(category = "LC_ALL", locale = "chs") | |
#' as.character(parse(text='subtext: 纯属虚构',encoding = 'UTF-8')) | |
#' https://github.com/tidyverse/stringr/issues/295 | |
#' Yeah, this is an underlying issue with R — when you create names using a call to c(), the names are converted to symbols, which are always encoded in the native encoding (which on windows will not be UTF-8). Unfortunately I don't think there's anything stringr can do about this. | |
#' Go to Control Panel --> Region and Language --> Administrative --> Change system locale --> Chinese | |
#' https://github.com/rstudio/shiny/issues/1053#issuecomment-167011937 !!! | |
#' SOLVED: use Sys.setlocale(,'Chinese') !! | |
#' | |
#' TODO | |
#' JS code box to select all by 1click: | |
#' works for textOutput, verbatimT(pre): https://codersblock.com/blog/using-css-to-control-text-selection/ | |
#' dont translate {:} if inside formatter string : save in vector, replace w @_index_@, finally replace back all in loop | |
#' formatter='{c}: {a}' https://echarts.apache.org/examples/en/editor.html?c=pie-nest | |
#' https://echarts.apache.org/examples/en/editor.html?c=line-marker | |
#' itemNameFormatter: 'exp {value}' https://echarts.apache.org/examples/en/editor.html?c=boxplot-light-velocity | |
#' itemNameFormatter: function (params) { https://echarts.apache.org/examples/en/editor.html?c=boxplot-light-velocity2 | |
#' ok except formatter in https://echarts.apache.org/examples/en/editor.html?c=gauge-stage | |
#' formatter=htmlwidgets::JS("function (param) {...} in https://echarts.apache.org/examples/en/editor.html?c=sunburst-label-rotate | |
#' both formatters in https://echarts.apache.org/examples/en/editor.html?c=pictorialBar-body-fill | |
#' color=htmlwidgets::JS("new echarts.graphic.LinearGradient https://echarts.apache.org/examples/en/editor.html?c=area-stack-gradient | |
#' explain comma error in series = "argument N is empty" (can parser catch?) ex: https://echarts.apache.org/examples/en/editor.html?c=pie-simple | |
#' extra ".revert()" in https://echarts.apache.org/examples/en/editor.html?c=radar-aqi | |
} | |
ui = fluidPage( | |
tags$style(type='text/css', " | |
#ero { background-color: lemonchiffon; color: red; | |
-webkit-user-select: all; user-select: all; } | |
"), | |
#tags$script("window.onload = function() { document.getElementById('jscode').tabIndex='0'; }"), | |
fluidRow( | |
column(10, titlePanel( h3(span(tags$a(href='https://github.com/helgasoft/echarty','Echarty')," Translate Assistant - Javascript data to R"), align = "center"))), | |
column(2, actionButton("info", label=tags$img(src ="https://img.icons8.com/metro/2x/info.png", alt='Help', width= '30')) ) | |
), | |
rclipboardSetup(), | |
div( tabindex="0", strong('1. Javascript code'),span('from'), | |
tags$a(href="https://echarts.apache.org/examples/en/", "examples"),span(', or '), | |
tags$a(href="https://www.makeapie.com/", "makeapie"),span(', or other source'), | |
textAreaInput("jscode", NULL, width='100%', height='150px', | |
placeholder='paste Echarts JS code here, like option = { ... };') | |
), | |
fluidRow( | |
column(3, div( strong('R code'), uiOutput("clip", inline=TRUE))), # copy-to-clipboard button | |
column(6, actionButton("doTranslate", "2. Translate"), align = "center"), | |
column(3, checkboxInput('chkCN', "CN chars", FALSE), align = "right") | |
), | |
textAreaInput("rcode", NULL, width = "1000px", height='150px', | |
placeholder='hit button Translate to see code here'), | |
column(12, actionButton("doPlot", "3. Plot in R"), align = "center"), | |
br(),br(), textOutput("ero"), | |
ecs.output("plot") | |
) | |
server <- function(input, output, session){ | |
proc <- function(jscode) { | |
tmp <- enc2utf8(jscode) | |
tmp <- gsub("/\\*(.*)\\*/", '', tmp) # kill JS multiline comments | |
{ | |
lines <- lapply(strsplit(tmp, '\n', fixed=TRUE), trimws) | |
lines <- unlist(lines) | |
# remove comments to end-of-line if not https:// path:// | |
lines <- gsub("(?<!:)//(.*)$", '', lines, perl=TRUE) | |
tmp <- paste(lines, collapse='') | |
} | |
tmp <- str_replace_all(tmp, fixed('var '), '' ) | |
tmp <- str_replace_all(tmp, fixed('= {'), '=list(' ) | |
tmp <- str_replace_all(tmp, fixed(': ['), '=list(' ) | |
tmp <- str_replace_all(tmp, fixed(':['), '=list(' ) | |
tmp <- str_replace_all(tmp, fixed(': {'), '=list(' ) | |
tmp <- str_replace_all(tmp, fixed(':{'), '=list(' ) | |
tmp <- str_replace_all(tmp, fixed(': '), '=' ) | |
tmp <- gsub(":(?!//)", '=', tmp, perl=TRUE) # exclude https:// path:// | |
tmp <- str_replace_all(tmp, fixed('{'), 'list(' ) | |
tmp <- str_replace_all(tmp, fixed('}'), ')' ) | |
tmp <- str_replace_all(tmp, fixed('['), 'list(' ) # was 'c(' | |
tmp <- str_replace_all(tmp, fixed(']'), ')' ) | |
tmp <- str_replace_all(tmp, fixed('true'), 'TRUE' ) | |
tmp <- str_replace_all(tmp, fixed('false'), 'FALSE' ) | |
tmp <- str_replace_all(tmp, fixed('null'), 'NULL' ) | |
# tmp <- str_replace_all(tmp, fixed(';'), '; p' ) | |
tmp <- str_replace_all(tmp, fixed('option ='), '\n p <- ec.init(); p$x$opts <- ' ) | |
# post-fix | |
tmp <- str_replace_all(tmp, fixed('https=#'), 'https://' ) | |
# tmp <- str_replace_all(tmp, fixed('list(c(list'), 'list(list(list') | |
tmp <- str_replace_all(tmp, fixed('=list()'), "=list(ey='')") # for [] or {} | |
tmp <- gsub(';', '\n', tmp, fixed=TRUE) | |
# some rudimentary code wrapping | |
kwords <- c('dataset','series','visualMap','dataZoom','tooltip','legend') | |
for(i in 1:length(kwords)) { kw <- paste0(kwords[i],'=') | |
tmp <- gsub(kw, paste('\n',kw), tmp, fixed=TRUE) } | |
tmp <- paste(tmp,'\n p') | |
enc2utf8(tmp) | |
} | |
observeEvent(input$doTranslate, { | |
output$ero <- renderText({ '' }) | |
output$plot <- ecs.render({ NULL }) | |
tmp <- proc(input$jscode) | |
tryCatch({ | |
tmp <- tidy_source(text=tmp, indent=2) | |
tmp <- paste(tmp$text.tidy, collapse = '\n') | |
} | |
,error = function(e) { | |
output$ero <- renderText({ paste('error:\n',e$message) }) } | |
) | |
updateTextAreaInput(session, 'rcode', value=tmp) | |
}) | |
observeEvent(input$doPlot, { | |
output$plot <- ecs.render({ | |
tmp <- NULL | |
tryCatch( | |
tmp <- parse(text = isolate(input$rcode)) | |
,error = function(e) { | |
output$ero <- renderText({ paste('ERROR:\n',e$message) }) } | |
) | |
if (!is.null(tmp)) { | |
output$ero <- renderText({ "" }) | |
eval(tmp) # display chart | |
} | |
}) | |
}) | |
observeEvent(input$chkCN, { | |
if (input$chkCN) Sys.setlocale(,'Chinese') | |
else Sys.setlocale(,) | |
}) | |
redit <- eventReactive(input$rcode, { | |
txt <- input$rcode | |
txt | |
}) | |
# Add clipboard button | |
output$clip <- renderUI({ | |
rclipButton("clipbtn", "Copy", redit(), icon=icon("clipboard")) | |
}) | |
# help info | |
observeEvent(input$info, { | |
showModal(modalDialog( | |
title = "Learn by example", | |
tags$div("Javascript library Echarts has lots of great ",tags$a(href="https://echarts.apache.org/examples/en/", "examples"), | |
". The goal here is to facilitate the translation of their ",strong('data')," to R, especially the ",strong('option')," object.", | |
"Option components represent the chart. In Echarty's R examples ",tags$em('option')," is implemented as ",strong('p$x$opts'), | |
". Javascript commands and functions will ",strong('not')," translate properly.", | |
br(), "So here are the steps:", | |
br(), "1. Open an ",tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=parallel-simple", "example")," and ",strong('copy')," the entire code from the left side", | |
br(), "2. ",strong('Paste')," the text in box ",tags$em('Javascript code')," here", | |
br(), "3. Hit button Translate and some text will appear under ",tags$em('R code'), | |
br(), "4. Edit the R code and/or copy to clipboard (optional)", | |
br(), "5. Hit button ",tags$em('Plot in R')," to show a chart, or code errors", | |
br(), | |
br(),"If your locale is English, checkbox ",strong("CN chars")," will show Chinese characters in plots. Check the box ",strong('before')," Translate. Uncheck to reset locale back to English.", | |
br(),"Most examples will not translate 100%, but here are some that did - ", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=line-simple", "line"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=parallel-simple", "parallel"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=radar", "radar"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=sunburst-simple", "sunburst"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=sunburst-visualMap", "sunburst-vMap"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=sunburst-drink", "drink"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=sankey-vertical", "sankey"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=sankey-itemstyle", "itemstyle"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=funnel", "funnel"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=bar-stack", "bar-stack"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=dataset-encode0", "dataset-encode"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=pie-roseType-simple", "pie-roseType"),",", | |
tags$a(href="https://echarts.apache.org/examples/en/editor.html?c=themeRiver-basic", "themeRiver")," - try them out!", | |
br(),tags$a(href="https://www.makeapie.com/", "Makeapie")," examples in general have more executable code and are harder to translate." | |
) | |
)) | |
}) | |
} | |
shinyApp(ui, server) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment