TerrenceRyan.com

I'm a 35 year old redhead geek from Philly.
I'm currently a Developer Evangelist for Adobe.
Also the author of Driving Technical Change

Automating Documentation Part 2

2 Comments

This is a follow up to the post Automating Documentation. Jim Priest wanted to see example code, and I'm happy to oblige.

For this example, I am sharing the code for documenting "steps" in Squidhead. Steps are operations that do one thing, like generate stored procs, or ant scripts, or email developers. They are powered by cfm templates in a specific folder. Once there they can be referenced through in the project's config file. The documentation for them is included in the download for Squidhead, and can be viewed online (Squdihead - Steps).

So after the jump, here is the code for creating this documentation.

So first thing I do is setup a few parameters.

<cfset stepsXMLfile = "#expandPath('.')#/stepsXML.xml" />
<cfset
outputfile="w:\inetpub\wwwroot\squidhead2\docs\steps.cfm" />

<cfdirectory action="list" recurse="false" directory="#expandPath('../../steps')#" name="steps" type="file" />

Then I conditionally build the file in case I deleted it.

<h2>Building XML</h2>
<cfif
not FileExists(stepsXMLfile)>

<p>Transforming Steps to XML.</p>

<cfxml variable="XMLOutput">
<steps>
<cfoutput query="steps">
<#ListFirst(name, '.')#>
<documentation />
<requires />
</#ListFirst(name, '.')#>
</cfoutput
</steps>
</cfxml>

<p>Writing to Disk.</p>

<cffile action="write" file="#stepsXMLfile#" output="#XMLOutput#">

<cfelse>

<p>Already Built.</p>

</cfif>

Then I go through and check to see if each file has a documentation node:

<h2>Checking XML</h2>

<cffile action="read" file="#stepsXMLfile#" variable="rawFile" />
<cfset
stepsXML = XMLParse(rawfile) />
<cfset
changed = FALSE />

<cfoutput>
<cfloop
query="steps">
<cfset stepName = ListFirst(name, '.')/>

<cfif not structKeyExists(stepsXML.steps, stepName)>

<p>Adding #stepName#</p>
<cfset changed = TRUE />
<cfset stepsXML.steps[stepName] = XmlElemNew(stepsXML,stepName) />
<cfset stepsXML.steps[stepName]['documentation'] = XmlElemNew(stepsXML,"documentation") />
<cfset stepsXML.steps[stepName]['requires'] = XmlElemNew(stepsXML,"requires") />

</cfif>

</cfloop>

</cfoutput>

<cfif changed>
    <cffile action="write" file="#stepsXMLfile#" output="#stepsXML#" />
</cfif>

Next I go through and mark any documentation that is not filled in as a problem and through a 500 error. This will cause ANT to stop running.

<cfset incomplete = FALSE />
<cfset
stepArray = StructKeyArray(stepsXML['steps']) />

<h2>Checking Documentation</h2>

<cfoutput>
<cfloop
index="i" from="1" to="#ArrayLen(stepArray)#">

<cfif StructKeyExists(stepsXML['steps'][stepArray[i]], "documentation") AND

len(stepsXML['steps'][stepArray[i]]['documentation']['XMLText']) lt 1>

<p>Documentation for step #stepArray[i]# is not filled in. </p>

<cfset incomplete = TRUE />

</cfif>

</cfloop>
</cfoutput>

<cfif incomplete>

<cfheader statuscode="500" />

</cfif>

I finish by writing the XML back out to disk as HTML. I'm sure this can be done through XSLT, but I don't bother.

<h2>Building HTML Reference.</h2>

<cfsaveContent variable="stepReference">

<h2>Step Reference</h2>

<cfinclude template="stepsDocs.cfm" />
<cfset
stepArray = StructKeyArray(stepsXML['steps']) />
<cfset
ArraySort(stepArray,'textNoCase' )>

<h2>Step Details</h2>

<cfoutput>
<dl>

<cfloop index="i" from="1" to="#ArrayLen(stepArray)#">

<dt>#stepArray[i]#</dt>
<dd>#stepXML['steps'][stepArray[i]]['documentation']['XMLText']#</dd>
<cfif len(stepXML['steps'][stepArray[i]]['documentation']['XMLText']) gt 0>

<dd class="requires">Requires: #stepXML['steps'][stepArray[i]]['requires']['XMLText']#</dd>
</cfif>

</cfloop>

</cfoutput>

</dl>

</cfsavecontent>

<cffile action="write" file="#outputfile#" output="#stepReference#" />

Then to call through ANT, I just add this line to a task in my ANT build file:

<get src="${project.url}/tools/stepDocumenter/" dest="${project.logPath}/tools/stepDocumenter.html" />

I then include these dynamic steps in a static document that includes some background on what steps are and what not.

2 responses so far ↓

  • 1 Jim Priest

    Thanks for the followup! I'm going to tinker with this just as soon as I finish up my current project!

Leave a Comment









Categories

Monthly Archives

Tag Cloud

coldfusion web development flex coldfusion builder appearances squidhead coldfusion builder extensions higher ed flash builder air mobile android adobe apptacular html5 driving technical change running a coldfusion shop adobemax06 movable type flash catalyst flash blackberry adobemax07 adobemax08 hero finicky css adobemax09 holy crap i’m a mobile developer centaur basecamp cfc unfuddle motorola metablog irrational characters ios git evangelism devices code reviews ant wharton subversion security phonegap philly philadelphia multidevice knowledge@wharton jobs browserlab adobemax10 adobe tv unfuddlecfc svnauth.cfc semantic html semantic html responsive web design qnx nlb linux jquery mobile java it github flexorg fireworks edge eclipse dreamweaver apps apple adobemax11