Raw HTML to R: converting <div class="x">text</div> to div("text",class="x") through a function

One of the best parts of developing HTML elements in R is the ability to create reusable layouts / elements, grids, through functions. (example below)

But I haven't found a great way to quickly go from raw HTML to R code. I've attempted to use rvest::read_html() %>% purrr::as_list() and recursively apply a custom function to each nested element, but often ran into unintended results.

I also tried to create a regex match and replace process, but found there wasn't a great way to do this.

Ideally I'd like to create a function that parses raw html and prints the body of the function to the console (for quick prototyping and testing).

Has anyone tried to approach this or knows of anything that might work for this use case?

raw_html <- '
<div class="card text-white bg-primary mb-3" style="max-width: 18rem;">
<div class="card-header">Header</div>
<div class="card-body">
<h5 class="card-title">Primary card title</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card\'s content.</p>
</div>
</div>
'

new_fun <- function(card_head = "", card_title = "", cart_text = "") {
# what id like to print to console via function
  div(
    div(card_head,
      class = "card-header"
    ),
    div(
      h5(card_title,
        class = "card-title"
      ),
      p(card_text,
        class = "card-text"
      ),
      class = "card-body"
    ),
    class = "card text-white bg-primary mb-3", style = "max-width: 18rem;"
  )
}


new_fun(
  "Header","Primary card title",
  "Some quick example text to build on"
)
1 Like

For anyone that's curious, this is where I ended up. It's not perfect, and im sure there are better approaches (if you have one, let me know!) I've found that it errors out on non-shiny tags (e.g. svg elements), and full web pages (scripts, js, etc.)

Output:

example:


# libraries ----
# devtools::install_github("zac-garland/zgtools")
# libraries
zgtools::zg_core_libs()

# html and conversion ----
pg <- read_html("https://getbootstrap.com/docs/4.5/components/buttons/")

raw_html <- pg %>% 
  html_nodes("pre") %>% 
  .[[1]] %>% 
  html_text()

# convert html to r and copy to clip
zgtools::raw_html_to_r(raw_html)


# the below section is copied to the clipboard ----

new_fun <- function(primary_1 = "Primary",
                    secondary_1 = "Secondary",
                    success_1 = "Success",
                    danger_1 = "Danger",
                    warning_1 = "Warning",
                    info_1 = "Info",
                    light_1 = "Light",
                    dark_1 = "Dark",
                    link_1 = "Link", ...) {
  shiny::withTags(
    div(
      body(
        button(
          type = "button",
          class = "btn btn-primary",
          primary_1
        ),
        button(
          type = "button",
          class = "btn btn-secondary",
          secondary_1
        ),
        button(
          type = "button",
          class = "btn btn-success",
          success_1
        ),
        button(
          type = "button",
          class = "btn btn-danger",
          danger_1
        ),
        button(
          type = "button",
          class = "btn btn-warning",
          warning_1
        ),
        button(
          type = "button",
          class = "btn btn-info",
          info_1
        ),
        button(
          type = "button",
          class = "btn btn-light",
          light_1
        ),
        button(
          type = "button",
          class = "btn btn-dark",
          dark_1
        ),
        button(
          type = "button",
          class = "btn btn-link",
          link_1
        )
      )
    )
  )
}

# example of usage ----

new_fun() %>% 
  fluidPage(
    bootstraplib::bootstrap(), .,
    plotly::plot_ly(mtcars,x = ~mpg,y = ~cyl)
    ) %>% 
  htmltools::browsable()



Created on 2020-07-21 by the reprex package (v0.3.0)

1 Like

Thank you for sharing your solution Zac. I'm having a crack at coming up with my own but can't figure out how you managed to style the body so neatly with the indentation. I've used recursion to construct the calls so the output is just a long string of them (EDIT: Got it to work with the style_text() function you've used in your solution).

I haven't been able to run your example as it throws an error below on my end:

Error: Column function_arg can't be modified because it's a grouping variable

Hi @m.merchant, this should be fixed in the latest, as per below. But I would be curious, were you able to come up with a different method? I'd love to improve it if you have any ideas.

Hi @m.merchant

This should be fixed in the latest version. Try to run the below and let me know if you run into any issues.

# libraries ----
remotes::install_github("zac-garland/zgtools",force = T)
zgtools::detach_packages()
zgtools::zg_core_libs()

# html and conversion ----
pg <- read_html("https://getbootstrap.com/docs/4.5/components/buttons/")

raw_html <- pg %>% 
  html_nodes("pre") %>% 
  .[[1]] %>% 
  html_text()

# convert html to r and copy to clip
zgtools::raw_html_to_r(raw_html)

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.