ultimate-base 0.3.1.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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
- ###