html element construction for R.
hypertext provides a deterministic, framework-agnostic DSL for building
html nodes and rendering them to a string.
it does not implement templating, dependency management, widgets or framework integrations.
heavily inspired by {htmltools}.
install the stable version from CRAN:
install.packages("hypertext")
or get the development version from github:
devtools::install_github("sigflux/hypertext")
library(hypertext)
page <- tag_list(
doctype(),
tags$html(
tags$head(
tags$title("hypertext")
),
tags$body(
tags$h1("Hello"),
tags$p(
class = c("lead", "mb-2"),
"Server-side HTML."
),
tags$input(
type = "text",
placeholder = "enter your nickname"
),
tags$button(
"Click"
)
)
)
)
render(page)
render() takes a tag tree and returns a single HTML string:
x <- tags$p(
class = "lead",
"hello"
)
# `x` contains the tag tree
class(x)
#> [1] "hypertext.tag"
# rendering produces an HTML string:
render(x)
#> [1] "<p class=\"lead\">hello</p>"
you can render() directly to an html file by supplying
the file parameter:
library(hypertext)
page <- tag_list(
doctype(),
tags$html(
tags$head(
tags$title("hypertext")
),
tags$body(
tags$h1("Hello"),
tags$p(
class = c("lead", "mb-2"),
"Server-side HTML."
),
tags$input(
type = "text",
placeholder = "enter your nickname"
),
tags$button(
"Click"
)
)
)
)
render(x = page, file = "index.html")
tag_list() groups sibling nodes without wrapping them in a parent element.
library(hypertext)
header <- tag_list(
tags$h1("hello"),
tags$p(
class = "lead",
"welcome aboard."
)
)
render(header)
#> [1] "<h1>hello</h1><p class=\"lead\">welcome aboard.</p>"
raw_html() marks a string as pre-rendered HTML so that render() outputs
it verbatim, without escaping. useful for injecting inline scripts, styles,
SVG markup, or any content that is already valid HTML.
library(hypertext)
page <- tags$div(
raw_html("<svg viewBox='0 0 100 100'><circle cx='50' cy='50' r='40'/></svg>")
)
render(page)
#> [1] "<div><svg viewBox='0 0 100 100'><circle cx='50' cy='50' r='40'/></svg></div>"
doctype() is a convenience wrapper around raw_html("<!DOCTYPE html>").
tag() creates elements for any tag name, including web components and
custom elements not in the built-in tags list. it takes 3 arguments:
tag_name: name of the html element....: attributes (named) & children (unnamed).tag_type: either "normal" (default) for the standard html
elements, or "void" for the self-closing elements.library(hypertext)
content <- tag(
tag_name = "calcite-action-bar",
layout = "horizontal"
)
render(content)
#> [1] "<calcite-action-bar layout=\"horizontal\"></calcite-action-bar>"
nest them freely with each other and with built-in tags:
page <- tags$div(
class = "app",
tag(
tag_name = "calcite-shell",
tag(
tag_name = "calcite-shell-panel",
slot = "panel-start",
tag(
tag_name = "calcite-action-bar",
tag(
tag_name = "calcite-action",
text = "Layers",
icon = "layers"
),
tag(
tag_name = "calcite-action",
text = "Basemaps",
icon = "basemap"
)
)
),
tags$div(id = "map")
)
)
render(page)
for self-closing elements, set tag_type = "void":
content <- tag(
tag_name = "my-icon",
name = "home",
tag_type = "void"
)
render(content)
#> [1] "<my-icon name=\"home\" />"
```r library(ambiorix) library(hypertext)
app <- Ambiorix$new(port = 3000L)
app$get("/", function(req, res) { html <- tags$h1("hello, world!") |> render()
res$send(html)
})
app$get("/about", function(req, res) { html <- tag_list( tags$h1("about us"), tags$p( "minimal ", tags$strong("html construction"), " for R." ) ) |> render()
res$send(html)
})
app$get("/team", function(req, res) { teammates <- c("you", "me", "other")
html <- tags$div(
class = "team",
tags$p("meet the team:"),
tags$ul(
lapply(teammates, tags$li)
)
) |>
render()
res$send(html)
})
app$start() ```
```r library(shiny) library(bslib) library(hypertext)
# use hypertext::tags explicitly to avoid clashing with shiny::tags.
ht <- hypertext::tags
card <- function(title, body) { ht$div( class = "card mt-3", ht$div( class = "card-header", title ), ht$div( class = "card-body", ht$p( class = "card-text", body ) ) ) }
content <- ht$div( class = "container py-4", card("First card", "Some quick example text."), card("Second card", "Another body of text.") ) |> render()
ui <- page( theme = bs_theme(version = 5L), # hypertext renders an HTML string, so wrap in shiny::HTML() HTML(content) )
server <- function(input, output, session) {}
shinyApp(ui, server) ```
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.