Skip to content

Instantly share code, notes, and snippets.

@roryl
Last active August 8, 2016 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save roryl/f7fcd0fc09be6a207adba91b495c55b7 to your computer and use it in GitHub Desktop.
Save roryl/f7fcd0fc09be6a207adba91b495c55b7 to your computer and use it in GitHub Desktop.
Lucee Custom Tag Examples
component {
this.customTagPaths = ["../custom_tag_import"];
}
component {
this.children = [];
/**
* Constructor for the custom tag
* @param {component} component parent Whether the tag has a parent tag, default is null
* @param {boolean} boolean hasEndTag Whether the tag has an end tag
* @return {void}
*/
public void function init(component parent, required boolean hasEndTag){
}
public function addChild(required component child){
this.children.append(child);
}
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
return true;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
param name="attributes.title";
echo("<h1>#attributes.title#</h1>");
if(this.children.len() == 0){
echo("<p>There are no sections yet</p>")
} else {
echo("<h2>Table of Contents</h2>");
echo("<ol>");
for(var child in this.children){
echo("<li>#child.getTitle()#</li>");
}
echo("</ol>");
}
for(var child in this.children){
echo("<h3>#child.getTitle()#</h3>");
echo("<p>#child.getBody()#</p>");
}
return false;
}
}
<html>
<head>
<meta charset="UTF-8">
<title>A Basic Custom Tag Example</title>
</head>
<body>
<div>
<cf_greeting firstName="Jim" />
</div>
</body>
</html>
<html>
<head>
<meta charset="UTF-8">
<title>A Basic Custom Tag Example</title>
</head>
<body>
<div>
<cf_greetingSmith firstName="Jim" />
</div>
</body>
</html>
component {
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.name";
writeOutput("Hello #attributes.name#");
return true;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
return false;
}
}
/**
* My xUnit Test
*/
component extends="testbox.system.BaseSpec"{
/*********************************** LIFE CYCLE Methods ***********************************/
// executes before all test cases
function beforeTests(){
}
// executes after all test cases
function afterTests(){
}
// executes before every test case
function setup( currentMethod ){
}
// executes after every test case
function teardown( currentMethod ){
}
/*********************************** TEST CASES BELOW ***********************************/
// Remember that test cases MUST start or end with the keyword 'test'
function checkAllSyntaxTest(){
var files = directoryList("");
for(file IN files){
if(file CONTAINS ".cfm" AND
!file CONTAINS "attribute_missing.cfm" AND
!file CONTAINS "view_metadata_fixed.cfm"){
include template="#getFileFromPath(file)#";
}
}
}
function checkFixedMetaDataErrorTest(){
expect(function(){
include template="view_metadata_fixed.cfm";
}).toThrow();
}
function checkAttrbitueMissingErrorTest(){
expect(function(){
include template="attribute_missing.cfm";
}).toThrow();
}
}
component {
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.firstName";
param name="attributes.lastName";
writeOutput("<p>Hello #attributes.FirstName# #attributes.lastName#, </p>");
writeOutput("<p>The time is #timeFormat(now(), "hh:mm tt")#</p>");
return false;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
return false;
}
}
component {
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.firstName";
param name="attributes.lastName";
writeOutput("<p>Hello #attributes.FirstName# #attributes.lastName#, </p>");
writeOutput("<p>The time is #timeFormat(now(), "hh:mm tt")#</p>");
return false;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
return false;
}
}
component {
this.metadata.attributetype="fixed";
this.metadata.attributes.firstName={required:true,type:"string"};
this.metadata.attributes.lastName={required:true,type:"string", hint:"Some hint to describe this tag"};
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
writeOutput("<p>Hello #attributes.FirstName# #attributes.lastName#, </p>");
writeOutput("<p>The time is #timeFormat(now(), "hh:mm tt")#</p>");
return false;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
return false;
}
}
component {
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.firstName";
param name="attributes.lastName" default="smith";
writeOutput("<p>Hello #attributes.FirstName# #attributes.lastName#, </p>");
writeOutput("<p>The time is #timeFormat(now(), "hh:mm tt")#</p>");
return false;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
return false;
}
}
component {
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.invitee";
writeOutput("Hello #attributes.invitee#,");
return true;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
writeOutput(generatedContent);
return false;
}
}
component {
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.invitee";
caller.salutation = "Hello #attributes.invitee#";
caller.message = "I'd like to let you know that you are invited to our party!";
return false;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
return false;
}
}
component {
this.metadata.parsebody = true;
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.invitee";
writeOutput("Hello #attributes.invitee#,");
return true;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
structAppend(local, caller);
writeOutput(evaluate(de(generatedContent)));
return false;
}
}
component {
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
param name="attributes.invitee";
writeOutput("Hello #attributes.invitee#,");
return true;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
writeOutput(ucase(generatedContent));
return false;
}
}
<cfscript>
writeDump(getTagData("cf", "greetingMetaDataFixed"));
</cfscript>
component {
/**
* Constructor for the custom tag
* @param {component} component parent Whether the tag has a parent tag, default is null
* @param {boolean} boolean hasEndTag Whether the tag has an end tag
* @return {void}
*/
public void function init(component parent, required boolean hasEndTag){
if(!isNull(parent)){
parent.addChild(this);
} else {
throw("Cannot have sections without a parent <cf_article>");
}
}
public function getTitle(){
return variables.title;
}
public function getBody(){
return variables.body;
}
/**
* Invoked during the start of the custom tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onStartTag(required struct attributes, required struct caller){
return true;
}
/**
* Invoked after the completion of the closing tag
* @param {struct} required struct attributes The attributes passed to the custom tag
* @param {struct} required struct caller A reference to the variables scope from the location that calls the custom tag
* @param {string} string generatedContent The output generated between the start and end tags at the caller
* @return {boolean} To control whether to execute the body of the custom tag
*/
public boolean function onEndTag(required struct attributes, required struct caller, string generatedContent){
param name="attributes.title";
variables.title = attributes.title;
variables.body = generatedContent;
return false;
}
}
<cfscript>
writeDump(expandPath("{lucee-server}/library/tag"));
writeDump(expandPath("{lucee-web}/library/tag"));
</cfscript>
<html>
<head>
<meta charset="UTF-8">
<title>Article Test</title>
</head>
<body>
<cf_article title="Driving a Car">
<cf_section title="Starting the car">
The first thing you need to do is put the key in in the ignition
</cf_section>
<cf_section title="Driving the car">
Pushing down on the gas pedal and makes the car go and turning the steering wheel
makes it go somewhere
</cf_section>
</cf_article>
</body>
</html>
<cfbasicTag name="there!"/>
<cf_invite invitee="Jimmy">
<p>I'd like to let you know that you are invited to our party!</p>
</cf_invite>
<cf_inviteInject invitee="Jimmy">
<cfoutput>
<p>#salutation#</p>
<p>#message#</p>
</cfoutput>
<cfset theDate = "1999" >
<cf_inviteParseBody invitee="Jimmy">
<p>I'd like to let you know that you are invited to our party on #theDate#!</p>
</cf_inviteParseBody>
<cfset theDate = "1999" >
<cf_invite invitee="Jimmy">
<p>I'd like to let you know that you are invited to our party on #theDate#!</p>
</cf_invite>
<cf_inviteUcase invitee="Jimmy">
<p>I'd like to let you know that you are invited to our party!</p>
</cf_inviteUcase>
<cfset theDate = "1999" >
<cf_invite invitee="Jimmy">
<cfoutput>
<p>I'd like to let you know that you are invited to our party on #theDate#!</p>
</cfoutput>
</cf_invite>
<html>
<head>
<meta charset="UTF-8">
<title>A Basic Custom Tag Example</title>
</head>
<body>
<div>
<cf_greeting firstName="Jim" lastName="Smith" />
</div>
</body>
</html>
<html>
<head>
<meta charset="UTF-8">
<title>A Basic Custom Tag Example</title>
</head>
<body>
<div>
<cf_greeting2 firstName="Jim" lastName="Smith" />
</div>
</body>
</html>
<!---
Commenting out because imported custom tags require an administrator mapping
<cfimport taglib="customtags" prefix="cf" />
<html>
<head>
<meta charset="UTF-8">
<title>A Basic Custom Tag Example</title>
</head>
<body>
<div>
<!--- <cfset try = new tags.greeting2()> --->
<cf:greeting2 firstName="Jim" lastName="Smith" />
</div>
</body> --->
</html>
<html>
<head>
<meta charset="UTF-8">
<title>A Basic Custom Tag Example</title>
</head>
<body>
<div>
<cf_greetingMetadataFixed firstName="Jim" middlename="Alan" lastName="Smith" />
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment