ultimate-base 0.3.1.1 → 0.3.2

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 (35) hide show
  1. data/Gemfile.lock +15 -15
  2. data/app/assets/javascripts/ultimate/backbone/lib/backbone.js +70 -56
  3. data/app/assets/javascripts/ultimate/backbone/model.js.coffee +2 -2
  4. data/app/assets/javascripts/ultimate/backbone/view.js.coffee +5 -4
  5. data/app/assets/javascripts/ultimate/backbone/views/typed-fields.js.coffee +1 -1
  6. data/app/assets/javascripts/ultimate/helpers/asset_tag.js.coffee +21 -19
  7. data/app/assets/javascripts/ultimate/helpers/form_options.js.coffee +65 -0
  8. data/app/assets/javascripts/ultimate/helpers/form_tag.js.coffee +177 -0
  9. data/app/assets/javascripts/ultimate/helpers/javascript.js.coffee +31 -0
  10. data/app/assets/javascripts/ultimate/helpers/record_tag.js.coffee +29 -15
  11. data/app/assets/javascripts/ultimate/helpers/tag.js.coffee +7 -3
  12. data/app/assets/javascripts/ultimate/helpers/url.js.coffee +62 -7
  13. data/app/assets/javascripts/ultimate/jquery-plugin-adapter.js.coffee +1 -0
  14. data/app/assets/javascripts/ultimate/jquery-plugin-class.js.coffee +35 -16
  15. data/app/assets/javascripts/ultimate/jquery.base.js.coffee +1 -1
  16. data/app/assets/javascripts/ultimate/underscore/underscore.js +292 -192
  17. data/app/assets/javascripts/ultimate/underscore/underscore.outcasts.js.coffee +27 -2
  18. data/app/assets/javascripts/ultimate/underscore/underscore.string.js +4 -4
  19. data/app/assets/stylesheets/polyfills/PIE.htc +81 -81
  20. data/app/assets/stylesheets/polyfills/boxsizing.htc +255 -54
  21. data/app/assets/stylesheets/ultimate/mixins/_vendors.scss +9 -0
  22. data/app/assets/stylesheets/ultimate/mixins/css3.scss +39 -28
  23. data/app/assets/stylesheets/ultimate/mixins/microstructures.scss +32 -6
  24. data/lib/ultimate/base/version.rb +1 -1
  25. data/test/javascripts/tests/helpers/asset_tag_test.js.coffee +1 -1
  26. data/test/javascripts/tests/helpers/form_options_test.js.coffee +96 -0
  27. data/test/javascripts/tests/helpers/form_tag_test.js.coffee +225 -0
  28. data/test/javascripts/tests/helpers/javascript_test.js.coffee +25 -0
  29. data/test/javascripts/tests/helpers/record_tag_test.js.coffee +5 -3
  30. data/test/javascripts/tests/helpers/tag_test.js.coffee +22 -17
  31. data/test/javascripts/tests/helpers/url_test.js.coffee +50 -6
  32. data/test/javascripts/tests/underscore/underscore.outcasts.test.js.coffee +9 -0
  33. metadata +8 -4
  34. data/app/assets/javascripts/ultimate/helpers/translation.js.coffee +0 -97
  35. data/test/javascripts/tests/helpers/translation_test.js.coffee +0 -140
