handlebars-helpers 0.0.5 → 0.0.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -3
  3. data/.gitignore +1 -0
  4. data/.handlebars_helpers.json +956 -0
  5. data/.handlebars_string_formatters.json +137 -0
  6. data/.rubocop.yml +4 -2
  7. data/.vscode/settings.json +6 -0
  8. data/Gemfile +3 -0
  9. data/README.md +31 -3
  10. data/Rakefile +1 -0
  11. data/STORIES.md +55 -7
  12. data/USAGE.md +1 -1
  13. data/bin/console +1 -1
  14. data/handlebars-helpers.gemspec +10 -1
  15. data/lib/handlebars/helpers.rb +2 -0
  16. data/lib/handlebars/helpers/base_helper.rb +36 -0
  17. data/lib/handlebars/helpers/base_safe_string_helper.rb +17 -0
  18. data/lib/handlebars/helpers/code_ruby/classify.rb +40 -0
  19. data/lib/handlebars/helpers/code_ruby/deconstantize.rb +48 -0
  20. data/lib/handlebars/helpers/code_ruby/demodulize.rb +58 -0
  21. data/lib/handlebars/helpers/code_ruby/foreign_key.rb +49 -0
  22. data/lib/handlebars/helpers/code_ruby/tableize.rb +35 -0
  23. data/lib/handlebars/helpers/comparison/and.rb +44 -0
  24. data/lib/handlebars/helpers/comparison/default.rb +66 -0
  25. data/lib/handlebars/helpers/comparison/eq.rb +35 -0
  26. data/lib/handlebars/helpers/comparison/gt.rb +35 -0
  27. data/lib/handlebars/helpers/comparison/gte.rb +43 -0
  28. data/lib/handlebars/helpers/comparison/lt.rb +35 -0
  29. data/lib/handlebars/helpers/comparison/lte.rb +43 -0
  30. data/lib/handlebars/helpers/comparison/ne.rb +35 -0
  31. data/lib/handlebars/helpers/comparison/or.rb +56 -0
  32. data/lib/handlebars/helpers/configuration.rb +72 -0
  33. data/lib/handlebars/helpers/inflection/ordinal.rb +58 -0
  34. data/lib/handlebars/helpers/inflection/ordinalize.rb +59 -0
  35. data/lib/handlebars/helpers/inflection/pluralize.rb +36 -0
  36. data/lib/handlebars/helpers/inflection/pluralize_by_number.rb +60 -0
  37. data/lib/handlebars/helpers/inflection/singularize.rb +35 -0
  38. data/lib/handlebars/helpers/misc/noop.rb +36 -0
  39. data/lib/handlebars/helpers/misc/safe.rb +37 -0
  40. data/lib/handlebars/helpers/register_helpers.rb +73 -0
  41. data/lib/handlebars/helpers/string_formatting/append_if.rb +42 -0
  42. data/lib/handlebars/helpers/string_formatting/back_slash.rb +33 -0
  43. data/lib/handlebars/helpers/string_formatting/camel.rb +29 -0
  44. data/lib/handlebars/helpers/string_formatting/constantize.rb +29 -0
  45. data/lib/handlebars/helpers/string_formatting/dasherize.rb +33 -0
  46. data/lib/handlebars/helpers/string_formatting/dotirize.rb +33 -0
  47. data/lib/handlebars/helpers/string_formatting/double_colon.rb +33 -0
  48. data/lib/handlebars/helpers/string_formatting/downcase.rb +31 -0
  49. data/lib/handlebars/helpers/string_formatting/format_as.rb +57 -0
  50. data/lib/handlebars/helpers/string_formatting/humanize.rb +39 -0
  51. data/lib/handlebars/helpers/string_formatting/lamel.rb +29 -0
  52. data/lib/handlebars/helpers/string_formatting/padl.rb +58 -0
  53. data/lib/handlebars/helpers/string_formatting/padr.rb +59 -0
  54. data/lib/handlebars/helpers/string_formatting/pluserize.rb +29 -0
  55. data/lib/handlebars/helpers/string_formatting/prepend_if.rb +42 -0
  56. data/lib/handlebars/helpers/string_formatting/singularize.rb +35 -0
  57. data/lib/handlebars/helpers/string_formatting/slash.rb +33 -0
  58. data/lib/handlebars/helpers/string_formatting/snake.rb +33 -0
  59. data/lib/handlebars/helpers/string_formatting/string.js +511 -0
  60. data/lib/handlebars/helpers/string_formatting/surround.rb +49 -0
  61. data/lib/handlebars/helpers/string_formatting/surround_if.rb +43 -0
  62. data/lib/handlebars/helpers/string_formatting/titleize.rb +39 -0
  63. data/lib/handlebars/helpers/string_formatting/upcase.rb +31 -0
  64. data/lib/handlebars/helpers/string_tokenizer.rb +43 -0
  65. data/lib/handlebars/helpers/template.rb +68 -0
  66. data/lib/handlebars/helpers/version.rb +1 -1
  67. metadata +97 -6
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_helper'
7
+
8
+ module Handlebars
9
+ module Helpers
10
+ # String manipulation methods for case formatting
11
+ module StringFormatting
12
+ # humanize wil convert text to human case, aka capitalize
13
+ class Humanize < Handlebars::Helpers::BaseHelper
14
+ # Parse will humanize wil convert text to human case, aka capitalize
15
+ #
16
+ # @side effects
17
+ #
18
+ # Text casing set to upper case for first letter only.
19
+ # Numbers will maintain their spacing
20
+ #
21
+ # @example
22
+ #
23
+ # puts Humanize.new.parse('the quick brown fox 99')
24
+ #
25
+ # The quick brown fox 99
26
+ #
27
+ # @return [String] value converted to sentence case
28
+ def parse(value)
29
+ tokenizer.parse(value,
30
+ separator: ' ',
31
+ preserve_case: true,
32
+ compress_prefix_numerals: false,
33
+ compress_suffix_numerals: false)
34
+ .humanize
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_helper'
7
+
8
+ module Handlebars
9
+ module Helpers
10
+ # String manipulation methods for case formatting
11
+ module StringFormatting
12
+ # lamel case is the same as camel case except with the first character as lower case
13
+ class Lamel < Handlebars::Helpers::BaseHelper
14
+ # Parse will lamel case is the same as camel case except with the first character as lower case
15
+ #
16
+ # @example
17
+ #
18
+ # puts Lamel.new.parse('the quick brown fox 99')
19
+ #
20
+ # theQuickBrownFox99
21
+ #
22
+ # @return [String] value converted to lamel case
23
+ def parse(value)
24
+ tokenizer.parse(value, separator: '_').camelize(:lower)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_safe_string_helper'
7
+
8
+ module Handlebars
9
+ module Helpers
10
+ # String manipulation methods for case formatting
11
+ module StringFormatting
12
+ # Add padding to the left of the value.
13
+ class Padl < Handlebars::Helpers::BaseSafeStringHelper
14
+ # Parse will Add padding to the left of the value.
15
+ #
16
+ # @example
17
+ #
18
+ # puts "[#{Padl.new.parse('aaa', 10)}]"
19
+ #
20
+ # [ aaa]
21
+ #
22
+ # @example
23
+ #
24
+ # puts "[#{Padl.new.parse('aaa')}]"
25
+ #
26
+ # [ aaa]
27
+ #
28
+ # @example
29
+ #
30
+ # puts Padl.new.parse('aaa', '10', '-')
31
+ #
32
+ # -------aaa
33
+ #
34
+ # @param [String] value - value to apply padding to
35
+ # @param [Integer] count - how much padding to apply. defaults to configuration.padl_count
36
+ # @param [String] char - character to pad with. defaults to configuration.padl_char
37
+ # @return [String] value with padding to left
38
+ def parse(value, count, char)
39
+ value = '' if value.nil?
40
+ count = Handlebars::Helpers.configuration.padl_count if count.nil?
41
+ count = count.to_i if count.is_a?(String)
42
+ char = Handlebars::Helpers.configuration.padl_char if char.nil?
43
+ value.rjust(count, char)
44
+ end
45
+
46
+ def handlebars_helper
47
+ proc do |_context, value, count, char|
48
+ # Handle optional: value, count and char
49
+ value = nil if value.is_a?(V8::Object)
50
+ count = nil if count.is_a?(V8::Object)
51
+ char = nil if char.is_a?(V8::Object)
52
+ wrapper(parse(value, count, char))
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_safe_string_helper'
7
+ require 'handlebars/helpers/configuration'
8
+
9
+ module Handlebars
10
+ module Helpers
11
+ # String manipulation methods for case formatting
12
+ module StringFormatting
13
+ # Add padding to the right of the value.
14
+ class Padr < Handlebars::Helpers::BaseSafeStringHelper
15
+ # Parse will Add padding to the right of the value.
16
+ #
17
+ # @example
18
+ #
19
+ # puts "[#{Padr.new.parse('aaa', 10)}]"
20
+ #
21
+ # [aaa ]
22
+ #
23
+ # @example
24
+ #
25
+ # puts "[#{Padr.new.parse('aaa')}]"
26
+ #
27
+ # [aaa ]
28
+ #
29
+ # @example
30
+ #
31
+ # puts Padr.new.parse('aaa', '10', '-')
32
+ #
33
+ # aaa-------
34
+ #
35
+ # @param [String] value - value to apply padding to
36
+ # @param [Integer] count - how much padding to apply. defaults to configuration.padr_count
37
+ # @param [String] char - character to pad with. defaults to configuration.padr_char
38
+ # @return [String] value with padding to right
39
+ def parse(value, count = nil, char = nil)
40
+ value = '' if value.nil?
41
+ count = Handlebars::Helpers.configuration.padr_count if count.nil?
42
+ count = count.to_i if count.is_a?(String)
43
+ char = Handlebars::Helpers.configuration.padr_char if char.nil?
44
+ value.ljust(count, char)
45
+ end
46
+
47
+ def handlebars_helper
48
+ proc do |_context, value, count, char|
49
+ # Handle optional: value, count and char
50
+ value = nil if value.is_a?(V8::Object)
51
+ count = nil if count.is_a?(V8::Object)
52
+ char = nil if char.is_a?(V8::Object)
53
+ wrapper(parse(value, count, char))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_helper'
7
+
8
+ module Handlebars
9
+ module Helpers
10
+ # String manipulation methods for case formatting
11
+ module StringFormatting
12
+ # convert to plus notation
13
+ class Pluserize < Handlebars::Helpers::BaseHelper
14
+ # Parse will convert to plus notation
15
+ #
16
+ # @example
17
+ #
18
+ # puts Pluserize.new.parse('the quick brown fox 99')
19
+ #
20
+ # the+quick+brown+fox99
21
+ #
22
+ # @return [String] value converted to plus notation
23
+ def parse(value)
24
+ tokenizer.parse(value, separator: '+')
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_safe_string_helper'
7
+ require 'handlebars/helpers/string_formatting/format_as'
8
+
9
+ module Handlebars
10
+ module Helpers
11
+ # String manipulation methods for case formatting
12
+ module StringFormatting
13
+ # Append If will prepend the prefix to value, if value is not empty
14
+ class PrependIf < Handlebars::Helpers::BaseSafeStringHelper
15
+ # Parse will Append If will prepend the prefix to value, if value is not empty
16
+ #
17
+ # @example
18
+ #
19
+ # puts PrependIf.new.parse('turn to symbol', ':', 'snake')
20
+ #
21
+ # :turn_to_symbol
22
+ #
23
+ # @param [String] value - value to add prepend too
24
+ # @param [String] prefix - prefix to insert in front of value
25
+ # @param [String] formats - list of formats to apply to value, defaults to none
26
+ # @return [String] prefix + value when value exists, otherwise ''
27
+ def parse(value, prefix, formats)
28
+ format_as = Handlebars::Helpers::StringFormatting::FormatAs.new
29
+ value.present? ? "#{prefix}#{format_as.parse(value, formats)}" : ''
30
+ end
31
+
32
+ def handlebars_helper
33
+ proc do |_context, value, prefix, formats|
34
+ # Handle optional: formats
35
+ formats = nil if formats.is_a?(V8::Object)
36
+ wrapper(parse(value, prefix, formats))
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_helper'
7
+
8
+ module Handlebars
9
+ module Helpers
10
+ # General purpose string manipulation helpers
11
+ module StringFormatting
12
+ # The reverse of #pluralize, returns the singular form of a word in a string
13
+ class Singularize < Handlebars::Helpers::BaseHelper
14
+ # Parse will reverse of #pluralize, returns the singular form of a word in a string
15
+ #
16
+ # @example
17
+ #
18
+ # puts Singularize.new.parse('names')
19
+ #
20
+ # name
21
+ #
22
+ # puts Singularize.new.parse('octopi')
23
+ #
24
+ # octopus
25
+ #
26
+ # @return [String] plural value turned to singular value
27
+ def parse(value)
28
+ return '' if value.nil?
29
+
30
+ value.singularize
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_helper'
7
+
8
+ module Handlebars
9
+ module Helpers
10
+ # String manipulation methods for case formatting
11
+ module StringFormatting
12
+ # slash case the characters in the given 'string'.
13
+ class Slash < Handlebars::Helpers::BaseHelper
14
+ # Parse will slash case the characters in the given 'string'.
15
+ #
16
+ # @side effects
17
+ #
18
+ # Text casing is preserved.
19
+ #
20
+ # @example
21
+ #
22
+ # puts Slash.new.parse('the Quick brown Fox 99')
23
+ #
24
+ # the/Quick/brown/Fox99
25
+ #
26
+ # @return [String] value converted to slash notation
27
+ def parse(value)
28
+ tokenizer.parse(value, preserve_case: true, separator: '/')
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # reference: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb
4
+ require 'active_support/core_ext/string'
5
+
6
+ require 'handlebars/helpers/base_helper'
7
+
8
+ module Handlebars
9
+ module Helpers
10
+ # String manipulation methods for case formatting
11
+ module StringFormatting
12
+ # snake case the characters in the given 'string'.
13
+ class Snake < Handlebars::Helpers::BaseHelper
14
+ # Parse will snake case the characters in the given 'string'.
15
+ #
16
+ # @side effects
17
+ #
18
+ # All text is in lower case
19
+ #
20
+ # @example
21
+ #
22
+ # puts Snake.new.parse('the quick brown fox 99')
23
+ #
24
+ # the-quick-brown-fox99
25
+ #
26
+ # @return [String] value converted to snake case
27
+ def parse(value)
28
+ tokenizer.parse(value, separator: '_')
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,511 @@
1
+ /**
2
+ * Center a string using non-breaking spaces
3
+ *
4
+ * @param {String} `str`
5
+ * @param {String} `spaces`
6
+ * @return {String}
7
+ * @api public
8
+ */
9
+
10
+ helpers.center = function(str, spaces) {
11
+ if (!util.isString(str)) return '';
12
+ var space = '';
13
+ var i = 0;
14
+ while (i < spaces) {
15
+ space += '&nbsp;';
16
+ i++;
17
+ }
18
+ return space + str + space;
19
+ };
20
+
21
+ /**
22
+ * Like trim, but removes both extraneous whitespace **and
23
+ * non-word characters** from the beginning and end of a string.
24
+ *
25
+ * ```handlebars
26
+ * {{chop "_ABC_"}}
27
+ * <!-- results in: 'ABC' -->
28
+ *
29
+ * {{chop "-ABC-"}}
30
+ * <!-- results in: 'ABC' -->
31
+ *
32
+ * {{chop " ABC "}}
33
+ * <!-- results in: 'ABC' -->
34
+ * ```
35
+ * @param {String} `string` The string to chop.
36
+ * @return {String}
37
+ * @api public
38
+ */
39
+
40
+ helpers.chop = function(str) {
41
+ if (!util.isString(str)) return '';
42
+ return utils.chop(str);
43
+ };
44
+
45
+
46
+ /**
47
+ * Truncates a string to the specified `length`, and appends
48
+ * it with an elipsis, `…`.
49
+ *
50
+ * ```handlebars
51
+ * {{ellipsis (sanitize "<span>foo bar baz</span>"), 7}}
52
+ * <!-- results in: 'foo bar…' -->
53
+ * {{ellipsis "foo bar baz", 7}}
54
+ * <!-- results in: 'foo bar…' -->
55
+ * ```
56
+ * @param {String} `str`
57
+ * @param {Number} `length` The desired length of the returned string.
58
+ * @return {String} The truncated string.
59
+ * @api public
60
+ */
61
+
62
+ helpers.ellipsis = function(str, limit) {
63
+ if (util.isString(str)) {
64
+ if (str.length <= limit) {
65
+ return str;
66
+ }
67
+ return helpers.truncate(str, limit) + '…';
68
+ }
69
+ };
70
+
71
+ /**
72
+ * Return true if `value` is a string.
73
+ *
74
+ * ```handlebars
75
+ * {{isString "foo"}}
76
+ * <!-- results in: 'true' -->
77
+ * ```
78
+ * @param {String} `value`
79
+ * @return {Boolean}
80
+ * @api public
81
+ */
82
+
83
+ helpers.isString = function(value) {
84
+ return typeof value === 'string';
85
+ };
86
+
87
+ /**
88
+ * Return the number of occurrences of `substring` within the
89
+ * given `string`.
90
+ *
91
+ * ```handlebars
92
+ * {{occurrences "foo bar foo bar baz" "foo"}}
93
+ * <!-- results in: 2 -->
94
+ * ```
95
+ * @param {String} `str`
96
+ * @param {String} `substring`
97
+ * @return {Number} Number of occurrences
98
+ * @api public
99
+ */
100
+
101
+ helpers.occurrences = function(str, substring) {
102
+ if (!util.isString(str)) return '';
103
+ var len = substring.length;
104
+ var pos = 0;
105
+ var n = 0;
106
+
107
+ while ((pos = str.indexOf(substring, pos)) > -1) {
108
+ n++;
109
+ pos += len;
110
+ }
111
+ return n;
112
+ };
113
+
114
+ /**
115
+ * Replace spaces in the given string with pluses.
116
+ *
117
+ * ```handlebars
118
+ * {{plusify "foo bar baz"}}
119
+ * <!-- results in: 'foo+bar+baz' -->
120
+ * ```
121
+ * @param {String} `str` The input string
122
+ * @return {String} Input string with spaces replaced by plus signs
123
+ * @source Stephen Way <https://github.com/stephenway>
124
+ * @api public
125
+ */
126
+
127
+ helpers.plusify = function(str, ch) {
128
+ if (!util.isString(str)) return '';
129
+ if (!util.isString(ch)) ch = ' ';
130
+ return str.split(ch).join('+');
131
+ };
132
+
133
+ /**
134
+ * Prepends the given `string` with the specified `prefix`.
135
+ *
136
+ * ```handlebars
137
+ * <!-- given that "val" is "bar" -->
138
+ * {{prepend val "foo-"}}
139
+ * <!-- results in: 'foo-bar' -->
140
+ * ```
141
+ * @param {String} `str`
142
+ * @param {String} `prefix`
143
+ * @return {String}
144
+ * @api public
145
+ */
146
+
147
+ helpers.prepend = function(str, prefix) {
148
+ return typeof str === 'string' && typeof prefix === 'string'
149
+ ? (prefix + str)
150
+ : str;
151
+ };
152
+
153
+ /**
154
+ * Render a block without processing mustache templates inside the block.
155
+ *
156
+ * ```handlebars
157
+ * {{{{#raw}}}}
158
+ * {{foo}}
159
+ * {{{{/raw}}}}
160
+ * <!-- results in: '{{foo}}' -->
161
+ * ```
162
+ *
163
+ * @param {Object} `options`
164
+ * @return {String}
165
+ * @block
166
+ * @api public
167
+ */
168
+
169
+ helpers.raw = function(options) {
170
+ var str = options.fn();
171
+ var opts = util.options(this, options);
172
+ if (opts.escape !== false) {
173
+ var idx = 0;
174
+ while (((idx = str.indexOf('{{', idx)) !== -1)) {
175
+ if (str[idx - 1] !== '\\') {
176
+ str = str.slice(0, idx) + '\\' + str.slice(idx);
177
+ }
178
+ idx += 3;
179
+ }
180
+ }
181
+ return str;
182
+ };
183
+
184
+ /**
185
+ * Remove all occurrences of `substring` from the given `str`.
186
+ *
187
+ * ```handlebars
188
+ * {{remove "a b a b a b" "a "}}
189
+ * <!-- results in: 'b b b' -->
190
+ * ```
191
+ * @param {String} `str`
192
+ * @param {String} `substring`
193
+ * @return {String}
194
+ * @api public
195
+ */
196
+
197
+ helpers.remove = function(str, ch) {
198
+ if (!util.isString(str)) return '';
199
+ if (!util.isString(ch)) return str;
200
+ return str.split(ch).join('');
201
+ };
202
+
203
+ /**
204
+ * Remove the first occurrence of `substring` from the given `str`.
205
+ *
206
+ * ```handlebars
207
+ * {{remove "a b a b a b" "a"}}
208
+ * <!-- results in: ' b a b a b' -->
209
+ * ```
210
+ * @param {String} `str`
211
+ * @param {String} `substring`
212
+ * @return {String}
213
+ * @api public
214
+ */
215
+
216
+ helpers.removeFirst = function(str, ch) {
217
+ if (!util.isString(str)) return '';
218
+ if (!util.isString(ch)) return str;
219
+ return str.replace(ch, '');
220
+ };
221
+
222
+ /**
223
+ * Replace all occurrences of substring `a` with substring `b`.
224
+ *
225
+ * ```handlebars
226
+ * {{replace "a b a b a b" "a" "z"}}
227
+ * <!-- results in: 'z b z b z b' -->
228
+ * ```
229
+ * @param {String} `str`
230
+ * @param {String} `a`
231
+ * @param {String} `b`
232
+ * @return {String}
233
+ * @api public
234
+ */
235
+
236
+ helpers.replace = function(str, a, b) {
237
+ if (!util.isString(str)) return '';
238
+ if (!util.isString(a)) return str;
239
+ if (!util.isString(b)) b = '';
240
+ return str.split(a).join(b);
241
+ };
242
+
243
+ /**
244
+ * Replace the first occurrence of substring `a` with substring `b`.
245
+ *
246
+ * ```handlebars
247
+ * {{replace "a b a b a b" "a" "z"}}
248
+ * <!-- results in: 'z b a b a b' -->
249
+ * ```
250
+ * @param {String} `str`
251
+ * @param {String} `a`
252
+ * @param {String} `b`
253
+ * @return {String}
254
+ * @api public
255
+ */
256
+
257
+ helpers.replaceFirst = function(str, a, b) {
258
+ if (!util.isString(str)) return '';
259
+ if (!util.isString(a)) return str;
260
+ if (!util.isString(b)) b = '';
261
+ return str.replace(a, b);
262
+ };
263
+
264
+ /**
265
+ * Reverse a string.
266
+ *
267
+ * ```handlebars
268
+ * {{reverse "abcde"}}
269
+ * <!-- results in: 'edcba' -->
270
+ * ```
271
+ * @param {String} `str`
272
+ * @return {String}
273
+ * @api public
274
+ */
275
+
276
+ helpers.reverse = function(str) {
277
+ if (!util.isString(str)) return '';
278
+ return str.split('').reverse().join('');
279
+ };
280
+
281
+ /**
282
+ * Sentence case the given string
283
+ *
284
+ * ```handlebars
285
+ * {{sentence "hello world. goodbye world."}}
286
+ * <!-- results in: 'Hello world. Goodbye world.' -->
287
+ * ```
288
+ * @param {String} `str`
289
+ * @return {String}
290
+ * @api public
291
+ */
292
+
293
+ helpers.sentence = function(str) {
294
+ if (!util.isString(str)) return '';
295
+ return str.replace(/((?:\S[^\.\?\!]*)[\.\?\!]*)/g, function(txt) {
296
+ return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
297
+ });
298
+ };
299
+
300
+ /**
301
+ * snake_case the characters in the given `string`.
302
+ *
303
+ * ```handlebars
304
+ * {{snakecase "a-b-c d_e"}}
305
+ * <!-- results in: 'a_b_c_d_e' -->
306
+ * ```
307
+ * @param {String} `string`
308
+ * @return {String}
309
+ * @api public
310
+ */
311
+
312
+ helpers.snakecase = function(str) {
313
+ if (!util.isString(str)) return '';
314
+ return utils.changecase(str, function(ch) {
315
+ return '_' + ch;
316
+ });
317
+ };
318
+
319
+ /**
320
+ * Split `string` by the given `character`.
321
+ *
322
+ * ```handlebars
323
+ * {{split "a,b,c" ","}}
324
+ * <!-- results in: ['a', 'b', 'c'] -->
325
+ * ```
326
+ * @param {String} `string` The string to split.
327
+ * @return {String} `character` Default is an empty string.
328
+ * @api public
329
+ */
330
+
331
+ helpers.split = function(str, ch) {
332
+ if (!util.isString(str)) return '';
333
+ if (!util.isString(ch)) ch = ',';
334
+ return str.split(ch);
335
+ };
336
+
337
+ /**
338
+ * Tests whether a string begins with the given prefix.
339
+ *
340
+ * ```handlebars
341
+ * {{#startsWith "Goodbye" "Hello, world!"}}
342
+ * Whoops
343
+ * {{else}}
344
+ * Bro, do you even hello world?
345
+ * {{/startsWith}}
346
+ * ```
347
+ * @contributor Dan Fox <http://github.com/iamdanfox>
348
+ * @param {String} `prefix`
349
+ * @param {String} `testString`
350
+ * @param {String} `options`
351
+ * @return {String}
352
+ * @block
353
+ * @api public
354
+ */
355
+
356
+ helpers.startsWith = function(prefix, str, options) {
357
+ var args = [].slice.call(arguments);
358
+ options = args.pop();
359
+ if (util.isString(str) && str.indexOf(prefix) === 0) {
360
+ return options.fn(this);
361
+ }
362
+ if (typeof options.inverse === 'function') {
363
+ return options.inverse(this);
364
+ }
365
+ return '';
366
+ };
367
+
368
+ /**
369
+ * Title case the given string.
370
+ *
371
+ * ```handlebars
372
+ * {{titleize "this is title case"}}
373
+ * <!-- results in: 'This Is Title Case' -->
374
+ * ```
375
+ * @param {String} `str`
376
+ * @return {String}
377
+ * @api public
378
+ */
379
+
380
+ helpers.titleize = function(str) {
381
+ if (!util.isString(str)) return '';
382
+ var title = str.replace(/[- _]+/g, ' ');
383
+ var words = title.split(' ');
384
+ var len = words.length;
385
+ var res = [];
386
+ var i = 0;
387
+ while (len--) {
388
+ var word = words[i++];
389
+ res.push(exports.capitalize(word));
390
+ }
391
+ return res.join(' ');
392
+ };
393
+
394
+ /**
395
+ * Removes extraneous whitespace from the beginning and end
396
+ * of a string.
397
+ *
398
+ * ```handlebars
399
+ * {{trim " ABC "}}
400
+ * <!-- results in: 'ABC' -->
401
+ * ```
402
+ * @param {String} `string` The string to trim.
403
+ * @return {String}
404
+ * @api public
405
+ */
406
+
407
+ helpers.trim = function(str) {
408
+ return typeof str === 'string' ? str.trim() : '';
409
+ };
410
+
411
+ /**
412
+ * Removes extraneous whitespace from the beginning of a string.
413
+ *
414
+ * ```handlebars
415
+ * {{trim " ABC "}}
416
+ * <!-- results in: 'ABC ' -->
417
+ * ```
418
+ * @param {String} `string` The string to trim.
419
+ * @return {String}
420
+ * @api public
421
+ */
422
+
423
+ helpers.trimLeft = function(str) {
424
+ if (util.isString(str)) {
425
+ return str.replace(/^\s+/, '');
426
+ }
427
+ };
428
+
429
+ /**
430
+ * Removes extraneous whitespace from the end of a string.
431
+ *
432
+ * ```handlebars
433
+ * {{trimRight " ABC "}}
434
+ * <!-- results in: ' ABC' -->
435
+ * ```
436
+ * @param {String} `string` The string to trim.
437
+ * @return {String}
438
+ * @api public
439
+ */
440
+
441
+ helpers.trimRight = function(str) {
442
+ if (util.isString(str)) {
443
+ return str.replace(/\s+$/, '');
444
+ }
445
+ };
446
+
447
+ /**
448
+ * Truncate a string to the specified `length`. Also see [ellipsis](#ellipsis).
449
+ *
450
+ * ```handlebars
451
+ * truncate("foo bar baz", 7);
452
+ * <!-- results in: 'foo bar' -->
453
+ * truncate(sanitize("<span>foo bar baz</span>", 7));
454
+ * <!-- results in: 'foo bar' -->
455
+ * ```
456
+ * @param {String} `str`
457
+ * @param {Number} `limit` The desired length of the returned string.
458
+ * @param {String} `suffix` Optionally supply a string to use as a suffix to
459
+ * denote when the string has been truncated. Otherwise an ellipsis (`…`) will be used.
460
+ * @return {String} The truncated string.
461
+ * @api public
462
+ */
463
+
464
+ helpers.truncate = function(str, limit, suffix) {
465
+ if (util.isString(str)) {
466
+ if (typeof suffix !== 'string') {
467
+ suffix = '';
468
+ }
469
+ if (str.length > limit) {
470
+ return str.slice(0, limit - suffix.length) + suffix;
471
+ }
472
+ return str;
473
+ }
474
+ };
475
+
476
+ /**
477
+ * Truncate a string to have the specified number of words.
478
+ * Also see [truncate](#truncate).
479
+ *
480
+ * ```handlebars
481
+ * truncateWords("foo bar baz", 1);
482
+ * <!-- results in: 'foo…' -->
483
+ * truncateWords("foo bar baz", 2);
484
+ * <!-- results in: 'foo bar…' -->
485
+ * truncateWords("foo bar baz", 3);
486
+ * <!-- results in: 'foo bar baz' -->
487
+ * ```
488
+ * @param {String} `str`
489
+ * @param {Number} `limit` The desired length of the returned string.
490
+ * @param {String} `suffix` Optionally supply a string to use as a suffix to
491
+ * denote when the string has been truncated.
492
+ * @return {String} The truncated string.
493
+ * @api public
494
+ */
495
+
496
+ helpers.truncateWords = function(str, count, suffix) {
497
+ if (util.isString(str) && isNumber(count)) {
498
+ if (typeof suffix !== 'string') {
499
+ suffix = '…';
500
+ }
501
+
502
+ var num = Number(count);
503
+ var arr = str.split(/[ \t]/);
504
+ if (num > arr.length) {
505
+ arr = arr.slice(0, num);
506
+ }
507
+
508
+ var val = arr.join(' ').trim();
509
+ return val + suffix;
510
+ }
511
+ };