cssparser

cssparser is a CSS parser (written in vanilla R) which can:

What’s in the box

Vignettes

Installation

You can install from GitHub with:

# install.package('remotes')
remotes::install_github('coolbutuseless/cssparser')

Limitations

Example: Parse CSS

library(cssparser)

stylesheet <- '
#main {
  background-color: red !important;
  color: blue;
}

.footer {
  border-color: rgb(50 100 255);
  font-weight: lighter;
  margin-left: 1cm;
}

.footer > p {
  background-color: green;
}
'

css <- cssparser::read_css(stylesheet)
css
>   $`#main`
>   $`#main`$`background-color`
>   [1] "red"
>   attr(,"important")
>   [1] TRUE
>   
>   $`#main`$color
>   [1] "blue"
>   
>   
>   $.footer
>   $.footer$`border-color`
>   [1] "rgb(50 100 255)"
>   
>   $.footer$`font-weight`
>   [1] "lighter"
>   
>   $.footer$`margin-left`
>   [1] "1cm"
>   
>   
>   $`.footer > p`
>   $`.footer > p`$`background-color`
>   [1] "green"
cssparser::css_pretty_print(css)
>   #main {
>     background-color: red !important;
>     color: blue;
>   }
>   
>   .footer {
>     border-color: rgb(50 100 255);
>     font-weight: lighter;
>     margin-left: 1cm;
>   }
>   
>   .footer > p {
>     background-color: green;
>   }

Example: Extract values from CSS in R

The object returned by read_css() is a nested list of name/value pairs.

The top-level name is the CSS Selector (e.g. #main). The value it points to is another named list - property/value pairs e.g. color = blue

To extract a single style from the CSS object, just subset it as you would for any R list

css[['.footer']][['font-weight']]
>   [1] "lighter"
css[['#main']][['background-color']]  # Note the 'important' attribute on this CSS declaration
>   [1] "red"
>   attr(,"important")
>   [1] TRUE

Example: Extract/Convert values

Some tools are included for extracting parsing CSS values into R values e.g.

colour <- css[['.footer']][['border-color']]
colour
>   [1] "rgb(50 100 255)"
cssparser::css_colour_to_hex( colour )
>   [1] "#3264FFFF"
value <- css[['.footer']][['margin-left']]
value
>   [1] "1cm"
cssparser::css_string_as_css_length(value)
>   [1] 1
>   attr(,"unit")
>   [1] "cm"
cssparser::css_string_as_pixels(value)
>   [1] 37.79528

Example: Apply CSS to html

Given css and an html/xml document, cssparser can produce a named list containing the computed style for every element.

The names in this list are the xpaths for each element, and the values are the named list of property/value declarations on this element.

The calculation of the style for each element takes into account:

In the computed_styles for the following HTML document, note the following:

html <- xml2::read_html('
<html>
<div id="main" class="thin" style="border: 2px; background-color: yellow;">
  <p>Lorem Ipsum</p>
</div>
<div class="footer">
  <p>Goodbye</p>
</div>

</html>')


computed_styles <- cssparser::css_apply(html, css)
cssparser::css_pretty_print(computed_styles)
>   /html/body/div[2] {
>     border-color: rgb(50 100 255);
>     font-weight: lighter;
>     margin-left: 1cm;
>   }
>   
>   /html/body/div[2]/p {
>     font-weight: lighter;
>     background-color: green;
>   }
>   
>   /html/body/div[1] {
>     background-color: red !important;
>     color: blue;
>     border: 2px;
>   }
>   
>   /html {
>   }
>   
>   /html/body {
>   }
>   
>   /html/body/div[1]/p {
>     color: blue;
>   }

Example: Manually merging CSS styles

The following code shows a manual way of combining styles from a number of different sources using style_merge()

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# StyleSheet
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stylesheet <- '
#greg {
  fill: red !important;
  color: blue;
}

.thin {
  border: 1px;
  border-color: hsl(30 50% 40%);
  font-weight: lighter;
}'

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Example HTML
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
html <- xml2::read_html('
<div id="greg" class="thin" style="border: 2px; fill: yellow;">
  Lorem Ipsum
</div>')

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Convert stylesheet into rulesets (i.e. R lists indexed by selector)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
css <- read_css(stylesheet)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Manually calculate style for this element by merging the various styles
# which apply to this element based upon the CSS selectors
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
greg_final <- style_merge(
  css[['div']],
  css[[".thin"]],
  css[['#greg']], 
  read_inline_style("border: 2px; fill: yellow;")
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Note: "!important" property carried through.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cssparser::style_pretty_print(greg_final)
>   border: 2px;
>   border-color: hsl(30 50% 40%);
>   font-weight: lighter;
>   fill: red !important;
>   color: blue;
cssparser::css_colour_to_hex(greg_final$`border-color`)
>   [1] "#996633FF"

Related Software

Acknowledgements