@@ -0,0 +1,25 @@
1
+ #= require ultimate/underscore/underscore
2
+ #= require ultimate/underscore/underscore.string
3
+ #= require ultimate/underscore/underscore.outcasts
4
+ #= require ultimate/helpers/javascript
5
+
6
+ module "Ultimate.Helpers.Javascript"
7
+
8
+ _.extend @, Ultimate.Helpers.Javascript
9
+
10
+ test "escape_javascript", ->
11
+ strictEqual escape_javascript(null), ''
12
+ equal escape_javascript('This "thing" is really\n netos\''), 'This \\"thing\\" is really\\n netos\\\''
13
+ equal escape_javascript('backslash\\test'), 'backslash\\\\test'
14
+ equal escape_javascript('dont </close> tags'), 'dont <\\/close> tags'
15
+ # equal escape_javascript('unicode \\342\\200\\250 newline'), 'unicode &#x2028; newline'
16
+ # equal escape_javascript('unicode \\342\\200\\251 newline'), 'unicode &#x2029; newline'
17
+ equal j('dont </close> tags'), 'dont <\\/close> tags'
18
+ equal escape_javascript('\'quoted\' "double-quoted" new-line:\n </closed>'), '\\\'quoted\\\' \\"double-quoted\\" new-line:\\n <\\/closed>'
19
+
20
+ test "javascript_tag", ->
21
+ equal javascript_tag("alert('hello')"), "<script>\n//<![CDATA[\nalert('hello')\n//]]>\n</script>"
22
+ equal javascript_tag("alert('hello')", id: "the_js_tag"), "<script id=\"the_js_tag\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>"
23
+
24
+ test "javascript_cdata_section", ->
25
+ equal javascript_cdata_section("alert('hello')"), "\n//<![CDATA[\nalert('hello')\n//]]>\n"
@@ -17,6 +17,7 @@ singular = 'record_tag_post'
17
17
 
18
18
  test "dom_class", ->
19
19
  equal dom_class(record), singular
20
+ equal dom_class(record.constructor.name), singular
20
21
  equal dom_class(record, "custom_prefix"), "custom_prefix_#{singular}"
21
22
 
22
23
  test "dom_id", ->
@@ -37,8 +38,8 @@ test "content_tag_for", ->
37
38
  "<tr class=\"#{singular} special\" id=\"#{singular}_45\" style=\"background-color: #f0f0f0\"></tr>"
38
39
  equal content_tag_for('tr', record, 'archived', class: "special", style: "background-color: #f0f0f0"),
39
40
  "<tr class=\"archived_#{singular} special\" id=\"archived_#{singular}_45\" style=\"background-color: #f0f0f0\"></tr>"
40
- equal content_tag_for('tr', record, -> record.body),
41
- "<tr class=\"#{singular}\" id=\"#{singular}_45\">What a wonderful world!</tr>"
41
+ equal content_tag_for('tr', record, -> "<b>#{record.body}</b>"),
42
+ "<tr class=\"#{singular}\" id=\"#{singular}_45\"><b>What a wonderful world!</b></tr>"
42
43
  post_1 = new RecordTagPost(id: 101, body: "Hello!")
43
44
  post_2 = new RecordTagPost(id: 102, body: "World!")
44
45
  equal content_tag_for('li', [post_1, post_2], (post) -> post.body),
@@ -48,8 +49,9 @@ test "content_tag_for", ->
48
49
  deepEqual options, class: 'important'
49
50
 
50
51
  test "div_for", ->
52
+ record.id = 36
51
53
  equal div_for(record, class: 'special', -> record.body),
52
- "<div class=\"#{singular} special\" id=\"#{singular}_45\">What a wonderful world!</div>"
54
+ "<div class=\"#{singular} special\" id=\"#{singular}_36\">What a wonderful world!</div>"
53
55
  post_1 = new RecordTagPost(id: 101, body: "Hello!")
54
56
  post_2 = new RecordTagPost(id: 102, body: "World!")
55
57
  equal div_for([post_1, post_2], (post) -> post.body),
@@ -10,24 +10,29 @@ test "tag_options", ->
10
10
  strictEqual tag_options(), ""
11
11
  strictEqual tag_options({}), ""
12
12
  ok /title="Some title"/.test tag_options(class: "some-class", title: "Some title")
