I've worked with different projects that perform tokenization differently; often it involves using different delimiters. While researching I saw that Drupal (which I don't use) has an official TokenReplace function documented in their API. I thought I'd write something similar since this this doesn't appear to be a function that Adobe ColdFusion currently has.
Usage
Create a string with tokens.
Here are some samples. (I don't personally recommend using HTML brackets, pound signs or parenthesis, but some frameworks use them.)
Hello {name}? Is this {address}? I have a special delivery for '{ccName}'.
Hello [name]? Is this [address]? I have a special delivery for '[ccName]'.
Hello <name>? Is this <address>? I have a special delivery for '<ccName>'.
Hello :name:? Is this :address:? I have a special delivery for ':ccName:'.
Hello <<name>>? Is this <<address>>? I have a special delivery for '<<ccName>>'.
Hello ::name::? Is this ::address::? I have a special delivery for '::ccName::'.
Hello #name#? Is this #address#? I have a special delivery for '#ccName#'.
Hello %name%? Is this %address%? I have a special delivery for '%ccName%'.
Hello -name-? Is this -address-? I have a special delivery for '-ccName-'.
Create a data structure.
(NOTE: The token is not case-sensitive.)
replacementData = {
"name" = "Bruce Wayne",
"Address" = "1007 Mountain Drive, Gotham",
"ccName" = "The Dark Night"
}
Use the UDF
TokenReplace(Text, replacementData, "{", "}")
// Hello Bruce Wayne? Is this 1007 Mountain Drive, Gotham? I have a special delivery for 'The Dark Night'.
NOTE: ReEscape may be an Adobe ColdFusion-only function, but BlueDragon supports it too. I'm not sure what the equivalent Lucee function is. (UPDATE: I replaced the ACF built-in function with the REEscape UDF from CFLib.)
TryCF Demo
https://trycf.com/gist/18e4d1662e8417fc824e264b2490dd1b
Source
https://gist.github.com/JamoCA/18e4d1662e8417fc824e264b2490dd1b
<!--- TokenReplace - replaces tokens in a string with data from a struct | |
2/27/2020 James Moberg https://www.sunstarmedia.com/ | |
GIST: https://gist.github.com/JamoCA/18e4d1662e8417fc824e264b2490dd1b | |
Blog: https://dev.to/gamesover/tokenreplace-a-coldfusion-user-defined-function-155b | |
TryCF: https://trycf.com/gist/18e4d1662e8417fc824e264b2490dd1b | |
3/2/2020 Updated ReplaceList() to support 5 params so it works w/Lucee. | |
---> | |
<cfscript> | |
string function TokenReplace(required string Text, required struct data, string startBracket = "[", string endBracket = "]", boolean clearEmpty=false) output=false hint="replaces tokens in a string with data from a struct" { | |
var response = javacast("string", arguments.text); | |
var tokens = []; | |
var token = ""; | |
var cleanTag = ""; | |
var test = ""; | |
var pos = 0; | |
var oldPos = 1; | |
var special_char_list = "\,+,*,?,.,[,],^,$,(,),{,},|,-"; | |
var esc_special_char_list = "\\,\+,\*,\?,\.,\[,\],\^,\$,\(,\),\{,\},\|,\-"; | |
var escStart = ReplaceList(arguments.startBracket, special_char_list, esc_special_char_list); | |
var escEnd = ReplaceList(arguments.endBracket, special_char_list, esc_special_char_list); | |
test = REFind("(#escStart#.+?#escEnd#)", response, 1, 1); | |
pos = test.pos[1]; | |
while(pos gt 0) { | |
arrayAppend(tokens, mid(response, pos, test.len[1])); | |
oldpos = pos+test.len[1]; | |
test = REFind("(#escStart#.+?#escEnd#)", response, oldPos, 1); | |
pos = test.pos[1]; | |
} | |
for (token in tokens){ | |
cleanTag = trim(replacelist(token, "#arguments.startBracket#,#arguments.endBracket#", ",", ",", true)); | |
if (StructKeyExists(arguments.data, cleanTag) AND isSimplevalue(arguments.data["#cleanTag#"])){ | |
response = response.replaceAll("(?i)#escStart##cleanTag##escEnd#", arguments.data["#cleanTag#"]); | |
} else if (arguments.clearEmpty){ | |
response = response.replaceAll("(?i)#escStart##cleanTag##escEnd#", ""); | |
} | |
} | |
return response; | |
} | |
</cfscript> | |
<h2>TokenReplace UDF Demo</h2> | |
<CFSET DelimiterData = [ | |
["[", "]"], | |
["{", "}"], | |
["<", ">"], | |
[":", ":"], | |
["<<", ">>"], | |
["::", "::"], | |
["##", "##"], | |
["%", "%"], | |
["-", "-"] | |
]> | |
<cfset replacementData = { | |
"name" = "Bruce Wayne", | |
"Address" = "1007 Mountain Drive, Gotham", | |
"ccName" = "The Dark Night" | |
}> | |
<cfoutput> | |
<cfloop array="#DelimiterData#" INDEX="Delimiters"> | |
<cfset Text = "Hello #Delimiters[1]#name#Delimiters[2]#? Is this #Delimiters[1]#address#Delimiters[2]#? I have a special delivery for '#Delimiters[1]#ccName#Delimiters[2]#'."> | |
<fieldset><legend>Delimiters: #EncodeforHTML(ArrayToList(Delimiters))#</legend> | |
<xmp>#Text#</xmp> | |
<div>#TokenReplace(Text, replacementData, Delimiters[1], Delimiters[2], true)#</div> | |
</fieldset> | |
</cfloop> | |
</cfoutput> |
Top comments (0)