{"id":22731875,"url":"https://github.com/dgkf/webviewer","last_synced_at":"2025-07-08T01:42:48.362Z","repository":{"id":129308618,"uuid":"385059975","full_name":"dgkf/webviewer","owner":"dgkf","description":"An R viewer to display outputs in a web browser","archived":false,"fork":false,"pushed_at":"2021-07-12T13:51:29.000Z","size":12,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-05T03:48:58.104Z","etag":null,"topics":["ide","plots","r","server"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dgkf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-11T22:00:50.000Z","updated_at":"2021-07-12T13:51:32.000Z","dependencies_parsed_at":"2023-07-28T10:46:47.751Z","dependency_job_id":null,"html_url":"https://github.com/dgkf/webviewer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgkf%2Fwebviewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgkf%2Fwebviewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgkf%2Fwebviewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgkf%2Fwebviewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dgkf","download_url":"https://codeload.github.com/dgkf/webviewer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246266271,"owners_count":20749754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ide","plots","r","server"],"created_at":"2024-12-10T19:33:50.066Z","updated_at":"2025-03-30T01:37:59.966Z","avatar_url":"https://github.com/dgkf.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `webviewer` :warning: SUPERCEDED :warning:\n\n\u003e :warning: The package \n\u003e [httpgd](https://github.com/nx10/httpgd) which does everything I was looking\n\u003e for. I don't have any plans to develop this further knowing that there is\n\u003e such a brilliant solution already out there. \n\nAn R package to host an output viewer as a locally hosted website. \n\n![Demo](https://user-images.githubusercontent.com/18220321/125220415-85e27e00-e27b-11eb-8679-4195a3977888.gif)\n\n# Use Case\n\nOutside of all-inclusive IDEs (RStudio), viewing outputs can be inconsistent.\nPlot devices often uses X11 (or OS-specific alternative) to display plots, while\ndynamic content may launch a local website of its own. If using R in a system\nwithout X11 support (for example, within a development container), [it can be a\npain to view\nresults](https://github.com/rocker-org/rocker-versioned/blob/master/X11/README.md).\nLaunching images this way is also host-OS specific, making environments less\nportable. With a web viewer, content can be shared to a host machine with\nminimal expectations of the host capabilities.\n\n# Quick Start\n\n## Examples\n\n```r\nlibrary(webviewer)\n\n# host a viewer at localhost:8001\n# for now you need to load the page before sending plots\nviewer_app \u003c- serve_viewer()\n\noptions(\n  viewer = viewer_app$show,\n  shiny.launch.browser = viewer_app$show\n)\n```\n\nExample plotting using base plotting devices (see example below for ragg device\nexample)\n\n```r\npng(f \u003c- tempfile(\"Rplot\", fileext = \".png\"), width = 500, height = 400)\nplot(rnorm(100))\ndev.off()\nviewer_app$show(f)\n```\n\nExample of Rmarkdown rendering, automatically picking up a shiny-hosted viewer\n\n```r\nlibrary(rmarkdown)\nrun(system.file(\"examples\", \"knitr-minimal.Rmd\", package = \"knitr\"))\n```\n\nExample of Rmarkdown rendering, showing an html file by passing a file name\n\n```r\nlibrary(rmarkdown)\nviewer_app$show(render(\n  system.file(\"examples\", \"knitr-minimal.Rmd\", package = \"knitr\"), \n  \"html_document\"\n))\n```\n\nExample automatically launching a shiny app viewer\n\n```r\nlibrary(shiny)\nrunApp(system.file(\"examples\", \"01_hello\", package = \"shiny\"))\n```\n\nExample showing interactive plots using plotly\n\n```r\nlibrary(plotly)\nplot_ly(iris, x = ~Sepal.Width, y = ~Sepal.Length)\n```\n\n## Device Setup\n\nDefault plotting devices can be burdensome to manage. This setup aims to mimic\nRStudio-style plot feedback, rendering content as soon as a plot is produced and\nupdating the viewer anytime the active rendering device is updated.\n\n```r\nlibrary(webviewer)\n\n# host a viewer at localhost:8001\n# for now you need to load the page before sending plots\nviewer_app \u003c- serve_viewer()\n.Last \u003c- function() { viewer_app$server$stop() }\n\noptions(\n  viewer = viewer_app$show,\n  shiny.launch.browser = viewer_app$show,\n  device = ragg::agg_capture\n)\n\nsuppressMessages(invisible({\n  # trace dev.flush to automatically show plots upon updates\n  trace(\"dev.flush\", print = FALSE, exit = quote({\n    f \u003c- file.path(tempdir(), \"Rplot.png\")\n    md5.old \u003c- if (file.exists(f)) tools::md5sum(f) else \"\"\n    png::writePNG(cap \u003c- dev.capture(native = TRUE), f)\n    md5.new \u003c- tools::md5sum(f)\n    if (any(cap != -1) \u0026\u0026 md5.old != md5.new) viewer_app$show(f)  \n  }))\n\n  # Flush current device to file after each top level call. For large plots, you \n  # may prefer not to set this callback and to just call dev.flush manually.\n  addTaskCallback(function(...) { dev.flush(); TRUE })\n}))\n```\n\n# Status\n\nThis is a very rough proof of concept, aiming to experiment with a middle-ground\nviewer solution so that it is easier to use alternative IDEs and containerized\nenvironments. \n\nThere are plenty of issues with the current implementation:\n\n- Server threads can hang around after you kill an R session\n- The `serve_viewer` function should probably be an `R6` object, not some\n  gnarly, undocumented environment that gets passed around.\n- I'm sure there are plenty of output types that I don't handle.\n- The webpage UI could use some love\n  - Perhaps a plot history\n  - Plot resolution isn't updated to correspond to browser window size\n- I'm sure this could be written to be ReactJS-less. There really isn't anything\n  that needs that deep of a web stack.\n- The graphics device setup is overbearing and could use some streamlined setup\n  that would make it easy to add to a `.Rprofile`\n\nFeedback, encouragement, suggestions and contributions welcome.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgkf%2Fwebviewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdgkf%2Fwebviewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgkf%2Fwebviewer/lists"}