Last active
November 11, 2024 02:22
-
-
Save JamoCA/bc5c58e829e191947f2e34289fd98a5a to your computer and use it in GitHub Desktop.
ColdFusion UDF that accept a struct with simple key-value pairs to generate legacy-valid, email-friendly html table and text-only key-value output
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfscript> | |
/** | |
* structToTable UDF | |
* @displayname structToTable | |
* @author James Moberg http://sunstarmedia.com, @sunstarmedia | |
* @version 1 | |
* @lastUpdate 10/28/2024 15:58 | |
* @gist https://gist.github.com/JamoCA/bc5c58e829e191947f2e34289fd98a5a | |
* @blog https://dev.to/gamesover/structtotable-generate-htmltext-output-for-displayemail-1mk4 | |
* @twitter https://x.com/gamesover/status/1851046259387469955 | |
* @LinkedIn https://www.linkedin.com/posts/jamesmoberg_coldfusion-activity-7256824771630243841-gYX7 | |
* @param String data A struct with key - simple value pairs. Required. | |
* @param String tableId Table ID to use. Optional. | |
* @param String tableClass Table class name(s) to use. Optional. | |
* @param Any keysToRedact Array to string list of keys to redact. Optional. | |
* @param Any keysToRemove Array to string list of keys to remove. Optional. | |
* @param Any sortOrder Array to string list of keys to prioritize in order (if they exist). Optional. | |
* @param Boolean niceVars An option to humanize variable names. Optional. Default = true | |
*/ | |
public struct function structToTable( | |
required struct data, | |
string tableId="", | |
string tableClass="", | |
any keysToRedact="", | |
any keysToRemove="", | |
any sortOrder="", | |
boolean niceVars=true | |
) output=false hint="I accept a struct with key-value pairs to generate legacy-valid, email-friendly html table and text-only key-value output" { | |
local.data = duplicate(arguments.data); | |
local.html = ["<table"]; | |
local.text = []; | |
local.td = "<td style=""word-break:break-word;"">"; | |
local.row = 0; | |
local.sortedKeys = []; | |
string function humanizeHeader(string string) hint="Convert a camelized/dasherized/underscored string into a humanized one" { | |
arguments.string = rereplace(arguments.string, "([^[:alnum:]_-]+)", " ", "ALL").replaceAll("_", " "); | |
arguments.string = rereplace(arguments.string, "([A-Z]+)([A-Z][a-z])", "\1 \2", "ALL"); | |
return rereplace(arguments.string, "([a-z\d])([A-Z])", "\1 \2", "ALL").replaceAll("\s+", " "); | |
} | |
if (len(trim(arguments.tableId))) arrayappend(local.html, " id=""#trim(arguments.tableId)#"""); | |
if (len(trim(arguments.tableClass))) arrayappend(local.html, " tableClass=""#trim(arguments.tableClass)#"""); | |
// update Sort Order | |
local.sortOrder = (isarray(arguments.sortOrder)) ? arguments.sortOrder : (issimplevalue(arguments.sortOrder)) ? listtoarray(arguments.sortOrder) : []; | |
// Get initial keys with original key case, append to sort order if they don't exist in user-defined order | |
local.initialKeys = listtoarray(structkeylist(local.data)); | |
for(local.key in local.sortOrder){ | |
if (arrayfindnocase(local.initialKeys, local.key)){ | |
arrayappend(local.sortedKeys, local.initialKeys[arrayfindnocase(local.initialKeys, local.key)]); | |
} | |
} | |
for(local.key in local.data){ | |
if (!arrayfindnocase(local.sortedKeys, local.key)){ | |
arrayappend(local.sortedKeys, local.key); | |
} | |
} | |
// remove keys | |
local.keys = (isarray(arguments.keysToRemove)) ? arguments.keysToRemove : (issimplevalue(arguments.keysToRemove)) ? listtoarray(arguments.keysToRemove) : []; | |
for(local.key in local.keys) { | |
if (arrayfindnocase(local.sortedKeys, local.key)){ | |
arraydeleteat(local.sortedKeys, arrayfindnocase(local.sortedKeys, local.key)); | |
} | |
} | |
arrayappend(local.html, " border=""1"" cellspacing=""0"" cellpadding=""2"">"); | |
for(local.key in local.sortedKeys){ | |
local.row += 1; | |
local.rowAttributes = !(local.row mod 2) ? " style=""background-color:##e0e0e0;"" class=""odd""" : ""; | |
local.keyText = (arguments.niceVars) ? humanizeHeader(local.key) : local.key; | |
arrayappend(local.html, "<tr#local.rowAttributes#><td style=""font-weight:bold; vertical-align:top;"">#local.keyText#:</td>"); | |
local.val = local.data[local.key]; | |
if (listfindnocase(arguments.keysToRedact, local.key)){ | |
arrayappend(local.html, "#local.td#REDACTED</td>"); | |
arrayappend(local.text, "#local.keyText#: REDACTED"); | |
} else if (isnull(local.data[local.key])){ | |
arrayappend(local.html, "#local.td#NULL</td>"); | |
arrayappend(local.text, "#local.keyText#: NULL"); | |
} else if (!issimplevalue(local.data[local.key])){ | |
arrayappend(local.html, "#local.td#[Complex Object]</td>"); | |
arrayappend(local.text, "#local.keyText#: [Complex Object]"); | |
} else if (isvalid("url", local.data[local.key])){ | |
arrayappend(local.html, "#local.td#<a href=""#local.data[local.key]#"" target=""_blank"" rel=""nofollow noreferrer"">#encodeforhtml(local.data[local.key])#</a></td>"); | |
arrayappend(local.text, "#local.keyText#: #local.val#"); | |
} else { | |
arrayappend(local.html, local.td & encodeforhtml(local.val) & "</td>"); | |
arrayappend(local.text, "#local.keyText#: #local.val#"); | |
} | |
arrayappend(local.html, "</tr>"); | |
} | |
arrayappend(local.html, "</table>"); | |
return [ | |
"html": arraytolist(local.html, " ") | |
,"text": arraytolist(local.text, chr(13) & chr(10)) | |
]; | |
} | |
</cfscript> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment