From 71b85629b6406eeb13697e3e1f322a2f5e3aeb80 Mon Sep 17 00:00:00 2001 From: Michael Schock Date: Tue, 28 Mar 2017 16:10:05 -0700 Subject: [PATCH] STENCIL-3323 - Implement approved Handlebars helpers from pack --- .gitignore | 1 + helpers/thirdParty.js | 149 +++++++++++++++++++++++++++++ package.json | 1 + test/helpers/thirdParty.js | 191 +++++++++++++++++++++++++++++++++++++ 4 files changed, 342 insertions(+) create mode 100644 .gitignore create mode 100644 helpers/thirdParty.js create mode 100644 test/helpers/thirdParty.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/helpers/thirdParty.js b/helpers/thirdParty.js new file mode 100644 index 00000000..0ba7fc7c --- /dev/null +++ b/helpers/thirdParty.js @@ -0,0 +1,149 @@ +'use strict'; + +const _ = require('lodash'); +const helpers = require('handlebars-helpers'); +const whitelist = [ + { + name: 'array', + include: [ + 'after', + 'arrayify', + 'before', + 'eachIndex', + 'filter', + 'first', + 'forEach', + 'inArray', + 'isArray', + 'last', + 'lengthEqual', + 'map', + 'some', + 'sort', + 'sortBy', + 'withAfter', + 'withBefore', + 'withFirst', + 'withLast', + 'withSort', + ], + }, + { + name: 'collection', + include: ['isEmpty', 'iterate', 'length'], + }, + { + name: 'comparison', + include: [ + 'and', + 'gt', + 'gte', + 'has', + 'eq', + 'ifEven', + 'ifNth', + 'ifOdd', + 'is', + 'isnt', + 'lt', + 'lte', + 'neither', + 'unlessEq', + 'unlessGt', + 'unlessLt', + 'unlessGteq', + 'unlessLteq', + ], + }, + { + name: 'date', + include: ['moment'], + }, + { + name: 'html', + include: ['ellipsis', 'sanitize', 'ul', 'ol', 'thumbnail'] + }, + { + name: 'inflection', + include: ['inflect', 'ordinalize'], + }, + { + name: 'markdown', + include: ['markdown'], + }, + { + name: 'math', + include: ['add', 'subtract', 'divide', 'multiply', 'floor', 'ceil', 'round', 'sum', 'avg'], + }, + { + name: 'misc', + include: ['default', 'option', 'noop', 'withHash'], + }, + { + name: 'number', + include: [ + 'addCommas', + 'phoneNumber', + 'random', + 'toAbbr', + 'toExponential', + 'toFixed', + 'toFloat', + 'toInt', + 'toPrecision', + ], + }, + { + name: 'object', + include: [ + 'extend', + 'forIn', + 'forOwn', + 'toPath', + 'get', + 'getObject', + 'hasOwn', + 'isObject', + 'merge', + 'JSONparse', + 'JSONstringify', + ], + }, + { + name: 'string', + include: [ + 'camelcase', + 'capitalize', + 'capitalizeAll', + 'center', + 'chop', + 'dashcase', + 'dotcase', + 'hyphenate', + 'isString', + 'lowercase', + 'occurrences', + 'pascalcase', + 'pathcase', + 'plusify', + 'reverse', + 'sentence', + 'snakecase', + 'split', + 'startsWith', + 'titleize', + 'trim', + 'uppercase' + ], + }, + { + name: 'url', + include: ['encodeURI', 'decodeURI', 'urlResolve', 'urlParse', 'stripQuerystring', 'stripProtocol'], + }, +]; + +function helper(paper) { + whitelist.forEach(helper => paper.handlebars.registerHelper(_.pick(helpers[helper.name](), helper.include))); +} + +module.exports = helper; diff --git a/package.json b/package.json index 479ee0fa..86b62972 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "accept-language-parser": "^1.0.2", "async": "^1.4.2", "handlebars": "^3.0.1", + "handlebars-helpers": "^0.8.0", "lodash": "^3.6.0", "messageformat": "^0.2.2", "stringz": "^0.1.1", diff --git a/test/helpers/thirdParty.js b/test/helpers/thirdParty.js new file mode 100644 index 00000000..ca894ffa --- /dev/null +++ b/test/helpers/thirdParty.js @@ -0,0 +1,191 @@ +var Code = require('code'), + Lab = require('lab'), + Paper = require('../../index'), + lab = exports.lab = Lab.script(), + describe = lab.experiment, + expect = Code.expect, + it = lab.it; + +function c(template, context) { + return new Paper().loadTemplatesSync({template: template}).render('template', context); +} + +var context = { + array: [1, 2, 3, 4, 5], + options: { a: { b: { c: 'd' } } } +}; + +describe('third party handlebars-helpers', function() { + + describe('array helpers', function() { + + describe('after helper', function() { + it('returns all the items in an array after the index', function(done) { + expect(c('{{after array 1}}', context)) + .to.be.equal('2,3,4,5'); + + done(); + }); + }); + + }); + + describe('collection helpers', function() { + + describe('length helper', function() { + it('returns the length of the array', function(done) { + expect(c('{{length array}}', context)) + .to.be.equal('5'); + + done(); + }); + }); + + }); + + describe('comparison helpers', function() { + + describe('contains helper', function() { + it('renders the contains block if it evaluates to true', function(done) { + expect(c(`{{#contains array 1}}This will be rendered.{{else}}This will not be rendered.{{/contains}}`, context)) + .to.be.equal('This will be rendered.'); + + done(); + }); + + it('renders the else block if it evaluates to false', function(done) { + expect(c(`{{#contains array '1'}}This will not be rendered.{{else}}This will be rendered.{{/contains}}`, context)) + .to.be.equal('This will be rendered.'); + + done(); + }); + }); + + }); + + describe('date helpers', function() { + + describe('contains moment', function() { + it('renders the date in the format specified', function(done) { + const now = new Date() + expect(c(`{{#moment "1 year ago" "YYYY"}}{{/moment}}`, context)) + .to.be.equal(`${now.getFullYear() - 1}`); + + done(); + }); + }); + + }); + + describe('html helpers', function() { + + describe('contains ellipsis', function() { + it('truncates a string to the specified length and appends an ellipsis', function(done) { + expect(c(`{{ellipsis "foo bar baz" 7}}`, context)) + .to.be.equal('foo bar…'); + + done(); + }); + }); + + }); + + describe('inflection helpers', function() { + + describe('contains ordinalize', function() { + it('returns an ordinalized number as a string', function(done) { + expect(c(`{{ordinalize 42}}`, context)) + .to.be.equal('42nd'); + + done(); + }); + }); + + }); + + describe('markdown helpers', function() { + + describe('contains markdown', function() { + it('converts a string of markdown to HTML', function(done) { + expect(c(`{{#markdown}}# Foo{{/markdown}}`, context)) + .to.be.equal('

Foo

\n'); + + done(); + }); + }); + + }); + + describe('math helpers', function() { + + describe('contains avg', function() { + it('returns the average of the numbers in an array', function(done) { + expect(c(`{{avg array}}`, context)) + .to.be.equal('3'); + + done(); + }); + }); + + }); + + describe('misc helpers', function() { + + describe('contains option', function() { + it('returns the nested prop of this.options', function(done) { + expect(c(`{{option "a.b.c"}}`, context)) + .to.be.equal('d'); + + done(); + }); + }); + + }); + + describe('object helpers', function() { + + describe('contains isObject', function() { + it('returns true if the value is an object', function(done) { + expect(c(`{{isObject options}}`, context)) + .to.be.equal('true'); + + done(); + }); + + it('returns false if the value is not an object', function(done) { + expect(c(`{{isObject "foo"}}`, context)) + .to.be.equal('false'); + + done(); + }); + }); + + }); + + describe('string helpers', function() { + + describe('contains capitalize', function() { + it('capitalizes the first word in a sentence', function(done) { + expect(c(`{{capitalize "foo bar baz"}}`, context)) + .to.be.equal('Foo bar baz'); + + done(); + }); + }); + + }); + + describe('url helpers', function() { + + describe('contains stripQuerystring', function() { + it('strips the query string from a given url', function(done) { + expect(c(`{{stripQuerystring 'http://www.example.com?foo=1&bar=2&baz=3'}}`, context)) + .to.be.equal('http://www.example.com'); + + done(); + }); + }); + + }); + +});