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
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
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: <br> #}
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 %}
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 %}
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 %}
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….