UNPKG

36.2 kBtext/coffeescriptView Raw
1#
2# * helper-lib
3# * https://github.com/assemble/helper-lib
4# *
5# * Copyright (c) 2013 Assemble, Jon Schlinkert, Brian Woodward, contributors.
6# * Licensed under the MIT license.
7#
8define = require("amdefine")(module) if not define or typeof define isnt "function"
9
10#
11# * Add any handlebars helpers here and they'll
12# * be loaded into templates.js so they can
13# * be used inside your handlebars templates
14#
15define [], ->
16
17 # figure out if this is node or browser
18 isServer = (typeof process isnt "undefined")
19 register = (Handlebars) ->
20 Dates = {}
21 HTML = {}
22 Utils = {}
23 __indexOf_ = [].indexOf or (item) ->
24 i = 0
25 l = @length
26
27 while i < l
28 return i if i of this and this[i] is item
29 i++
30 -1
31
32
33 # if(isServer) {
34 assemble = require("../../../assemble.js")
35 fs = require("fs")
36 util = require("util")
37 path = require("path")
38 dest = "./"
39 markdown = assemble.Markdown(
40 gfm: true
41 highlight: "auto"
42 )
43
44 # }
45
46 ###
47 Utils
48 ###
49 Utils.toString = Object::toString
50 Utils.isUndefined = (value) ->
51 value is "undefined" or Utils.toString.call(value) is "[object Function]" or (value.hash?)
52
53 Utils.safeString = (str) ->
54 new Handlebars.SafeString(str)
55
56 Utils.trim = (str) ->
57 trim = undefined
58 trim = (if /\S/.test(" ") then /^[\s\xA0]+|[\s\xA0]+$/g else /^\s+|\s+$/g)
59 str.toString().replace trim, ""
60
61
62 # Normalize slashes in URLs
63 Utils.urlNormalize = (urlString) ->
64 urlString.replace /\\/g, "/"
65
66
67 ###
68 HTML
69 ###
70 HTML.parseAttributes = (hash) ->
71 Object.keys(hash).map((key) ->
72 "" + key + "=\"" + hash[key] + "\""
73 ).join " "
74
75
76 ###
77 Dates
78 ###
79 Dates.padNumber = (num, count, padCharacter) ->
80 lenDiff = undefined
81 padding = undefined
82 padCharacter = "0" if typeof padCharacter is "undefined"
83 lenDiff = count - String(num).length
84 padding = ""
85 padding += padCharacter while lenDiff-- if lenDiff > 0
86 padding + num
87
88 Dates.dayOfYear = (date) ->
89 oneJan = undefined
90 oneJan = new Date(date.getFullYear(), 0, 1)
91 Math.ceil (date - oneJan) / 86400000
92
93 Dates.weekOfYear = (date) ->
94 oneJan = undefined
95 oneJan = new Date(date.getFullYear(), 0, 1)
96 Math.ceil (((date - oneJan) / 86400000) + oneJan.getDay() + 1) / 7
97
98 Dates.isoWeekOfYear = (date) ->
99 dayDiff = undefined
100 dayNr = undefined
101 jan4 = undefined
102 target = undefined
103 target = new Date(date.valueOf())
104 dayNr = (date.getDay() + 6) % 7
105 target.setDate target.getDate() - dayNr + 3
106 jan4 = new Date(target.getFullYear(), 0, 4)
107 dayDiff = (target - jan4) / 86400000
108 1 + Math.ceil(dayDiff / 7)
109
110 Dates.tweleveHour = (date) ->
111 if date.getHours() > 12
112 date.getHours() - 12
113 else
114 date.getHours()
115
116 Dates.timeZoneOffset = (date) ->
117 hoursDiff = undefined
118 result = undefined
119 hoursDiff = -date.getTimezoneOffset() / 60
120 result = Dates.padNumber(Math.abs(hoursDiff), 4)
121 ((if hoursDiff > 0 then "+" else "-")) + result
122
123 Dates.format = (date, format) ->
124 format.replace Dates.formats, (m, p) ->
125 switch p
126 when "a"
127 Dates.abbreviatedWeekdays[date.getDay()]
128 when "A"
129 Dates.fullWeekdays[date.getDay()]
130 when "b"
131 Dates.abbreviatedMonths[date.getMonth()]
132 when "B"
133 Dates.fullMonths[date.getMonth()]
134 when "c"
135 date.toLocaleString()
136 when "C"
137 Math.round date.getFullYear() / 100
138 when "d"
139 Dates.padNumber date.getDate(), 2
140 when "D"
141 Dates.format date, "%m/%d/%y"
142 when "e"
143 Dates.padNumber date.getDate(), 2, " "
144 when "F"
145 Dates.format date, "%Y-%m-%d"
146 when "h"
147 Dates.format date, "%b"
148 when "H"
149 Dates.padNumber date.getHours(), 2
150 when "I"
151 Dates.padNumber Dates.tweleveHour(date), 2
152 when "j"
153 Dates.padNumber Dates.dayOfYear(date), 3
154 when "k"
155 Dates.padNumber date.getHours(), 2, " "
156 when "l"
157 Dates.padNumber Dates.tweleveHour(date), 2, " "
158 when "L"
159 Dates.padNumber date.getMilliseconds(), 3
160 when "m"
161 Dates.padNumber date.getMonth() + 1, 2
162 when "M"
163 Dates.padNumber date.getMinutes(), 2
164 when "n"
165 "\n"
166 when "p"
167 if date.getHours() > 11
168 return "PM"
169 else
170 return "AM"
171 when "P"
172 Dates.format(date, "%p").toLowerCase()
173 when "r"
174 Dates.format date, "%I:%M:%S %p"
175 when "R"
176 Dates.format date, "%H:%M"
177 when "s"
178 date.getTime() / 1000
179 when "S"
180 Dates.padNumber date.getSeconds(), 2
181 when "t"
182 "\t"
183 when "T"
184 Dates.format date, "%H:%M:%S"
185 when "u"
186 if date.getDay() is 0
187 return 7
188 else
189 return date.getDay()
190 when "U"
191 Dates.padNumber Dates.weekOfYear(date), 2
192 when "v"
193 Dates.format date, "%e-%b-%Y"
194 when "V"
195 Dates.padNumber Dates.isoWeekOfYear(date), 2
196 when "W"
197 Dates.padNumber Dates.weekOfYear(date), 2
198 when "w"
199 Dates.padNumber date.getDay(), 2
200 when "x"
201 date.toLocaleDateString()
202 when "X"
203 date.toLocaleTimeString()
204 when "y"
205 String(date.getFullYear()).substring 2
206 when "Y"
207 date.getFullYear()
208 when "z"
209 Dates.timeZoneOffset date
210 else
211 match
212
213
214 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
215 Dates.abbreviatedWeekdays = ["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"]
216 Dates.fullWeekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
217 Dates.abbreviatedMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
218 Dates.fullMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
219
220 # Handlebars Helpers - Dan Harper (http://github.com/danharper)
221
222 # This program is free software. It comes without any warranty, to
223 # * the extent permitted by applicable law. You can redistribute it
224 # * and/or modify it under the terms of the Do What The Fuck You Want
225 # * To Public License, Version 2, as published by Sam Hocevar. See
226 # * http://sam.zoy.org/wtfpl/COPYING for more details.
227
228 ###
229 If Equals
230 if_eq this compare=that
231 ###
232 Handlebars.registerHelper "if_eq", (context, options) ->
233 return options.fn(this) if context is options.hash.compare
234 options.inverse this
235
236
237 ###
238 Unless Equals
239 unless_eq this compare=that
240 ###
241 Handlebars.registerHelper "unless_eq", (context, options) ->
242 return options.inverse(this) if context is options.hash.compare
243 options.fn this
244
245
246 ###
247 If Greater Than
248 if_gt this compare=that
249 ###
250 Handlebars.registerHelper "if_gt", (context, options) ->
251 return options.fn(this) if context > options.hash.compare
252 options.inverse this
253
254
255 ###
256 Unless Greater Than
257 unless_gt this compare=that
258 ###
259 Handlebars.registerHelper "unless_gt", (context, options) ->
260 return options.inverse(this) if context > options.hash.compare
261 options.fn this
262
263
264 ###
265 If Less Than
266 if_lt this compare=that
267 ###
268 Handlebars.registerHelper "if_lt", (context, options) ->
269 return options.fn(this) if context < options.hash.compare
270 options.inverse this
271
272
273 ###
274 Unless Less Than
275 unless_lt this compare=that
276 ###
277 Handlebars.registerHelper "unless_lt", (context, options) ->
278 return options.inverse(this) if context < options.hash.compare
279 options.fn this
280
281
282 ###
283 If Greater Than or Equal To
284 if_gteq this compare=that
285 ###
286 Handlebars.registerHelper "if_gteq", (context, options) ->
287 return options.fn(this) if context >= options.hash.compare
288 options.inverse this
289
290
291 ###
292 Unless Greater Than or Equal To
293 unless_gteq this compare=that
294 ###
295 Handlebars.registerHelper "unless_gteq", (context, options) ->
296 return options.inverse(this) if context >= options.hash.compare
297 options.fn this
298
299
300 ###
301 If Less Than or Equal To
302 if_lteq this compare=that
303 ###
304 Handlebars.registerHelper "if_lteq", (context, options) ->
305 return options.fn(this) if context <= options.hash.compare
306 options.inverse this
307
308
309 ###
310 Unless Less Than or Equal To
311 unless_lteq this compare=that
312 ###
313 Handlebars.registerHelper "unless_lteq", (context, options) ->
314 return options.inverse(this) if context <= options.hash.compare
315 options.fn this
316
317
318 ###
319 Convert new line (\n) to <br>
320 from http://phpjs.org/functions/nl2br:480
321 ###
322 Handlebars.registerHelper "nl2br", (text) ->
323 nl2br = (text + "").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1" + "<br>" + "$2")
324 new Handlebars.SafeString(nl2br)
325
326
327 ###
328 Hyphenate
329 Replace spaces in string with hyphens.
330 ###
331 Handlebars.registerHelper "hyphenate", (tag) ->
332 tag.split(" ").join "-"
333
334
335 ###
336 Dashify
337 Replace periods in string with hyphens.
338 ###
339 Handlebars.registerHelper "dashify", (tag) ->
340 tag.split(".").join "-"
341
342
343 ###
344 To Lower Case
345 Turns a string to lowercase.
346 ###
347 Handlebars.registerHelper "lowercase", (str) ->
348 str.toLowerCase()
349
350
351 ###
352 To Upper Case
353 Turns a string to uppercase.
354 ###
355 Handlebars.registerHelper "uppercase", (str) ->
356 str.toUpperCase()
357
358
359 ###
360 Capitalize First
361 ###
362 Handlebars.registerHelper "capitalizeFirst", (str) ->
363 str.charAt(0).toUpperCase() + str.slice(1)
364
365
366 ###
367 Capitalize Each
368 ###
369 Handlebars.registerHelper "capitalizeEach", (str) ->
370 str.replace /\w\S*/g, (txt) ->
371 txt.charAt(0).toUpperCase() + txt.substr(1)
372
373
374
375 ###
376 Title Case
377 ###
378 Handlebars.registerHelper "titleize", (str) ->
379 capitalize = undefined
380 title = undefined
381 word = undefined
382 words = undefined
383 title = str.replace(/[ \-_]+/g, " ")
384 words = title.match(/\w+/g)
385 capitalize = (word) ->
386 word.charAt(0).toUpperCase() + word.slice(1)
387
388 ((->
389 _i = undefined
390 _len = undefined
391 _results = undefined
392 _results = []
393 _i = 0
394 _len = words.length
395
396 while _i < _len
397 word = words[_i]
398 _results.push capitalize(word)
399 _i++
400 _results
401 )()).join " "
402
403
404 ###
405 Sentence
406 ###
407 Handlebars.registerHelper "sentence", (str) ->
408 str.replace /((?:\S[^\.\?\!]*)[\.\?\!]*)/g, (txt) ->
409 txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
410
411
412
413 ###
414 Reverse
415 Reverses a string.
416 ###
417 Handlebars.registerHelper "reverse", (str) ->
418 str.split("").reverse().join ""
419
420
421 ###
422 Truncate
423 Truncates a string given a specified `length`, providing a custom string to denote an `omission`.
424
425 Parameters:
426
427 length [int] - The number of characters to keep (Required)
428 omission [string] - A string to denote an omission (Optional)
429
430 Usage:
431 {{truncate "Bender should not be allowed on tv." 31 "..."}}
432 Bender should not be allowed...
433 ###
434 Handlebars.registerHelper "truncate", (str, length, omission) ->
435 omission = "" if Utils.isUndefined(omission)
436 if str.length > length
437 str.substring(0, length - omission.length) + omission
438 else
439 str
440
441
442 ###
443 Center
444 Centers a string using non-breaking spaces.
445 ###
446 Handlebars.registerHelper "center", (str, spaces) ->
447 i = undefined
448 space = undefined
449 space = ""
450 i = 0
451 while i < spaces
452 space += "&nbsp;"
453 i++
454 "" + space + str + space
455
456
457 # ==========================================================
458 #
459 # COLLECTIONS
460 #
461 # ==========================================================
462
463 ###
464 First
465 Returns the first item in a collection.
466 ###
467 Handlebars.registerHelper "first", (array, count) ->
468 if Utils.isUndefined(count)
469 array[0]
470 else
471 array.slice 0, count
472
473
474 ###
475 withFirst
476 Use the first item in a collection inside a block.
477 ###
478 Handlebars.registerHelper "withFirst", (array, count, options) ->
479 item = undefined
480 result = undefined
481 if Utils.isUndefined(count)
482 options = count
483 options.fn array[0]
484 else
485 array = array.slice(0, count)
486 result = ""
487 for item of array
488 result += options.fn(array[item])
489 result
490
491
492 ###
493 Last
494 Returns the last item in a collection. Opposite of `first`.
495 ###
496 Handlebars.registerHelper "last", (array, count) ->
497 if Utils.isUndefined(count)
498 array[array.length - 1]
499 else
500 array.slice -count
501
502
503 ###
504 With Last
505 Use the last item in a collection inside a block. Opposite of `withFirst`.
506 ###
507 Handlebars.registerHelper "withLast", (array, count, options) ->
508 item = undefined
509 result = undefined
510 if Utils.isUndefined(count)
511 options = count
512 options.fn array[array.length - 1]
513 else
514 array = array.slice(-count)
515 result = ""
516 for item of array
517 result += options.fn(array[item])
518 result
519
520
521 ###
522 After
523 Returns all of the items in the collection after the specified count.
524 ###
525 Handlebars.registerHelper "after", (array, count) ->
526 array.slice count
527
528
529 ###
530 With After
531 Use all of the items in the collection after the specified count inside a block.
532 ###
533 Handlebars.registerHelper "withAfter", (array, count, options) ->
534 item = undefined
535 result = undefined
536 array = array.slice(count)
537 result = ""
538 for item of array
539 result += options.fn(array[item])
540 result
541
542
543 ###
544 Before
545 Returns all of the items in the collection before the specified count. Opposite of `after`.
546 ###
547 Handlebars.registerHelper "before", (array, count) ->
548 array.slice 0, -count
549
550
551 ###
552 With Before
553 Use all of the items in the collection before the specified count inside a block. Opposite of `withAfter`.
554 ###
555 Handlebars.registerHelper "withBefore", (array, count, options) ->
556 item = undefined
557 result = undefined
558 array = array.slice(0, -count)
559 result = ""
560 for item of array
561 result += options.fn(array[item])
562 result
563
564
565 ###
566 Join
567 Joins all elements of a collection into a string using a separator if specified.
568 ###
569 Handlebars.registerHelper "join", (array, separator) ->
570 array.join (if Utils.isUndefined(separator) then " " else separator)
571
572
573 ###
574 Sort
575 Returns the collection sorted.
576 ###
577 Handlebars.registerHelper "sort", (array, field) ->
578 if Utils.isUndefined(field)
579 array.sort()
580 else
581 array.sort (a, b) ->
582 a[field] > b[field]
583
584
585
586 ###
587 With Sort
588 Uses the sorted collection inside the block.
589 ###
590 Handlebars.registerHelper "withSort", (array, field, options) ->
591 item = undefined
592 result = undefined
593 _i = undefined
594 _len = undefined
595 result = ""
596 if Utils.isUndefined(field)
597 options = field
598 array = array.sort()
599 _i = 0
600 _len = array.length
601
602 while _i < _len
603 item = array[_i]
604 result += options.fn(item)
605 _i++
606 else
607 array = array.sort((a, b) ->
608 a[field] > b[field]
609 )
610 for item of array
611 result += options.fn(array[item])
612 result
613
614
615 ###
616 Length
617 Returns the length of the collection.
618 ###
619 Handlebars.registerHelper "length", (array) ->
620 array.length
621
622
623 ###
624 Length Equal
625 Conditionally render a block based on the length of a collection.
626 ###
627 Handlebars.registerHelper "lengthEqual", (array, length, options) ->
628 if array.length is length
629 options.fn this
630 else
631 options.inverse this
632
633
634 ###
635 Empty
636 Conditionally render a block if the collection is empty.
637 ###
638 Handlebars.registerHelper "empty", (array, options) ->
639 if array.length <= 0
640 options.fn this
641 else
642 options.inverse this
643
644
645 ###
646 Any
647 Conditionally render a block if the collection isn't empty. Opposite of `empty`
648 ###
649 Handlebars.registerHelper "any", (array, options) ->
650 if array.length > 0
651 options.fn this
652 else
653 options.inverse this
654
655
656 ###
657 inArray
658 Conditionally render a block if a specified value is in the collection.
659 ###
660 Handlebars.registerHelper "inArray", (array, value, options) ->
661 if array.indexOf(value) isnt -1
662 options.fn this
663 else
664 options.inverse this
665
666
667 ###
668 eachIndex
669 Current implementation of the default Handlebars loop
670 helper {{#each}} adding index (0-based index) to the loop context.
671 ###
672 Handlebars.registerHelper "eachIndex", (context, options) ->
673 data = undefined
674 i = undefined
675 j = undefined
676 ret = undefined
677 ret = ""
678 data = Handlebars.createFrame(options.data) if options.data?
679 if context and context.length > 0
680 i = 0
681 j = context.length
682 while i < j
683 data.index = i if data
684 context[i].index = i
685 ret = ret + options.fn(context[i])
686 i++
687 else
688 ret = options.inverse(this)
689 ret
690
691
692 ###
693 keyValue
694 Iterate over an object, setting 'key' and 'value' for each property in the object.
695
696 Credit: [@strathmeyer](https://gist.github.com/strathmeyer)
697
698 Example:
699 {{#keyValue obj}}
700 Key: {{key}}
701 Value: {{value}}
702 {{/keyValue}}
703 ###
704 Handlebars.registerHelper "keyValue", (obj, fn) ->
705 buffer = ""
706 key = undefined
707 for key of obj
708 if obj.hasOwnProperty(key)
709 buffer += fn(
710 key: key
711 value: obj[key]
712 )
713 buffer
714
715
716 ###
717 Relative path
718 Returns the derived relative path from one to the other.
719 ###
720 Handlebars.registerHelper "relative", (from, to) ->
721 relativePath = path.relative(from, to)
722 relativePath = dest if relativePath is "." or relativePath.length is 0
723 relativePath = Utils.urlNormalize(path.relative(path.resolve(path.join(dest, relative)), path.resolve(relativePath)))
724 relativePath
725
726
727 ###
728 absolute
729 Returns the absolute path to the current directory.
730
731 Usage:
732 {{absolute}}
733
734 Returns:
735 C:\path\to\the\current\current\directory
736 ###
737 Handlebars.registerHelper "absolute", (absolute) ->
738 absolute = __filename
739 absolute
740
741
742 ###
743 Basename
744 Returns the basename of a given file.
745
746 Usage:
747 {{base "docs/toc.md"}}
748
749 Returns:
750 toc
751 ###
752 Handlebars.registerHelper "basename", (base, ext) ->
753 fullName = path.basename(base, ext)
754 base = path.basename(base, path.extname(fullName))
755 base
756
757
758 ###
759 Filename
760 Returns the filename of a given file.
761
762 Usage:
763 {{filename "docs/toc.md"}}
764
765 Returns:
766 toc.md
767 ###
768 Handlebars.registerHelper "filename", (base, ext) ->
769 filename = path.basename(base, ext)
770 filename
771
772
773 ###
774 Extension
775 Returns the extension of a given file.
776
777 Usage:
778 {{ext "docs/toc.md"}}
779
780 Returns:
781 .md
782 ###
783 Handlebars.registerHelper "ext", (ext) ->
784 extension = path.extname(ext)
785 extension
786
787 Handlebars.registerHelper "file", (pathname, host, url) ->
788 pathname = url.parse(host).pathname
789 pathname = pathname.substring(0, pathname.lastIndexOf("/"))
790 pathname
791
792
793 ###
794 Add
795 Returns the sum of two numbers.
796 ###
797 Handlebars.registerHelper "add", (value, addition) ->
798 value + addition
799
800
801 ###
802 Subtract
803 Returns the difference of two numbers. Opposite of `add`
804 ###
805 Handlebars.registerHelper "subtract", (value, substraction) ->
806 value - substraction
807
808
809 ###
810 Divide
811 Returns the division of two numbers.
812 ###
813 Handlebars.registerHelper "divide", (value, divisor) ->
814 value / divisor
815
816
817 ###
818 Multiply
819 Returns the multiplication of two numbers.
820 ###
821 Handlebars.registerHelper "multiply", (value, multiplier) ->
822 value * multiplier
823
824
825 ###
826 Floor
827 Returns the value rounded down to the nearest integer.
828 ###
829 Handlebars.registerHelper "floor", (value) ->
830 Math.floor value
831
832
833 ###
834 Ceil
835 Returns the value rounded up to the nearest integer.
836 ###
837 Handlebars.registerHelper "ceil", (value) ->
838 Math.ceil value
839
840
841 ###
842 Round
843 Returns the value rounded to the nearest integer.
844 ###
845 Handlebars.registerHelper "round", (value) ->
846 Math.round value
847
848
849 ###
850 To Fixed
851 Returns exactly `digits` after the decimal place.
852 The number is rounded if necessary, and the fractional
853 part is padded with zeros if necessary so that it has the specified length.
854 ###
855 Handlebars.registerHelper "toFixed", (number, digits) ->
856 digits = 0 if Utils.isUndefined(digits)
857 number.toFixed digits
858
859
860 ###
861 To Precision
862 Returns the number in fixed-point or exponential
863 notation rounded to `precision` significant digits.
864 ###
865 Handlebars.registerHelper "toPrecision", (number, precision) ->
866 precision = 1 if Utils.isUndefined(precision)
867 number.toPrecision precision
868
869
870 ###
871 To Exponential
872 Returns the number in exponential notation with one
873 digit before the decimal point, rounded to `fractions`
874 digits after the decimal point.
875 ###
876 Handlebars.registerHelper "toExponential", (number, fractions) ->
877 fractions = 0 if Utils.isUndefined(fractions)
878 number.toExponential fractions
879
880
881 ###
882 To Int
883 Returns an integer.
884 ###
885 Handlebars.registerHelper "toInt", (number) ->
886 parseInt number, 10
887
888
889 ###
890 To Float
891 Returns a floating point number.
892 ###
893 Handlebars.registerHelper "toFloat", (number) ->
894 parseFloat number
895
896
897 ###
898 Add Commas
899 Adds commas to a number.
900 ###
901 Handlebars.registerHelper "addCommas", (number) ->
902 number.toString().replace /(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"
903
904
905 ###
906 Is
907 Conditionally render a block if the condition is true.
908 ###
909 Handlebars.registerHelper "is", (value, test, options) ->
910 if value is test
911 options.fn this
912 else
913 options.inverse this
914
915
916 ###
917 Isn't
918 Conditionally render a block if the condition is false. Opposite of `is`.
919 ###
920 Handlebars.registerHelper "isnt", (value, test, options) ->
921 if value isnt test
922 options.fn this
923 else
924 options.inverse this
925
926
927 ###
928 Greater Than
929 Conditionally render a block if the value is greater than a given number.
930 ###
931 Handlebars.registerHelper "gt", (value, test, options) ->
932 if value > test
933 options.fn this
934 else
935 options.inverse this
936
937
938 ###
939 Greater than or equal to
940 Conditionally render a block if the value is greater than
941 or equal to a given number.
942 ###
943 Handlebars.registerHelper "gte", (value, test, options) ->
944 if value >= test
945 options.fn this
946 else
947 options.inverse this
948
949
950 ###
951 Less Than
952 Conditionally render a block if the value is less than
953 a given number. Opposite of `gt`.
954 ###
955 Handlebars.registerHelper "lt", (value, test, options) ->
956 if value < test
957 options.fn this
958 else
959 options.inverse this
960
961
962 ###
963 Conditionally render a block if the value is less than or
964 equal to a given number. Opposite of `gte`.
965 ###
966 Handlebars.registerHelper "lte", (value, test, options) ->
967 if value <= test
968 options.fn this
969 else
970 options.inverse this
971
972
973 ###
974 Or
975 Conditionally render a block if one of the values is truthy.
976 ###
977 Handlebars.registerHelper "or", (testA, testB, options) ->
978 if testA or testB
979 options.fn this
980 else
981 options.inverse this
982
983
984 ###
985 And
986 Conditionally render a block if both values are truthy.
987 ###
988 Handlebars.registerHelper "and", (testA, testB, options) ->
989 if testA and testB
990 options.fn this
991 else
992 options.inverse this
993
994
995 ###
996 Format Phone Number
997 from: http://blog.teamtreehouse.com/handlebars-js-part-2-partials-and-helpers
998 Helper function to output a formatted phone number
999
1000 Usage:
1001
1002 {{formatPhoneNumber phoneNumber}}
1003 ###
1004 Handlebars.registerHelper "formatPhoneNumber", (phoneNumber) ->
1005 phoneNumber = phoneNumber.toString()
1006 "(" + phoneNumber.substr(0, 3) + ") " + phoneNumber.substr(3, 3) + "-" + phoneNumber.substr(6, 4)
1007
1008
1009 ###
1010 Format Date
1011 Formats a date into a string given a format. Accepts any
1012 value that can be passed to `new Date()`. This helper is a port of
1013 [formatDate-js](http://https://github.com/michaelbaldry/formatDate-js)
1014 by [Michael Baldry](https://github.com/michaelbaldry).
1015 ###
1016 Handlebars.registerHelper "formatDate", (date, format) ->
1017 date = new Date(date)
1018 Dates.format date, format
1019
1020
1021 ###
1022 Now
1023 Returns the current date.
1024 ###
1025 Handlebars.registerHelper "now", (format) ->
1026 date = undefined
1027 date = new Date()
1028 if Utils.isUndefined(format)
1029 date
1030 else
1031 Dates.format date, format
1032
1033
1034 ###
1035 Time Ago
1036 Returns a human-readable time phrase from the given date.
1037 ###
1038 Handlebars.registerHelper "timeago", (date) ->
1039 interval = undefined
1040 seconds = undefined
1041 date = new Date(date)
1042 seconds = Math.floor((new Date() - date) / 1000)
1043 interval = Math.floor(seconds / 31536000)
1044 return "" + interval + " years ago" if interval > 1
1045 interval = Math.floor(seconds / 2592000)
1046 return "" + interval + " months ago" if interval > 1
1047 interval = Math.floor(seconds / 86400)
1048 return "" + interval + " days ago" if interval > 1
1049 interval = Math.floor(seconds / 3600)
1050 return "" + interval + " hours ago" if interval > 1
1051 interval = Math.floor(seconds / 60)
1052 return "" + interval + " minutes ago" if interval > 1
1053 if Math.floor(seconds) is 0
1054 "Just now"
1055 else
1056 Math.floor(seconds) + " seconds ago"
1057
1058
1059 # ==========================================================
1060 #
1061 # INFLECTIONS
1062 #
1063 # ==========================================================
1064
1065 ###
1066 Inflect
1067 Returns the plural or singular form of a word based on a count.
1068
1069 Parameters:
1070
1071 singular [string] - The singular form of the word. (Required)
1072 plural [string] - The plural form of the word. (Required)
1073 include [boolean] - whether or not to include the count before the word. (Optional)
1074
1075 Usage:
1076
1077 enemies = 0
1078 friends = 1
1079
1080 {{inflect enemies "enemy" "enemies"}}
1081 {{inflect friends "friend" "friends" true}}
1082
1083 enemies
1084 1 friend
1085 ###
1086 Handlebars.registerHelper "inflect", (count, singular, plural, include) ->
1087 word = undefined
1088 word = (if count > 1 or count is 0 then plural else singular)
1089 if Utils.isUndefined(include) or include is false
1090 word
1091 else
1092 "" + count + " " + word
1093
1094
1095 ###
1096 Ordinalize
1097 Turns a number into an ordinal string.
1098 Taken from the templating library
1099 [Walrus](https://github.com/jeremyruppel/walrus)
1100 by [Jeremy Ruppel](https://github.com/jeremyruppel).
1101
1102 Usage:
1103
1104 {{ordinalize 3}}
1105 {{ordinalize 1}}
1106 {{ordinalize 22}}
1107
1108 3rd
1109 1st
1110 22nd
1111 ###
1112 Handlebars.registerHelper "ordinalize", (value) ->
1113 normal = undefined
1114 _ref = undefined
1115 normal = Math.abs(Math.round(value))
1116 _ref = normal % 100
1117 if __indexOf_.call([11, 12, 13], _ref) >= 0
1118 "" + value + "th"
1119 else
1120 switch normal % 10
1121 when 1
1122 "" + value + "st"
1123 when 2
1124 "" + value + "nd"
1125 when 3
1126 "" + value + "rd"
1127 else
1128 "" + value + "th"
1129
1130
1131 ###
1132 <ul>
1133 Creates an unordered list.
1134 Parameters:
1135
1136 hash [html attributes] - HTML attributes to use on the ul element. (Optional)
1137
1138 Usage:
1139
1140 collection = [
1141 name: 'Leela'
1142 deliveries: 8021
1143 ,
1144 name: 'Bender'
1145 deliveries: 239
1146 ,
1147 name: 'Fry'
1148 deliveries: 1
1149 ]
1150
1151 {{#ul collection class="deliveries-list"}}
1152 {{name}} - {{inflect deliveries "delivery" "deliveries" true}}
1153 {{/ul}}
1154
1155 <ul class="deliveries-list">
1156 <li>
1157 Leela - 8021 deliveries
1158 </li>
1159 <li>
1160 Bender - 239 deliveries
1161 </li>
1162 <li>
1163 Fry - 1 delivery
1164 </li>
1165 </ul>
1166 ###
1167 Handlebars.registerHelper "ul", (context, options) ->
1168 ("<ul " + (HTML.parseAttributes(options.hash)) + ">") + context.map((item) ->
1169 "<li>" + (options.fn(item)) + "</li>"
1170 ).join("\n") + "</ul>"
1171
1172
1173 ###
1174 <ol>
1175 Same as the `ul` helper but creates and ordered list.
1176 ###
1177 Handlebars.registerHelper "ol", (context, options) ->
1178 ("<ol " + (HTML.parseAttributes(options.hash)) + ">") + context.map((item) ->
1179 "<li>" + (options.fn(item)) + "</li>"
1180 ).join("\n") + "</ol>"
1181
1182
1183 ###
1184 Stripes block helper
1185
1186 Credit: http://blog.teamtreehouse.com/handlebars-js-part-2-partials-and-helpers
1187 Block helper that iterates through an array, letting the contents know whether
1188 it’s an even or odd row. The helper takes the array to iterate over, the css
1189 class name for even rows, and the css class name for odd rows as arguments.
1190
1191 Usage:
1192
1193 {{#stripes myArray "even" "odd"}}
1194 <div class="{{stripeClass}}">
1195 ... code for the row ...
1196 </div>
1197 {{else}}
1198 <em>There aren't any people.</em>
1199 {{/stripes}}
1200 ###
1201 Handlebars.registerHelper "stripes", (array, even, odd, fn) ->
1202 if array and array.length > 0
1203 buffer = ""
1204 i = 0
1205 j = array.length
1206
1207 while i < j
1208 item = array[i]
1209
1210 # we'll just put the appropriate stripe class name onto the item for now
1211 item.stripeClass = ((if i % 2 is 0 then even else odd))
1212
1213 # show the inside of the block
1214 buffer += fn(item)
1215 i++
1216
1217 # return the finished buffer
1218 buffer
1219
1220
1221 ###
1222 Timeline helper
1223
1224 Credit: http://github.com/jonschlinkert
1225 Block helper that iterates through an array, letting the contents know whether
1226 it’s an left or right column. The helper takes the array to iterate over, the css
1227 class name for left columns, and the css class name for right columns as arguments.
1228
1229 Usage:
1230
1231 <div class="timeline">
1232 {{#timeline myArray "left" "right"}}
1233 <div class="{{columnClass}}">
1234 {{> entry}}
1235 </div>
1236 {{else}}
1237 <em>There aren't any entries.</em>
1238 {{/timeline}}
1239 </div>
1240 ###
1241 Handlebars.registerHelper "timeline", (array, left, right, fn) ->
1242 if array and array.length > 0
1243 buffer = ""
1244 i = 0
1245 j = array.length
1246
1247 while i < j
1248 item = array[i]
1249
1250 # we'll just put the appropriate timeline class name onto the item for now
1251 item.columnClass = ((if i % 2 is 0 then left else right))
1252
1253 # show the inside of the block
1254 buffer += fn(item)
1255 i++
1256
1257 # return the finished buffer
1258 buffer
1259
1260
1261 ###
1262 <br>
1263 Returns `<br>` tags based on a count.
1264 Usage:
1265
1266 {{br 5}}
1267
1268 <br><br><br><br><br>
1269 ###
1270 Handlebars.registerHelper "br", (count, options) ->
1271 br = undefined
1272 i = undefined
1273 br = "<br>"
1274 unless Utils.isUndefined(count)
1275 i = 0
1276 while i < count - 1
1277 br += "<br>"
1278 i++
1279 Utils.safeString br
1280
1281
1282 ###
1283 Each Property
1284 Loop through an objects properties
1285 Usage:
1286
1287 {{#eachProperty object}}
1288 {{property}}: {{value}}<br/>
1289 {{/eachProperty }}
1290 ###
1291 Handlebars.registerHelper "eachProperty", (context, options) ->
1292 ret = ""
1293 for prop of context
1294 ret = ret + options.fn(
1295 property: prop
1296 value: context[prop]
1297 )
1298 ret
1299
1300
1301 ###
1302 Inline Partials
1303 Loop through an objects properties
1304 Usage:
1305
1306 {{{include "scripts"}}}
1307
1308 and then:
1309
1310 {{#extend "scripts"}}
1311 <script>
1312 document.write('foo bar!');
1313 </script>
1314 {{/extend}}
1315 ###
1316 inlinePartials = {}
1317 Handlebars.registerHelper "extend", (name, context) ->
1318 include = inlinePartials[name]
1319 include = inlinePartials[name] = [] unless include
1320 include.push context.fn(this)
1321
1322 Handlebars.registerHelper "include", (name) ->
1323 val = (inlinePartials[name] or []).join("\n")
1324
1325 # clear the include
1326 inlinePartials[name] = []
1327 val
1328
1329
1330 # ==========================================================
1331 #
1332 # LOGGING
1333 #
1334 # ==========================================================
1335
1336 ###
1337 Log
1338 Simple console.log()
1339
1340 Parameters: none.
1341
1342 Usage:
1343
1344 {{log "Hi console :)"}}
1345
1346 Hi console :)
1347 ###
1348 Handlebars.registerHelper "log", (value) ->
1349 console.log value
1350
1351
1352 ###
1353 Debug
1354 Simple console.debug() that shows the current context.
1355
1356 Parameters: none.
1357
1358 Usage:
1359
1360 collection = [
1361 name: 'Leela'
1362 deliveries: 8021
1363 ,
1364 name: 'Bender'
1365 deliveries: 239
1366 ,
1367 name: 'Fry'
1368 deliveries: 1
1369 ]
1370
1371 {{#withFirst collection}}
1372 {{debug name}}
1373 {{/withFirst}}
1374
1375 Context: { deliveries: 8021, name: "Leela" }
1376 Value: Leela
1377 ###
1378 Handlebars.registerHelper "debug", (value) ->
1379 console.log "Context: ", this
1380 console.log "Value: ", value unless Utils.isUndefined(value)
1381 console.log "-----------------------------------------------"
1382
1383
1384 # ==========================================================
1385 #
1386 # MISCELLANEOUS
1387 #
1388 # ==========================================================
1389
1390 ###
1391 Default
1392 Provides a default or fallback value if a value doesn't exist.
1393
1394 Usage:
1395
1396 title = ''
1397
1398 {{default title "Not title available."}}
1399
1400 Not title available.
1401 ###
1402 Handlebars.registerHelper "default", (value, defaultValue) ->
1403 (if value? then value else defaultValue)
1404
1405
1406 ###
1407 Markdown
1408
1409 Markdown helper used to write markdown inside and
1410 rendered the markdown inline with the HTML
1411
1412 Usage:
1413
1414 {{#markdown}}
1415 # This is a title.
1416 {{/markdown}}
1417
1418 Renders to:
1419 <h1>This is a title </h1>
1420 ###
1421 Handlebars.registerHelper "markdown", (options) ->
1422 content = options.fn(this)
1423 markdown.convert content
1424
1425 if isServer
1426
1427 ###
1428 Markdown helper used to read in a file and inject
1429 the rendered markdown into the HTML.
1430
1431 Usage:
1432
1433 {{md ../path/to/file.md}}
1434 ###
1435 Handlebars.registerHelper "md", (path) ->
1436 content = markdown.read(path)
1437 content
1438
1439
1440 register: register