13
- strictEqual tag_options(class: ["song", "play>"]), ' class="song play&gt;"'
14
- strictEqual tag_options(disabled: true, itemscope: false, multiple: true, readonly: true), ' disabled="disabled" multiple="multiple" readonly="readonly"'
15
- strictEqual tag_options(data: {remote: true}, role: "ajax"), ' data-remote="true" role="ajax"'
16
- strictEqual tag_options(data: {inner: {section: true}}), ' data-inner="{&quot;section&quot;:true}"'
17
- strictEqual tag_options(data: {inner: {section: true}}, false), ' data-inner="{"section":true}"'
18
- strictEqual tag_options(included: ''), ' included=""'
13
+ equal tag_options(class: ["song", "play>"]), ' class="song play&gt;"'
14
+ equal tag_options(disabled: true, itemscope: false, multiple: true, readonly: true), ' disabled="disabled" multiple="multiple" readonly="readonly"'
15
+ equal tag_options(data: {remote: true}, role: "ajax"), ' data-remote="true" role="ajax"'
16
+ equal tag_options(data: {inner: {section: true}}), ' data-inner="{&quot;section&quot;:true}"'
17
+ equal tag_options(data: {inner: {section: true}}, false), ' data-inner="{"section":true}"'
18
+ equal tag_options(included: ''), ' included=""'
19
19
 
20
20
  test "tag", ->
21
- strictEqual tag('br'), '<br />'
22
- strictEqual tag('br', null, true), '<br>'
23
- strictEqual tag('input', type: 'text', disabled: true), '<input disabled="disabled" type="text" />'
24
- strictEqual tag('img', src: 'open & shut.png'), '<img src="open &amp; shut.png" />'
25
- # strictEqual tag("img", {src: "open &amp; shut.png"}, false, false), '<img src="open &amp; shut.png" />'
26
- # strictEqual tag("div", data: {name: 'Stephen', city_state: "(Chicago IL)"}), '<div data-name="Stephen" data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]" />'
21
+ equal tag('br'), '<br />'
22
+ equal tag('br', null, true), '<br>'
23
+ equal tag('input', type: 'text', disabled: true), '<input disabled="disabled" type="text" />'
24
+ equal tag('img', src: 'open & shut.png'), '<img src="open &amp; shut.png" />'
25
+ equal tag("img", {src: "open &amp; shut.png"}, false, false), '<img src="open &amp; shut.png" />'
26
+ equal tag("div", data: {name: 'Stephen', city_state: ['Chicago', 'IL']}), '<div data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]" data-name="Stephen" />'
27
27
 
28
28
  test "content_tag", ->
29
- strictEqual content_tag('div', '', class: ['some', 'class']), '<div class="some class"></div>'
30
- strictEqual content_tag('div', '<Inner content>', class: 'some class'), '<div class="some class">&lt;Inner content&gt;</div>'
31
- strictEqual content_tag('div', '<Inner content>', class: 'some class', false), '<div class="some class"><Inner content></div>'
32
- strictEqual content_tag('div', class: 'some class', -> '<Inner content>'), '<div class="some class">&lt;Inner content&gt;</div>'
33
- strictEqual content_tag('div', class: 'some class', false, -> '<Inner content>'), '<div class="some class">&lt;Inner content&gt;</div>'
29
+ equal content_tag('div', '', class: ['some', 'class']), '<div class="some class"></div>'
30
+ equal content_tag('div', '<Inner content>', class: 'some class'), '<div class="some class">&lt;Inner content&gt;</div>'
31
+ equal content_tag('div', '<Inner content>', class: 'some class', false), '<div class="some class"><Inner content></div>'
32
+ equal content_tag('div', class: 'some class', -> '<Inner content>'), '<div class="some class">&lt;Inner content&gt;</div>'
33
+ equal content_tag('div', class: 'some class', false, -> '<Inner content>'), '<div class="some class">&lt;Inner content&gt;</div>'
34
+
35
+ test "cdata_section", ->
36
+ equal cdata_section("<hello world>"), "<![CDATA[<hello world>]]>"
37
+ equal cdata_section("hello]]>world"), "<![CDATA[hello]]]]><![CDATA[>world]]>"
38
+ equal cdata_section("hello]]>world]]>again"), "<![CDATA[hello]]]]><![CDATA[>world]]]]><![CDATA[>again]]>"
@@ -20,9 +20,53 @@ test "url_for", ->
20
20
  strictEqual url_for("/back"), '/back'
