SlideShare une entreprise Scribd logo
1  sur  55
Télécharger pour lire hors ligne
CBT{# ColdBox Templating Language #}
Luis Majano 

@lmajano
@ortussolutions
{{ ortussolutions.com }}
WHO AM I?
• Luis Majano - Computer Engineer
• Imported from El Salvador
• Houston,Texas
• CEO of Ortus Solutions
• Creator of many boxes
www.ortussolutions.com


@ortussolutions
@lmajano
What is CBT?
Why CBT?
When to use
Getting Started
Templating System
• ColdBox Module
• Templating Engine based on Twig
• Powered by Pebble Java Engine
• Seamless integration for HMVC apps
What is CBT
http://www.mitchellbosecke.com/pebble/home
Why CBT
• Sponsored by IDG Media Group
• Main Goals:
• Empower their custom CMS
• Enable editors with templating
capabilities
• Restricted programming
• Template Inheritance
• Selfish Goal:
• Get into language design, parsers and
compilers.
What is a templating engine
• A software to combine a template (simple text)
with data to produce content
• Content can be html, xml, json, css, js, cfml, csv,
etc
• Provides reusability of templates
+
Template
Data
Why a templating engine
• Easy to learn, read and write
• Simple control flow
• Limited Constructs & Expressions
• Security - Automatic HTML Escaping
• Cross language compatible
• Great for MVC patterns
• Great for CMS based systems
• Template Inheritance
• Generate other language files: js, css, cfml
• Much More…
?
When to use CBT
• When your users edit templates and you don’t
trust them
• Serving Dynamic Content (CMS)
• Simple DSL for view layer
• Template Reusability
• Enforce Separation of Concerns
• Dont’ want to bite the JS Frameworks Bullet
{{?}}
Getting Started
Installation + IDE Support
• Using CommandBox $ install cbt
• IDE Support
• Sublime: https://packagecontrol.io/packages/Twig
• Atom: https://atom.io/packages/language-twig
• VSCode: https://marketplace.visualstudio.com/items?
itemName=bajdzis.vscode-twig-pack
• CFBuilder: http://twig.dubture.com/
• Add .cbt to the twig language association
"files.associations": {
"*.cbt": "twig"
}
Settings
cbt = {
// If in strict mode, exceptions will be thrown for variables that do not exist, else it prints
them out as empty values
strictVariables = false,
// Sets whether or not XSS escaping should be performed automatically, defaults to true.
autoEscaping = true,
// Enable/disable all templating cache
cacheActive = false,
// By default, Pebble will trim a newline that immediately follows a Pebble tag
// For example, {{key1}}n{{key2}} will have the newline removed.
newLineTrimming = true,
// Bind the ColdBox Flash scope
bindFlash = true,
// Bind the session scope to templates
bindSession = true,
// Bind the cgi scope to templates
bindCGI = true,
// Bind the request scope to templates
bindRequest = true,
// Bind the server scope to templates
bindServer = true,
// Bind to the request's HTTP Request Data elements
bindHTTPRequestData = true,
// The default cbt templating language template extension
templateExtension = ".cbt"
}
Usage
• Create .cbt files in:
• MVC - In views and layouts
• HMVC - Modules
• Inject the cbt engine to handlers, interceptors, models:
• property name=“cbt” inject=“engine@cbt”
• Render Stuff Out!
• renderTemplate( template, context={}, module=“”)
• renderContent( content, context={} )
• What is this context?
Rendering Context/Model
• Every template is bound with a model context (structure)
• Think rc/prc
• Templates cannot go out to get data, they are provided with data (MVC)
Template
Context 

/
Model
Render by Conventions
    function inheritance( event, rc, prc ){
        return cbt.renderTemplate( "main/inheritance" );
    }
• Looks for views/main/inheritance.cbt in main conventions or module conventions
// Content Variables
    prc.moduleView = cbt.renderTemplate( template="home/simple", module="testing" );
• Looks for views/home/simple in the testing module
Get Funky
CBT
Render DynamicTemplates
var onDemand = "
        <h2>On-Demand Renderings</h2>
        {{ 'Rendering from OnDemand Baby' | upper }}
        <br>
        {{ max( 20, 100 ) }}
        <br>
        Today is {{ now | date( 'yyyy-MMM-dd HH:mm:ss' ) }}
        <br>
        BaseURL: {{ baseURL }}
    ";
    return cbt.renderContent( onDemand );
Templating
Constructs
Templating System
TemplateContext/Model
{
variables
functions
expressions
tags
Template
Template
Template
<<inherit>>
{# CBT template #}
<ul>
{% for item in items %}
<li>{{ item.value }}</li>
{% endfor %}
<ul>
{% block content %}
    Hello {{ name | title }}
Categories {{ categories | join(‘, ‘) }}
{% endblock %}
{% for i in range(0,3) %}
{{ i }},
{% endfor %}
Templating System
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
Comments
tag
variables
tags
filter
filter with args
functions
Delimiters
• {{ expression }}
• Outputs the result of an expression. A simple context variable or
complex expression
• {% tags %}
• Tag based context (control flows, blocks, function calls, setting variables
etc)
• {# Comment #}
• Comment to your ❤ content
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
Expressions
• Similar to expressions in Java/CFML world:
• Can be variables from the bound context or created on the fly
• {{ prc.link }}
• Can be variable assignments
• {% set foo = 'foo' + bar %}
• Can be output of literals: strings, booleans, numbers, structs, arrays or nulls
• {{ ["apple", "banana", "pear"] }}
• Complex mathematical operations or logical expressions
• {% for item in values %}
• Comparisons
• {% if user.age >= 30 %}
• Test evaluations
• {% if user.role is null %}
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
Variables
• Context variable output {{ myVar }}
• You can use (.) notation or [ “key” ] notation for navigating structures and queries
• {{ prc[ “my-key” ] }}
• All output is XSS Escaped for HTML by default
• Null values will be presented as empty strings, even if deep nested
• {{ foo.bar.yea }} => empty if foo and bar are null
• All variables can be passed through filters using the | pipe operator
• {{ var | filter1 | filter2 | filter( args ) }}
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
GlobalVariables
• rc
• prc
• flash
• now
• baseURL
• currentAction
• currentEvent
• currentHandler
• currentModule
• currentRoute
• currentRoutedURL
• currentRoutedNamespace
• currentView
• moduleRoot
• cgi
• session
• request
• server
• httpData
ColdBox Centric CFML Scopes
• appPath
• layoutsPath
• viewsPath
• modulePath
• moduleLayoutsPath
• modulesViewsPath
Pathing
SettingVariables
• {% set varName = “value” %}
• Use + to concatenate strings
• Set from other expressions
{% set danger = "<br>" %}
{% set foo = “<p>Hello</p>” + danger %}
{{ danger }}
{# will output: &lt;br&gt; #}
Filters
• Used to modify variables
• {{ name | striptags | title }} {# remove HTML and title case #}
• Separated by pipe and can be chained
• {{ list | join(‘, ‘) }} {# list joined by commas #}
• Arguments can be positional or named, just like CF (Sort of)
• {{ stringDate | date("yyyy/MMMM/d", existingFormat="yyyy-MMMM-d") }}
• Can also be used via tag wrapping
• {% filter upper %}

hello

{% endfilter %}
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
Filters
• abbreviate
• abs
• capitalize
• date
• default
• escape
• first
• join
• last
• length
• lower
• numberformat
• raw
• rsort
• slice
• sort
• title
• trim
• upper
• urlencode
http://www.mitchellbosecke.com/pebble/documentation
Tags
• Written between {% %} delimiters
• Control Flows
• Execute Functions
• Define Blocks
• Macros
• EndingTag is optional
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
{% block stylesheets %}
<link href=”/css/reset.css” rel=”stylesheet” type=”text/css” />
{% endblock %}
Tags
• autoescape
• block
• cache
• extends
• filter
• flush
• for
• if
• import
• include
• macro
• parallel
• set
• verbatim
http://www.mitchellbosecke.com/pebble/documentation
{% %}
Functions
• Called to generate content
• Called by their name followed by parentheses ()
• Arguments can be positional or named
http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
{% block "post" %} content {% endblock %}
{{ block("post") }}
{{ max(user.age, 80) }}
{{ min(user.age, 18) }}
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
Functions
• block
• i18n
• max
• min
• parent
• range
http://www.mitchellbosecke.com/pebble/documentation
x()
Tests
• Tests variables against common expressions using the is operator
• The not operator negates them
{% if user.email is empty %}
    ...
{% endif %}
{% if 2 is even or odd %}
    ...
{% endif %}
{% if {"apple":"red", "banana":"yellow"} is map %}
    ...
{% endif %}
{% if user.email is null %}
    ...
{% endif %}
Tests
• empty
• even
• map
• null
• odd
• iterable
http://www.mitchellbosecke.com/pebble/documentation
√
Literals
• "Hello World"
• Everything between two double or single quotes is a string.You can use a
backslash to escape quotation marks within the string.
• 100 * 2.5
• Integers and floating point numbers are similar to their Java counterparts.
• true / false
• Boolean values equivalent to their Java counterparts.
• null
• Represents no specific value, similar to it's Java counterpart. none is an alias for
null.
Collections
• Both structs and arrays can be created directly
• ["apple", "banana", "pear"]
• {"apple":"red", "banana":"yellow", “pear":"green"}
• FYI: Collections can also contain expressions
Math
• CBT allows you to calculate values using some basic mathematical operators.The
following operators are supported:
• +: Addition
• -: Subtraction
• /: Division
• %: Modulus
• *: Multiplication
Logic
• You can combine multiple expressions with the following operators:
• and: Returns true if both operands are true
• or: Returns true if either operand is true
• not: Negates an expression
• (...): Groups expressions together
Comparisons
• The following comparison operators are supported in any expression:
• ==, !=, <, >, >=, and <=
{% if user.age >= 18 %}
    ...
{% endif %}
Ternary Operator
• Same as CFML
{{ foo ? "yes" : "no" }}
Operators
• Supported Operators in precedence:
• .
• |
• %, /, *
• -, +
• ==, !=, >, <, >=, <=
• is, is not
• and
• or
Flows in-depth
For Loops
• Loops over each item in a list, array, query or struct
• Special else for empty sequences
{# Arrays #}
{% for user in users %}
    {{ loop.index }} - {{ user.id }}
{% else %}
    There are no users to display.
{% endfor %}
{# Structs #}
{% for entry in map %}
{{ entry.key }} - {{ entry.value }}
{% endfor %}
• SpecialVariables
• loop.index = numeric, loop.revindex = numeric
• loop.length = numeric
• loop.last = boolean, loop.first = boolean
For : Sequences
• Iterate over sequences
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
{# outputs 0, 1, 2, 3, #}
{% for i in range(0, 6, 2) %}
{{ i }},
{% endfor %}
{# outputs 0, 2, 4, 6, #}
{% for i in 0..3 %}
{{ i }},
{% endfor %}
{# outputs 0, 1, 2, 3, #}
{% for letter in 'a'..'z' %}
 {{ letter }},
{% endfor %}
if / else
• Similar to Java/CFML
• Leverage expressions, operators, tests, math, etc.
{% if users is empty %}
    There are no users.
{% elseif users.length == 1 %}
    There is only one user.
{% else %}
    There are many users.
{% endif %}
{# null checks#}
{% if users %}
Going Deep
Macros
• Reusable template fragments, think web components
• Invoked like functions
• Can have input arguments with default values
• Only works on the input provided not the bonded context
• Can be imported (reusable)
{% macro input(type="text", name, value) %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}" />
{% endmacro %}
{{ input(name="country") }}
{# will output: <input type="text" name="country" value="" /> #}
{% import "form_util" %}
{{ input("text", "country", "Canada") }}
Whitespace
• The first newline after a template tag is removed automatically
• - is the whitespace control modifier
• It can be used in {{- -}} or {%- -%}
<p>         {{- "no whitespace" -}}     </p>
{# output: "<p>no whitespace</p>" #}
Escaping
• Automatic (html) default escape strategy or custom strategy (css, html, html_attr, js, url_param)
{{ danger | raw }}
• autoescape tag can be used to temporarily disable/enable the auto escaper and strategy
{{ danger }} {# will be escaped by default #}
{% autoescape false %}
    {{ danger }} {# will not be escaped #}
{% endautoescape %}
{{ danger }} {# will use the "html" escaping strategy #}
{% autoescape "js" %}
    {{ danger }} {# will use the "js" escaping strategy #}
{% endautoescape %}
• raw filter to output raw html
{{ danger }}
{{ danger | escape( "js" ) }}
{{ danger | escape( "html_attr" ) }}
Includes
• Just like cfinclude(), please note that relative pathing needs the ./ prefix
{% include "advertisement" with {"foo":"bar"} %}
• Dynamic includes using expressions
• You can add additional variables to the context of the included template, 

just pass a struct using the with keyword
{% include "./header.cbt" %}
{% include admin ? 'adminFooter' : 'defaultFooter' %}
• Dynamic includes using global variables
{% include appPath + "./header.cbt" %}
Get Funky…again
CBT
Template Inheritance
• Most powerful part of cbt
• Build a layout with most common elements
• Blocks are named slots or holes in a template that a child can fill
• Blocks can be used in any order
• Blocks can be imported from other templates
• Blocks can have default content in the middle or none at all
{% block header %}
    <h1> Introduction </h1>
{% endblock header %}
{% block footer %}
{% endblock footer %}
Layout.cbt - Parent
<!DOCTYPE html>
<html lang=”en”>
<head>
{% block metatags %}
<meta charset=”utf-8”>
{% endblock %}
{% block title %}
<title>CBT Rules!</title>
{% endblock %}
{% block stylesheets %}
<link href=”/includes/css/bootstrap.css” rel=”stylesheet”>
{% endblock %}
</head>
<body>
{% block body %}
{% block body_inner %}{% endblock %}
{% endblock %}
{% block javascripts %}
<script src=”/includes/js/vue.js”></script>
{% endblock %}
</body>
</html>
Block = slots for content
Blocks can be nested
Blocks can be empty
Template Child
{% extends layoutsPath + "Main.twig" %}
{% block stylesheets %}
{{ parent() }}
<link href="/includes/css/theme.css" rel="stylesheet">
{% endblock %}
{% block body %}
{% include "./helpers/header.cbt" %}
<div class=”container theme-showcase”>
{% block mainView %}{% endblock %}
</div>
{% include ‘./helpers/footer.cbt’ %}
{% endblock %}
{% block javascripts %}
<script src=”/includes/js/vue.js”></script>
<script src=”/includes/js/app.js”></script>
{% endblock %}
Extend the template
Position existing content
Still use includes
Child changes the block
Template Child
• extends tag should be the first tag in the template
• By using the same block name you either
• override completely
• add content to it with the parent() function
• The content of the child block can go above or below existing contents
• Use {{ block( name ) }} to render blocks a-la-carte
More to come….
• Project still in its infancy
• Will explore custom parsers via Antlr
for CFML customizations
• Tag libraries
• Input very welcomed
• The future is bright….
Thanks

Contenu connexe

Tendances

13 java beans
13 java beans13 java beans
13 java beans
snopteck
 

Tendances (20)

Jquery 4
Jquery 4Jquery 4
Jquery 4
 
The Django Book chapter 4 templates (supplement)
The Django Book chapter 4 templates (supplement)The Django Book chapter 4 templates (supplement)
The Django Book chapter 4 templates (supplement)
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
 
REST/JSON/CoreData Example Code - A Tour
REST/JSON/CoreData Example Code - A TourREST/JSON/CoreData Example Code - A Tour
REST/JSON/CoreData Example Code - A Tour
 
SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8
 
Wt unit 4 server side technology-2
Wt unit 4 server side technology-2Wt unit 4 server side technology-2
Wt unit 4 server side technology-2
 
JavaScript - Chapter 7 - Advanced Functions
 JavaScript - Chapter 7 - Advanced Functions JavaScript - Chapter 7 - Advanced Functions
JavaScript - Chapter 7 - Advanced Functions
 
GDG Almaty Meetup: Reactive full-stack .NET web applications with WebSharper
GDG Almaty Meetup: Reactive full-stack .NET web applications with WebSharperGDG Almaty Meetup: Reactive full-stack .NET web applications with WebSharper
GDG Almaty Meetup: Reactive full-stack .NET web applications with WebSharper
 
Object Oriented PHP - PART-1
Object Oriented PHP - PART-1Object Oriented PHP - PART-1
Object Oriented PHP - PART-1
 
Jsp1
Jsp1Jsp1
Jsp1
 
Ad java prac sol set
Ad java prac sol setAd java prac sol set
Ad java prac sol set
 
Developing application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDDDeveloping application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDD
 
Geotalk presentation
Geotalk presentationGeotalk presentation
Geotalk presentation
 
JavaScript Refactoring
JavaScript RefactoringJavaScript Refactoring
JavaScript Refactoring
 
13 java beans
13 java beans13 java beans
13 java beans
 
Rest in flask
Rest in flaskRest in flask
Rest in flask
 
Java script tutorial
Java script tutorialJava script tutorial
Java script tutorial
 
JavaScript 101
JavaScript 101JavaScript 101
JavaScript 101
 
FYBSC IT Web Programming Unit IV PHP and MySQL
FYBSC IT Web Programming Unit IV  PHP and MySQLFYBSC IT Web Programming Unit IV  PHP and MySQL
FYBSC IT Web Programming Unit IV PHP and MySQL
 
Wt unit 2 ppts client side technology
Wt unit 2 ppts client side technologyWt unit 2 ppts client side technology
Wt unit 2 ppts client side technology
 

Similaire à Into The Box 2018 - CBT

GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
Yared Ayalew
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 
gdscWorkShopJavascriptintroductions.pptx
gdscWorkShopJavascriptintroductions.pptxgdscWorkShopJavascriptintroductions.pptx
gdscWorkShopJavascriptintroductions.pptx
sandeshshahapur
 
django_introduction20141030
django_introduction20141030django_introduction20141030
django_introduction20141030
Kevin Wu
 
MVC & SQL_In_1_Hour
MVC & SQL_In_1_HourMVC & SQL_In_1_Hour
MVC & SQL_In_1_Hour
Dilip Patel
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
Puppet
 

Similaire à Into The Box 2018 - CBT (20)

Practical catalyst
Practical catalystPractical catalyst
Practical catalyst
 
Integrating Microservices with Apache Camel
Integrating Microservices with Apache CamelIntegrating Microservices with Apache Camel
Integrating Microservices with Apache Camel
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
EIP In Practice
EIP In PracticeEIP In Practice
EIP In Practice
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
ASP.Net 5 and C# 6
ASP.Net 5 and C# 6ASP.Net 5 and C# 6
ASP.Net 5 and C# 6
 
gdscWorkShopJavascriptintroductions.pptx
gdscWorkShopJavascriptintroductions.pptxgdscWorkShopJavascriptintroductions.pptx
gdscWorkShopJavascriptintroductions.pptx
 
Wt unit 2 ppts client sied technology
Wt unit 2 ppts client sied technologyWt unit 2 ppts client sied technology
Wt unit 2 ppts client sied technology
 
Python (Jinja2) Templates for Network Automation
Python (Jinja2) Templates for Network AutomationPython (Jinja2) Templates for Network Automation
Python (Jinja2) Templates for Network Automation
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHP
 
django_introduction20141030
django_introduction20141030django_introduction20141030
django_introduction20141030
 
MVC & SQL_In_1_Hour
MVC & SQL_In_1_HourMVC & SQL_In_1_Hour
MVC & SQL_In_1_Hour
 
Javascript
JavascriptJavascript
Javascript
 
Price of an Error
Price of an ErrorPrice of an Error
Price of an Error
 
Session on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh GundechaSession on Selenium Powertools by Unmesh Gundecha
Session on Selenium Powertools by Unmesh Gundecha
 
BITM3730 10-3.pptx
BITM3730 10-3.pptxBITM3730 10-3.pptx
BITM3730 10-3.pptx
 
Service Oriented Integration With ServiceMix
Service Oriented Integration With ServiceMixService Oriented Integration With ServiceMix
Service Oriented Integration With ServiceMix
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
 

Plus de Ortus Solutions, Corp

Plus de Ortus Solutions, Corp (20)

BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Ortus Government.pdf
Ortus Government.pdfOrtus Government.pdf
Ortus Government.pdf
 
Luis Majano The Battlefield ORM
Luis Majano The Battlefield ORMLuis Majano The Battlefield ORM
Luis Majano The Battlefield ORM
 
Brad Wood - CommandBox CLI
Brad Wood - CommandBox CLI Brad Wood - CommandBox CLI
Brad Wood - CommandBox CLI
 
Secure your Secrets and Settings in ColdFusion
Secure your Secrets and Settings in ColdFusionSecure your Secrets and Settings in ColdFusion
Secure your Secrets and Settings in ColdFusion
 
Daniel Garcia ContentBox: CFSummit 2023
Daniel Garcia ContentBox: CFSummit 2023Daniel Garcia ContentBox: CFSummit 2023
Daniel Garcia ContentBox: CFSummit 2023
 
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdfITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
 
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdfITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
 
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdfITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
 
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdfITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
 
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdfITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
 
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdfITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
 
ITB_2023_CBWire_v3_Grant_Copley.pdf
ITB_2023_CBWire_v3_Grant_Copley.pdfITB_2023_CBWire_v3_Grant_Copley.pdf
ITB_2023_CBWire_v3_Grant_Copley.pdf
 
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdfITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
 
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdfITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
 
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdfITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
 
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdfITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
 
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdfITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
 
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdfITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
 
ITB2023 Developing for Performance - Denard Springle.pdf
ITB2023 Developing for Performance - Denard Springle.pdfITB2023 Developing for Performance - Denard Springle.pdf
ITB2023 Developing for Performance - Denard Springle.pdf
 

Dernier

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 

Into The Box 2018 - CBT

  • 1. CBT{# ColdBox Templating Language #} Luis Majano 
 @lmajano @ortussolutions {{ ortussolutions.com }}
  • 2. WHO AM I? • Luis Majano - Computer Engineer • Imported from El Salvador • Houston,Texas • CEO of Ortus Solutions • Creator of many boxes www.ortussolutions.com 
 @ortussolutions @lmajano
  • 3. What is CBT? Why CBT? When to use Getting Started Templating System
  • 4. • ColdBox Module • Templating Engine based on Twig • Powered by Pebble Java Engine • Seamless integration for HMVC apps What is CBT http://www.mitchellbosecke.com/pebble/home
  • 5. Why CBT • Sponsored by IDG Media Group • Main Goals: • Empower their custom CMS • Enable editors with templating capabilities • Restricted programming • Template Inheritance • Selfish Goal: • Get into language design, parsers and compilers.
  • 6. What is a templating engine • A software to combine a template (simple text) with data to produce content • Content can be html, xml, json, css, js, cfml, csv, etc • Provides reusability of templates + Template Data
  • 7. Why a templating engine • Easy to learn, read and write • Simple control flow • Limited Constructs & Expressions • Security - Automatic HTML Escaping • Cross language compatible • Great for MVC patterns • Great for CMS based systems • Template Inheritance • Generate other language files: js, css, cfml • Much More… ?
  • 8. When to use CBT • When your users edit templates and you don’t trust them • Serving Dynamic Content (CMS) • Simple DSL for view layer • Template Reusability • Enforce Separation of Concerns • Dont’ want to bite the JS Frameworks Bullet {{?}}
  • 10. Installation + IDE Support • Using CommandBox $ install cbt • IDE Support • Sublime: https://packagecontrol.io/packages/Twig • Atom: https://atom.io/packages/language-twig • VSCode: https://marketplace.visualstudio.com/items? itemName=bajdzis.vscode-twig-pack • CFBuilder: http://twig.dubture.com/ • Add .cbt to the twig language association "files.associations": { "*.cbt": "twig" }
  • 11. Settings cbt = { // If in strict mode, exceptions will be thrown for variables that do not exist, else it prints them out as empty values strictVariables = false, // Sets whether or not XSS escaping should be performed automatically, defaults to true. autoEscaping = true, // Enable/disable all templating cache cacheActive = false, // By default, Pebble will trim a newline that immediately follows a Pebble tag // For example, {{key1}}n{{key2}} will have the newline removed. newLineTrimming = true, // Bind the ColdBox Flash scope bindFlash = true, // Bind the session scope to templates bindSession = true, // Bind the cgi scope to templates bindCGI = true, // Bind the request scope to templates bindRequest = true, // Bind the server scope to templates bindServer = true, // Bind to the request's HTTP Request Data elements bindHTTPRequestData = true, // The default cbt templating language template extension templateExtension = ".cbt" }
  • 12. Usage • Create .cbt files in: • MVC - In views and layouts • HMVC - Modules • Inject the cbt engine to handlers, interceptors, models: • property name=“cbt” inject=“engine@cbt” • Render Stuff Out! • renderTemplate( template, context={}, module=“”) • renderContent( content, context={} ) • What is this context?
  • 13. Rendering Context/Model • Every template is bound with a model context (structure) • Think rc/prc • Templates cannot go out to get data, they are provided with data (MVC) Template Context 
 / Model
  • 14. Render by Conventions     function inheritance( event, rc, prc ){         return cbt.renderTemplate( "main/inheritance" );     } • Looks for views/main/inheritance.cbt in main conventions or module conventions // Content Variables     prc.moduleView = cbt.renderTemplate( template="home/simple", module="testing" ); • Looks for views/home/simple in the testing module
  • 16. Render DynamicTemplates var onDemand = "         <h2>On-Demand Renderings</h2>         {{ 'Rendering from OnDemand Baby' | upper }}         <br>         {{ max( 20, 100 ) }}         <br>         Today is {{ now | date( 'yyyy-MMM-dd HH:mm:ss' ) }}         <br>         BaseURL: {{ baseURL }}     ";     return cbt.renderContent( onDemand );
  • 19. {# CBT template #} <ul> {% for item in items %} <li>{{ item.value }}</li> {% endfor %} <ul> {% block content %}     Hello {{ name | title }} Categories {{ categories | join(‘, ‘) }} {% endblock %} {% for i in range(0,3) %} {{ i }}, {% endfor %} Templating System http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage Comments tag variables tags filter filter with args functions
  • 20. Delimiters • {{ expression }} • Outputs the result of an expression. A simple context variable or complex expression • {% tags %} • Tag based context (control flows, blocks, function calls, setting variables etc) • {# Comment #} • Comment to your ❤ content http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
  • 21. Expressions • Similar to expressions in Java/CFML world: • Can be variables from the bound context or created on the fly • {{ prc.link }} • Can be variable assignments • {% set foo = 'foo' + bar %} • Can be output of literals: strings, booleans, numbers, structs, arrays or nulls • {{ ["apple", "banana", "pear"] }} • Complex mathematical operations or logical expressions • {% for item in values %} • Comparisons • {% if user.age >= 30 %} • Test evaluations • {% if user.role is null %} http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
  • 22. Variables • Context variable output {{ myVar }} • You can use (.) notation or [ “key” ] notation for navigating structures and queries • {{ prc[ “my-key” ] }} • All output is XSS Escaped for HTML by default • Null values will be presented as empty strings, even if deep nested • {{ foo.bar.yea }} => empty if foo and bar are null • All variables can be passed through filters using the | pipe operator • {{ var | filter1 | filter2 | filter( args ) }} http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
  • 23. GlobalVariables • rc • prc • flash • now • baseURL • currentAction • currentEvent • currentHandler • currentModule • currentRoute • currentRoutedURL • currentRoutedNamespace • currentView • moduleRoot • cgi • session • request • server • httpData ColdBox Centric CFML Scopes • appPath • layoutsPath • viewsPath • modulePath • moduleLayoutsPath • modulesViewsPath Pathing
  • 24. SettingVariables • {% set varName = “value” %} • Use + to concatenate strings • Set from other expressions {% set danger = "<br>" %} {% set foo = “<p>Hello</p>” + danger %} {{ danger }} {# will output: &lt;br&gt; #}
  • 25. Filters • Used to modify variables • {{ name | striptags | title }} {# remove HTML and title case #} • Separated by pipe and can be chained • {{ list | join(‘, ‘) }} {# list joined by commas #} • Arguments can be positional or named, just like CF (Sort of) • {{ stringDate | date("yyyy/MMMM/d", existingFormat="yyyy-MMMM-d") }} • Can also be used via tag wrapping • {% filter upper %}
 hello
 {% endfilter %} http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage
  • 26. Filters • abbreviate • abs • capitalize • date • default • escape • first • join • last • length • lower • numberformat • raw • rsort • slice • sort • title • trim • upper • urlencode http://www.mitchellbosecke.com/pebble/documentation
  • 27. Tags • Written between {% %} delimiters • Control Flows • Execute Functions • Define Blocks • Macros • EndingTag is optional http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage {% block stylesheets %} <link href=”/css/reset.css” rel=”stylesheet” type=”text/css” /> {% endblock %}
  • 28. Tags • autoescape • block • cache • extends • filter • flush • for • if • import • include • macro • parallel • set • verbatim http://www.mitchellbosecke.com/pebble/documentation {% %}
  • 29. Functions • Called to generate content • Called by their name followed by parentheses () • Arguments can be positional or named http://www.mitchellbosecke.com/pebble/documentation/guide/basic-usage {% block "post" %} content {% endblock %} {{ block("post") }} {{ max(user.age, 80) }} {{ min(user.age, 18) }} {% for i in range(0, 3) %} {{ i }}, {% endfor %}
  • 30. Functions • block • i18n • max • min • parent • range http://www.mitchellbosecke.com/pebble/documentation x()
  • 31. Tests • Tests variables against common expressions using the is operator • The not operator negates them {% if user.email is empty %}     ... {% endif %} {% if 2 is even or odd %}     ... {% endif %} {% if {"apple":"red", "banana":"yellow"} is map %}     ... {% endif %} {% if user.email is null %}     ... {% endif %}
  • 32. Tests • empty • even • map • null • odd • iterable http://www.mitchellbosecke.com/pebble/documentation √
  • 33. Literals • "Hello World" • Everything between two double or single quotes is a string.You can use a backslash to escape quotation marks within the string. • 100 * 2.5 • Integers and floating point numbers are similar to their Java counterparts. • true / false • Boolean values equivalent to their Java counterparts. • null • Represents no specific value, similar to it's Java counterpart. none is an alias for null.
  • 34. Collections • Both structs and arrays can be created directly • ["apple", "banana", "pear"] • {"apple":"red", "banana":"yellow", “pear":"green"} • FYI: Collections can also contain expressions
  • 35. Math • CBT allows you to calculate values using some basic mathematical operators.The following operators are supported: • +: Addition • -: Subtraction • /: Division • %: Modulus • *: Multiplication
  • 36. Logic • You can combine multiple expressions with the following operators: • and: Returns true if both operands are true • or: Returns true if either operand is true • not: Negates an expression • (...): Groups expressions together
  • 37. Comparisons • The following comparison operators are supported in any expression: • ==, !=, <, >, >=, and <= {% if user.age >= 18 %}     ... {% endif %}
  • 38. Ternary Operator • Same as CFML {{ foo ? "yes" : "no" }}
  • 39. Operators • Supported Operators in precedence: • . • | • %, /, * • -, + • ==, !=, >, <, >=, <= • is, is not • and • or
  • 41. For Loops • Loops over each item in a list, array, query or struct • Special else for empty sequences {# Arrays #} {% for user in users %}     {{ loop.index }} - {{ user.id }} {% else %}     There are no users to display. {% endfor %} {# Structs #} {% for entry in map %} {{ entry.key }} - {{ entry.value }} {% endfor %} • SpecialVariables • loop.index = numeric, loop.revindex = numeric • loop.length = numeric • loop.last = boolean, loop.first = boolean
  • 42. For : Sequences • Iterate over sequences {% for i in range(0, 3) %} {{ i }}, {% endfor %} {# outputs 0, 1, 2, 3, #} {% for i in range(0, 6, 2) %} {{ i }}, {% endfor %} {# outputs 0, 2, 4, 6, #} {% for i in 0..3 %} {{ i }}, {% endfor %} {# outputs 0, 1, 2, 3, #} {% for letter in 'a'..'z' %}  {{ letter }}, {% endfor %}
  • 43. if / else • Similar to Java/CFML • Leverage expressions, operators, tests, math, etc. {% if users is empty %}     There are no users. {% elseif users.length == 1 %}     There is only one user. {% else %}     There are many users. {% endif %} {# null checks#} {% if users %}
  • 45. Macros • Reusable template fragments, think web components • Invoked like functions • Can have input arguments with default values • Only works on the input provided not the bonded context • Can be imported (reusable) {% macro input(type="text", name, value) %}     <input type="{{ type }}" name="{{ name }}" value="{{ value }}" /> {% endmacro %} {{ input(name="country") }} {# will output: <input type="text" name="country" value="" /> #} {% import "form_util" %} {{ input("text", "country", "Canada") }}
  • 46. Whitespace • The first newline after a template tag is removed automatically • - is the whitespace control modifier • It can be used in {{- -}} or {%- -%} <p>         {{- "no whitespace" -}}     </p> {# output: "<p>no whitespace</p>" #}
  • 47. Escaping • Automatic (html) default escape strategy or custom strategy (css, html, html_attr, js, url_param) {{ danger | raw }} • autoescape tag can be used to temporarily disable/enable the auto escaper and strategy {{ danger }} {# will be escaped by default #} {% autoescape false %}     {{ danger }} {# will not be escaped #} {% endautoescape %} {{ danger }} {# will use the "html" escaping strategy #} {% autoescape "js" %}     {{ danger }} {# will use the "js" escaping strategy #} {% endautoescape %} • raw filter to output raw html {{ danger }} {{ danger | escape( "js" ) }} {{ danger | escape( "html_attr" ) }}
  • 48. Includes • Just like cfinclude(), please note that relative pathing needs the ./ prefix {% include "advertisement" with {"foo":"bar"} %} • Dynamic includes using expressions • You can add additional variables to the context of the included template, 
 just pass a struct using the with keyword {% include "./header.cbt" %} {% include admin ? 'adminFooter' : 'defaultFooter' %} • Dynamic includes using global variables {% include appPath + "./header.cbt" %}
  • 50. Template Inheritance • Most powerful part of cbt • Build a layout with most common elements • Blocks are named slots or holes in a template that a child can fill • Blocks can be used in any order • Blocks can be imported from other templates • Blocks can have default content in the middle or none at all {% block header %}     <h1> Introduction </h1> {% endblock header %} {% block footer %} {% endblock footer %}
  • 51. Layout.cbt - Parent <!DOCTYPE html> <html lang=”en”> <head> {% block metatags %} <meta charset=”utf-8”> {% endblock %} {% block title %} <title>CBT Rules!</title> {% endblock %} {% block stylesheets %} <link href=”/includes/css/bootstrap.css” rel=”stylesheet”> {% endblock %} </head> <body> {% block body %} {% block body_inner %}{% endblock %} {% endblock %} {% block javascripts %} <script src=”/includes/js/vue.js”></script> {% endblock %} </body> </html> Block = slots for content Blocks can be nested Blocks can be empty
  • 52. Template Child {% extends layoutsPath + "Main.twig" %} {% block stylesheets %} {{ parent() }} <link href="/includes/css/theme.css" rel="stylesheet"> {% endblock %} {% block body %} {% include "./helpers/header.cbt" %} <div class=”container theme-showcase”> {% block mainView %}{% endblock %} </div> {% include ‘./helpers/footer.cbt’ %} {% endblock %} {% block javascripts %} <script src=”/includes/js/vue.js”></script> <script src=”/includes/js/app.js”></script> {% endblock %} Extend the template Position existing content Still use includes Child changes the block
  • 53. Template Child • extends tag should be the first tag in the template • By using the same block name you either • override completely • add content to it with the parent() function • The content of the child block can go above or below existing contents • Use {{ block( name ) }} to render blocks a-la-carte
  • 54. More to come…. • Project still in its infancy • Will explore custom parsers via Antlr for CFML customizations • Tag libraries • Input very welcomed • The future is bright….