Adobe ColdFusion 2018 Compatible Version Of My ColdFusion Custom Tag DSL For HTML Emails
Over the past couple of months, I've been working on a ColdFusion custom tag DSL (Domain Specific Language) for HTML emails. It's been a thrilling adventure; and, it's been tremendously satisfying to see this approach being applied for great good at InVision. That said, InVision runs on Lucee CFML and my personal blog (this blog) runs on Adobe ColdFusion 2018. And, unfortunately, there's enough incompatibility between the two runtimes such that I can't easily use the same code. As such, I've created a new repository for an Adobe ColdFusion compatible version.
View this code in my ColdFusion Custom Tag Emails (ACF) project on GitHub.
The main compatibility issues are:
Lucee CFML
getBaseTagData()
function is fundamentally different.Adobe ColdFusion 2018 won't compile if
cachedWithin
is applied to a Function.Adobe ColdFusion 2018 throws an error if you use
name
as aCFModule
attribute.Adobe ColdFusion 2018 doesn't support fat-arrow syntax for closures.
Adobe ColdFusion 2018 doesn't have a
createUniqueId()
function.Adobe ColdFusion 2018 can't seem to access parent tag data for tags used in the same file.
Most of these issues could be smoothed-over such that a single code-base could be used for both the Lucee CFML and Adobe ColdFusion runtimes. But, we would lose efficiencies, especially with the cacheWithin
compile issues. So, for the time being, these will be in different proof-of-concept repositories.
Just as a reminder, this is what it looks like to author an email using my ColdFusion custom tag DSL:
<!--- Import custom tag libraries. --->
<cfimport prefix="core" taglib="./core/" />
<cfimport prefix="html" taglib="./core/html/" />
<cfimport prefix="imageGrid" taglib="./customized/image-grid/" />
<cfimport prefix="customized" taglib="./customized/" />
<!--- // ------------------------------------------------------------------------- // --->
<!--- // ------------------------------------------------------------------------- // --->
<core:Email
subject="Ben Nadel has met some amazing people!"
teaser="See them for yourself!">
<core:Body>
<html:h1>
<core:NoWrapText>Ben Nadel</core:NoWrapText> has met some truly
<html:a href="https://www.bennadel.com/people" decoration="false">
amazing people
</html:a>
</html:h1>
<html:p>
Good morning my beautiful, beautiful friends!
</html:p>
<html:p>
In the midst of the <html:em>stress</html:em> of this global pandemic, it's
important to <html:strong>remain thankful</html:strong> for all the good
people that we have in our lives. And, while we can't see our people as much
as we might like, we can let the memory of them keep us warm.
</html:p>
<html:p>
Here are some of the great people that I've met:
</html:p>
<imageGrid:List>
<imageGrid:Image
title="Sara Dunnack"
src="https://bennadel-cdn.com/images/header/photos/sara_dunnack_3.jpg"
/>
<imageGrid:Image
title="Sara Dunnack"
src="https://bennadel-cdn.com/images/header/photos/sara_dunnack_3.jpg"
/>
<imageGrid:Image
title="Sara Dunnack"
src="https://bennadel-cdn.com/images/header/photos/sara_dunnack_3.jpg"
/>
<imageGrid:Image
title="Sara Dunnack"
src="https://bennadel-cdn.com/images/header/photos/sara_dunnack_3.jpg"
/>
</imageGrid:List>
<html:p>
Oh the memories! To see more wonderful people, check out my People section.
</html:p>
<customized:CallToAction href="https://www.bennadel.com/people" margins="normal">
See More People
</customized:CallToAction>
<html:hr margins="double" />
<html:p>
The following is just a bunch of random style stuff to experiment with and
to see how this all renders in email clients.
</html:p>
<html:h1>
Favorite movies
</html:h1>
<html:p>
There are a lot of great movies out there. I like movies across all genres;
from action, to rom-com, to sci-fi, to drama — they all have their
place. But, I have to admit that my <html:em>favorite genres</html:em> are
definitely <html:strong>Action</html:strong> and
<html:strong>Romantic Comedies</html:strong>
</html:p>
<html:h2>
Best Meg Ryan movies
</html:h2>
<html:p>
And ... when it comes to Romantic Comedies, there's no one better than Meg
Ryan. For Years, Ryan was America's sweetheart, delighting audiences and
making us swoon in such films as:
</html:p>
<html:ul>
<html:li>
<html:a href="https://www.imdb.com/title/tt0098635/">
When Harry Met Sally
</html:a>
—
<html:mark>this is my favorite!</html:mark>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0128853/">
You've Got Mail
</html:a>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0108160/">
Sleepless in Seattle
</html:a>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0113117/">
French Kiss
</html:a>
</html:li>
</html:ul>
<html:h2>
Great movie quotes
</html:h2>
<html:p>
One of the great features of a <html:em>feature</html:em> film (see what I
did there) is that they leave you with dynamite quotes that really make you
think. One of the highly quotable scenes that I've been thinking about a lot
lately is from Blade Runner.
</html:p>
<html:h3>
Blade Runner (1982)
</html:h3>
<html:p>
In the last scene of this sci-fi classic, Rutger Hauer contemplates existence
in the final moments of this life:
</html:p>
<html:blockquote>
<html:p margins="none">
I've seen things you people wouldn't believe. Attack ships on fire off
the shoulder of Orion. I watched C-beams glitter in the dark near the
Tannhauser Gate. All those moments will be lost in time, like tears
in rain.
</html:p>
</html:blockquote>
<html:p>
Now, in the <html:em>Director's cut</html:em> of the film, that the end of
it. But, in the general release cut, Harris Ford follow-up with some
narration that—in my opinion— adds a lot of needed color:
</html:p>
<html:blockquote>
<html:p margins="none">
I don't know why he saved my life. Maybe in those last moments he loved
life more than he ever had before. Not just his life - anybody's life;
my life. All he'd wanted were the same answers the rest of us want.
Where did I come from? Where am I going? How long have I got? All I could
do was sit there and watch him die.
</html:p>
</html:blockquote>
<html:h2>
Top 5 Arnold Schwarzenegger movies
</html:h2>
<html:p>
Obviously, no discussion about movies could ever be considered complete if it
didn't pay homage to the <html:em>master blaster</html:em> himself —
<html:mark>Arnold Schwarzenegger</html:mark>. To make sure we cover all of
our bases, here are my Top 5:
</html:p>
<html:ol>
<html:li>
<html:a href="https://www.imdb.com/title/tt0103064/">
Terminator 2
</html:a>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0111503/">
True Lies
</html:a>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0100802/">
Total Recall
</html:a>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0099938/">
Kindergarten Copy
</html:a>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0096320/">
Twins
</html:a>
</html:li>
<html:li>
<html:a href="https://www.imdb.com/title/tt0093773/">
Predator
</html:a>
—
<html:mark>Because "5" isn't enough!</html:mark>
</html:li>
</html:ol>
</core:Body>
<core:TrackingPixel src="https://img.spacergif.org/v1/spacer.gif" />
</core:Email>
As you can see, we're using ColdFusion custom tags to implement basic HTML elements. These custom tags then handle all of the CSS property inlining into style
attributes.
Want to use code from this post? Check out the license.
Reader Comments
Adobe added this in update 5 and finished fixing the bugs in update 6. Were you testing on an older version of 2018?
https://helpx.adobe.com/coldfusion/developing-applications/the-cfml-programming-language/extending-coldfusion-pages-with-cfml-scripting/using-closures.html
@Brad,
Good question. I just use CommandBox via
cfengine=adobe@2018
. I guess I just assumed that would be using whatever the latest version was. But, maybe I need to update the cached artifacts or use a patch number in the engine call. As you know, I only CommandBox at a 2nd grade level :D@All,
I wanted to further document some of the
getBaseTagData()
issues. Specifically when trying to store a key into the parent tag / base tag that contains invalid variable name characters:www.bennadel.com/blog/4065-strange-variable-name-error-when-writing-to-base-tag-in-adobe-coldfusion-2018.htm
In Adobe ColdFusion, you have to explicitly reference the
variables
scope (which doesn't work in Lucee CFML, FYI).The command you showed should start the latest update of 2018 which supports lambdas. Are they not working for you on the server you started? No need to do anything with artifacts, etc. Each version of the engine is a new version of the artifact, so CommandBox will download it as necessary.
@Brad,
Hmmmm, Ok, so when I went to test it out this morning, it looked like CommandBox actually installed something new:
And now, when I try the same code that was causing compilation errors before, it works
:man-shrug:
. No idea why this wasn't working earlier. I wonder it's because I had aserver.json
file that had"cfengine":"adobe@2018"
? Maybe that caches harder somehow? For this test (above), I just did started the server directly from the CLI rather than from the directory that has theserver.json
file.@Brad,
Also, totally random aside, I never a problem stopping a Lucee server. But, when I go to stop an ACF server, I've been getting this lately:
@Ben,
That's a new one. I did fix an issue in the latest version of CommandBox that output any messages from the console that occurred when stopping a server. That message was likely always there but not showing up. I don't recognize any of it though. Perhaps it's specific to a Mac. Can you ping me when you get a chance on Slack so I can take a look at it? I think I also converted some old cfexecute code to Java's Process builder inside the stop command but it's working on Windows so there may just be a pathing issue on Mac.
@Brad,
I also just updated my MacOS. I'll try updating my CommandBox to see if that fixes things.