Converting FontAwesome CSS to Lua with R: A Unicode Adventure

quarto
lua
r
Author

James Balamuta

Published

October 19, 2024

As a die-hard Quarto fan, you often find yourself needing to bridge gaps between different technologies. Recently, I faced an interesting challenge: converting FontAwesome’s CSS definitions into a Lua table, complete with Unicode escape sequences. This task, while seemingly straightforward, presented some unique hurdles. In this post, I’ll walk you through the R script I developed to tackle this problem.

The Challenge

FontAwesome provides its icons in a CSS file, where each icon is defined with a class name and a Unicode value. Our goal was to create a Lua table that maps these class names to their corresponding Unicode values, but with a twist: we needed to represent these Unicode values as escape sequences in Lua strings.

Here’s an example of how the CSS looks:

.fa-0:before{content:"\30"}

And here’s how we wanted the Lua table to look:

local fontawesome_map = {
  ["fa-0"] = "\\30",
  -- more icons...
}

The Solution

Not wanting to tackle this task manually, we turned to R for help. We used R’s string manipulation capabilities to extract the necessary data from the CSS file and convert it into the desired Lua table format. With this script, we can now automate the process and handle any edge cases that might arise in the future.

Here’s the script that does the magic:

# Bring in stringr for peace of mind with regex matching
library(stringr)

# Location of the FontAwesome CSS file
url <- "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css"

# Read the CSS file
css_content <- readLines(url)

# Function to convert unicode to Lua safe string format
unicode_to_escaped_lua_string <- function(unicode) {
  sprintf('"\\\\%s"', unicode)
}

# Extract class names and unicode values
pattern <- "\\.(fa-[\\w-]+):before\\{content:\"\\\\([\\w]+)\"\\}"
matches <- str_match_all(css_content, pattern)

# Combine all matches
all_matches <- do.call(rbind, matches)

# Create a data frame
fa_data <- data.frame(
  class = all_matches[, 2],
  unicode = all_matches[, 3],
  stringsAsFactors = FALSE
)

# Convert unicode values to Lua string format
fa_data$lua_unicode <- sapply(fa_data$unicode, unicode_to_escaped_lua_string)

# Generate Lua table
lua_table <- paste0('  ["', fa_data$class, '"] = ', fa_data$lua_unicode, ",\n", collapse = "")

# Create Lua accessor function
lua_accessor <- paste0(
  "-- Function to get Unicode value for a FontAwesome icon name\n",
  "local function fa_unicode(icon_name)\n",
  "  return fa_icons[icon_name] or nil\n",
  "end\n\n",
  "return {\n",
  "  fa_unicode = fa_unicode\n",
  "}\n"
)

# Write the Lua table to a file
cat(
    "local fa_icons = {\n",
    lua_table,  
    "}\n\n",
    file = "fa.lua",
    sep = ""
)

# Write the Lua accessor function and export to file
cat(
    lua_accessor,
    file = "fa.lua",
    sep = "",
    append = TRUE
)

# Status message
print("FontAwesome Class to Unicode table has been generated and saved to 'fa.lua'")

Breaking It Down

  1. Reading the CSS: We start by reading the FontAwesome CSS file into R by using readLines() to have each line listed in a character vector.

  2. Extracting the Data: Using a regular expression, we extract the icon class names and their corresponding Unicode values from the CSS.

  3. Converting to Lua Format: We convert the unicode values into an escaped Lua string. The unicode_to_escaped_lua_string() function handles this conversion.

  4. Generating the Lua Table and Accessor: We construct the Lua table as a string, mapping each FontAwesome class to its Unicode value. We also create a Lua accessor function that allows users to retrieve the Unicode value for a given icon class.

  5. Writing the Output: Finally, we write the generated Lua table to a file named fa.lua.

The Result

The script produces a Lua file that looks something like this:

local fa_icons = {
  ["fa-quidditch"] = "\\f458",
  ["fa-toggle-off"] = "\\f204",
  -- ... lots more icons ...
}

-- Function to get Unicode value for a FontAwesome icon name
local function fa_unicode(icon_name)
  return fa_icons[icon_name] or nil
end

return {
  fa_unicode = fa_unicode
}

With the Lua table and accessor function in place, we can now access FontAwesome unicode values in their Lua projects by using the fa_unicode function after importing the fa.lua file.

Fin

By bridging the gap between CSS and Lua, we’ve created a useful tool for developers working with FontAwesome icons in Lua environments.