Permalink
Browse files

repo and Gruntfile updated with mocha tests for 71 helpers, bug fixes…

…. rebuild README.
  • Loading branch information...
1 parent c1143e2 commit 5d581579c08eb6bd3ba9ee3ec2cde1cd5e5e9e36 @jonschlinkert jonschlinkert committed Mar 29, 2013
Showing with 5,403 additions and 115 deletions.
  1. +12 −0 .npmignore
  2. +4 −0 CHANGELOG
  3. +72 −51 Gruntfile.js
  4. +28 −20 README.md
  5. +1 −3 ROADMAP
  6. +1 −1 component.json
  7. +22 −18 docs/helpers/helpers-misc.md
  8. +22 −17 docs/sections/docs-helpers.md
  9. +1 −0 index.js
  10. +718 −0 lib/helpers-lib.js
  11. +180 −0 lib/helpers/helpers-collections.js
  12. +66 −0 lib/helpers/helpers-comparisons.js
  13. +6 −0 lib/helpers/helpers-config.js
  14. +216 −0 lib/helpers/helpers-dates.js
  15. +38 −0 lib/helpers/helpers-html.js
  16. +35 −0 lib/helpers/helpers-inflections.js
  17. +14 −0 lib/helpers/helpers-logging.js
  18. +30 −0 lib/helpers/helpers-math.js
  19. +15 −0 lib/helpers/helpers-miscellaneous.js
  20. +35 −0 lib/helpers/helpers-numbers.js
  21. +77 −0 lib/helpers/helpers-strings.js
  22. +23 −0 lib/helpers/helpers-utils.js
  23. +14 −0 lib/helpers/helpers.js
  24. +20 −5 package.json
  25. +1,440 −0 src/helper-lib.coffee
  26. +96 −0 src/helpers-collections.coffee
  27. +23 −0 src/helpers-comparisons.coffee
  28. +2 −0 src/helpers-config.coffee
  29. +113 −0 src/helpers-dates.coffee
  30. +28 −0 src/helpers-html.coffee
  31. +15 −0 src/helpers-inflections.coffee
  32. +7 −0 src/helpers-logging.coffee
  33. +20 −0 src/helpers-math.coffee
  34. +9 −0 src/helpers-miscellaneous.coffee
  35. +20 −0 src/helpers-numbers.coffee
  36. +40 −0 src/helpers-strings.coffee
  37. +13 −0 src/helpers-utils.coffee
  38. +6 −0 src/helpers.coffee
  39. +262 −0 src/tests/collections_test.coffee
  40. +108 −0 src/tests/comparisons_test.coffee
  41. +31 −0 src/tests/dates_test.coffee
  42. +34 −0 src/tests/html_test.coffee
  43. +29 −0 src/tests/inflections_test.coffee
  44. +33 −0 src/tests/logging_test.coffee
  45. +63 −0 src/tests/math_test.coffee
  46. +25 −0 src/tests/miscellaneous_test.coffee
  47. +82 −0 src/tests/numbers_test.coffee
  48. +91 −0 src/tests/strings_test.coffee
  49. +7 −0 src/tests/templates/some_template.coffee
  50. +365 −0 test/collections_test.js
  51. +164 −0 test/comparisons_test.js
  52. +53 −0 test/dates_test.js
  53. +56 −0 test/html_test.js
  54. +49 −0 test/inflections_test.js
  55. +48 −0 test/logging_test.js
  56. +104 −0 test/math_test.js
  57. +38 −0 test/miscellaneous_test.js
  58. +4 −0 test/mocha.opts
  59. +136 −0 test/numbers_test.js
  60. +139 −0 test/strings_test.js
