I recently got a very interesting PR for my Cross-platform Release Notes Azure DevOps Pipelines Extension from Kenneth Scott. He had added a new templating engine to the task, Handlebars.
Previous to this PR the templating in the task was done with a line by line evaluation of a template that used my own mark-up. This method worked but has limitations, mostly due to the line by line evaluation model. With the Kenneth’s PR the option was added to write your templates in Handlebars, or stay with my previous templating engine.
Using Handlebars
If you use Handlebars, the template becomes something like
\## Notes for release {{releaseDetails.releaseDefinition.name}}
\*\*Release Number\*\* : {{releaseDetails.name}}
\*\*Release completed\*\* : {{releaseDetails.modifiedOn}}
\*\*Build Number\*\*: {{buildDetails.id}}
\*\*Compared Release Number\*\* : {{compareReleaseDetails.name}}
### Associated Work Items ({{workItems.length}})
{{#each workItems}}
\* \*\*{{this.id}}\*\* {{lookup this.fields 'System.Title'}}
- \*\*WIT\*\* {{lookup this.fields 'System.WorkItemType'}}
- \*\*Tags\*\* {{lookup this.fields 'System.Tags'}}
{{/each}}
### Associated commits ({{commits.length}})
{{#each commits}}
\* \*\* ID{{this.id}}\*\*
- \*\*Message:\*\* {{this.message}}
- \*\*Commited by:\*\* {{this.author.displayName}}
{{/each}}
The whole template is evaluated by the Handlebars engine using its own mark-up to provide a means for looping across arrays and the like.
This seemed a great enhancement to the task. However, we soon realised that it could be better. Handlebars is extensible, so why not allow the extensibility to be used?
Using Handlebars Extensions
I have added extensibility in two ways. Firstly I have also added support for the common Handlebar-Helpers extensions, this added over 150 helpers. These are just accessed in a template as follows
\## To confirm the handbars-helpers is work
The year is {{year}}
We can capitalize "foo bar baz" {{capitalizeAll "foo bar baz"}}
I have also added the ability to provide a block of JavaScript as a task parameter is that is loaded as a custom Handlebars extension. So if you add the following block in the tasks customHandlebarsExtensionCode parameter.
module.exports = {foo: function () {return 'Returns foo';}};
You can access in the templates as
\## To confirm our custom extension works
We can call our custom extension {{foo}}
It will be interesting to see how popular this alternative way of templating will be.