Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Into The Box 2018 - CBT

37 views

Published on

Luis Majano

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Into The Box 2018 - CBT

  1. 1. CBT{# ColdBox Templating Language #} Luis Majano 
 @lmajano @ortussolutions {{ ortussolutions.com }}
  2. 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. 3. What is CBT? Why CBT? When to use Getting Started Templating System
  4. 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. 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. 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. 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. 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 {{?}}
  9. 9. Getting Started
  10. 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. 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. 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. 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. 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
  15. 15. Get Funky CBT
  16. 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 );
  17. 17. Templating Constructs
  18. 18. Templating System TemplateContext/Model { variables functions expressions tags Template Template Template <<inherit>>
  19. 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. 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. 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. 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. 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. 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. 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. 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. 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. 28. Tags • autoescape • block • cache • extends • filter • flush • for • if • import • include • macro • parallel • set • verbatim http://www.mitchellbosecke.com/pebble/documentation {% %}
  29. 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. 30. Functions • block • i18n • max • min • parent • range http://www.mitchellbosecke.com/pebble/documentation x()
  31. 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. 32. Tests • empty • even • map • null • odd • iterable http://www.mitchellbosecke.com/pebble/documentation √
  33. 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. 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. 35. Math • CBT allows you to calculate values using some basic mathematical operators.The following operators are supported: • +: Addition • -: Subtraction • /: Division • %: Modulus • *: Multiplication
  36. 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. 37. Comparisons • The following comparison operators are supported in any expression: • ==, !=, <, >, >=, and <= {% if user.age >= 18 %}     ... {% endif %}
  38. 38. Ternary Operator • Same as CFML {{ foo ? "yes" : "no" }}
  39. 39. Operators • Supported Operators in precedence: • . • | • %, /, * • -, + • ==, !=, >, <, >=, <= • is, is not • and • or
  40. 40. Flows in-depth
  41. 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. 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. 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 %}
  44. 44. Going Deep
  45. 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. 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. 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. 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" %}
  49. 49. Get Funky…again CBT
  50. 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. 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. 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. 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. 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….
  55. 55. Thanks

×