Skip to content

Commit

Permalink
Add custom handlebars helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
satterly committed Nov 9, 2021
1 parent cd386bf commit 242fcbc
Show file tree
Hide file tree
Showing 6 changed files with 246 additions and 26 deletions.
4 changes: 2 additions & 2 deletions __tests__/fixtures/slack.yml
@@ -1,7 +1,7 @@
username: GitHub-CI
icon_url: https://octodex.github.com/images/mona-the-rivetertocat.png

pretext: Triggered via {{eventName}} by {{actor}} {{or action "action"}} {{ref}} `{{diffRef}}`
pretext: Triggered via {{eventName}} by {{actor}} {{default action "action"}} {{ref}} `{{diffRef}}`
title: GitHub Actions
title_link: https://support.github.com

Expand All @@ -11,7 +11,7 @@ text: |
{{#if payload.commits}}
*Commits*
{{#each payload.commits}}
<{{this.url}}|`{{limitTo this.id 8}}`> - {{this.message}}
<{{this.url}}|`{{truncate this.id 8}}`> - {{this.message}}
{{/each}}
{{/if}}
Expand Down
157 changes: 157 additions & 0 deletions __tests__/handlebars.test.ts
@@ -0,0 +1,157 @@
import Handlebars from '../src/handlebars'

const data = {
foo: 'bar',
fu: 'bar',
obj: {
a: 'b',
c: 123,
d: ['x', 'y', 'z']
},
text: 'this is a long line of text',
uuid: 'CFE20509-E7CF-4401-9733-7615EF3E8A25',
want: 0,
t: true,
f: false,
empty: [],
commits: ['088fcd5a5bc73a6733edcc58d0d30869ddbe2e2f'],
numbers: [1, 2, 3, 4],
letters: ['abc', 'def', 'ghi'],
foobars: [
{foo: true, bar: 1},
{foo: false, bar: 3},
{foo: true, bar: 3}
],
attendees: ['dave', 'mike', 'jane', 'betty'],
items: [1, 2, 3]
}

// utilities
test('json stringify', () => {
const template = Handlebars.compile('{{{json obj}}}')
const text = template(data)
expect(text).toStrictEqual('{"a":"b","c":123,"d":["x","y","z"]}')
})

test('truncate uuid', () => {
const template = Handlebars.compile('{{truncate uuid 8}}')
const text = template(data)
expect(text).toStrictEqual('CFE20509')
})

test('default is not needed', () => {
const template = Handlebars.compile('{{default want "fallback"}}')
const text = template(data)
expect(text).toStrictEqual('0')
})

test('default is needed', () => {
const template = Handlebars.compile('{{default fallback "fallback"}}')
const text = template(data)
expect(text).toStrictEqual('fallback')
})

test('pluralize empty list', () => {
const template = Handlebars.compile('{{pluralize empty}}')
const text = template(data)
expect(text).toStrictEqual('no items')
})

test('pluralize commits', () => {
const template = Handlebars.compile('{{pluralize commits "commit"}}')
const text = template(data)
expect(text).toStrictEqual('1 commit')
})

test('pluralize attendees', () => {
const template = Handlebars.compile('{{pluralize attendees "attendee"}}')
const text = template(data)
expect(text).toStrictEqual('4 attendees')
})

test('pluralize people', () => {
const template = Handlebars.compile('{{pluralize attendees "person" "people"}}')
const text = template(data)
expect(text).toStrictEqual('4 people')
})

// equality
test('eq is true', () => {
const template = Handlebars.compile('{{#if (eq foo fu)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('eq is false', () => {
const template = Handlebars.compile('{{#if (eq foo "foo")}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('neq is true', () => {
const template = Handlebars.compile('{{#if (neq foo fu)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('neq is false', () => {
const template = Handlebars.compile('{{#if (neq foo "foo")}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

// boolean operators
test('not false', () => {
const template = Handlebars.compile('{{#if (not f)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('not true', () => {
const template = Handlebars.compile('{{#if (not t)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('not false and (true or false)', () => {
const template = Handlebars.compile('{{#if (and (not f) (or t f))}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('or is true', () => {
const template = Handlebars.compile('{{#if (or t f)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('and is false', () => {
const template = Handlebars.compile('{{#if (and t f)}}yes{{else}}no{{/if}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

// conditionals
test('#ifeq is true', () => {
const template = Handlebars.compile('{{#ifeq foo fu}}yes{{else}}no{{/ifeq}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})

test('#ifeq is false', () => {
const template = Handlebars.compile('{{#ifeq foo "foo"}}yes{{else}}no{{/ifeq}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('#ifneq is true', () => {
const template = Handlebars.compile('{{#ifneq foo fu}}yes{{else}}no{{/ifneq}}')
const text = template(data)
expect(text).toStrictEqual('no')
})

test('#ifneq is false', () => {
const template = Handlebars.compile('{{#ifneq foo "foo"}}yes{{else}}no{{/ifneq}}')
const text = template(data)
expect(text).toStrictEqual('yes')
})
54 changes: 44 additions & 10 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions src/handlebars.ts
@@ -0,0 +1,41 @@
import Handlebars from 'handlebars'

// utilities
Handlebars.registerHelper('json', value => new Handlebars.SafeString(JSON.stringify(value)))

Handlebars.registerHelper('truncate', (text, size) => text.substring(0, size))

Handlebars.registerHelper('default', (want, fallback) => want ?? fallback)

Handlebars.registerHelper('pluralize', (items, ...args) => {
const count = items.length
const singular = args.length === 1 ? 'item' : args[0]
const plural = args.length === 3 ? args[1] : `${singular}s`

if (count === 0) return `no ${plural}`
if (count === 1) return `1 ${singular}`
return `${count} ${plural}`
})

// equality
Handlebars.registerHelper('eq', (a, b) => a === b)

Handlebars.registerHelper('neq', (a, b) => a !== b)

// logical operators
Handlebars.registerHelper('not', a => !a)

Handlebars.registerHelper('and', (a, b) => a && b)

Handlebars.registerHelper('or', (a, b) => a || b)

// conditionals
Handlebars.registerHelper('ifeq', (a, b, opts) => {
return a === b ? opts.fn(this) : opts.inverse(this) // eslint-disable-line no-invalid-this
})

Handlebars.registerHelper('ifneq', (a, b, opts) => {
return a !== b ? opts.fn(this) : opts.inverse(this) // eslint-disable-line no-invalid-this
})

export default Handlebars
14 changes: 1 addition & 13 deletions src/slack.ts
Expand Up @@ -2,7 +2,7 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import {IncomingWebhook, IncomingWebhookResult} from '@slack/webhook'
import {EventPayloads} from '@octokit/webhooks'
import Handlebars from 'handlebars'
import Handlebars from './handlebars'

interface ColorOptions {
success?: string | undefined
Expand Down Expand Up @@ -155,18 +155,6 @@ export async function send(
return stepIcon(status, opts?.icons)
})

Handlebars.registerHelper('json', function (context) {
return JSON.stringify(context)
})

Handlebars.registerHelper('limitTo', function (text, size) {
return text.substring(0, size)
})

Handlebars.registerHelper('or', function (op1, op2) {
return op1 || op2
})

const pretextTemplate = Handlebars.compile(opts?.pretext || '')
const titleTemplate = Handlebars.compile(opts?.title || '')

Expand Down

0 comments on commit 242fcbc

Please sign in to comment.