I use Atom as my primary code editor of late and one thing I really like in it is the automatic code beautification of atom-beautifier. It works great on my html and javascript projects. However, that cool feature isn’t extended to ColdFusion. Fortunately, Austin Cheney, the guy who maintains the library that actually does the beautification showed a willingness to implement a beautifier for CF if someone would just tell him what the rules were for the various tags in regards to them needing to be closed.
There are three different tag types in CF - those that require
an end tag, those that have an optional (free
) end tag, and those that can not (prohibited
) have an end tag.
Those tags with an optional end tag can be ended in any of the following three ways:
<cfstoredproc>
<cfstoredproc />
<cfstoredproc></cfstoredproc>
The other two categories are pretty self explanatory.
I tried to manually go through the list of tags at CFDocs but that was prone to mistakes on my part. Adam Cameron on twitter recommended I get help from Dom Watson and Dom pointed me to two helpful lucee functions; getTagList
and getTagData
which, when combined, provided me with the answers I needed.
PROTIP If you don’t have lucee installed you can put together quick cf scripts to run against all of the main CF engines at http://trycf.com/ - that’s how I ran this code.
Here is the code I used to get a definitive list:
<cfset tags = GetTagList() />
<cfset bodies = structNew() />
<cfset namespace = "cf" />
<cfset tags = tags[namespace] />
<cfset maxLength = 0 >
<cfloop list="#StructKeyList(tags)#" index="tagname">
<cfset tag = getTagData(namespace, tagname) />
<cfif not structkeyExists(bodies, tag.bodyType)>
<cfset bodies[tag.bodyType] = ArrayNew(1) />
</cfif>
<cfset ArrayAppend(bodies[tag.bodyType], tagname)>
</cfloop>
<cfoutput>
<table>
<tr>
<cfloop list="#structKeyList(bodies)#" index="key">
<th>#key# end tag</th>
<cfif ArrayLen(bodies[key]) GT maxLength>
<cfset maxLength = ArrayLen(bodies[key])>
</cfif>
<cfset ArraySort(bodies[key], "text", "asc")>
</cfloop>
<cfloop from="1" to="#maxLength#" index="i">
<tr>
<cfloop list="#structKeyList(bodies)#" index="key">
<td>
<cfif ArrayLen(bodies[key]) GTE i>
#bodies[key][i]#
<cfelse>
</cfif>
</td>
</cfloop>
</tr>
</cfloop>
</tr>
</table>
</cfoutput>
And here is the final result:
required end tag | free end tag | prohibited end tag |
---|---|---|
case | _ | abort |
catch | ajaximport | applet |
component | ajaxproxy | application |
defaultcase | cache | argument |
execute | chart | associate |
finally | chartseries | authenticate |
form | content | break |
function | div | chartdata |
graph | document | col |
if | documentitem | collection |
interface | documentsection | continue |
lock | dump | cookie |
login | file | dbinfo |
loop | htmlbody | directory |
htmlhead | else | |
mailpart | http | elseif |
output | invoke | error |
query | layout | exit |
savecontent | layoutarea | feed |
script | map | flush |
select | mapitem | forward |
silent | mediaplayer | ftp |
static | module | graphdata |
stopwatch | pageencoding | header |
switch | httpparam | |
table | processingdirective | image |
timer | setting | imap |
transaction | storedproc | import |
try | thread | include |
while | trace | index |
xml | videoplayer | input |
window | insert | |
zip | invokeargument | |
ldap | ||
location | ||
log | ||
loginuser | ||
logout | ||
mailparam | ||
object | ||
objectcache | ||
param | ||
pdfparam | ||
pop | ||
procparam | ||
procresult | ||
property | ||
queryparam | ||
registry | ||
rethrow | ||
retry | ||
return | ||
schedule | ||
search | ||
servlet | ||
servletparam | ||
set | ||
sleep | ||
slider | ||
throw | ||
update | ||
video | ||
videoplayerparam | ||
wddx | ||
x_ | ||
zipparam |