Commit 1ed4f03e authored by Caleb Weeks's avatar Caleb Weeks

adding handlebars guide

parent c45ca916
## JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
.idea/
.tmp/
.vscode/
jsconfig.json
## Sublime workspace files
*.sublime-workspace
public
public/test/
# node/bower
node_modules/
npm-debug.log
bower_components/
# Mac system files
.DS_Store
# Blacklight files
blacklight_modules/
# sass
.sach-cache/
# build
public
# generated breakpoints sass file
asset-build/scss/base/_breakpoints.scss
# Conflict resolution files
*.orig
### `component` ###
```handlebars
{{component context [resourceType] }}
```
##### Description #####
Finds the template associated with the resource type in context._meta._sling_resourceType or resourceType, if provided, evaluates the template with the provided context, and inserts the resulting HTML into the invoking template.
##### Arguments #####
**context _(Object)_**: The data context to be used when evaluating the template associated with the determined resource type.
**resourceType _(String)_**: Optional. Specifies the resource type to be used in looking up the template to render the provided context. If this isn't provided then the resource type will be pull from context._meta._sling_resourceType. If the resource type can't be determined from either source then the context is output in a tabular format. The value "raw" can be explicitly passed as well to force the tabular format. "raw" can be useful during development and debugging, but should not be used in production code.
##### Examples #####
```javascript
/* Example context provided to HBS template*/
{
title: "Top Level Title",
header: {
_meta: {_sling_resourceType: "fshr/demo/content/header"},
title: "Landing Page",
name: "Herald"
},
customHeader: {
title: "Personal Landing Page",
name: "Jane"
}
}
```
```handlebars
{{! 'fshr/demo/content/header' template}}
<h1>{{title}}</h1>
{{! 'fshr/demo/content/altHeader' template}}
<h2>{{name}}</h2>
{{! test template }}
{{component header}}
{{! resource would be automatically determined from header._meta._sling_resourceType }}
{{! RESULT: <h1>Landing Page</h1>}}
{{component "fshr/demo/content/header" .}}
{{! use resource type provided}}
{{! RESULT: <h1>Top Level Title</h1>}}
{{component customHeader}}
{{! no resource type provided, and one can't be determined automatically }}
{{! RESULT: tabular output of customHeader}}
{{component "fshr/demo/content/altHeader" customerHeader}}
{{! use resource type provided}}
{{! RESULT: <h2>Jane</h2>}}
```
### `if-author` ###
```handlebars
{{#if-author }}
{{else}}
{{/if-author}}
```
##### Description #####
Helper block that allows outputting of content only in author mode. The {{else}} block is optional.
##### Arguments #####
_none_
##### Examples #####
```handlebars
<div>
{{#if title}}
<h1>{{title}}</h1>
{{else}}
{{#if-author }}
<p>No title has been configured. This is a mandatory field</p>
{{/if-author}}
{{/if}}
</div>
{{! Assuming {{title}} is blank }}
{{! RESULT on author: <div><p>No title has been configured. This is a mandatory field</p></div>}}
{{! RESULT on publish: <div></div>}}
```
### `ifop / ifOp` ###
```handlebars
{{#ifop valueOne operand valueTwo}}
{{else}}
{{/ifop}}
```
##### Description #####
Checks the truthiness of the result of comparing valueOne against valueTwo. The type of comparison done is based on the operand provided.
##### Arguments #####
**valueOne _(String|number)_** : First value in the comparison
**operand _(String)_** : Must be one of the follwing values:
- "==" : Returns true if valueOne and valueTwo are abstractly equal (uses == JS operator)
- "!=" : Returns true if valueOne and valueTwo are not equal
- "===" : Returns true if valueOne and valueTwo are strictly equal (uses === JS operator)
- "<" : Returns true if valueOne is less than valueTwo
- "<=" : Returns true if valueOne is less than or equal to valueTwo
- ">" : Returns true if valueOne is greater than valueTwo
- ">=" : Returns true if valueOne is greater than or equal to valueTwo
- "&&" : Returns true if valueOne and valueTwo are truthy
- "||" : Returns true if either valueOne or valueTwo is truthy
- "contains" : Returns false if valueOne does not have a `indexOf` function otherwise the result of `valueOne.indexOf(valueTwo)` is returned
- "nonmeta" : Returns true if valueOne is String and does not match `/^(jcr|bl|cq|sling)\:/`. valueTwo is ignored.
- "nonblank" : Returns true if valueOne is truthy. valueTwo is ignored.
- "iseven" : Returns true if valueOne is an even number. valueTwo is ignored.
- "isstring": Returns true if valueOne is a String. valueTwo is ignored.
- "in" : Returns true if valueOne is a member of the array resulting from splitting valueTwo on ','.
**valueTwo _(String|number)_** : Second value in the comparison. May not be required depending on the operand used.
##### Examples #####
```handlebars
{{#ifop 3 "===" "3"}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifop}}
{{! RESULT : <h1>Fail</h1>}}
{{#ifop 3 "==" "3"}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifop}}
{{! RESULT : <h1>Pass</h1>}}
{{#ifop 3 "<" 4}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifop}}
{{! RESULT : <h1>Pass</h1>}}
{{#ifop "test" "isstring"}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifop}}
{{! RESULT : <h1>Pass</h1>}}
{{#ifop "test" "contains" "art"}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifop}}
{{! RESULT : <h1>Fail</h1>}}
```
### `ifnot` ###
```handlebars
{{#ifnot valueOne operand valueTwo}}
{{else}}
{{/ifnot}}
```
##### Description #####
Same as ifop, but it asserts that the negative of the expression is true.
##### Arguments #####
See [ifop Arguments](blacklight-handlebar-helpers#arguments-2). The same list of arguments apply, but the inverse will be returned for each operand.
##### Examples #####
```handlebars
{{#ifnot 5 "===" "5"}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifnot}}
{{! RESULT : <h1>Pass</h1>}}
{{#ifnot 4 "==" 4}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifnot}}
{{! RESULT : <h1>Fail</h1>}}
{{#ifnot 12 ">=" 31}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifnot}}
{{! RESULT : <h1>Pass</h1>}}
{{#ifnot 5 "isstring"}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifnot}}
{{! RESULT : <h1>Pass</h1>}}
es
{{#ifnot "twelve" "in" "one,three,five,ten,twelve"}}
<h1>Pass</h1>
{{else}}
<h1>Fail</h1>
{{/ifnot}}
{{! RESULT : <h1>Fail</h1>}}
```
### `translate` ###
```handlebars
{{translate text [language=""] [0=""] [1=""]...[n=""]}}
```
##### Description #####
Translates the the given text. The langugage can optionally be specified. If a language is not provided then the langauage will be inferred from the page, if possible. Parameters can be specified in the text using '{number}'. If a translation for the text isn't found in the dictionary associated with the determined language then the provided text will be rendered.
##### Arguments #####
**language _(String)_** : Optional. The language to translate the text into. If no language is directly provided then it tries to determine the page language by checking the following properties in the root template context in the specified order:
1. @root.meta.iso
2. @root.meta.language
**0,1...n _(String)_** : The associated parameter in the text will be replaced with these values.
##### Examples #####
```handlebars
{{! For the following examples assume that the @root.page.iso is 'zh' and we have translations for whatever language specified}}
{{translate "I have {0} car, but I want {1}" 0="1" 1="2"}}
{{! RESULT: 我有1车,但我想要2 }}
{{translate "I have {0} car, but I want {1}" language="en" 0="1"}}
{{! RESULT: I have 1 car, but I want {1} }}
{{translate "I have {0} car, but I want {1}" language="es" 0="1" 1="12"}}
{{! RESULT: Tengo 1 coche, pero quiero 12 }}
```
### `replace` ###
```handlebars
{{replace text find replaceWith}}
```
##### Description #####
Replaces all matches of `find` in `text` with `replaceWith`. Regexes can be used as the value of `find`.
##### Arguments #####
**text _(String)_** : Text to modify.
**find _(String)_** : The pattern to find.
**replaceWith _(String)_** : Matches in text will be replaced with this value.
##### Examples #####
```handlebars
{{replace "Where is the kitchen" "kitchen" "deck"}}
{{! RESULT: Where is the deck }}
{{replace "We didn't want more than $3 for the 50/50 cut (chapter 2.1)" "[^A-Za-z0-9]" "-"}}
{{! RESULT: We-didn-t-want-more-than--3-for-the-50-50-cut--chapter-2-1- }}
```
### `trim` ###
```handlebars
{{trim text}}
```
##### Description #####
Trims whitespace from the provided `text`
##### Arguments #####
**text _(String)_** : Text to modify.
##### Examples #####
```handlebars
{{trim " some text "}}
{{! RESULT: "some text" }}
```
### `count` ###
```handlebars
{{count toCount [type="components"]}}
```
##### Description #####
Counts the number of properties in the provided `toCount`. Does not include properties that have a key that matches `/^(jcr|bl|cq|sling)\:/`.
##### Arguments #####
**toCount _(Object|Array)_** : Object to count properties of. If an array is provided this will return the length of the array.
**type _(String)_** : Optional. Mechanism to filter which child members are included in the count. Currently the only supported type is **components**. This will only include members that are Objects and have a child property called **sling:resourceType**.
##### Examples #####
```javascript
/* context provided to handlebar template */
{
children: ["one", "two", "three"],
header: {
"jcr:title" : "Home Run",
"sling:resourceType": "fshr/demo/content/header",
link: "www.google.com",
count: 4
},
nodes: {
node000: {
"sling:resourceType": "fshr/demo/content/node",
"key": "value"
},
node001: {
"sling:resourceType": "fshr/demo/content/node",
"key": "value"
},
node003: {
"key": "value"
}
}
````
```handlebars
{{count children}}
{{! RESULT: 3}}
{{count header}}
{{! RESULT: 2}}
{{count nodes type="components"}}
{{! RESULT: 2}}
```
### `modulus` ###
```handlebars
{{modulus dividend divisor}}
```
##### Description #####
Returns the remainder of divident divided by divisor.
##### Arguments #####
**dividend _(number)_** : Number to be divided.
**divisor _(number)_** : Number to divide by.
##### Examples #####
```handlebars
{{modulus 4 3}}
{{! RESULT: 1}}
{{modulus 21 6}}
{{! RESULT: 3}}
```
### `rev` ###
```handlebars
{{rev staticAsset}}
```
##### Description #####
Appends a revision number before the extension of the specified asset. The revision number only changes when the asset itself is modifie making this very useful for ensuring unique URLs for caching purposes.
##### Arguments #####
**staticAsset _(String)_** : Reference to a valid static asset. Should begin with '/alt/'.
##### Examples #####
```handlebars
{{rev "/alt/fshr/shared/caw/caw.js"}}
{{! RESULT (note that the exact number will vary): /alt/fshr/shared/caw/caw.1474553126.js }}
```
### `log` ###
```handlebars
{{log logMessage}}
```
##### Description #####
Output the specified `logMessage` to the node console. The log message will be prepended with 'TEMPLATE_LOG'. Useful for debugging and development, but should not be used in production.
##### Arguments #####
**logMessage _(String)_** : Message to output to the console.
##### Examples #####
```handlebars
{{log "Made it to this point."}}
{{!-- RESULT: the following will be output to the node console
-----------------------------------------------------------
TEMPLATE_LOG: Made it to this point.
--}}
```
### `img-opt` ###
```handlebars
{{img-opt assetPath [quality=""] [size=""] }}
```
##### Description #####
Rewrites the `assetPath` to use the /alt/img-opt route which caches and optimizes raw images from the repository.
##### Arguments #####
**assetPath _(String)_** : Path to the asset to be included. Must start with '/content/dam'. If the path matches `/\.(png|svg|gif)$/` it will be returned unmodified.
**quality _(number)_** : Optional. The compression quality to be used. Defaults to 70.
**size _(String|number)_** : Optional. Indicates the desired geometry of the final image. Any valid geometry defined [here](https://www.imagemagick.org/script/command-line-processing.php#geometry) can be specified.
##### Examples #####
```handlebars
{{! Assumes that /content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg is a valid image, and the original dimensions are 1000x563}}
{{img-opt "/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg"}}
{{! RESULT (will be 1000x533 reduced to 70% quality): /alt/img-opt/author/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg/70.jpg }}
{{img-opt "/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-.jpg" quality="60"}}
{{! RESULT (will be 1000x533 reduced to 60% quality): /alt/img-opt/author/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg/60.jpg }}
{{img-opt "/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg" size="300"}}
{{! RESULT (will be 300x169 reduced to 70% quality): /alt/img-opt/author/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg/70.300.jpg }}
{{img-opt "/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg" size="400x"}}
{{! RESULT (will be 400x225 reduced to 70% quality): /alt/img-opt/author/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg/70.400x.jpg }}
{{img-opt "/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg" size="x400"}}
{{! RESULT (will be 710x400 reduced to 70% quality): /alt/img-opt/author/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg/70.x400.jpg }}
{{img-opt "/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg" size="400x200"}}
{{! RESULT (will be 355x200 reduced to 70% quality): /alt/img-opt/author/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg/70.400x200.jpg }}
{{img-opt "/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg" size="400x200!"}}
{{! RESULT (will be 400x200 reduced to 70% quality): /alt/img-opt/author/content/dam/fourseasons_magazine/BEJ/forbidden-city-beijing-1000x563.jpg/70.400x200!.jpg }}
```
### `bl-edit` ###
```handlebars
{{bl-edit}}
```
##### Description #####
Returns a data attribute that can be added to a DOM element. This data attribute is only rendered in author. Holding alt+clicking the DOM element with the data attribute will open the Edit UI with focus on the configuration associated with the current component context.
##### Arguments #####
_none_
##### Examples #####
```handlebars
{{! assumes the current component is at the path /content/fourseasons/en/properties/beijing/destination/things-to-do/jcr:content/header}}
<div class="component-wrapper" {{bl-edit}}>
<!-- content -->
</div>
{{!-- RESULT in author:
<div class="component-wrapper" data-bl-edit="{"slingPath":"/header"}">
<!-- content -->
</div>
--}}
{{!-- RESULT in publish:
<div class="component-wrapper">
<!-- content -->
</div>
--}}
```
### `markdown` ###
```handlebars
{{markdown markdownText}}
```
##### Description #####
Compiles the provided `markdownText` and returns the resultant HTML
##### Arguments #####
**markdownText _(String)_** : Text in Markdown format.
##### Examples #####
```handlebars
{{markdown "# Headline #"}}
{{! RESULT: <h1>Headline</h1>}}
```
### `first-of` ###
```handlebars
{{first-of valueOne...valueN}}
```
##### Description #####
Returns the first non empty value found. Primarily used as a mechanism to provide a default value if the preferred value is empty.
##### Arguments #####
**valueOne...valueN _(String|number|Object|Array)_** : List of values to pick from.
##### Examples #####
```javascript
/* context provided to handlebar template */
{
title: "Big Screen"
}
```
```handlebars
<h1>{{first-of title "Default title"}}</h1>
{{! RESULT: <h1>Big Screen</h1> }}
<h1>{{first-of name "Default Name"}}</h1>
{{! RESULT: <h1>Default Name</h1> }}
```
### `raw-helper` ###
```
{{{{raw-helper}}}}
{{! Escaped Handlebar template}}
{{{{/raw-helper}}}}
```
##### Description #####
The body of the raw-helper will be completely ignored when evaluating the Handlebar template. Useful if you need to have a client side Handlebar template. Note the need for double, double brackets.
##### Arguments #####
_none_
##### Examples #####
```
<script id="header" type="text/x-handlebars-template">​
{{{{raw-helper}}}}
<div> Name: {{ headerTitle }} </div>​
{{#each items}}
<p>{{.}}</p>
{{/each}}
{{{{/raw-helper}}}}
</script>
{{!-- RESULT:
<script id="header" type="text/x-handlebars-template">​
<div> Name: {{ headerTitle }} </div>​
{{#each items}}
<p>{{.}}</p>
{{/each}}
</script>
--}}
```
\ No newline at end of file
## Quickstart Guide ##
## Required Dependencies ##
1. Node.js (https://nodejs.org/en/download/package-manager/)
2. GIT (https://git-scm.com/downloads)
3. ImageMagick (https://www.imagemagick.org/script/binary-releases.php)
4. Valid credentials and permissions for Gitlab (https://gitlab.entropy.cc/fs-blacklight/fs-blacklight) and FS Stage AEM instance (https://author13.stage.fourseasons.com)
5. An SSH key configured in your Gitlab account (https://docs.gitlab.com/ce/ssh/README.html)
## Installation Steps ##
#### 1. Install Blacklight Command Line Utility ####
```bash
npm install -g blacklight-cli
```
#### 2. Clone fs-blacklight GIT repo ####
```bash
git clone git@gitlab.entropy.cc:fs-blacklight/fs-blacklight.git
cd fs-blacklight
npm install
```
#### 3. Setup Config file ####
```
cp config/local.json.dist config/local.json
```
Open local.json in your editor of choice, and configure your AEM credentials and ImageMagick executable
```javascript
//...
"author":{
"port":4400, // <-- this can be set to any port you want Blacklight to run on
"sling":{
"baseUri": "https://author13.stage.fourseasons.com",
"username": "",
"password": ""
}
}
//...
"imageOptimizer":{
//...
"imagemagick-convert":"/usr/local/bin/convert" // <-- set to your path.
}
```
#### 4. Install Core modules ####
```
bl module install fshr.site -u git@gitlab.entropy.cc:fs-blacklight/site.git
bl module install blacklight.edit -u git@gitlab.entropy.cc:blacklight/edit.git
```
#### 5. Install Project modules
```
bl module install fshr.shared
bl module install fshr.magazine
```
#### 6. Start Blacklight and verify pages are working correctly ####
```
bl start
```
In a web browsers navigate to http://localhost:4400/content/fourseasons/en/properties/santafe/destination/things-to-do
The page should look the same as it does here: http://www.stage13.fourseasons.com/santafe/destination/things-to-do/