21
21
 
22
22
  test "link_to", ->
23
- strictEqual link_to('Hello', 'http://www.example.com'), '<a href="http://www.example.com">Hello</a>'
24
- strictEqual link_to('Test Link', '/'), '<a href="/">Test Link</a>'
25
- strictEqual link_to(null, 'http://ya.ru/'), '<a href="http://ya.ru/">http://ya.ru/</a>'
26
- strictEqual link_to('caption'), '<a href="javascript:;">caption</a>'
27
- strictEqual link_to("Hello", "http://www.example.com", class: "red", data: {confirm: 'You cant possibly be sure,\n can you?'}),
28
- '<a class="red" data-confirm="You cant possibly be sure,\n can you?" href="http://www.example.com">Hello</a>'
23
+ equal link_to('Hello', 'http://www.example.com'), '<a href="http://www.example.com">Hello</a>'
24
+ equal link_to('Test Link', '/'), '<a href="/">Test Link</a>'
25
+ equal link_to(null, 'http://ya.ru/'), '<a href="http://ya.ru/">http://ya.ru/</a>'
26
+ equal link_to('caption'), '<a href="javascript:;">caption</a>'
27
+ equal link_to('caption', null, class: 'link'), '<a class="link" href="javascript:;">caption</a>'
28
+ equal link_to("Hello", "http://www.example.com", class: "red", data: {confirm: 'You cant possibly be sure,\n can you?'}),
29
+ '<a class="red" data-confirm="You cant possibly be sure,\n can you?" href="http://www.example.com">Hello</a>'
30
+ equal link_to(null, -> 'caption'), '<a href="javascript:;">caption</a>'
31
+ equal link_to(-> 'caption'), '<a href="javascript:;">caption</a>'
32
+
33
+ test "link_to_js", ->
34
+ equal link_to_js('caption'), '<a href="javascript:;">caption</a>'
35
+ equal link_to_js('caption', class: 'link'), '<a class="link" href="javascript:;">caption</a>'
36
+ equal link_to_js("Hello", class: "red", data: {confirm: 'You cant possibly be sure,\n can you?'}),
37
+ '<a class="red" data-confirm="You cant possibly be sure,\n can you?" href="javascript:;">Hello</a>'
38
+ equal link_to_js(null, -> 'caption'), '<a href="javascript:;">caption</a>'
39
+ equal link_to_js(class: 'link', -> 'caption'), '<a class="link" href="javascript:;">caption</a>'
40
+ equal link_to_js(-> 'caption'), '<a href="javascript:;">caption</a>'
41
+
42
+ test "mail_to", ->
43
+ equal mail_to("david@loudthinking.com"),
44
+ '<a href="mailto:david@loudthinking.com">david@loudthinking.com</a>'
45
+ equal mail_to("david@loudthinking.com", "David Heinemeier Hansson"),
46
+ '<a href="mailto:david@loudthinking.com">David Heinemeier Hansson</a>'
47
+ equal mail_to("david@loudthinking.com", "David Heinemeier Hansson", class: "admin"),
48
+ '<a class="admin" href="mailto:david@loudthinking.com">David Heinemeier Hansson</a>'
49
+ equal mail_to("me@domain.com", "My email", encode: "javascript"),
50
+ "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>"
51
+ # equal mail_to("unicode@example.com", "únicode", encode: "javascript"),
52
+ # "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%5c%22%3e%c3%ba%6e%69%63%6f%64%65%3c%5c%2f%61%3e%27%29%3b'))</script>"
53
+ equal mail_to("me@example.com", "My email", cc: "ccaddress@example.com", bcc: "bccaddress@example.com", subject: "This is an example email", body: "This is the body of the message."),
54
+ '<a href="mailto:me@example.com?cc=ccaddress%40example.com&amp;bcc=bccaddress%40example.com&amp;body=This%20is%20the%20body%20of%20the%20message.&amp;subject=This%20is%20an%20example%20email">My email</a>'
55
+ equal mail_to('feedback@example.com', '<img src="/feedback.png" />'),
56
+ '<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>'
57
+ equal mail_to("me@domain.com", "My email", encode: "hex"),
58
+ '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>'
59
+ equal mail_to("me@domain.com", null, encode: "hex"),
60
+ '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">&#109;&#101;&#64;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;</a>'
61
+ equal mail_to("wolfgang@stufenlos.net", null, replace_at: "(at)", replace_dot: "(dot)"),
62
+ '<a href="mailto:wolfgang@stufenlos.net">wolfgang(at)stufenlos(dot)net</a>'
63
+ equal mail_to("me@domain.com", null, encode: "hex", replace_at: "(at)"),
64
+ '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">&#109;&#101;&#40;&#97;&#116;&#41;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;</a>'
65
+ equal mail_to("me@domain.com", "My email", encode: "hex", replace_at: "(at)"),
66
+ '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>'
67
+ equal mail_to("me@domain.com", null, encode: "hex", replace_at: "(at)", replace_dot: "(dot)"),
68
+ '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">&#109;&#101;&#40;&#97;&#116;&#41;&#100;&#111;&#109;&#97;&#105;&#110;&#40;&#100;&#111;&#116;&#41;&#99;&#111;&#109;</a>'
69
+ equal mail_to("me@domain.com", "My email", encode: "javascript", replace_at: "(at)", replace_dot: "(dot)"),
70
+ "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>"
71
+ equal mail_to("me@domain.com", null, encode: "javascript", replace_at: "(at)", replace_dot: "(dot)"),
72
+ "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%5c%2f%61%3e%27%29%3b'))</script>"
@@ -36,3 +36,12 @@ test "invert", ->
36
36
  deepEqual _.invert(obj), {1: ['a', 'd'], 2: 'b', 0: 'c', 'e-1': '2'}
37
37
  deepEqual _.invert(_.invert(obj)), {a: '1', b: '2', c: '0', d: '1', 2: 'e-1'}
38
38
  deepEqual _.invert(), {}
39
+
40
+ test "scan", ->
41
+ a = "cruel world"
42
+ deepEqual _.scan(a, /\w+/) , ["cruel", "world"]
43
+ deepEqual _.scan(a, /.../) , ["cru", "el ", "wor"]
44
+ deepEqual _.scan(a, /(...)/) , [["cru"], ["el "], ["wor"]]
45
+ deepEqual _.scan(a, /(..)(..)/) , [["cr", "ue"], ["l ", "wo"]]
46
+ equal _.scan(a, /\w+/, (w) -> "<<#{w}>> ").join(''), '<<cruel>> <<world>> '
47
+ equal _.scan(a, /(.)(.)/, (x, y) -> y + x).join(''), 'rceu lowlr'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ultimate-base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-28 00:00:00.000000000 Z
12
+ date: 2012-10-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -92,10 +92,12 @@ files:
92
92
  - app/assets/javascripts/ultimate/helpers/asset_tag.js.coffee
93
93
  - app/assets/javascripts/ultimate/helpers/base.js.coffee
94
94
  - app/assets/javascripts/ultimate/helpers/decor.js.coffee
95
+ - app/assets/javascripts/ultimate/helpers/form_options.js.coffee
96
+ - app/assets/javascripts/ultimate/helpers/form_tag.js.coffee
97
+ - app/assets/javascripts/ultimate/helpers/javascript.js.coffee
95
98
  - app/assets/javascripts/ultimate/helpers/number.js.coffee
96
99
  - app/assets/javascripts/ultimate/helpers/record_tag.js.coffee
97
100
  - app/assets/javascripts/ultimate/helpers/tag.js.coffee
98
- - app/assets/javascripts/ultimate/helpers/translation.js.coffee
99
101
  - app/assets/javascripts/ultimate/helpers/url.js.coffee
100
102
  - app/assets/javascripts/ultimate/improves/datepicker.js.coffee
101
103
  - app/assets/javascripts/ultimate/improves/devise.js.coffee
@@ -182,10 +184,12 @@ files:
182
184
  - test/javascripts/test_helper.js.coffee
183
185
  - test/javascripts/tests/base_test.js.coffee
184
186
  - test/javascripts/tests/helpers/asset_tag_test.js.coffee
187
+ - test/javascripts/tests/helpers/form_options_test.js.coffee
188
+ - test/javascripts/tests/helpers/form_tag_test.js.coffee
189
+ - test/javascripts/tests/helpers/javascript_test.js.coffee
185
190
  - test/javascripts/tests/helpers/number_test.js.coffee
186
191
  - test/javascripts/tests/helpers/record_tag_test.js.coffee
187
192
  - test/javascripts/tests/helpers/tag_test.js.coffee
188
- - test/javascripts/tests/helpers/translation_test.js.coffee
189
193
  - test/javascripts/tests/helpers/url_test.js.coffee
190
194
  - test/javascripts/tests/helpers_test.js.coffee
191
195
  - test/javascripts/tests/improves/i18n-lite_test.js.coffee
@@ -1,97 +0,0 @@
1
- #= require ./base
2
- #= require ./tag
3
-
4
- #module I18n
5
- # class ExceptionHandler
6
- # include Module.new {
7
- # def call(exception, locale, key, options)
8
- # exception.is_a?(MissingTranslation) && options[:rescue_format] == :html ? super.html_safe : super
9
- # end
10
- # }
11
- # end
12
- #end
13
-
14
- @Ultimate.Helpers.Translation =
15
-
16
- ###**
17
- * Delegates to <tt>I18n#translate</tt> but also performs three additional functions.
18
- *
19
- * First, it'll pass the <tt>:rescue_format => :html</tt> option to I18n so that any
20
- * thrown +MissingTranslation+ messages will be turned into inline spans that
21
- *
22
- * * have a "translation-missing" class set,
23
- * * contain the missing key as a title attribute and
24
- * * a titleized version of the last key segment as a text.
25
- *
26
- * E.g. the value returned for a missing translation key :"blog.post.title" will be
27
- * <span class="translation_missing" title="translation missing: en.blog.post.title">Title</span>.
28
- * This way your views will display rather reasonable strings but it will still
29
- * be easy to spot missing translations.
30
- *
31
- * Second, it'll scope the key by the current partial if the key starts
32
- * with a period. So if you call <tt>translate(".foo")</tt> from the
33
- * <tt>people/index.html.erb</tt> template, you'll actually be calling
34
- * <tt>I18n.translate("people.index.foo")</tt>. This makes it less repetitive
35
- * to translate many keys within the same partials and gives you a simple framework
36
- * for scoping them consistently. If you don't prepend the key with a period,
37
- * nothing is converted.
38
- *
39
- * Third, it'll mark the translation as safe HTML if the key has the suffix
40
- * "_html" or the last element of the key is the word "html". For example,
41
- * calling translate("footer_html") or translate("footer.html") will return
42
- * a safe HTML string that won't be escaped by other HTML helper methods. This
43
- * naming convention helps to identify translations that include HTML tags so that
44
- * you know what kind of output to expect when you call translate in a template.
45
- ###
46
- translate: (key, options = {}) ->
47
- _.extend(options, rescue_format: 'html') unless _.has(options, 'rescue_format')
48
- options['default'] = @wrap_translate_defaults(options['default']) if options['default']
49
- if @html_safe_translation_key(key)
50
- html_safe_options = _.clone(options)
51
- options.except(I18n.RESERVED_KEYS).each do |name, value|
52
- unless name == :count && value.is_a?(Numeric)
53
- html_safe_options[name] = ERB::Util.html_escape(value.to_s)
54
- end
55
- end
56
- translation = I18n.translate(scope_key_by_partial(key), html_safe_options)
57
-
58
- translation.respond_to?(:html_safe) ? translation.html_safe : translation
59
- else
60
- I18n.translate(scope_key_by_partial(key), options)
61
- end
62
- end
63
- alias :t :translate
64
-
65
- # Delegates to <tt>I18n.localize</tt> with no additional functionality.
66
- #
67
- # See http://rubydoc.info/github/svenfuchs/i18n/master/I18n/Backend/Base:localize
68
- # for more information.
69
- localize: ->
70
- I18n.localize(arguments...)
71
-
72
- l: -> @localize(arguments...)
73
-
74
- # private
75
-
76
- scope_key_by_partial: (key) ->
77
- if /^\./.test(key)
78
- if @virtual_path?
79
- @virtual_path.replace(/_/g, ".") + key
80
- else
81
- throw new Error("Cannot use t(#{key.inspect}) shortcut because path is not available")
82
- else
83
- key
84
-
85
- html_safe_translation_key: (key) ->
86
- /(\b|_|\.)html$/.test(key)
87
-
88
- wrap_translate_defaults: (defaults) ->
89
- new_defaults = []
90
- defaults = _.toArray(defaults)
91
- while key = defaults.shift()
92
- if _.isString(key)
93
- new_defaults.push (_, options) -> @translate(key, _.extend(options, default: defaults))
94
- break
95
- else
96
- new_defaults.push key
97
- new_defaults
@@ -1,140 +0,0 @@
1
- ###
2
- require 'abstract_unit'
3
-
4
- class TranslationHelperTest < ActiveSupport::TestCase
5
- include ActionView::Helpers::TagHelper
6
- include ActionView::Helpers::TranslationHelper
7
-
8
- attr_reader :request, :view
9
-
10
- def setup
11
- I18n.backend.store_translations(:en,
12
- :translations => {
13
- :templates => {
14
- :found => { :foo => 'Foo' },
15
- :array => { :foo => { :bar => 'Foo Bar' } },
16
- :default => { :foo => 'Foo' }
17
- },
18
- :foo => 'Foo',
19
- :hello => '<a>Hello World</a>',
20
- :html => '<a>Hello World</a>',
21
- :hello_html => '<a>Hello World</a>',
22
- :interpolated_html => '<a>Hello %{word}</a>',
23
- :array_html => %w(foo bar),
24
- :array => %w(foo bar),
25
- :count_html => {
26
- :one => '<a>One %{count}</a>',
27
- :other => '<a>Other %{count}</a>'
28
- }
29
- }
30
- )
31
- @view = ::ActionView::Base.new(ActionController::Base.view_paths, {})
32
- end
33
-
34
- def test_delegates_to_i18n_setting_the_rescue_format_option_to_html
35
- I18n.expects(:translate).with(:foo, :locale => 'en', :rescue_format => :html).returns("")
36
- translate :foo, :locale => 'en'
37
- end
38
-
39
- def test_delegates_localize_to_i18n
40
- @time = Time.utc(2008, 7, 8, 12, 18, 38)
41
- I18n.expects(:localize).with(@time)
42
- localize @time
43
- end
44
-
45
- def test_returns_missing_translation_message_wrapped_into_span
46
- expected = '<span class="translation_missing" title="translation missing: en.translations.missing">Missing</span>'
47
- assert_equal expected, translate(:"translations.missing")
48
- assert_equal true, translate(:"translations.missing").html_safe?
49
- end
50
-
51
- def test_returns_missing_translation_message_using_nil_as_rescue_format
52
- expected = 'translation missing: en.translations.missing'
53
- assert_equal expected, translate(:"translations.missing", :rescue_format => nil)
54
- assert_equal false, translate(:"translations.missing", :rescue_format => nil).html_safe?
55
- end
56
-
57
- def test_i18n_translate_defaults_to_nil_rescue_format
58
- expected = 'translation missing: en.translations.missing'
59
- assert_equal expected, I18n.translate(:"translations.missing")
60
- assert_equal false, I18n.translate(:"translations.missing").html_safe?
61
- end
62
-
63
- def test_translation_returning_an_array
64
- expected = %w(foo bar)
65
- assert_equal expected, translate(:"translations.array")
66
- end
67
-
68
- def test_finds_translation_scoped_by_partial
69
- assert_equal 'Foo', view.render(:file => 'translations/templates/found').strip
70
- end
71
-
72
- def test_finds_array_of_translations_scoped_by_partial
73
- assert_equal 'Foo Bar', @view.render(:file => 'translations/templates/array').strip
74
- end
75
-
76
- def test_default_lookup_scoped_by_partial
77
- assert_equal 'Foo', view.render(:file => 'translations/templates/default').strip
78
- end
79
-
80
- def test_missing_translation_scoped_by_partial
81
- expected = '<span class="translation_missing" title="translation missing: en.translations.templates.missing.missing">Missing</span>'
82
- assert_equal expected, view.render(:file => 'translations/templates/missing').strip
83
- end
84
-
85
- def test_translate_does_not_mark_plain_text_as_safe_html
86
- assert_equal false, translate(:'translations.hello').html_safe?
87
- end
88
-
89
- def test_translate_marks_translations_named_html_as_safe_html
90
- assert translate(:'translations.html').html_safe?
91
- end
92
-
93
- def test_translate_marks_translations_with_a_html_suffix_as_safe_html
94
- assert translate(:'translations.hello_html').html_safe?
95
- end
96
-
97
- def test_translate_escapes_interpolations_in_translations_with_a_html_suffix
98
- assert_equal '<a>Hello &lt;World&gt;</a>', translate(:'translations.interpolated_html', :word => '<World>')
99
- assert_equal '<a>Hello &lt;World&gt;</a>', translate(:'translations.interpolated_html', :word => stub(:to_s => "<World>"))
100
- end
101
-
102
- def test_translate_with_html_count
103
- assert_equal '<a>One 1</a>', translate(:'translations.count_html', :count => 1)
104
- assert_equal '<a>Other 2</a>', translate(:'translations.count_html', :count => 2)
105
- assert_equal '<a>Other &lt;One&gt;</a>', translate(:'translations.count_html', :count => '<One>')
106
- end
107
-
108
- def test_translation_returning_an_array_ignores_html_suffix
109
- assert_equal ["foo", "bar"], translate(:'translations.array_html')
110
- end
111
-
112
- def test_translate_with_default_named_html
113
- translation = translate(:'translations.missing', :default => :'translations.hello_html')
114
- assert_equal '<a>Hello World</a>', translation
115
- assert_equal true, translation.html_safe?
116
- end
117
-
118
- def test_translate_with_two_defaults_named_html
119
- translation = translate(:'translations.missing', :default => [:'translations.missing_html', :'translations.hello_html'])
120
- assert_equal '<a>Hello World</a>', translation
121
- assert_equal true, translation.html_safe?
122
- end
123
-
124
- def test_translate_with_last_default_named_html
125
- translation = translate(:'translations.missing', :default => [:'translations.missing', :'translations.hello_html'])
126
- assert_equal '<a>Hello World</a>', translation
127
- assert_equal true, translation.html_safe?
128
- end
129
-
130
- def test_translate_with_string_default
131
- translation = translate(:'translations.missing', default: 'A Generic String')
132
- assert_equal 'A Generic String', translation
133
- end
134
-
135
- def test_translate_with_array_of_string_defaults
136
- translation = translate(:'translations.missing', default: ['A Generic String', 'Second generic string'])
137
- assert_equal 'A Generic String', translation
138
- end
139
- end
140
- ###