{"id":16896266,"url":"https://github.com/clauswilke/sinab","last_synced_at":"2025-03-22T09:31:44.374Z","repository":{"id":56000576,"uuid":"270390495","full_name":"clauswilke/sinab","owner":"clauswilke","description":"Sinab is not a browser.","archived":false,"fork":false,"pushed_at":"2020-12-02T01:48:04.000Z","size":1211,"stargazers_count":27,"open_issues_count":10,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-15T02:11:57.633Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://clauswilke.com/sinab","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clauswilke.png","metadata":{"files":{"readme":"README.Rmd","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}},"created_at":"2020-06-07T18:08:37.000Z","updated_at":"2022-05-15T08:15:27.000Z","dependencies_parsed_at":"2022-08-15T11:10:21.959Z","dependency_job_id":null,"html_url":"https://github.com/clauswilke/sinab","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/clauswilke%2Fsinab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clauswilke%2Fsinab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clauswilke%2Fsinab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clauswilke%2Fsinab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clauswilke","download_url":"https://codeload.github.com/clauswilke/sinab/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244937751,"owners_count":20535124,"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":[],"created_at":"2024-10-13T17:29:35.735Z","updated_at":"2025-03-22T09:31:43.508Z","avatar_url":"https://github.com/clauswilke.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\",\n  dpi = 192\n)\n```\n\n# Sinab is not a browser\n\n\u003c!-- badges: start --\u003e\n[![R build status](https://github.com/clauswilke/sinab/workflows/R-CMD-check/badge.svg)](https://github.com/clauswilke/sinab/actions)\n[![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/clauswilke/sinab?branch=master\u0026svg=true)](https://ci.appveyor.com/project/clauswilke/sinab)\n[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental)\n\u003c!-- badges: end --\u003e\n\nA basic html rendering engine for R, written in Rust. The purpose is not to write a browser, but rather to provide the ability to render simple, static html documents to an R graphics device.\n\n## Installation\n\nThis package needs to be compiled from source and requires a working Rust toolchain (i.e., [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html)). If you have Cargo up and running, the following should work to install this package:\n\n```{r eval = FALSE}\nremotes::install_github(\"clauswilke/sinab\")\n```\n\nTo get Rust up and running on your system, follow the instructions [provided here.](https://www.rust-lang.org/learn/get-started)\n\nIn brief, on macOS or Linux, you simply run the following command in a shell:\n```\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n```\n(You can also install `rustc` and `cargo` through your package manager of choice, though `rustup` is preferred if you want to do any Rust development work yourself.)\n\nOn Windows, things are a little more complicated:\n\n- Download `rustup-init.exe` from here: https://win.rustup.rs/\n- Then run the following three commands in the Windows\n  command prompt (not powershell):  \n  ```\n  rustup-init.exe -y --default-host x86_64-pc-windows-gnu --default-toolchain stable\n  set PATH=%PATH%;\\%USERPROFILE%\\.cargo\\bin\n  rustup target add i686-pc-windows-gnu\n  ```\n  (If the last line gives you trouble, try restarting your\n  command prompt window.)\n\nIf you are using Rust regularly on Windows but normally build for the Visual Studio target (`x86_64-pc-windows-msvc`), then you may have to run the following two commands to successfully build this R package on your machine:\n\n```\nrustup target add x86_64-pc-windows-gnu\nrustup target add i686-pc-windows-gnu\n```\n\n## Examples\n\n**Note:** This project is in the early proof-of-concept stage. Expect most things to be broken.\n\nThe main function provided by this package is `html_grob()`, which takes as input some Markdown or HTML text and associated CSS and renders it using the grid graphics system. The convenience function `draw_html()` uses `html_grob()` to generate the grob and then draws it with `grid::grid.draw()`.\n\n```{r}\nlibrary(sinab)\nlibrary(grid)\n\nmdtext \u003c- \"\nHere are a few examples of word-wrapped and non-word-wrapped text. First\nregular text pre-formatted:\n\u003cpre\u003e\nThe quick brown\n  fox jumps over\n    the lazy dog.\n\u003c/pre\u003e\nNow some inline code: `x \u003c- 10; y \u003c- 200; z \u003c- 2*x + y;`\nIt gets wrapped.\n\nWe can also write block code. Notice how the long comment runs beyond\nthe box limits:\n\n    x \u003c- 10\n    y \u003c- 200\n    z \u003c- 2*x + y;  # and a really really long comment\n\"\n\ncss \u003c- '\npre { background-color: #eee;\n      padding: 6px;\n      border-left: 5px solid #888; }\np   { background-color: #def;\n      margin: 16px 0px 4px 0px;\n      padding: 4px; }\ncode { border: 1px solid #aaa; \n       padding: 2px; }\npre code { border: none;\n           padding: 0px; }\n'\n\n# can also use `html_grob()` to obtain a grid grob for later drawing\ndraw_html(\n  mdtext, css = css,\n  x = unit(0.1, \"npc\"), y = unit(1, \"npc\"), width = unit(4, \"inches\"),\n)\n```\n\nIf the grob width is specified as a relative unit, then the grob is reactive and reflows as the graphics window is resized. (Try this example interactively.)\n\n```{r}\ndraw_html(\n  mdtext, css = css,\n  x = unit(0.1, \"npc\"), y = unit(1, \"npc\"), width = unit(0.8, \"npc\"),\n)\n```\n\nSimple markdown-to-html conversion is also implemented:\n```{r}\nmd_to_html(\"This is *a* **test**.\")\n```\n\n\n## FAQ\n\n* **Why is HTML/CSS feature X, Y, or Z not available?**  \nRendering is done with a purpose-built layouting pipeline, and to date only a small subset of all possible features has been implemented. \n\n* **Will you support Javascript?**  \nProbably not. The goal for Sinab is to render static pages. Interactivity doesn't work well with R graphics devices.\n\n* **Is MathML supported?**  \nNot at this time.\n\n* **Why is rendering so slow?**  \nThe Sinab library itself is actually quite fast. Slowness comes mostly from R graphics devices. In particular, text shaping can be extremely slow. For faster rendering, try one of the graphics devices provided by the ragg library, such as `agg_png()`. The following benchmark highlights the importance of the graphics device. The agg device is approximately 300 times faster than the quartz device! All this extra time is spent text shaping.\n\n\u003c!-- --\u003e\n\n    text \u003c- paste(rep(\"Hello\", 50), collapse = \" \")\n    n \u003c- 100L\n\n    file \u003c- tempfile(fileext = \".png\")\n    png(file, width = 1920, height = 1920, res = 288, type = \"quartz\")\n    microbenchmark::microbenchmark(render_markdown(text), times = n)\n    #\u003e Unit: milliseconds\n    #\u003e                   expr      min       lq     mean   median       uq      max\n    #\u003e  render_markdown(text) 685.3594 704.2026 722.0359 711.3405 720.7934 894.4264\n    #\u003e  neval\n    #\u003e    100\n    invisible(dev.off())\n\n    ragg::agg_png(file, width = 1920, height = 1920, res = 288)\n    microbenchmark::microbenchmark(render_markdown(text), times = n)\n    #\u003e Unit: milliseconds\n    #\u003e                   expr      min       lq     mean   median       uq      max\n    #\u003e  render_markdown(text) 2.097382 2.145262 2.400133 2.207823 2.349058 13.56952\n    #\u003e  neval\n    #\u003e    100\n    invisible(dev.off())\n\n* **Why aren't you supporting links (i.e., the `\u003ca\u003e` tag)?**  \nThis is a limitation of the current R graphics device API. There is simply no way to create a link in an R graphics device. Once this feature gets added, it will be easy to support it in Sinab.\n\n* **Why do my colors look wrong?**  \nSinab uses the color names defined by CSS, which in some cases are different from the color names that R uses. The most obvious example is probably \"green\", which corresponds to #00ff00 in R but #008000 in CSS. If you want to be certain that you get the colors you want, specify them with hex codes in RGB format.\n\n## Acknowledgments\n\nThe actual HTML/CSS parsing and rendering code is written in Rust, and it draws heavily from software developed for the Servo project. HTML parsing is done with [html5ever](https://github.com/servo/html5ever), CSS parsing is done with [cssparser](https://github.com/servo/rust-cssparser), and CSS selectors are implemented using the [selectors](https://github.com/servo/servo/tree/master/components/selectors) crate. DOM, layout, and rendering is using custom code that is in no small part based on the experimental [Victor](https://github.com/SimonSapin/victor) project written by Simon Sapin.\n\nMarkdown to HTML conversion is performed through the [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) crate, which implements a lightweight Markdown parser that complies with the [CommonMark spec.](https://spec.commonmark.org/)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclauswilke%2Fsinab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclauswilke%2Fsinab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclauswilke%2Fsinab/lists"}