Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created March 25, 2014 00:53
Compiling Several Linked Files Into One File
<!--- Import tag library. --->
<cfimport taglib="./" prefix="linked" />
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Linked File ColdFusion Custom Tags</title>
<!--- Include javascript files. --->
<linked:files
type="javascript"
rebuildparam="reset"
file="#APPLICATION.Root#scripts.js"
url="#REQUEST.WebRoot#scripts.js">
<linked:file path="#APPLICATION.Root#forms.js" />
<linked:file path="#APPLICATION.Root#util.js" />
<linked:file path="#APPLICATION.Root#calendar.js" />
</linked:files>
</head>
<body>
<h1>
Linked File ColdFusion Custom Tags
</h1>
<p>
Hello World.
</p>
</body>
</html>
<head>
<title>Linked File ColdFusion Custom Tags</title>
<script type="text/javascript" src="./scripts.js"></script>
</head>
<!--- Kill extra output. --->
<cfsilent>
<!--- Check to see which mode we are executing. --->
<cfswitch expression="#THISTAG.ExecutionMode#">
<cfcase value="Start">
<!--- Param tag attributes. --->
<!---
The type of linked file. Currently, only
Javascript and Style are supported.
--->
<cfparam
name="ATTRIBUTES.Type"
type="regex"
pattern="(?i)javascript|style"
/>
<!---
This is the URL key that will trigger a rebuild
of the merged file data.
--->
<cfparam
name="ATTRIBUTES.RebuildParam"
type="string"
default=""
/>
<!---
This is the expanded path to the compiled file
that we are going to create.
--->
<cfparam
name="ATTRIBUTES.File"
type="string"
/>
<!---
This is the page-relative URL to the compiled
file that we are going to create. This will
have to make sense from the client's (browser)
perspective.
--->
<cfparam
name="ATTRIBUTES.Url"
type="string"
/>
<!---
This struct will hold the nested file path
data. Due to logic in the nested File tag, we
can be sure that this holds ONLY valid paths.
--->
<cfset VARIABLES.FilePaths = [] />
<!---
Before we execute the child tags, we want to
set a flag to determine whether the local file
system should even be checked. File reads are
a relatively expensive process, so we want to
limit them whenever we don't need them
(including FileExists() checks).
We will want to rebuild the file (and therefore
need access to the local file system) if the
rebuild param exists in the URL or the actual
compiled file does not exist.
--->
<cfset VARIABLES.Rebuild = (
StructKeyExists( URL, ATTRIBUTES.RebuildParam ) OR
(NOT FileExists( ATTRIBUTES.File ))
) />
</cfcase>
<cfcase value="End">
<!---
At this point, we might need to build or re-build
the compiled file. This will happen if the file
either does not exist, or the rebuild parameter
is present.
--->
<cfif VARIABLES.Rebuild>
<!--- Try to delete the existing file. --->
<cfif FileExists( ATTRIBUTES.File )>
<cffile
action="delete"
file="#ATTRIBUTES.File#"
/>
</cfif>
<!--- Loop over the file paths. --->
<cfloop
index="VARIABLES.FilePath"
array="#VARIABLES.FilePaths#">
<!--- Read in the file data. --->
<cffile
action="read"
file="#VARIABLES.FilePath#"
variable="VARIABLES.FileData"
/>
<!---
Write the individual file data to the
compiled file, appending the data and
a new line (to make sure nothing breaks
cross-file).
--->
<cffile
action="append"
file="#ATTRIBUTES.File#"
output="#VARIABLES.FileData#"
addnewline="true"
/>
</cfloop>
</cfif>
<!--- Check to see which type of file we linking. --->
<cfswitch expression="#ATTRIBUTES.Type#">
<cfcase value="Javascript">
<!--- Store the output. --->
<cfsavecontent variable="THISTAG.GeneratedContent">
<cfoutput>
<script type="text/javascript" src="#ATTRIBUTES.Url#"></script>
</cfoutput>
</cfsavecontent>
</cfcase>
<cfcase value="Style">
<!--- Store the output. --->
<cfsavecontent variable="THISTAG.GeneratedContent">
<cfoutput>
<link rel="stylesheet" type="text/css" href="#ATTRIBUTES.Url#"></link>
</cfoutput>
</cfsavecontent>
</cfcase>
</cfswitch>
<!---
As one final cleaning, just trim the generated
content to make sure there is no leading or
trailing spaces.
--->
<cfset THISTAG.GeneratedContent = Trim(
THISTAG.GeneratedContent
) />
</cfcase>
</cfswitch>
</cfsilent>
<!--- Check to see which mode we are executing. --->
<cfswitch expression="#THISTAG.ExecutionMode#">
<cfcase value="Start">
<!--- Get base tag data. --->
<cfset VARIABLES.FilesTag = GetBaseTagData( "cf_files" ) />
<!--- Param tag attributes. --->
<!--- This is the expanded path to the given file. --->
<cfparam
name="ATTRIBUTES.Path"
type="string"
/>
<!---
Check to see if we even need to worry about this
file. Only go further if the base tags contains
the rebuild flag.
--->
<cfif NOT VARIABLES.FilesTag.Rebuild>
<!---
We have no need to use the child tag, so exit
it without processing.
--->
<cfexit method="exittag" />
</cfif>
<!---
ASSERT: At this point, we know that the compiled
file needs to be rebuilt and therefore we will need
to check this child tag.
--->
<!---
Store path in base tag. Check to see if the file
exists so that we only have valid files passed
up to the base tag.
--->
<cfif FileExists( ATTRIBUTES.Path )>
<cfset ArrayAppend(
VARIABLES.FilesTag.FilePaths,
ATTRIBUTES.Path
) />
</cfif>
</cfcase>
<cfcase value="End">
</cfcase>
</cfswitch>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment