mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
1119 lines
19 KiB
Markdown
1119 lines
19 KiB
Markdown
---
|
|
presentation: true
|
|
---
|
|
|
|
Brown Bag
|
|
======================
|
|
|
|

|
|
|
|
# Introducing Marko v3
|
|
|
|
### Patrick Steele-Idem (Node.js Platform Team)
|
|
|
|
#### March 11, 2016
|
|
|
|
<hr class="page-break">
|
|
|
|
# Marko is getting a major update!
|
|
|
|
<hr class="page-break">
|
|
|
|
# Why Marko?
|
|
|
|
- Streaming and async rendering
|
|
- Progressive HTML rendering
|
|
- Custom tags
|
|
- Lightweight and fast
|
|
- Marko Widgets for UI components
|
|
- Clean HTML-based syntax
|
|
|
|
<hr class="page-break">
|
|
|
|
# Marko is _really_ fast
|
|
|
|
| Template Engine | Results |
|
|
|-----------------|------------------------------|
|
|
| __marko__ | __187,729 op/s (fastest)__ |
|
|
| dot | 183,161 op/s (2.43% slower) |
|
|
| handlebars | 104,634 op/s (44.26% slower) |
|
|
| dust | 83,773 op/s (55.38% slower) |
|
|
| swig | 54,866 op/s (70.77% slower) |
|
|
| jade | 32,929 op/s (82.46% slower) |
|
|
| nunjucks | 32,306 op/s (82.79% slower) |
|
|
| react | 3,651 op/s (98.06% slower) |
|
|
|
|
Source: https://github.com/marko-js/templating-benchmarks
|
|
|
|
# Marko vs React
|
|
|
|

|
|
|
|
<hr class="page-break">
|
|
|
|
# Growing Community
|
|
|
|
<img width="100%" width="1123" alt="screen shot 2016-03-11 at 8 52 31 am" src="https://cloud.githubusercontent.com/assets/978214/13709070/e25fc432-e766-11e5-8ef8-a945da5fce63.png">
|
|
|
|
<hr class="page-break">
|
|
|
|
# Marko v3 is a huge release
|
|
|
|
- 295 commits to [marko](https://github.com/marko-js/marko/compare/v2.8.4...master)
|
|
- Almost 100 commits to the new parser: [htmljs-parser](https://github.com/philidem/htmljs-parser)
|
|
- Both breaking and non-breaking changes
|
|
- Don't worry, we have a migration tool
|
|
|
|
<hr class="page-break">
|
|
|
|
# Why is Marko changing?
|
|
|
|
- Issue #90 - Proposal: Replace HTML parser with a new parser that recognizes attribute types
|
|
- Issue #211 - Marko v3: Support concise (Jade-like) syntax
|
|
|
|
<hr class="page-break">
|
|
|
|
## Strict HTML parser was holding Marko back
|
|
|
|
<hr class="page-break">
|
|
|
|
# Old HTML Parser
|
|
|
|
## ***Bad:*** All HTML attributes are parsed in as Strings
|
|
|
|
## Separate schema files were used to add type information. :(
|
|
|
|
<hr class="page-break">
|
|
|
|
## ***Solution:*** HTML parser that recognizes types
|
|
|
|
```xml
|
|
<div class=data.myClassName>
|
|
<input type="checkbox" checked=data.isChecked/>
|
|
|
|
<my-component string="Hello"/>
|
|
<my-component number=1/>
|
|
<my-component template-string="Hello ${name}"/>
|
|
<my-component boolean=true/>
|
|
<my-component array=[1, 2, 3]/>
|
|
<my-component object={hello: 'world'}/>
|
|
<my-component variable=name/>
|
|
<my-component function-call=data.foo()/>
|
|
<my-component complex-expression=1+2/>
|
|
<my-component super-complex-expression=(data.foo() + data.bar(['a', 'b', 'c']))/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Marko History
|
|
|
|
## XML (Raptor Templates) ➙ HTML ➙ HTML-JS
|
|
|
|
<hr class="page-break">
|
|
|
|
# New and Improved Syntax(es)
|
|
|
|
<hr class="page-break">
|
|
|
|
# HTML syntax
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>Marko Templating Engine</title>
|
|
</head>
|
|
<body>
|
|
<!-- Welcome to Marko! -->
|
|
<app-hello name=data.name/>
|
|
|
|
<ul if(data.colors.length)>
|
|
<li for(color in data.colors)>
|
|
${color}
|
|
</li>
|
|
</ul>
|
|
<div else>
|
|
No colors!
|
|
</div>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Concise syntax
|
|
|
|
```xml
|
|
<!DOCTYPE html>
|
|
html lang="en"
|
|
head
|
|
title - Marko Templating Engine
|
|
body
|
|
// Welcome to Marko!
|
|
app-hello name=data.name
|
|
ul if(data.colors.length)
|
|
li for(color in data.colors)
|
|
${color}
|
|
div else
|
|
- No colors!
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Mixed syntax
|
|
|
|
|
|
```xml
|
|
<!DOCTYPE html>
|
|
html lang="en"
|
|
head
|
|
<title>Marko Templating Engine</title>
|
|
body
|
|
// Welcome to Marko!
|
|
<app-hello name=data.name/>
|
|
ul if(data.colors.length)
|
|
li for(color in data.colors)
|
|
${color}
|
|
div else
|
|
- No colors!
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Improved Editor and IDE Support
|
|
|
|
- Atom: [language-marko](https://atom.io/packages/language-marko)
|
|
- Sublime Text: [marko-sublime](https://github.com/merwan7/sublime-marko)
|
|
- WebStorm: [marko.tmbundle](https://github.com/marko-js/marko-tmbundle) (See: [Importing TextMate Bundles](https://www.jetbrains.com/phpstorm/help/importing-textmate-bundles.html)) (New!)
|
|
- TextMate: [marko.tmbundle](https://github.com/marko-js/marko-tmbundle)
|
|
- CodeMirror/Brackets
|
|
|
|
|
|
<hr class="page-break">
|
|
|
|
<a name="improved-directives"></a>
|
|
# Improved syntax for directives
|
|
|
|
<hr class="page-break">
|
|
|
|
# Macros
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<def function="greeting(name, count)">
|
|
Hello ${name}! You have ${count} new messages.
|
|
</def>
|
|
|
|
<invoke function="greeting" name="John" count="${10}"/>
|
|
<invoke function="greeting('Frank', 20)"/>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
|
|
```xml
|
|
<macro greeting(name, count)>
|
|
Hello ${name}! You have ${count} new messages.
|
|
</macro>
|
|
|
|
<greeting name="Frank" count=30/>
|
|
<greeting('Frank', 30)/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Macro with body content
|
|
|
|
```xml
|
|
<macro section-heading(className)>
|
|
<h1 class=className>
|
|
<macro-body/>
|
|
</h1>
|
|
</macro>
|
|
|
|
<section-heading className="foo">
|
|
Hello World!
|
|
</section-heading>
|
|
|
|
<!-- Output: -->
|
|
<h1 class="foo">Hello World!</h1>
|
|
```
|
|
<hr class="page-break">
|
|
|
|
# Includes
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<include template="./include-target.marko" name="Frank" count="${20}"/>
|
|
<include template="./include-target.marko" template-data="{name: 'Frank', count: 20}"/>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<include("./include-target.marko") name='Frank' count=20/>
|
|
<include("./include-target.marko", {name: 'Frank', count: 20})/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Conditionals (as tags)
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<if test="a > b">...</if>
|
|
<else-if test="b < a">...</else-if>
|
|
<else>...</else>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<if(a > b)>...</if>
|
|
<else-if(b < a)>...</else-if>
|
|
<else>...</else>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Conditionals (as attributes)
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<div if="a > b">...</div>
|
|
<div else-if="b < a">...</div>
|
|
<div else>...</div>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<div if(a > b)>...</div>
|
|
<div else-if(b < a)>...</div>
|
|
<div else>...</div>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# for(item in items) - As tag
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<ul>
|
|
<for test="color in colors"><li>${color}</li>
|
|
</for>
|
|
</ul>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<ul>
|
|
<for(color in colors)>
|
|
<li>${color}</li>
|
|
</for>
|
|
</ul>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# for(item in items) - As attribute
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<ul>
|
|
<li for="color in colors">
|
|
${color}
|
|
</li>
|
|
</ul>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<ul>
|
|
<li for(color in colors)>
|
|
${color}
|
|
</li>
|
|
</ul>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Looping Options
|
|
|
|
```xml
|
|
<for(color in ['red', 'green', 'blue'] | separator=", ")>
|
|
${color}
|
|
</for>
|
|
```
|
|
|
|
Output:
|
|
|
|
```html
|
|
red, green, blue
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Iterator function as target
|
|
|
|
```xml
|
|
<script marko-init>
|
|
function myColorsIterator(callback) {
|
|
callback('red');
|
|
callback('green');
|
|
callback('blue');
|
|
}
|
|
</script>
|
|
|
|
<ul>
|
|
<for(color in myColorsIterator)>
|
|
<li>${color}</li>
|
|
</for>
|
|
</ul>
|
|
```
|
|
|
|
Output:
|
|
|
|
```html
|
|
<ul>
|
|
<li>red</li>
|
|
<li>green</li>
|
|
<li>blue</li>
|
|
</ul>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# for(`<init>`; `<test>`; `<update>`)
|
|
|
|
```xml
|
|
<for(var i=1; i<=3; i++)>
|
|
${i}
|
|
</for>
|
|
```
|
|
|
|
Output:
|
|
|
|
```html
|
|
123
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# for(key, value in object)
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<for each="(name,value) in {'foo': 'low', 'bar': 'high'}">
|
|
${name}: ${value}
|
|
</for>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<for(name,value in {'foo': 'low', 'bar': 'high'})>
|
|
${name}: ${value}
|
|
</for>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# for(`<range>`)
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<for each="i from 0 to 9">
|
|
${i}
|
|
</for>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<for(i from 0 to 9)>
|
|
${i}
|
|
</for>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# while(`<test>`)
|
|
|
|
Marko v3 now supports native while loops:
|
|
|
|
```xml
|
|
<!-- Applied as a tag: -->
|
|
<var n=0/>
|
|
<ul>
|
|
<while(n < 4)>
|
|
<li>${n++}</li>
|
|
</while>
|
|
</ul>
|
|
|
|
<!-- Applied as an attribute: -->
|
|
<var n=0/>
|
|
<ul>
|
|
<li while(n < 4)>
|
|
${n++}
|
|
</li>
|
|
</ul>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Imports
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<require module="change-case" var="changeCase"/>
|
|
```
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<script marko-init>
|
|
var reverse = require('./helpers').reverse;
|
|
var changeCase = require('change-case');
|
|
</script>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Variables
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<var name="foo" value="'bar'" />
|
|
<var name="count" value="0" />
|
|
<assign var="count" value="count+1" />
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<var foo="bar" count=0/>
|
|
<assign count=count+1/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Scoped Variables
|
|
|
|
```xml
|
|
<var name="Frank">
|
|
Hello ${name}!
|
|
</var>
|
|
<!-- The "name" variable will be `undefined` here -->
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Scriptlets
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
{% if (true) { %}
|
|
HELLO
|
|
{% } %}
|
|
{% if (false) { %}
|
|
WORLD
|
|
{% } %}
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<% console.log('Hello World'); %>
|
|
|
|
<% if (true) { %>
|
|
HELLO
|
|
<% } %>
|
|
<% if (false) { %>
|
|
WORLD
|
|
<% } %>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Layout taglib
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<layout-use template="./layout-default.marko" show-header="$false">
|
|
<layout-put into="body">BODY CONTENT</layout-put>
|
|
<layout-put into="footer">FOOTER CONTENT</layout-put>
|
|
</layout-use>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<layout-use("./layout-default.marko") show-header=false>
|
|
<layout-put into="body">BODY CONTENT</layout-put>
|
|
<layout-put into="footer">FOOTER CONTENT</layout-put>
|
|
</layout-use>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Invoke tag
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<invoke function="test('World')"/>
|
|
<invoke function="console.log('Hello World')"/>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<invoke test('World') />
|
|
<invoke console.log('Hello World')/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Empty closing tag
|
|
|
|
```xml
|
|
<my-custom-tag>
|
|
Hello world!
|
|
</>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
## Shorthand ID and class names
|
|
|
|
```xml
|
|
#section
|
|
ul.colors
|
|
li.color - red
|
|
li.color - green
|
|
button#submitButton.enabled - Submit Form
|
|
```
|
|
|
|
Output:
|
|
|
|
```html
|
|
<div id="section">
|
|
<ul class="colors">
|
|
<li class="color">red</li>
|
|
<li class="color">green</li>
|
|
<li class="color">blue</li>
|
|
</ul>
|
|
<button id="submitButton" class="enabled">
|
|
Submit Form
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
The shorthand syntax also works with the more verbose HTML syntax:
|
|
|
|
```html
|
|
<#section>
|
|
<ul.colors>
|
|
<li.color>red</li>
|
|
<li.color>green</li>
|
|
<li.color>blue</li>
|
|
</ul.colors>
|
|
<button#submitButton.enabled>
|
|
Submit Form
|
|
</button>
|
|
</>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Validating parser
|
|
|
|
```xml
|
|
<div>Hello World</foo>
|
|
```
|
|
|
|
You will get a friendly error message:
|
|
|
|
```text
|
|
The closing "foo" tag does not match the corresponding opening "div" tag
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Validation for JavaScript Expression
|
|
|
|
```xml
|
|
<div if(someCondition INVALID)>
|
|
...
|
|
</div>
|
|
```
|
|
|
|
Error message:
|
|
|
|
```text
|
|
1) [template.marko:1:0] Invalid expression for if statement:
|
|
|
|
Unexpected identifier: (someCondition INVALID)
|
|
^
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Style attribute
|
|
|
|
```xml
|
|
<div style={color: 'red', 'font-weight': 'bold'}>
|
|
```
|
|
|
|
Output:
|
|
|
|
```html
|
|
<div style="color:red;font-weight:bold">
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Class attribute
|
|
|
|
The value of the class attribute can now be an object expression or an array expression as shown below:
|
|
|
|
```xml
|
|
<!-- array: -->
|
|
<div class=['a', null, 'c']>
|
|
|
|
<!-- object: -->
|
|
<div class={a: true, b: false, c: true}>
|
|
```
|
|
|
|
In both cases, the output will be the same:
|
|
|
|
```html
|
|
<div class="a c">
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Dynamic attributes
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<div attrs="myAttrs"/>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<var myAttrs={'class': 'foo', 'style': 'background-color: red'}/>
|
|
<div ${myAttrs}/>
|
|
```
|
|
|
|
Output:
|
|
|
|
```html
|
|
<div class="foo" style="background-color: red"></div>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Dynamic tag names
|
|
|
|
```xml
|
|
<${foo ? 'div' : 'span'}>
|
|
Hello World!
|
|
</>
|
|
```
|
|
|
|
Output:
|
|
|
|
```xml
|
|
<!-- If foo is true: -->
|
|
<div>Hello World!</div>
|
|
|
|
<!-- If foo is false: -->
|
|
<span>Hello World!</span>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Input data for custom tags
|
|
|
|
```xml
|
|
<greeting({name: 'Frank'})/>
|
|
|
|
<!-- Equivalent to: -->
|
|
<greeting name='Frank' />
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Tag body content parsing
|
|
|
|
The `marko-body` attribute can be used to control how body content is parsed. The following values are supported:
|
|
|
|
- `"html"`
|
|
- `"static-text"`
|
|
- `"parsed-text"`
|
|
|
|
```xml
|
|
<div marko-body="static-text">
|
|
This is just one
|
|
<span if(foo)>
|
|
Hello ${THIS IS NOT VALID}!
|
|
</span>
|
|
big text block
|
|
</div>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Preserve whitespace
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<div c-space="preserve">
|
|
This whitespace will
|
|
be preserved.
|
|
</div>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<div marko-preserve-whitespace>
|
|
This whitespace will
|
|
be preserved.
|
|
</div>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Compiler options
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<compiler-options whitespace="preserve" />
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<marko-compiler-options preserve-whitespace preserve-comments />
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Open tag only
|
|
|
|
Tag definition:
|
|
|
|
```json
|
|
{
|
|
"<my-custom-tag>": {
|
|
"open-tag-only": true,
|
|
...
|
|
}
|
|
}
|
|
```
|
|
|
|
Usage:
|
|
|
|
```xml
|
|
<!-- Allowed: -->
|
|
<my-custom-tag>
|
|
<my-custom-tag/>
|
|
|
|
<!-- Not allowed: -->
|
|
<my-custom-tag>Foo</my-custom-tag>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Improved readability of compiled code
|
|
|
|
```xml
|
|
<my-custom-tag name="World"/>
|
|
|
|
<ul if(data.colors.length)>
|
|
<li for(color in data.colors)>
|
|
${color}
|
|
</li>
|
|
</ul>
|
|
<div else>
|
|
No colors!
|
|
</div>
|
|
```
|
|
|
|
```javascript
|
|
function create(__helpers) {
|
|
var str = __helpers.s,
|
|
empty = __helpers.e,
|
|
notEmpty = __helpers.ne,
|
|
escapeXml = __helpers.x,
|
|
__loadTag = __helpers.t,
|
|
my_custom_tag = __loadTag(require("./components/my-custom-tag/renderer")),
|
|
forEach = __helpers.f;
|
|
|
|
return function render(data, out) {
|
|
my_custom_tag({
|
|
name: "World"
|
|
}, out);
|
|
|
|
if (data.colors.length) {
|
|
out.w("<ul>");
|
|
|
|
forEach(data.colors, function(color) {
|
|
out.w("<li>" +
|
|
escapeXml(color) +
|
|
"</li>");
|
|
});
|
|
|
|
out.w("</ul>");
|
|
} else {
|
|
out.w("<div>No colors!</div>");
|
|
}
|
|
};
|
|
}
|
|
|
|
(module.exports = require("marko").c(__filename)).c(create);
|
|
```
|
|
<hr class="page-break">
|
|
|
|
# Removed features
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: $<variable-name>
|
|
|
|
Use `${<variable-name>}` instead.
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: $!<variable-name>
|
|
|
|
Use `$!{<variable-name>}` instead.
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: "simple conditional" syntax
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<div class="{?data.isActive; active; inactive}">
|
|
<div class="{?data.isActive; active}">
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<div class=(data.isActive ? 'active' : 'inactive')>
|
|
<div class=(data.isActive && 'active')>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: nested attributes
|
|
|
|
Nested attributes are no longer supported (likely never used):
|
|
|
|
```xml
|
|
<test-popover>
|
|
<attr name="title">Popover Title</attr>
|
|
<attr name="content">Popover Content</attr>
|
|
|
|
Link Text
|
|
</test-popover>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: `<require>` tag
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<require module="./my-include-target.marko" var="myIncludeTarget" />
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<script marko-init>
|
|
var myIncludeTarget = require('./my-include-target.marko');
|
|
</script>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: `c-data`/`c-input` attribute
|
|
|
|
Custom tag data should be passed using an argument:
|
|
|
|
```xml
|
|
<my-custom-tag({name: 'Frank'})/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: `c-space`/`c-whitespace` attribute
|
|
|
|
Use `marko-preserve-whitespace` attribute instead:
|
|
|
|
```xml
|
|
<div marko-preserve-whitespace>
|
|
This whitespace
|
|
will be preserved.
|
|
</div>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: `c-escape-xml` attribute
|
|
|
|
No longer applicable.
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: `c-parse-body-text` attribute
|
|
|
|
Use the `marko-body="<body-type>"` attribute instead.
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: `attrs` attribute
|
|
|
|
Use placeholder within open tag instead:
|
|
|
|
```xml
|
|
<div ${myAttrs}>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: `with` tag and attribute
|
|
|
|
Instead, use `<var>` tag with nested content to create scoped variables.
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: JavaScript operator aliases
|
|
|
|
The following JavaScript operator aliases are no longer supported:
|
|
|
|
JavaScript Operator | Marko Equivalent
|
|
------------------- | -----------------
|
|
`&&` | `and`
|
|
<code>||</code> | `or`
|
|
`===` | `eq`
|
|
`!==` | `ne`
|
|
`<` | `lt`
|
|
`>` | `gt`
|
|
`<=` | `le`
|
|
`>=` | `ge`
|
|
|
|
<hr class="page-break">
|
|
|
|
# Removed: Dynamic string path for includes
|
|
|
|
```javascript
|
|
var includeTemplate = require('./include.marko');
|
|
|
|
// ...
|
|
|
|
var templateData = {
|
|
includeTarget: includeTemplate
|
|
}
|
|
```
|
|
|
|
```xml
|
|
<include(data.includeTarget})/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Other notable changes
|
|
|
|
<hr class="page-break">
|
|
|
|
# marko-taglib.json → marko.json
|
|
|
|
<hr class="page-break">
|
|
|
|
# Nested tags separator changed
|
|
|
|
___Old syntax:___
|
|
|
|
```xml
|
|
<tabs>
|
|
<tabs.tab title="Tab 1">
|
|
Content for tab 1
|
|
</tabs.tab>
|
|
<tabs.tab title="Tab 2">
|
|
Content for tab 2
|
|
</tabs.tab>
|
|
</tabs>
|
|
```
|
|
|
|
___New syntax:___
|
|
|
|
```xml
|
|
<tabs>
|
|
<tabs:tab title="Tab 1">
|
|
Content for tab 1
|
|
</tabs:tab>
|
|
<tabs:tab title="Tab 2">
|
|
Content for tab 2
|
|
</tabs:tab>
|
|
</tabs>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Node.js v4+ is now required for compiling
|
|
|
|
Unlike Marko v2, Marko v3 requires Node.js v4+ to compile Marko templates. The new Marko compiler was written using ECMAScript 2015 (ES6) features that are only found in Node.js v4+. The Marko runtime, however, still works in all JavaScript runtimes.
|
|
|
|
<hr class="page-break">
|
|
|
|
# Case-sensitive HTML parser
|
|
|
|
The Marko parser and compiler are now case sensitive. The following tags are not equal with Marko v3:
|
|
|
|
```xml
|
|
<my-custom-tag/>
|
|
<My-CUSTOM-Tag/>
|
|
```
|
|
|
|
<hr class="page-break">
|
|
|
|
# Special Thanks:
|
|
|
|
[@adammcarth](https://github.com/adammcarth), [@BryceEWatson](https://github.com/BryceEWatson), [@crsandeep](https://github.com/crsandeep), [@DanCech](https://github.com/DanCech), [@danrichman](https://github.com/danrichman), [@kristianmandrup](https://github.com/kristianmandrup), [@onemrkarthik](https://github.com/onemrkarthik), [@philidem](https://github.com/philidem), [@pswar](https://github.com/pswar), [@scttdavs](https://github.com/scttdavs), [@SunnyGurnani](https://github.com/SunnyGurnani), [@tindli](https://github.com/tindli), [@vedam](https://github.com/vedam) and [@yomed](https://github.com/yomed)
|
|
|
|
<hr class="page-break">
|
|
|
|
# Thank You!
|
|
|
|
- Join the Marko community on Gitter: [gitter.im/marko-js/marko](gitter.im/marko-js/marko)
|
|
- Please help improve code, tests and docs
|
|
- Pull requests greatly appreciated!
|
|
- Please tell your friends :) |