View
12 .npmignore
@@ -0,0 +1,12 @@
+/node_modules/
+*.sublime-project
+*.sublime-workspace
+
+docs
+temp
+tmp
+
+.jshintrc
+Gruntfile.js
+ROADMAP
+component.json
View
4 CHANGELOG
@@ -1,3 +1,7 @@
+v0.1.8:
+ date: "2013-03-28"
+ changes:
+ - Gruntfile updated with mocha tests for 71 helpers, bug fixes.
v0.1.7:
date: "2013-03-18"
changes:
View
123 Gruntfile.js
@@ -1,81 +1,102 @@
-'use strict';
+/*
+ * helper-lib
+ * http://github.com/assemble/helper-lib
+ *
+ * Copyright (c) 2013 Assemble
+ * MIT License
+ */
+
module.exports = function(grunt) {
+'use strict';
// Project configuration.
grunt.initConfig({
pkg : grunt.file.readJSON('package.json'),
- docs: grunt.file.readJSON('docs/templates/data/docs.json'),
- nodeunit: {
- files: ['test/**/*_test.js']
- },
- jshint: {
- options: {
- jshintrc: '.jshintrc'
- },
- gruntfile: {
- src: 'Gruntfile.js'
+ // Configuration to be run (and then tested).
+ coffee: {
+ glob: {
+ expand: true,
+ cwd: 'src',
+ src: ['*.coffee', '!helper-lib.coffee'],
+ dest: 'lib/helpers/',
+ ext: '.js'
},
- lib: {
- src: ['lib/**/*.js']
+ tests: {
+ expand: true,
+ cwd: 'src/tests',
+ src: ['*.coffee'],
+ dest: 'test/',
+ ext: '.js'
},
- test: {
- src: ['test/**/*.js']
+ concat: {
+ options: { join: true },
+ files: {
+ 'lib/helpers-lib.js': [
+ 'src/helpers.coffee',
+ 'src/helpers-dates.coffee',
+ 'src/helpers-collections.coffee',
+ 'src/helpers-comparisons.coffee',
+ 'src/helpers-config.coffee',
+ 'src/helpers-html.coffee',
+ 'src/helpers-inflections.coffee',
+ 'src/helpers-logging.coffee',
+ 'src/helpers-math.coffee',
+ 'src/helpers-numbers.coffee',
+ 'src/helpers-strings.coffee',
+ 'src/helpers-utils.coffee',
+ 'src/helpers-miscellaneous.coffee'
+ ]
+ }
}
},
- watch: {
- gruntfile: {
- files: '<%= jshint.gruntfile.src %>',
- tasks: ['jshint:gruntfile']
- },
- lib: {
- files: '<%= jshint.lib.src %>',
- tasks: ['jshint:lib', 'nodeunit']
- },
- test: {
- files: '<%= jshint.test.src %>',
- tasks: ['jshint:test', 'nodeunit']
+
+ // Run mocha tests.
+ mochaTest: {
+ files: ['test/*_test.js']
+ },
+ mochaTestConfig: {
+ options: {
+ reporter: 'nyan'
}
},
+
+ // Build templates to test helpers.
assemble: {
- // Run basic tests on templates and data.
tests: {
files: {
- 'test/actual': ['test/spec/*.hbs']
- }
- },
- // Internal task to build README, docs.
- readme: {
- options: {
- today: '<%= grunt.template.today() %>',
- partials: ['docs/*.md','docs/helpers/*.md','docs/templates/sections/*.{md,hbs}'],
- changelog: grunt.file.readYAML('CHANGELOG'),
- roadmap: grunt.file.readYAML('ROADMAP'),
- data: ['docs/templates/data/docs.json', '<%= docs.urls %>','<%= docs.repos %>'],
- ext: '.md'
- },
- files: {
- '.': ['docs/templates/README.hbs']
+ 'test/actual': ['test/fixtures/*.hbs']
}
}
+ },
+
+ // Clean test files before building or re-testing.
+ clean: {
+ tests: ['temp', 'test/actual'],
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('assemble');
- grunt.loadNpmTasks('grunt-contrib-nodeunit');
- grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-contrib-clean');
+ grunt.loadNpmTasks('grunt-contrib-coffee');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+ grunt.loadNpmTasks('grunt-mocha-test');
- // Default task.
+ // By default, build templates using helpers and run all tests.
grunt.registerTask('default', [
- 'jshint',
- 'nodeunit'
+ 'clean',
+
+ // Compile JavaScript
+ 'coffee'
]);
- // Internal task to build docs.
- grunt.registerTask('readme', [
- 'assemble:readme'
+ // Build templates using helpers and run all tests.
+ grunt.registerTask('test', [
+ // 'assemble',
+ 'coffee',
+ 'mochaTest'
]);
};
View
48 README.md
@@ -1,4 +1,4 @@
-# [Helper Library v0.1.7](http://github.com/[object Object]/helper-lib) [![Build Status](https://travis-ci.org/[object Object]/helper-lib.png)](https://travis-ci.org/[object Object]/helper-lib)
+# [Helper Library v0.1.8](http://github.com/[object Object]/helper-lib) [![Build Status](https://travis-ci.org/[object Object]/helper-lib.png)](https://travis-ci.org/[object Object]/helper-lib)
> An extensive collection of useful Handlebars helpers.
@@ -1531,40 +1531,45 @@ _Provides a default or fallback value if a value doesn't exist._
Not title available.
```
-#### partial (**NOT USED IN ASSEMBLE**)
+#### include
_Provides an easy way to register and use partials inside your templates._
-This helper only works if you define your templates as common.js modules, since it uses the common.js `require` function to find and register your templates with `Handlebars.registerPartial`. It was created with [brunch](http://brunch.io) in mind (which I use a lot), because brunch automatically wraps your scripts and templates in common.js modules to use in the browser.
+This helper only works if you define your templates as common.js modules, since it uses the common.js `require` function to find and register your templates with `Handlebars.registerPartial`.
+<br>Pattern: `{{include [name] [data]}}`
<br>Parameters:
-* name `string` - The name or path of the file in which your template is defined. (Required)
-* data `int|string|collection` - The data you want to use inside the partial. (Optional)
+* name (required): `[string]` - The name or path of the file in which your template is defined. (Required)
+* data (optional): `[int|string|collection]` - Data you want to use inside the include.
-``` js
-// Path to your templates from where you override config.partialsPath
-// The path must finish with a foward slash '/'
-config.partialsPath = '../views/templates/'
+Data (collection): `planet-express.json`
-// Data
-collection = [
- 'Professor Farnsworth',
- 'Fry',
- 'Bender'
+``` js
+[
+ "Professor Farnsworth",
+ "Fry",
+ "Bender"
]
```
+
+Include (partial to be "included"): `planet-express.hbs`
``` html
-// Your Partial (planet_express.hbs)
{{sort this}}
+```
-// Your template
-<p>{{partial "planet_express" collection}}</p>
+Template:
+``` html
+<p>{{include "planet-express.hbs" data}}</p>
+```
-// Result:
+Result:
+``` html
<p>Bender, Fry, Professor Farnsworth</p>
```
+
+
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using Grunt.
@@ -1596,19 +1601,22 @@ Copyright NaN Object Object
[MIT License](LICENSE-MIT)
## Release History
+* 2013-03-28 v0.1.8 Gruntfile updated with mocha tests for 71 helpers, bug fixes.
* 2013-03-18 v0.1.7 New path helper "relative", for resolving relative path from one absolute path to another.
* 2013-03-16 v0.1.3 New helpers, "formatPhoneNumber" and "eachProperty"
* 2013-03-15 v0.1.2 Update README.md with documentation, examples.
* 2013-03-06 v0.1.0 First commit.
### Roadmap
-_(Big plans in the works)_
+* Separate into modules
+* YAML format, use templates for easier maintenance
+
---
Authored by [assemble](https://github.com/assemble/assemble)
-_This file was generated using Grunt and [assemble](http://github.com/assemble/assemble) on Thu Mar 28 2013 00:52:55._
+_This file was generated using Grunt and [assemble](http://github.com/assemble/assemble) on Thu Mar 28 2013 21:49:13._
View
4 ROADMAP
@@ -1,5 +1,3 @@
-roadmap:
- tasks:
+todo:
- Separate into modules
- - Proper testing for each helper
- YAML format, use templates for easier maintenance
View
2 component.json
@@ -1,7 +1,7 @@
{
"name": "helpers",
"description": "A massive collection of useful Handlebars helpers.",
- "version": "0.1.6",
+ "version": "0.1.8",
"main": "./lib/helpers.js",
"dependencies": {
"type": "git",
View
40 docs/helpers/helpers-misc.md
@@ -10,35 +10,39 @@ _Provides a default or fallback value if a value doesn't exist._
Not title available.
```
-#### partial (**NOT USED IN ASSEMBLE**)
+#### include
_Provides an easy way to register and use partials inside your templates._
-This helper only works if you define your templates as common.js modules, since it uses the common.js `require` function to find and register your templates with `Handlebars.registerPartial`. It was created with [brunch](http://brunch.io) in mind (which I use a lot), because brunch automatically wraps your scripts and templates in common.js modules to use in the browser.
+This helper only works if you define your templates as common.js modules, since it uses the common.js `require` function to find and register your templates with `Handlebars.registerPartial`.
+<br>Pattern: `{{include [name] [data]}}`
<br>Parameters:
-* name `string` - The name or path of the file in which your template is defined. (Required)
-* data `int|string|collection` - The data you want to use inside the partial. (Optional)
+* name (required): `[string]` - The name or path of the file in which your template is defined. (Required)
+* data (optional): `[int|string|collection]` - Data you want to use inside the include.
+
+Data (collection): `planet-express.json`
``` js
-// Path to your templates from where you override config.partialsPath
-// The path must finish with a foward slash '/'
-config.partialsPath = '../views/templates/'
-
-// Data
-collection = [
- 'Professor Farnsworth',
- 'Fry',
- 'Bender'
+[
+ "Professor Farnsworth",
+ "Fry",
+ "Bender"
]
```
+
+Include (partial to be "included"): `planet-express.hbs`
``` html
-// Your Partial (planet_express.hbs)
{{sort this}}
+```
-// Your template
-<p>{{partial "planet_express" collection}}</p>
+Template:
+``` html
+<p>{{include "planet-express.hbs" data}}</p>
+```
-// Result:
+Result:
+``` html
<p>Bender, Fry, Professor Farnsworth</p>
-```
+```
+
View
39 docs/sections/docs-helpers.md
@@ -1371,35 +1371,40 @@ _Provides a default or fallback value if a value doesn't exist._
Not title available.
```
-#### partial (**NOT USED IN ASSEMBLE**)
+#### include
_Provides an easy way to register and use partials inside your templates._
-This helper only works if you define your templates as common.js modules, since it uses the common.js `require` function to find and register your templates with `Handlebars.registerPartial`. It was created with [brunch](http://brunch.io) in mind (which I use a lot), because brunch automatically wraps your scripts and templates in common.js modules to use in the browser.
+This helper only works if you define your templates as common.js modules, since it uses the common.js `require` function to find and register your templates with `Handlebars.registerPartial`.
+<br>Pattern: `{{include [name] [data]}}`
<br>Parameters:
-* name `string` - The name or path of the file in which your template is defined. (Required)
-* data `int|string|collection` - The data you want to use inside the partial. (Optional)
+* name (required): `[string]` - The name or path of the file in which your template is defined. (Required)
+* data (optional): `[int|string|collection]` - Data you want to use inside the include.
-``` js
-// Path to your templates from where you override config.partialsPath
-// The path must finish with a foward slash '/'
-config.partialsPath = '../views/templates/'
+Data (collection): `planet-express.json`
-// Data
-collection = [
- 'Professor Farnsworth',
- 'Fry',
- 'Bender'
+``` js
+[
+ "Professor Farnsworth",
+ "Fry",
+ "Bender"
]
```
+
+Include (partial to be "included"): `planet-express.hbs`
``` html
-// Your Partial (planet_express.hbs)
{{sort this}}
+```
-// Your template
-<p>{{partial "planet_express" collection}}</p>
+Template:
+``` html
+<p>{{include "planet-express.hbs" data}}</p>
+```
-// Result:
+Result:
+``` html
<p>Bender, Fry, Professor Farnsworth</p>
```
+
+
View
1 index.js
@@ -0,0 +1 @@
+module.exports = require('./lib/helpers');
View
718 lib/helpers-lib.js
@@ -0,0 +1,718 @@
+(function() {
+ var Assemble, Dates, HTML, Handlebars, Utils,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ if (typeof window !== "undefined" && window !== null) {
+ Handlebars = window.Handlebars;
+ window.Assemble = Assemble = {};
+ }
+
+ if (typeof module !== "undefined" && module !== null) {
+ Handlebars = require('handlebars');
+ module.exports = Assemble = {};
+ }
+
+ Dates = {};
+
+ Dates.padNumber = function(num, count, padCharacter) {
+ var lenDiff, padding;
+
+ if (typeof padCharacter === 'undefined') {
+ padCharacter = '0';
+ }
+ lenDiff = count - String(num).length;
+ padding = '';
+ if (lenDiff > 0) {
+ while (lenDiff--) {
+ padding += padCharacter;
+ }
+ }
+ return padding + num;
+ };
+
+ Dates.dayOfYear = function(date) {
+ var oneJan;
+
+ oneJan = new Date(date.getFullYear(), 0, 1);
+ return Math.ceil((date - oneJan) / 86400000);
+ };
+
+ Dates.weekOfYear = function(date) {
+ var oneJan;
+
+ oneJan = new Date(date.getFullYear(), 0, 1);
+ return Math.ceil((((date - oneJan) / 86400000) + oneJan.getDay() + 1) / 7);
+ };
+
+ Dates.isoWeekOfYear = function(date) {
+ var dayDiff, dayNr, jan4, target;
+
+ target = new Date(date.valueOf());
+ dayNr = (date.getDay() + 6) % 7;
+ target.setDate(target.getDate() - dayNr + 3);
+ jan4 = new Date(target.getFullYear(), 0, 4);
+ dayDiff = (target - jan4) / 86400000;
+ return 1 + Math.ceil(dayDiff / 7);
+ };
+
+ Dates.tweleveHour = function(date) {
+ if (date.getHours() > 12) {
+ return date.getHours() - 12;
+ } else {
+ return date.getHours();
+ }
+ };
+
+ Dates.timeZoneOffset = function(date) {
+ var hoursDiff, result;
+
+ hoursDiff = -date.getTimezoneOffset() / 60;
+ result = Dates.padNumber(Math.abs(hoursDiff), 4);
+ return (hoursDiff > 0 ? '+' : '-') + result;
+ };
+
+ Dates.format = function(date, format) {
+ return format.replace(Dates.formats, function(m, p) {
+ switch (p) {
+ case 'a':
+ return Dates.abbreviatedWeekdays[date.getDay()];
+ case 'A':
+ return Dates.fullWeekdays[date.getDay()];
+ case 'b':
+ return Dates.abbreviatedMonths[date.getMonth()];
+ case 'B':
+ return Dates.fullMonths[date.getMonth()];
+ case 'c':
+ return date.toLocaleString();
+ case 'C':
+ return Math.round(date.getFullYear() / 100);
+ case 'd':
+ return Dates.padNumber(date.getDate(), 2);
+ case 'D':
+ return Dates.format(date, '%m/%d/%y');
+ case 'e':
+ return Dates.padNumber(date.getDate(), 2, ' ');
+ case 'F':
+ return Dates.format(date, '%Y-%m-%d');
+ case 'h':
+ return Dates.format(date, '%b');
+ case 'H':
+ return Dates.padNumber(date.getHours(), 2);
+ case 'I':
+ return Dates.padNumber(Dates.tweleveHour(date), 2);
+ case 'j':
+ return Dates.padNumber(Dates.dayOfYear(date), 3);
+ case 'k':
+ return Dates.padNumber(date.getHours(), 2, ' ');
+ case 'l':
+ return Dates.padNumber(Dates.tweleveHour(date), 2, ' ');
+ case 'L':
+ return Dates.padNumber(date.getMilliseconds(), 3);
+ case 'm':
+ return Dates.padNumber(date.getMonth() + 1, 2);
+ case 'M':
+ return Dates.padNumber(date.getMinutes(), 2);
+ case 'n':
+ return '\n';
+ case 'p':
+ if (date.getHours() > 11) {
+ return 'PM';
+ } else {
+ return 'AM';
+ }
+ case 'P':
+ return Dates.format(date, '%p').toLowerCase();
+ case 'r':
+ return Dates.format(date, '%I:%M:%S %p');
+ case 'R':
+ return Dates.format(date, '%H:%M');
+ case 's':
+ return date.getTime() / 1000;
+ case 'S':
+ return Dates.padNumber(date.getSeconds(), 2);
+ case 't':
+ return '\t';
+ case 'T':
+ return Dates.format(date, '%H:%M:%S');
+ case 'u':
+ if (date.getDay() === 0) {
+ return 7;
+ } else {
+ return date.getDay();
+ }
+ case 'U':
+ return Dates.padNumber(Dates.weekOfYear(date), 2);
+ case 'v':
+ return Dates.format(date, '%e-%b-%Y');
+ case 'V':
+ return Dates.padNumber(Dates.isoWeekOfYear(date), 2);
+ case 'W':
+ return Dates.padNumber(Dates.weekOfYear(date), 2);
+ case 'w':
+ return Dates.padNumber(date.getDay(), 2);
+ case 'x':
+ return date.toLocaleDateString();
+ case 'X':
+ return date.toLocaleTimeString();
+ case 'y':
+ return String(date.getFullYear()).substring(2);
+ case 'Y':
+ return date.getFullYear();
+ case 'z':
+ return Dates.timeZoneOffset(date);
+ default:
+ return match;
+ }
+ });
+ };
+
+ Dates.formats = /%(a|A|b|B|c|C|d|D|e|F|h|H|I|j|k|l|L|m|M|n|p|P|r|R|s|S|t|T|u|U|v|V|W|w|x|X|y|Y|z)/g;
+
+ Dates.abbreviatedWeekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
+
+ Dates.fullWeekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+
+ Dates.abbreviatedMonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+ Dates.fullMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+ Handlebars.registerHelper('formatDate', function(date, format) {
+ date = new Date(date);
+ return Dates.format(date, format);
+ });
+
+ Handlebars.registerHelper('now', function(format) {
+ var date;
+
+ date = new Date();
+ if (Utils.isUndefined(format)) {
+ return date;
+ } else {
+ return Dates.format(date, format);
+ }
+ });
+
+ Handlebars.registerHelper('timeago', function(date) {
+ var interval, seconds;
+
+ date = new Date(date);
+ seconds = Math.floor((new Date() - date) / 1000);
+ interval = Math.floor(seconds / 31536000);
+ if (interval > 1) {
+ return "" + interval + " years ago";
+ }
+ interval = Math.floor(seconds / 2592000);
+ if (interval > 1) {
+ return "" + interval + " months ago";
+ }
+ interval = Math.floor(seconds / 86400);
+ if (interval > 1) {
+ return "" + interval + " days ago";
+ }
+ interval = Math.floor(seconds / 3600);
+ if (interval > 1) {
+ return "" + interval + " hours ago";
+ }
+ interval = Math.floor(seconds / 60);
+ if (interval > 1) {
+ return "" + interval + " minutes ago";
+ }
+ if (Math.floor(seconds) === 0) {
+ return 'Just now';
+ } else {
+ return Math.floor(seconds) + ' seconds ago';
+ }
+ });
+
+ Handlebars.registerHelper('first', function(array, count) {
+ if (Utils.isUndefined(count)) {
+ return array[0];
+ } else {
+ return array.slice(0, count);
+ }
+ });
+
+ Handlebars.registerHelper('withFirst', function(array, count, options) {
+ var item, result;
+
+ if (Utils.isUndefined(count)) {
+ options = count;
+ return options.fn(array[0]);
+ } else {
+ array = array.slice(0, count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ }
+ });
+
+ Handlebars.registerHelper('last', function(array, count) {
+ if (Utils.isUndefined(count)) {
+ return array[array.length - 1];
+ } else {
+ return array.slice(-count);
+ }
+ });
+
+ Handlebars.registerHelper('withLast', function(array, count, options) {
+ var item, result;
+
+ if (Utils.isUndefined(count)) {
+ options = count;
+ return options.fn(array[array.length - 1]);
+ } else {
+ array = array.slice(-count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ }
+ });
+
+ Handlebars.registerHelper('after', function(array, count) {
+ return array.slice(count);
+ });
+
+ Handlebars.registerHelper('withAfter', function(array, count, options) {
+ var item, result;
+
+ array = array.slice(count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('before', function(array, count) {
+ return array.slice(0, -count);
+ });
+
+ Handlebars.registerHelper('withBefore', function(array, count, options) {
+ var item, result;
+
+ array = array.slice(0, -count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('join', function(array, separator) {
+ return array.join(Utils.isUndefined(separator) ? ' ' : separator);
+ });
+
+ Handlebars.registerHelper('sort', function(array, field) {
+ if (Utils.isUndefined(field)) {
+ return array.sort();
+ } else {
+ return array.sort(function(a, b) {
+ return a[field] > b[field];
+ });
+ }
+ });
+
+ Handlebars.registerHelper('withSort', function(array, field, options) {
+ var item, result, _i, _len;
+
+ result = '';
+ if (Utils.isUndefined(field)) {
+ options = field;
+ array = array.sort();
+ for (_i = 0, _len = array.length; _i < _len; _i++) {
+ item = array[_i];
+ result += options.fn(item);
+ }
+ } else {
+ array = array.sort(function(a, b) {
+ return a[field] > b[field];
+ });
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('length', function(array) {
+ return array.length;
+ });
+
+ Handlebars.registerHelper('lengthEqual', function(array, length, options) {
+ if (array.length === length) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('empty', function(array, options) {
+ if (array.length <= 0) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('any', function(array, options) {
+ if (array.length > 0) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('inArray', function(array, value, options) {
+ if (array.indexOf(value) !== -1) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('eachIndex', function(array, options) {
+ var index, result, value, _i, _len;
+
+ result = '';
+ for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) {
+ value = array[index];
+ result += options.fn({
+ item: value,
+ index: index
+ });
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('eachProperty', function(obj, options) {
+ var key, result, value;
+
+ result = '';
+ for (key in obj) {
+ value = obj[key];
+ result += options.fn({
+ key: key,
+ value: value
+ });
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('is', function(value, test, options) {
+ if (value === test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('isnt', function(value, test, options) {
+ if (value !== test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('gt', function(value, test, options) {
+ if (value > test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('gte', function(value, test, options) {
+ if (value >= test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('lt', function(value, test, options) {
+ if (value < test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('lte', function(value, test, options) {
+ if (value <= test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('or', function(testA, testB, options) {
+ if (testA || testB) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('and', function(testA, testB, options) {
+ if (testA && testB) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Assemble.Config = {
+ partialsPath: ''
+ };
+
+ HTML = {};
+
+ HTML.parseAttributes = function(hash) {
+ return Object.keys(hash).map(function(key) {
+ return "" + key + "=\"" + hash[key] + "\"";
+ }).join(' ');
+ };
+
+ Handlebars.registerHelper('ul', function(context, options) {
+ return ("<ul " + (HTML.parseAttributes(options.hash)) + ">") + context.map(function(item) {
+ return "<li>" + (options.fn(item)) + "</li>";
+ }).join('\n') + "</ul>";
+ });
+
+ Handlebars.registerHelper('ol', function(context, options) {
+ return ("<ol " + (HTML.parseAttributes(options.hash)) + ">") + context.map(function(item) {
+ return "<li>" + (options.fn(item)) + "</li>";
+ }).join('\n') + "</ol>";
+ });
+
+ Handlebars.registerHelper('br', function(count, options) {
+ var br, i;
+
+ br = '<br>';
+ if (!Utils.isUndefined(count)) {
+ i = 0;
+ while (i < count - 1) {
+ br += '<br>';
+ i++;
+ }
+ }
+ return Utils.safeString(br);
+ });
+
+ Handlebars.registerHelper('inflect', function(count, singular, plural, include) {
+ var word;
+
+ word = count > 1 || count === 0 ? plural : singular;
+ if (Utils.isUndefined(include) || include === false) {
+ return word;
+ } else {
+ return "" + count + " " + word;
+ }
+ });
+
+ Handlebars.registerHelper('ordinalize', function(value) {
+ var normal, _ref;
+
+ normal = Math.abs(Math.round(value));
+ if (_ref = normal % 100, __indexOf.call([11, 12, 13], _ref) >= 0) {
+ return "" + value + "th";
+ } else {
+ switch (normal % 10) {
+ case 1:
+ return "" + value + "st";
+ case 2:
+ return "" + value + "nd";
+ case 3:
+ return "" + value + "rd";
+ default:
+ return "" + value + "th";
+ }
+ }
+ });
+
+ Handlebars.registerHelper('log', function(value) {
+ return console.log(value);
+ });
+
+ Handlebars.registerHelper('debug', function(value) {
+ console.log('Context: ', this);
+ if (!Utils.isUndefined(value)) {
+ console.log('Value: ', value);
+ }
+ return console.log('-----------------------------------------------');
+ });
+
+ Handlebars.registerHelper('add', function(value, addition) {
+ return value + addition;
+ });
+
+ Handlebars.registerHelper('subtract', function(value, substraction) {
+ return value - substraction;
+ });
+
+ Handlebars.registerHelper('divide', function(value, divisor) {
+ return value / divisor;
+ });
+
+ Handlebars.registerHelper('multiply', function(value, multiplier) {
+ return value * multiplier;
+ });
+
+ Handlebars.registerHelper('floor', function(value) {
+ return Math.floor(value);
+ });
+
+ Handlebars.registerHelper('ceil', function(value) {
+ return Math.ceil(value);
+ });
+
+ Handlebars.registerHelper('round', function(value) {
+ return Math.round(value);
+ });
+
+ Handlebars.registerHelper('toFixed', function(number, digits) {
+ if (Utils.isUndefined(digits)) {
+ digits = 0;
+ }
+ return number.toFixed(digits);
+ });
+
+ Handlebars.registerHelper('toPrecision', function(number, precision) {
+ if (Utils.isUndefined(precision)) {
+ precision = 1;
+ }
+ return number.toPrecision(precision);
+ });
+
+ Handlebars.registerHelper('toExponential', function(number, fractions) {
+ if (Utils.isUndefined(fractions)) {
+ fractions = 0;
+ }
+ return number.toExponential(fractions);
+ });
+
+ Handlebars.registerHelper('toInt', function(number) {
+ return parseInt(number, 10);
+ });
+
+ Handlebars.registerHelper('toFloat', function(number) {
+ return parseFloat(number);
+ });
+
+ Handlebars.registerHelper('addCommas', function(number) {
+ return number.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
+ });
+
+ Handlebars.registerHelper('lowercase', function(str) {
+ return str.toLowerCase();
+ });
+
+ Handlebars.registerHelper('uppercase', function(str) {
+ return str.toUpperCase();
+ });
+
+ Handlebars.registerHelper('capitalizeFirst', function(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+ });
+
+ Handlebars.registerHelper('capitalizeEach', function(str) {
+ return str.replace(/\w\S*/g, function(txt) {
+ return txt.charAt(0).toUpperCase() + txt.substr(1);
+ });
+ });
+
+ Handlebars.registerHelper('titleize', function(str) {
+ var capitalize, title, word, words;
+
+ title = str.replace(/[ \-_]+/g, ' ');
+ words = title.match(/\w+/g);
+ capitalize = function(word) {
+ return word.charAt(0).toUpperCase() + word.slice(1);
+ };
+ return ((function() {
+ var _i, _len, _results;
+
+ _results = [];
+ for (_i = 0, _len = words.length; _i < _len; _i++) {
+ word = words[_i];
+ _results.push(capitalize(word));
+ }
+ return _results;
+ })()).join(' ');
+ });
+
+ Handlebars.registerHelper('sentence', function(str) {
+ return str.replace(/((?:\S[^\.\?\!]*)[\.\?\!]*)/g, function(txt) {
+ return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
+ });
+ });
+
+ Handlebars.registerHelper('reverse', function(str) {
+ return str.split('').reverse().join('');
+ });
+
+ Handlebars.registerHelper('truncate', function(str, length, omission) {
+ if (Utils.isUndefined(omission)) {
+ omission = '';
+ }
+ if (str.length > length) {
+ return str.substring(0, length - omission.length) + omission;
+ } else {
+ return str;
+ }
+ });
+
+ Handlebars.registerHelper('center', function(str, spaces) {
+ var i, space;
+
+ space = '';
+ i = 0;
+ while (i < spaces) {
+ space += '&nbsp;';
+ i++;
+ }
+ return "" + space + str + space;
+ });
+
+ Handlebars.registerHelper('newLineToBr', function(str) {
+ return str.replace(/\r?\n|\r/g, '<br>');
+ });
+
+ Utils = {};
+
+ Utils.toString = Object.prototype.toString;
+
+ Utils.isUndefined = function(value) {
+ return value === 'undefined' || Utils.toString.call(value) === '[object Function]' || (value.hash != null);
+ };
+
+ Utils.safeString = function(str) {
+ return new Handlebars.SafeString(str);
+ };
+
+ Utils.trim = function(str) {
+ var trim;
+
+ trim = /\S/.test("\xA0") ? /^[\s\xA0]+|[\s\xA0]+$/g : /^\s+|\s+$/g;
+ return str.toString().replace(trim, '');
+ };
+
+ Handlebars.registerHelper('default', function(value, defaultValue) {
+ return value != null ? value : defaultValue;
+ });
+
+ /*
+ Handlebars.registerHelper 'partial', (name, data) ->
+ partial = Assemble.Config.partialsPath + name
+ data = if Utils.isUndefined(data) then {} else data
+ Handlebars.registerPartial(name, require partial) unless Handlebars.partials[name]?
+ Utils.safeString Handlebars.partials[name](data)
+ */
+
+
+}).call(this);
View
180 lib/helpers/helpers-collections.js
@@ -0,0 +1,180 @@
+(function() {
+ Handlebars.registerHelper('first', function(array, count) {
+ if (Utils.isUndefined(count)) {
+ return array[0];
+ } else {
+ return array.slice(0, count);
+ }
+ });
+
+ Handlebars.registerHelper('withFirst', function(array, count, options) {
+ var item, result;
+
+ if (Utils.isUndefined(count)) {
+ options = count;
+ return options.fn(array[0]);
+ } else {
+ array = array.slice(0, count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ }
+ });
+
+ Handlebars.registerHelper('last', function(array, count) {
+ if (Utils.isUndefined(count)) {
+ return array[array.length - 1];
+ } else {
+ return array.slice(-count);
+ }
+ });
+
+ Handlebars.registerHelper('withLast', function(array, count, options) {
+ var item, result;
+
+ if (Utils.isUndefined(count)) {
+ options = count;
+ return options.fn(array[array.length - 1]);
+ } else {
+ array = array.slice(-count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ }
+ });
+
+ Handlebars.registerHelper('after', function(array, count) {
+ return array.slice(count);
+ });
+
+ Handlebars.registerHelper('withAfter', function(array, count, options) {
+ var item, result;
+
+ array = array.slice(count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('before', function(array, count) {
+ return array.slice(0, -count);
+ });
+
+ Handlebars.registerHelper('withBefore', function(array, count, options) {
+ var item, result;
+
+ array = array.slice(0, -count);
+ result = '';
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('join', function(array, separator) {
+ return array.join(Utils.isUndefined(separator) ? ' ' : separator);
+ });
+
+ Handlebars.registerHelper('sort', function(array, field) {
+ if (Utils.isUndefined(field)) {
+ return array.sort();
+ } else {
+ return array.sort(function(a, b) {
+ return a[field] > b[field];
+ });
+ }
+ });
+
+ Handlebars.registerHelper('withSort', function(array, field, options) {
+ var item, result, _i, _len;
+
+ result = '';
+ if (Utils.isUndefined(field)) {
+ options = field;
+ array = array.sort();
+ for (_i = 0, _len = array.length; _i < _len; _i++) {
+ item = array[_i];
+ result += options.fn(item);
+ }
+ } else {
+ array = array.sort(function(a, b) {
+ return a[field] > b[field];
+ });
+ for (item in array) {
+ result += options.fn(array[item]);
+ }
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('length', function(array) {
+ return array.length;
+ });
+
+ Handlebars.registerHelper('lengthEqual', function(array, length, options) {
+ if (array.length === length) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('empty', function(array, options) {
+ if (array.length <= 0) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('any', function(array, options) {
+ if (array.length > 0) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('inArray', function(array, value, options) {
+ if (array.indexOf(value) !== -1) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('eachIndex', function(array, options) {
+ var index, result, value, _i, _len;
+
+ result = '';
+ for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) {
+ value = array[index];
+ result += options.fn({
+ item: value,
+ index: index
+ });
+ }
+ return result;
+ });
+
+ Handlebars.registerHelper('eachProperty', function(obj, options) {
+ var key, result, value;
+
+ result = '';
+ for (key in obj) {
+ value = obj[key];
+ result += options.fn({
+ key: key,
+ value: value
+ });
+ }
+ return result;
+ });
+
+}).call(this);
View
66 lib/helpers/helpers-comparisons.js
@@ -0,0 +1,66 @@
+(function() {
+ Handlebars.registerHelper('is', function(value, test, options) {
+ if (value === test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('isnt', function(value, test, options) {
+ if (value !== test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('gt', function(value, test, options) {
+ if (value > test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('gte', function(value, test, options) {
+ if (value >= test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('lt', function(value, test, options) {
+ if (value < test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('lte', function(value, test, options) {
+ if (value <= test) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('or', function(testA, testB, options) {
+ if (testA || testB) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+ Handlebars.registerHelper('and', function(testA, testB, options) {
+ if (testA && testB) {
+ return options.fn(this);
+ } else {
+ return options.inverse(this);
+ }
+ });
+
+}).call(this);
View
6 lib/helpers/helpers-config.js
@@ -0,0 +1,6 @@
+(function() {
+ Assemble.Config = {
+ partialsPath: ''
+ };
+
+}).call(this);
View
216 lib/helpers/helpers-dates.js
@@ -0,0 +1,216 @@
+(function() {
+ var Dates;
+
+ Dates = {};
+
+ Dates.padNumber = function(num, count, padCharacter) {
+ var lenDiff, padding;
+
+ if (typeof padCharacter === 'undefined') {
+ padCharacter = '0';
+ }
+ lenDiff = count - String(num).length;
+ padding = '';
+ if (lenDiff > 0) {
+ while (lenDiff--) {
+ padding += padCharacter;
+ }
+ }
+ return padding + num;
+ };
+
+ Dates.dayOfYear = function(date) {
+ var oneJan;
+
+ oneJan = new Date(date.getFullYear(), 0, 1);
+ return Math.ceil((date - oneJan) / 86400000);
+ };
+
+ Dates.weekOfYear = function(date) {
+ var oneJan;
+
+ oneJan = new Date(date.getFullYear(), 0, 1);
+ return Math.ceil((((date - oneJan) / 86400000) + oneJan.getDay() + 1) / 7);
+ };
+
+ Dates.isoWeekOfYear = function(date) {
+ var dayDiff, dayNr, jan4, target;
+
+ target = new Date(date.valueOf());
+ dayNr = (date.getDay() + 6) % 7;
+ target.setDate(target.getDate() - dayNr + 3);
+ jan4 = new Date(target.getFullYear(), 0, 4);
+ dayDiff = (target - jan4) / 86400000;
+ return 1 + Math.ceil(dayDiff / 7);
+ };
+
+ Dates.tweleveHour = function(date) {
+ if (date.getHours() > 12) {
+ return date.getHours() - 12;
+ } else {
+ return date.getHours();
+ }
+ };
+
+ Dates.timeZoneOffset = function(date) {
+ var hoursDiff, result;
+
+ hoursDiff = -date.getTimezoneOffset() / 60;
+ result = Dates.padNumber(Math.abs(hoursDiff), 4);
+ return (hoursDiff > 0 ? '+' : '-') + result;
+ };
+
+ Dates.format = function(date, format) {
+ return format.replace(Dates.formats, function(m, p) {
+ switch (p) {
+ case 'a':
+ return Dates.abbreviatedWeekdays[date.getDay()];
+ case 'A':
+ return Dates.fullWeekdays[date.getDay()];
+ case 'b':
+ return Dates.abbreviatedMonths[date.getMonth()];
+ case 'B':
+ return Dates.fullMonths[date.getMonth()];
+ case 'c':
+ return date.toLocaleString();
+ case 'C':
+ return Math.round(date.getFullYear() / 100);
+ case 'd':
+ return Dates.padNumber(date.getDate(), 2);
+ case 'D':
+ return Dates.format(date, '%m/%d/%y');
+ case 'e':
+ return Dates.padNumber(date.getDate(), 2, ' ');
+ case 'F':
+ return Dates.format(date, '%Y-%m-%d');
+ case 'h':
+ return Dates.format(date, '%b');
+ case 'H':
+ return Dates.padNumber(date.getHours(), 2);
+ case 'I':
+ return Dates.padNumber(Dates.tweleveHour(date), 2);
+ case 'j':
+ return Dates.padNumber(Dates.dayOfYear(date), 3);
+ case 'k':
+ return Dates.padNumber(date.getHours(), 2, ' ');
+ case 'l':
+ return Dates.padNumber(Dates.tweleveHour(date), 2, ' ');
+ case 'L':
+ return Dates.padNumber(date.getMilliseconds(), 3);
+ case 'm':
+ return Dates.padNumber(date.getMonth() + 1, 2);
+ case 'M':
+ return Dates.padNumber(date.getMinutes(), 2);
+ case 'n':
+ return '\n';
+ case 'p':
+ if (date.getHours() > 11) {
+ return 'PM';
+ } else {
+ return 'AM';
+ }
+ case 'P':
+ return Dates.format(date, '%p').toLowerCase();
+ case 'r':
+ return Dates.format(date, '%I:%M:%S %p');
+ case 'R':
+ return Dates.format(date, '%H:%M');
+ case 's':
+ return date.getTime() / 1000;
+ case 'S':
+ return Dates.padNumber(date.getSeconds(), 2);
+ case 't':
+ return '\t';
+ case 'T':
+ return Dates.format(date, '%H:%M:%S');
+ case 'u':
+ if (date.getDay() === 0) {
+ return 7;
+ } else {
+ return date.getDay();
+ }
+ case 'U':
+ return Dates.padNumber(Dates.weekOfYear(date), 2);
+ case 'v':
+ return Dates.format(date, '%e-%b-%Y');
+ case 'V':
+ return Dates.padNumber(Dates.isoWeekOfYear(date), 2);
+ case 'W':
+ return Dates.padNumber(Dates.weekOfYear(date), 2);
+ case 'w':
+ return Dates.padNumber(date.getDay(), 2);
+ case 'x':
+ return date.toLocaleDateString();
+ case 'X':
+ return date.toLocaleTimeString();
+ case 'y':
+ return String(date.getFullYear()).substring(2);
+ case 'Y':
+ return date.getFullYear();
+ case 'z':
+ return Dates.timeZoneOffset(date);
+ default:
+ return match;
+ }
+ });
+ };
+
+ Dates.formats = /%(a|A|b|B|c|C|d|D|e|F|h|H|I|j|k|l|L|m|M|n|p|P|r|R|s|S|t|T|u|U|v|V|W|w|x|X|y|Y|z)/g;
+
+ Dates.abbreviatedWeekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
+
+ Dates.fullWeekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+
+ Dates.abbreviatedMonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+ Dates.fullMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+ Handlebars.registerHelper('formatDate', function(date, format) {
+ date = new Date(date);
+ return Dates.format(date, format);
+ });
+
+ Handlebars.registerHelper('now', function(format) {
+ var date;
+
+ date = new Date();
+ if (Utils.isUndefined(format)) {
+ return date;
+ } else {
+ return Dates.format(date, format);
+ }
+ });
+
+ Handlebars.registerHelper('timeago', function(date) {
+ var interval, seconds;
+
+ date = new Date(date);
+ seconds = Math.floor((new Date() - date) / 1000);
+ interval = Math.floor(seconds / 31536000);
+ if (interval > 1) {
+ return "" + interval + " years ago";
+ }
+ interval = Math.floor(seconds / 2592000);
+ if (interval > 1) {
+ return "" + interval + " months ago";
+ }
+ interval = Math.floor(seconds / 86400);
+ if (interval > 1) {
+ return "" + interval + " days ago";
+ }
+ interval = Math.floor(seconds / 3600);
+ if (interval > 1) {
+ return "" + interval + " hours ago";
+ }
+ interval = Math.floor(seconds / 60);
+ if (interval > 1) {
+ return "" + interval + " minutes ago";
+ }
+ if (Math.floor(seconds) === 0) {
+ return 'Just now';
+ } else {
+ return Math.floor(seconds) + ' seconds ago';
+ }
+ });
+
+}).call(this);
View
38 lib/helpers/helpers-html.js
@@ -0,0 +1,38 @@
+(function() {
+ var HTML;
+
+ HTML = {};
+
+ HTML.parseAttributes = function(hash) {
+ return Object.keys(hash).map(function(key) {
+ return "" + key + "=\"" + hash[key] + "\"";
+ }).join(' ');
+ };
+
+ Handlebars.registerHelper('ul', function(context, options) {
+ return ("<ul " + (HTML.parseAttributes(options.hash)) + ">") + context.map(function(item) {
+ return "<li>" + (options.fn(item)) + "</li>";
+ }).join('\n') + "</ul>";
+ });
+
+ Handlebars.registerHelper('ol', function(context, options) {
+ return ("<ol " + (HTML.parseAttributes(options.hash)) + ">") + context.map(function(item) {
+ return "<li>" + (options.fn(item)) + "</li>";
+ }).join('\n') + "</ol>";
+ });
+
+ Handlebars.registerHelper('br', function(count, options) {
+ var br, i;
+
+ br = '<br>';
+ if (!Utils.isUndefined(count)) {
+ i = 0;
+ while (i < count - 1) {
+ br += '<br>';
+ i++;
+ }
+ }
+ return Utils.safeString(br);
+ });
+
+}).call(this);
View
35 lib/helpers/helpers-inflections.js
@@ -0,0 +1,35 @@
+(function() {
+ var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ Handlebars.registerHelper('inflect', function(count, singular, plural, include) {
+ var word;
+
+ word = count > 1 || count === 0 ? plural : singular;
+ if (Utils.isUndefined(include) || include === false) {
+ return word;
+ } else {
+ return "" + count + " " + word;
+ }
+ });
+
+ Handlebars.registerHelper('ordinalize', function(value) {
+ var normal, _ref;
+
+ normal = Math.abs(Math.round(value));
+ if (_ref = normal % 100, __indexOf.call([11, 12, 13], _ref) >= 0) {
+ return "" + value + "th";
+ } else {
+ switch (normal % 10) {
+ case 1:
+ return "" + value + "st";
+ case 2:
+ return "" + value + "nd";
+ case 3:
+ return "" + value + "rd";
+ default:
+ return "" + value + "th";
+ }
+ }
+ });
+
+}).call(this);
View
14 lib/helpers/helpers-logging.js
@@ -0,0 +1,14 @@
+(function() {
+ Handlebars.registerHelper('log', function(value) {
+ return console.log(value);
+ });
+
+ Handlebars.registerHelper('debug', function(value) {
+ console.log('Context: ', this);
+ if (!Utils.isUndefined(value)) {
+ console.log('Value: ', value);
+ }
+ return console.log('-----------------------------------------------');
+ });
+
+}).call(this);
View
30 lib/helpers/helpers-math.js
@@ -0,0 +1,30 @@
+(function() {
+ Handlebars.registerHelper('add', function(value, addition) {
+ return value + addition;
+ });
+
+ Handlebars.registerHelper('subtract', function(value, substraction) {
+ return value - substraction;
+ });
+
+ Handlebars.registerHelper('divide', function(value, divisor) {
+ return value / divisor;
+ });
+
+ Handlebars.registerHelper('multiply', function(value, multiplier) {
+ return value * multiplier;
+ });
+
+ Handlebars.registerHelper('floor', function(value) {
+ return Math.floor(value);
+ });
+
+ Handlebars.registerHelper('ceil', function(value) {
+ return Math.ceil(value);
+ });
+
+ Handlebars.registerHelper('round', function(value) {
+ return Math.round(value);
+ });
+
+}).call(this);
View
15 lib/helpers/helpers-miscellaneous.js
@@ -0,0 +1,15 @@
+(function() {
+ Handlebars.registerHelper('default', function(value, defaultValue) {
+ return value != null ? value : defaultValue;
+ });
+
+ /*
+ Handlebars.registerHelper 'partial', (name, data) ->
+ partial = Assemble.Config.partialsPath + name
+ data = if Utils.isUndefined(data) then {} else data
+ Handlebars.registerPartial(name, require partial) unless Handlebars.partials[name]?
+ Utils.safeString Handlebars.partials[name](data)
+ */
+
+
+}).call(this);
View
35 lib/helpers/helpers-numbers.js
@@ -0,0 +1,35 @@
+(function() {
+ Handlebars.registerHelper('toFixed', function(number, digits) {
+ if (Utils.isUndefined(digits)) {
+ digits = 0;
+ }
+ return number.toFixed(digits);
+ });
+
+ Handlebars.registerHelper('toPrecision', function(number, precision) {
+ if (Utils.isUndefined(precision)) {
+ precision = 1;
+ }
+ return number.toPrecision(precision);
+ });
+
+ Handlebars.registerHelper('toExponential', function(number, fractions) {
+ if (Utils.isUndefined(fractions)) {
+ fractions = 0;
+ }
+ return number.toExponential(fractions);
+ });
+
+ Handlebars.registerHelper('toInt', function(number) {
+ return parseInt(number, 10);
+ });
+
+ Handlebars.registerHelper('toFloat', function(number) {
+ return parseFloat(number);
+ });
+
+ Handlebars.registerHelper('addCommas', function(number) {
+ return number.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
+ });
+
+}).call(this);
View
77 lib/helpers/helpers-strings.js
@@ -0,0 +1,77 @@
+(function() {
+ Handlebars.registerHelper('lowercase', function(str) {
+ return str.toLowerCase();
+ });
+
+ Handlebars.registerHelper('uppercase', function(str) {
+ return str.toUpperCase();
+ });
+
+ Handlebars.registerHelper('capitalizeFirst', function(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+ });
+
+ Handlebars.registerHelper('capitalizeEach', function(str) {
+ return str.replace(/\w\S*/g, function(txt) {
+ return txt.charAt(0).toUpperCase() + txt.substr(1);
+ });
+ });
+
+ Handlebars.registerHelper('titleize', function(str) {
+ var capitalize, title, word, words;
+
+ title = str.replace(/[ \-_]+/g, ' ');
+ words = title.match(/\w+/g);
+ capitalize = function(word) {
+ return word.charAt(0).toUpperCase() + word.slice(1);
+ };
+ return ((function() {
+ var _i, _len, _results;
+
+ _results = [];
+ for (_i = 0, _len = words.length; _i < _len; _i++) {
+ word = words[_i];
+ _results.push(capitalize(word));
+ }
+ return _results;
+ })()).join(' ');
+ });
+
+ Handlebars.registerHelper('sentence', function(str) {
+ return str.replace(/((?:\S[^\.\?\!]*)[\.\?\!]*)/g, function(txt) {
+ return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
+ });
+ });
+
+ Handlebars.registerHelper('reverse', function(str) {
+ return str.split('').reverse().join('');
+ });
+
+ Handlebars.registerHelper('truncate', function(str, length, omission) {
+ if (Utils.isUndefined(omission)) {
+ omission = '';
+ }
+ if (str.length > length) {
+ return str.substring(0, length - omission.length) + omission;
+ } else {
+ return str;
+ }
+ });
+
+ Handlebars.registerHelper('center', function(str, spaces) {
+ var i, space;
+
+ space = '';
+ i = 0;
+ while (i < spaces) {
+ space += '&nbsp;';
+ i++;
+ }
+ return "" + space + str + space;
+ });
+
+ Handlebars.registerHelper('newLineToBr', function(str) {
+ return str.replace(/\r?\n|\r/g, '<br>');
+ });
+
+}).call(this);
View
23 lib/helpers/helpers-utils.js
@@ -0,0 +1,23 @@
+(function() {
+ var Utils;
+
+ Utils = {};
+
+ Utils.toString = Object.prototype.toString;
+
+ Utils.isUndefined = function(value) {
+ return value === 'undefined' || Utils.toString.call(value) === '[object Function]' || (value.hash != null);
+ };
+
+ Utils.safeString = function(str) {
+ return new Handlebars.SafeString(str);
+ };
+
+ Utils.trim = function(str) {
+ var trim;
+
+ trim = /\S/.test("\xA0") ? /^[\s\xA0]+|[\s\xA0]+$/g : /^\s+|\s+$/g;
+ return str.toString().replace(trim, '');
+ };
+
+}).call(this);
View
14 lib/helpers/helpers.js
@@ -0,0 +1,14 @@
+(function() {
+ var Assemble, Handlebars;
+
+ if (typeof window !== "undefined" && window !== null) {
+ Handlebars = window.Handlebars;
+ window.Assemble = Assemble = {};
+ }
+
+ if (typeof module !== "undefined" && module !== null) {
+ Handlebars = require('handlebars');
+ module.exports = Assemble = {};
+ }
+
+}).call(this);
View
25 package.json
@@ -1,7 +1,7 @@
{
"name": "helper-lib",
"description": "An extensive collection of useful Handlebars helpers.",
- "version": "0.1.7",
+ "version": "0.1.8",
"homepage": "https://github.com/assemble/helper-lib",
"author": {
"name": "assemble",
@@ -38,14 +38,27 @@
"test": "grunt test"
},
"dependencies": {
- "assemble": "0.3.14"
+ "assemble": "*",
+ "grunt-contrib-clean": "~0.4.0",
+ "grunt-contrib-coffee": "~0.6.4",
+ "grunt-contrib-uglify": "~0.2.0",
+ "grunt-mocha-test": "~0.2.0",
+ "should": "~1.2.2",
+ "testem": "~0.2.79",
+ "chai": "~1.5.0"
+ },
+ "peerDependencies": {
+ "assemble": "*"
},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.2.0",
- "grunt-contrib-nodeunit": "~0.1.2"
+ "grunt-contrib-nodeunit": "~0.1.2",
+ "handlebars": "~1.0.10",
+ "amdefine": "0.0.4"
},
"keywords": [
+ "assemble",
"block helper",
"client-side templates",
"example helper",
@@ -57,6 +70,7 @@
"handlebars for loop",
"handlebars helper",
"handlebars helpers",
+ "handlebars helpers",
"handlebars if helper",
"handlebars list",
"handlebars loop index",
@@ -75,7 +89,8 @@
"mustaches templates",
"site builder",
"template helpers",
+ "templates",
"use handlebars",
- "templates"
+ "utilities"
]
-}
+}
View
1,440 src/helper-lib.coffee
@@ -0,0 +1,1440 @@
+#
+# * helper-lib
+# * https://github.com/assemble/helper-lib
+# *
+# * Copyright (c) 2013 Assemble, Jon Schlinkert, Brian Woodward, contributors.
+# * Licensed under the MIT license.
+#
+define = require("amdefine")(module) if not define or typeof define isnt "function"
+
+#
+# * Add any handlebars helpers here and they'll
+# * be loaded into templates.js so they can
+# * be used inside your handlebars templates
+#
+define [], ->
+
+ # figure out if this is node or browser
+ isServer = (typeof process isnt "undefined")
+ register = (Handlebars) ->
+ Dates = {}
+ HTML = {}
+ Utils = {}
+ __indexOf_ = [].indexOf or (item) ->
+ i = 0
+ l = @length
+
+ while i < l
+ return i if i of this and this[i] is item
+ i++
+ -1
+
+
+ # if(isServer) {
+ assemble = require("../../../assemble.js")
+ fs = require("fs")
+ util = require("util")
+ path = require("path")
+ dest = "./"
+ markdown = assemble.Markdown(
+ gfm: true
+ highlight: "auto"
+ )
+
+ # }
+
+ ###
+ Utils
+ ###
+ Utils.toString = Object::toString
+ Utils.isUndefined = (value) ->
+ value is "undefined" or Utils.toString.call(value) is "[object Function]" or (value.hash?)
+
+ Utils.safeString = (str) ->
+ new Handlebars.SafeString(str)
+
+ Utils.trim = (str) ->
+ trim = undefined
+ trim = (if /\S/.test(" ") then /^[\s\xA0]+|[\s\xA0]+$/g else /^\s+|\s+$/g)
+ str.toString().replace trim, ""
+
+
+ # Normalize slashes in URLs
+ Utils.urlNormalize = (urlString) ->
+ urlString.replace /\\/g, "/"
+
+
+ ###
+ HTML
+ ###
+ HTML.parseAttributes = (hash) ->
+ Object.keys(hash).map((key) ->
+ "" + key + "=\"" + hash[key] + "\""
+ ).join " "
+
+
+ ###
+ Dates
+ ###
+ Dates.padNumber = (num, count, padCharacter) ->
+ lenDiff = undefined
+ padding = undefined
+ padCharacter = "0" if typeof padCharacter is "undefined"
+ lenDiff = count - String(num).length
+ padding = ""
+ padding += padCharacter while lenDiff-- if lenDiff > 0
+ padding + num
+
+ Dates.dayOfYear = (date) ->
+ oneJan = undefined
+ oneJan = new Date(date.getFullYear(), 0, 1)
+ Math.ceil (date - oneJan) / 86400000
+
+ Dates.weekOfYear = (date) ->
+ oneJan = undefined
+ oneJan = new Date(date.getFullYear(), 0, 1)
+ Math.ceil (((date - oneJan) / 86400000) + oneJan.getDay() + 1) / 7
+
+ Dates.isoWeekOfYear = (date) ->
+ dayDiff = undefined
+ dayNr = undefined
+ jan4 = undefined
+ target = undefined
+ target = new Date(date.valueOf())
+ dayNr = (date.getDay() + 6) % 7
+ target.setDate target.getDate() - dayNr + 3
+ jan4 = new Date(target.getFullYear(), 0, 4)
+ dayDiff = (target - jan4) / 86400000
+ 1 + Math.ceil(dayDiff / 7)
+
+ Dates.tweleveHour = (date) ->
+ if date.getHours() > 12
+ date.getHours() - 12
+ else
+ date.getHours()
+
+ Dates.timeZoneOffset = (date) ->
+ hoursDiff = undefined
+ result = undefined
+ hoursDiff = -date.getTimezoneOffset() / 60
+ result = Dates.padNumber(Math.abs(hoursDiff), 4)
+ ((if hoursDiff > 0 then "+" else "-")) + result
+
+ Dates.format = (date, format) ->
+ format.replace Dates.formats, (m, p) ->
+ switch p