fortitude 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.fix_bundler_for_jruby_17 +26 -0
  3. data/.gitignore +1 -0
  4. data/.travis.yml +33 -40
  5. data/CHANGES.md +44 -0
  6. data/CONTRIBUTORS.md +26 -0
  7. data/Rakefile +1 -1
  8. data/ext/com/fortituderuby/ext/fortitude/FortitudeNativeLibrary.java +45 -33
  9. data/ext/fortitude_native_ext/fortitude_native_ext.c +23 -23
  10. data/fortitude.gemspec +25 -8
  11. data/lib/fortitude/erector.rb +26 -18
  12. data/lib/fortitude/errors.rb +15 -4
  13. data/lib/fortitude/extensions/fortitude_ruby_ext.rb +35 -10
  14. data/lib/fortitude/rails/helpers.rb +59 -2
  15. data/lib/fortitude/rails/railtie.rb +238 -157
  16. data/lib/fortitude/rails/renderer.rb +15 -0
  17. data/lib/fortitude/rails/rendering_methods.rb +46 -33
  18. data/lib/fortitude/rails/template_handler.rb +49 -18
  19. data/lib/fortitude/rails/yielded_object_outputter.rb +3 -2
  20. data/lib/fortitude/rendering_context.rb +14 -5
  21. data/lib/fortitude/support/method_overriding.rb +90 -0
  22. data/lib/fortitude/support/staticized_method.rb +12 -0
  23. data/lib/fortitude/version.rb +1 -1
  24. data/lib/fortitude/widget/content.rb +4 -2
  25. data/lib/fortitude/widget/files.rb +17 -11
  26. data/lib/fortitude/widget/helpers.rb +7 -1
  27. data/lib/fortitude/widget/integration.rb +4 -0
  28. data/lib/fortitude/widget/localization.rb +63 -4
  29. data/lib/fortitude/widget/rendering.rb +17 -10
  30. data/lib/fortitude_jruby_native_ext.jar +0 -0
  31. data/spec/helpers/fortitude_rails_helpers.rb +26 -4
  32. data/spec/rails/capture_system_spec.rb +1 -1
  33. data/spec/rails/class_loading_system_spec.rb +16 -2
  34. data/spec/rails/complex_helpers_system_spec.rb +29 -0
  35. data/spec/rails/data_passing_system_spec.rb +2 -2
  36. data/spec/rails/development_mode_system_spec.rb +1 -1
  37. data/spec/rails/erector_coexistence_system_spec.rb +1 -1
  38. data/spec/rails/helpers_system_spec.rb +20 -2
  39. data/spec/rails/layouts_system_spec.rb +1 -1
  40. data/spec/rails/rendering_system_spec.rb +4 -4
  41. data/spec/rails/rules_system_spec.rb +2 -2
  42. data/spec/rails/templates/class_loading_system_spec/app/views/some_namespace/some_other_namespace/placeholder.rb +5 -0
  43. data/spec/rails/templates/complex_helpers_system_spec/app/controllers/complex_helpers_system_spec_controller.rb +4 -0
  44. data/spec/rails/templates/complex_helpers_system_spec/app/views/complex_helpers_system_spec/label_block_test.rb +9 -0
  45. data/spec/rails/templates/helpers_system_spec/app/controllers/helpers_system_spec_controller.rb +4 -0
  46. data/spec/rails/templates/helpers_system_spec/app/controllers/home_controller.rb +9 -0
  47. data/spec/rails/templates/helpers_system_spec/app/views/helpers_system_spec/rails_helpers_without_automatic_helper_access.rb +37 -0
  48. data/spec/rails/templates/helpers_system_spec/app/views/helpers_system_spec/url_helpers_without_automatic_helper_access.rb +45 -0
  49. data/spec/rails/templates/helpers_system_spec/config/initializers/host.rb +1 -0
  50. data/spec/rails/templates/helpers_system_spec/config/routes.rb +7 -0
  51. data/spec/rails/templates/static_method_system_spec/app/views/static_method_system_spec/localization.rb +1 -1
  52. data/spec/rails/templates/view_paths_system_spec/app/controllers/view_paths_system_spec_controller.rb +15 -0
  53. data/spec/rails/templates/view_paths_system_spec/config/application.rb +30 -0
  54. data/spec/rails/templates/view_paths_system_spec/view_path_one/baseone/basetwo/base_class_one.rb +5 -0
  55. data/spec/rails/templates/view_paths_system_spec/view_path_one/view_paths_system_spec/added_view_path.html.rb +5 -0
  56. data/spec/rails/templates/view_paths_system_spec/view_path_one/view_paths_system_spec/autoloading_from_added_view_path.html.rb +5 -0
  57. data/spec/rails/templates/view_paths_system_spec/view_path_two/view_paths_system_spec/added_view_path_from_controller.html.rb +5 -0
  58. data/spec/rails/templates/view_paths_system_spec/view_path_two/view_paths_system_spec/added_view_path_from_controller_with_impossible_to_guess_name.html.rb +14 -0
  59. data/spec/rails/view_paths_system_spec.rb +19 -0
  60. data/spec/system/escaping_system_spec.rb +10 -2
  61. data/spec/system/helpers_system_spec.rb +37 -6
  62. data/spec/system/inline_system_spec.rb +19 -0
  63. data/spec/system/static_method_system_spec.rb +16 -0
  64. data/spec/system/tag_rendering_system_spec.rb +4 -4
  65. data/spec/system/widget_class_from_spec.rb +39 -0
  66. data/spec/system/yield_system_spec.rb +53 -1
  67. metadata +54 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01ce3b6762f088fca61147da654a6f3508d1fcb5
4
- data.tar.gz: b2cc3632e67c21dc00edcbf4f87d9b538b168b53
3
+ metadata.gz: e628239070a163ab3cf3431cd1541827f7164bce
4
+ data.tar.gz: 680d6b3550680358167ad185658e31836a4fb1ea
5
5
  SHA512:
6
- metadata.gz: 54f01af0007be5caa3b469ac3ff26952c8b365ee65f78fc402f9ea53e37ab757da20a64f271807fc1547d6c3625f755aa3f15ac918347c6c016276930e2e5a21
7
- data.tar.gz: 89e9ca7d79dd014124cca6d12d564847206169d4f0fe9df34a71c59b1f6dfd99333ae959b22db9cf0eff8051afbc306327cf250d9210f55b96e23fc4611f8680
6
+ metadata.gz: 1abdd3e8929afb29866c8af7728f07a6b8969e1401a1168234cb9b1cebf9b9d14c3b713b8c9a21e5335a03b2a1fb719a344620a3f60ac6d2923f3b2183791e28
7
+ data.tar.gz: f5b5fb078f3484478dbe89eb8e04cea9de528b2427821c89692e1fdcc77c8f981333dddf33838e3f467b15def7cf9ee797f6abec82cca69f1b701b3dd3638860
@@ -0,0 +1,26 @@
1
+ def safe_system(cmd)
2
+ $stderr.puts "Running: #{cmd}"
3
+ result = system("#{cmd} 2>&1")
4
+ unless result && $? && $?.success?
5
+ raise "Command failed: #{$?.inspect}"
6
+ end
7
+ end
8
+
9
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE.to_s == 'jruby' && defined?(JRUBY_VERSION) && JRUBY_VERSION.to_s =~ /^1\.7\./
10
+ safe_system("gem update --system")
11
+
12
+ target_dir = "/home/travis/.rvm/gems"
13
+ targets = Dir.entries(target_dir).select { |e| e =~ /^jruby\-#{JRUBY_VERSION}.*@global$/i }
14
+
15
+ targets.each do |target|
16
+ full_path = File.join(target_dir, target)
17
+ safe_system("gem uninstall -i '#{full_path}' bundler")
18
+ end
19
+
20
+ safe_system("gem install bundler -v 1.12.5 --no-rdoc --no-ri --no-document")
21
+ else
22
+ ruby_engine = if defined?(RUBY_ENGINE) then RUBY_ENGINE.inspect else 'nil' end
23
+ jruby_version = if defined?(JRUBY_VERSION) then JRUBY_VERSION.inspect else 'nil' end
24
+
25
+ puts "No need to fix Bundler versions. RUBY_ENGINE is #{ruby_engine} and JRUBY_VERSION is #{jruby_version}."
26
+ end
data/.gitignore CHANGED
@@ -18,3 +18,4 @@ lib/*.bundle
18
18
  /*.sublime-project
19
19
  /*.sublime-workspace
20
20
  /doc/source/.retina_images_workaround
21
+ *.swp
data/.travis.yml CHANGED
@@ -1,56 +1,49 @@
1
+ sudo: false
1
2
  rvm:
2
3
  - "1.8.7"
3
4
  - "1.9.3-p551"
4
- - "2.0.0-p598"
5
- - "2.1.5"
6
- - "2.2.0"
7
- - "jruby-1.7.18"
5
+ - "2.0.0-p648"
6
+ - "2.1.10"
7
+ - "2.2.5"
8
+ - "2.3.1"
9
+ - "jruby-1.7.26"
10
+ - "jruby-9.1.5.0"
11
+ # 2016-09-20 ageweke -- This is temporary, and is because JRuby 1.7.26 is incompatible with Bundler 1.13.0/1,
12
+ # because of the following issue: https://github.com/bundler/bundler/issues/4975.
13
+ before_install:
14
+ - ruby .fix_bundler_for_jruby_17
8
15
  env:
9
- - FORTITUDE_SPECS_RAILS_VERSION=4.2.0
10
- - FORTITUDE_SPECS_RAILS_VERSION=4.1.9
16
+ - FORTITUDE_SPECS_RAILS_VERSION=5.0.0.1
17
+ - FORTITUDE_SPECS_RAILS_VERSION=4.2.7.1
18
+ - FORTITUDE_SPECS_RAILS_VERSION=4.1.16
11
19
  - FORTITUDE_SPECS_RAILS_VERSION=4.0.13
12
- - FORTITUDE_SPECS_RAILS_VERSION=3.2.21
20
+ - FORTITUDE_SPECS_RAILS_VERSION=3.2.22.5
13
21
  - FORTITUDE_SPECS_RAILS_VERSION=3.1.12
14
22
  - FORTITUDE_SPECS_RAILS_VERSION=3.0.20
15
- - FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.2.0
23
+ - FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.2.7.1
16
24
  - FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=3.0.20
17
- before_script:
18
- - export JRUBY_OPTS="$JRUBY_OPTS -J-Xmx128m -J-Xms128m -J-Xss2048k"
19
25
  matrix:
20
26
  exclude:
21
27
  # Rails 4.x doesn't support Ruby 1.8.7
22
28
  - rvm: 1.8.7
23
- env: FORTITUDE_SPECS_RAILS_VERSION=4.2.0
29
+ env: FORTITUDE_SPECS_RAILS_VERSION=4.2.7.1
24
30
  - rvm: 1.8.7
25
- env: FORTITUDE_SPECS_RAILS_VERSION=4.1.9
31
+ env: FORTITUDE_SPECS_RAILS_VERSION=4.1.16
26
32
  - rvm: 1.8.7
27
- env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.2.0
33
+ env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.2.7.1
28
34
  - rvm: 1.8.7
29
35
  env: FORTITUDE_SPECS_RAILS_VERSION=4.0.13
30
- # 2014-06-19 ageweke -- ARGH. After trying about seventeen different things, no matter what I do,
31
- # Travis fails JRuby builds about 20% of the time with "Killed". Their documentation indicates that this
32
- # is likely an out-of-memory issue (i.e., entire VM's memory is consumed). However, I'm running JRuby with
33
- # only 128MB allocated to each VM (per above) -- yuck -- and it's still happening; this makes no sense, as it
34
- # would take something like 20+ concurrent JRuby processes to consume 3GB, and we should never be running
35
- # more than 2-3.
36
- #
37
- # At this point, I have little choice other than to mark these as 'allowed failures', and check in on each
38
- # one manually to make sure there aren't other failures, too. This is very frustrating, but I can't seem to
39
- # find a way around it. If there's a fix out there somewhere, I'm all ears!
40
- allow_failures:
41
- - rvm: jruby-1.7.18
42
- env: FORTITUDE_SPECS_RAILS_VERSION=4.2.0
43
- - rvm: jruby-1.7.18
44
- env: FORTITUDE_SPECS_RAILS_VERSION=4.1.9
45
- - rvm: jruby-1.7.18
46
- env: FORTITUDE_SPECS_RAILS_VERSION=4.0.13
47
- - rvm: jruby-1.7.18
48
- env: FORTITUDE_SPECS_RAILS_VERSION=3.2.21
49
- - rvm: jruby-1.7.18
50
- env: FORTITUDE_SPECS_RAILS_VERSION=3.1.12
51
- - rvm: jruby-1.7.18
52
- env: FORTITUDE_SPECS_RAILS_VERSION=3.0.20
53
- - rvm: jruby-1.7.18
54
- env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.2.0
55
- - rvm: jruby-1.7.18
56
- env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=3.0.20
36
+ # Rails 5.x doesn't support Ruby < 2.2
37
+ - rvm: 1.8.7
38
+ env: FORTITUDE_SPECS_RAILS_VERSION=5.0.0.1
39
+ - rvm: "1.9.3-p551"
40
+ env: FORTITUDE_SPECS_RAILS_VERSION=5.0.0.1
41
+ - rvm: "2.0.0-p648"
42
+ env: FORTITUDE_SPECS_RAILS_VERSION=5.0.0.1
43
+ - rvm: "2.1.10"
44
+ env: FORTITUDE_SPECS_RAILS_VERSION=5.0.0.1
45
+ - rvm: "jruby-1.7.26"
46
+ env: FORTITUDE_SPECS_RAILS_VERSION=5.0.0.1
47
+ # JRuby doesn't support Rails 5 yet
48
+ - rvm: jruby-9.1.5.0
49
+ env: FORTITUDE_SPECS_RAILS_VERSION=5.0.0.1
data/CHANGES.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Fortitude Releases
2
2
 
3
+ ## 0.9.5, 12 October 2016
4
+
5
+ * Rails 5 compatibility: Fortitude now is fully compatible with Rails 5.0.0.1.
6
+ * Significant improvements in performance to our dispatching to #t, the Rails method to produce translations of
7
+ localized strings. Localized Rails applications tend to use this method a _lot_, so its performance can have a
8
+ big impact on overall application performance.
9
+ * A much better error message if you try to declare a method `static` when it hasn't been defined yet &mdash; this
10
+ can often be the result of putting the `static` declaration above the method definition in the source file,
11
+ rather than below it. (Thanks to [`tobymao`](https://github.com/tobymao) for the bug report!)
12
+ * Updated versions of Ruby and Rails that Travis CI tests against to the very latest.
13
+ * Fixed an issue where Fortitude wasn't properly respecting Rails' view paths. Fortitude templates could be found at
14
+ alternate view paths, but our trick of namespacing views under `Views::` wouldn't apply. Now, it all works
15
+ perfectly. (Thanks to [Karl He](https://github.com/karlhe) for the bug report and example patch!)
16
+ * Fixed an issue where `#block_given?` always returned `true` inside a Fortitude widget's `#content` method, whether
17
+ a block was supplied to it or not. (Thanks to [Jeff Dickey](https://github.com/jdickey) for the bug report!)
18
+ * Fixed an incompatibility between Fortitude and Rails 4.2.5.1, since Rails 4.2.5.1 added a fifth parameter to
19
+ `ActionView::PathResolver#find_templates`. (Thanks to [Luke Francl](https://github.com/look) for the bug report!)
20
+ * Fixed incompatibilities with more-recently released versions of gems (`uglifier`, `rake`, `activesupport`) that
21
+ otherwise broke compatibility with previous Ruby versions.
22
+ * Fixed an issue where Fortitude’s system for figuring out what the name of a Fortitude widget would be, based on its
23
+ filename, could be confused by filenames ending in other extensions before `.rb` (for example, `.html.rb`).
24
+ * Eliminated a deprecation warning from Rails 5 caused by Fortitude's use of `render :text` internally.
25
+ * Removed usage of `alias_method_chain` on Ruby 2.0 and later, in favor of `Module#prepend`. This removes deprecation
26
+ warnings otherwise triggered by Rails 5. (Using `Module#prepend` causes problems in JRuby, so `alias_method_chain`
27
+ is still used on JRuby instead.)
28
+ * Changed the behavior of `automatic_helper_access false` so that, in a Rails application, it still makes all the
29
+ built-in Rails helpers properly accessible, but does not make user-defined helpers accessible. (If there are even
30
+ certain built-in Rails helpers you don’t want people using, you can easily override them in your widget class to
31
+ raise an exception.) Without this, `automatic_helper_access false` became so cumbersome to use that it was nearly
32
+ pointless. (Thanks to [Matt Walters](https://github.com/mattwalters) for the pull request!)
33
+ * Fixed an issue where explicitly declaring an assignment method as a helper (_e.g._, `helper :foo=`) did not work
34
+ properly.
35
+ * Fixed an issue where passing a block to (_e.g._) `f.label`, where `f` is the object yielded to a `form_for` helper,
36
+ did not work properly. (Thanks to [Adam Becker](https://github.com/ajb) for the bug report and test case!)
37
+ * Reduced escaping in attribute values: only `"` and `&` need to be escaped, not `<`, `>`, or `'`. (Thanks to
38
+ [Adam Becker](https://github.com/ajb) for the bug report!)
39
+ * Fixed an issue where, under certain extremely rare circumstances, adding a view path in the controller (using
40
+ [`ActionView::ViewPaths.append_view_path`](http://api.rubyonrails.org/classes/ActionView/ViewPaths/ClassMethods.html#method-i-prepend_view_path)
41
+ and related methods) would not be able to figure out the proper class name of the widget, and would fail. (Thanks
42
+ to [Leaf](https://github.com/leafo) for the bug report!)
43
+ * Added the ability for the `inline_html` method on a widget class to accept a `Fortitude::RenderingContext`, thus
44
+ allowing you to use it with code requiring access to helpers. (Thanks to [Adam Becker](https://github.com/ajb) for
45
+ the bug report!)
46
+
3
47
  ## 0.9.4, 11 February 2015
4
48
 
5
49
  * Fixed an issue where use of Rails' `form_for` or `fields_for` from within another `form_for` or `fields_for` block
data/CONTRIBUTORS.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Fortitude is written by [Andrew Geweke](https://github.com/ageweke), with contributions from:
4
4
 
5
+ * [`tobymao`](https://github.com/tobymao): reporting a bug where trying to declare a method `static` before it's been
6
+ defined resulted in a confusing error.
5
7
  * [Ahto Jussila](https://github.com/ahto): a patch to provide separate MRI and JRuby gems, so that
6
8
  `gem install fortitude` works properly no matter which platform you're on.
7
9
  * [Roman Heinrich](https://github.com/mindreframer): reporting a bug where trying to use Fortitude as a Tilt
@@ -37,7 +39,31 @@ Fortitude is written by [Andrew Geweke](https://github.com/ageweke), with contri
37
39
  a memory leak.
38
40
  * Reporting an issue where use of Rails' `form_for` and/or `fields_for` from within another `form_for` or
39
41
  `fields_for` block would not produce the correct output.
42
+ * Reporting an issue where, under certain extremely rare circumstances, adding a view path in the controller (using
43
+ [`ActionView::ViewPaths.append_view_path`](http://api.rubyonrails.org/classes/ActionView/ViewPaths/ClassMethods.html#method-i-prepend_view_path)
44
+ and related methods) would not be able to figure out the proper class name of the widget, and would fail.
40
45
  * [Adam Becker](https://github.com/ajb) for:
41
46
  * Discussion and details around exactly what `:attribute => true`, `:attribute => false`, and so on should render
42
47
  from Fortitude.
43
48
  * Reporting an issue where you could not easily render a Fortitude widget from Erector, nor vice-versa.
49
+ * Fixes for compatibility with Rails 5.
50
+ * Fix for a deprecation warning from Rails 5 caused by Fortitude's use of `render :text` internally.
51
+ * Reporting an issue and providing a test case and patch for an issue where calling `f.label` with a block, where
52
+ `f` is the object yielded to Rails' `form_for`, would cause an exception from Fortitude.
53
+ * Reporting an issue where Fortitude was escaping characters that it didn’t need to in attribute values
54
+ (specifically, `<`, `>`, and `'`).
55
+ * Reporting an issue where you couldn't use `inline_html` in a way that allowed you to pass a
56
+ `Fortitude::RenderingContext`, thus preventing you from using it with code that required access to helpers.
57
+ * [Karl He](https://github.com/karlhe) for:
58
+ * Reporting an issue (and supplying an example patch) where Fortitude wasn't respecting Rails' additional view
59
+ paths correctly &mdash; only `app/views`.
60
+ * [Jeff Dickey](https://github.com/jdickey) for:
61
+ * Reporting an issue where `#block_given?` inside a Fortitude widget's `#content` method returned `true` always,
62
+ whether or not there was anything to yield to.
63
+ * [Luke Francl](https://github.com/look) for:
64
+ * Reporting an incompatibility between Fortitude and Rails 4.2.5.1, and discovering the underlying cause (a fifth
65
+ parameter added to `ActionView::PathResolver#find_templates`.)
66
+ * [Victor Lymar](https://github.com/vlymar) for:
67
+ * Fixes for compatibility with Rails 5.
68
+ * [Matt Walters](https://github.com/mattwalters) for:
69
+ * A patch to make built-in Rails helpers work even when `automatic_helper_access` was set to `false`.
data/Rakefile CHANGED
@@ -32,7 +32,7 @@ namespace :jruby do
32
32
  end
33
33
 
34
34
  task :ensure_jruby do
35
- unless RUBY_ENGINE == 'jruby'
35
+ unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
36
36
  raise "You must run this task using JRuby, not #{RUBY_ENGINE}"
37
37
  end
38
38
  end
@@ -57,13 +57,13 @@ public class FortitudeNativeLibrary implements Library {
57
57
  outputString.cat(selfString);
58
58
  } else {
59
59
  byte[] selfBytes = selfString.getBytes();
60
- fortitude_escaped_strcpy(outputString, selfBytes);
60
+ fortitude_escaped_strcpy(outputString, selfBytes, false);
61
61
  }
62
62
 
63
63
  return runtime.getNil();
64
64
  }
65
65
 
66
- public static void fortitude_escaped_strcpy(RubyString output, byte[] source) {
66
+ public static void fortitude_escaped_strcpy(RubyString output, byte[] source, boolean forAttributeValue) {
67
67
  byte[] buffer = new byte[BUFFER_SIZE];
68
68
  int bufferPos = 0;
69
69
 
@@ -84,35 +84,47 @@ public class FortitudeNativeLibrary implements Library {
84
84
  buffer[bufferPos++] = ';';
85
85
  break;
86
86
 
87
- case LESS_THAN_BYTE:
87
+ case DOUBLE_QUOTE_BYTE:
88
88
  buffer[bufferPos++] = '&';
89
- buffer[bufferPos++] = 'l';
89
+ buffer[bufferPos++] = 'q';
90
+ buffer[bufferPos++] = 'u';
91
+ buffer[bufferPos++] = 'o';
90
92
  buffer[bufferPos++] = 't';
91
93
  buffer[bufferPos++] = ';';
92
94
  break;
93
95
 
94
- case GREATER_THAN_BYTE:
95
- buffer[bufferPos++] = '&';
96
- buffer[bufferPos++] = 'g';
97
- buffer[bufferPos++] = 't';
98
- buffer[bufferPos++] = ';';
96
+ case LESS_THAN_BYTE:
97
+ if (forAttributeValue) {
98
+ buffer[bufferPos++] = '<';
99
+ } else {
100
+ buffer[bufferPos++] = '&';
101
+ buffer[bufferPos++] = 'l';
102
+ buffer[bufferPos++] = 't';
103
+ buffer[bufferPos++] = ';';
104
+ }
99
105
  break;
100
106
 
101
- case SINGLE_QUOTE_BYTE:
102
- buffer[bufferPos++] = '&';
103
- buffer[bufferPos++] = '#';
104
- buffer[bufferPos++] = '3';
105
- buffer[bufferPos++] = '9';
106
- buffer[bufferPos++] = ';';
107
+ case GREATER_THAN_BYTE:
108
+ if (forAttributeValue) {
109
+ buffer[bufferPos++] = '>';
110
+ } else {
111
+ buffer[bufferPos++] = '&';
112
+ buffer[bufferPos++] = 'g';
113
+ buffer[bufferPos++] = 't';
114
+ buffer[bufferPos++] = ';';
115
+ }
107
116
  break;
108
117
 
109
- case DOUBLE_QUOTE_BYTE:
110
- buffer[bufferPos++] = '&';
111
- buffer[bufferPos++] = 'q';
112
- buffer[bufferPos++] = 'u';
113
- buffer[bufferPos++] = 'o';
114
- buffer[bufferPos++] = 't';
115
- buffer[bufferPos++] = ';';
118
+ case SINGLE_QUOTE_BYTE:
119
+ if (forAttributeValue) {
120
+ buffer[bufferPos++] = '\'';
121
+ } else {
122
+ buffer[bufferPos++] = '&';
123
+ buffer[bufferPos++] = '#';
124
+ buffer[bufferPos++] = '3';
125
+ buffer[bufferPos++] = '9';
126
+ buffer[bufferPos++] = ';';
127
+ }
116
128
  break;
117
129
 
118
130
  default:
@@ -130,11 +142,11 @@ public class FortitudeNativeLibrary implements Library {
130
142
  public static class FortitudeHashExtensions {
131
143
  public static final byte SPACE = (byte) ' ';
132
144
 
133
- public static void fortitude_append_to(IRubyObject object, RubyString rbOutput) {
145
+ public static void fortitude_append_to(IRubyObject object, RubyString rbOutput, boolean forAttributeValue) {
134
146
  if (object instanceof RubyString) {
135
- FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, ((RubyString) object).getBytes());
147
+ FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, ((RubyString) object).getBytes(), forAttributeValue);
136
148
  } else if (object instanceof RubySymbol) {
137
- FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, ((RubyString) ((RubySymbol) object).to_s()).getBytes());
149
+ FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, ((RubyString) ((RubySymbol) object).to_s()).getBytes(), forAttributeValue);
138
150
  } else if (object instanceof RubyArray) {
139
151
  RubyArray array = (RubyArray) object;
140
152
 
@@ -143,16 +155,16 @@ public class FortitudeNativeLibrary implements Library {
143
155
  if (i > 0) {
144
156
  rbOutput.cat(SPACE);
145
157
  }
146
- fortitude_append_to(element, rbOutput);
158
+ fortitude_append_to(element, rbOutput, forAttributeValue);
147
159
  }
148
160
  } else if (object instanceof RubyNil) {
149
161
  // nothing here
150
162
  } else if (object instanceof RubyFixnum) {
151
163
  RubyString asString = ((RubyFixnum) object).to_s();
152
- FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, asString.getBytes());
164
+ FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, asString.getBytes(), forAttributeValue);
153
165
  } else {
154
166
  RubyString asString = (RubyString) ((RubyBasicObject) object).callMethod("to_s");
155
- FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, asString.getBytes());
167
+ FortitudeStringExtensions.fortitude_escaped_strcpy(rbOutput, asString.getBytes(), forAttributeValue);
156
168
  }
157
169
  }
158
170
 
@@ -177,10 +189,10 @@ public class FortitudeNativeLibrary implements Library {
177
189
 
178
190
  if (prefix != null) {
179
191
  newPrefix = (RubyString) prefix.dup();
180
- fortitude_append_to(key, newPrefix);
192
+ fortitude_append_to(key, newPrefix, false);
181
193
  } else {
182
194
  newPrefix = RubyString.newEmptyString(runtime);
183
- fortitude_append_to(key, newPrefix);
195
+ fortitude_append_to(key, newPrefix, false);
184
196
  }
185
197
 
186
198
  newPrefix.cat('-');
@@ -196,19 +208,19 @@ public class FortitudeNativeLibrary implements Library {
196
208
  // nothing here
197
209
  }
198
210
 
199
- fortitude_append_to(key, output);
211
+ fortitude_append_to(key, output, false);
200
212
 
201
213
  if ((value instanceof RubyBoolean) && (value.isTrue())) {
202
214
  if (this.allowsBareAttributes.isTrue()) {
203
215
  // ok, nothing here
204
216
  } else {
205
217
  output.cat(EQUALS_QUOTE);
206
- fortitude_append_to(key, output);
218
+ fortitude_append_to(key, output, false);
207
219
  output.cat('"');
208
220
  }
209
221
  } else {
210
222
  output.cat(EQUALS_QUOTE);
211
- fortitude_append_to(value, output);
223
+ fortitude_append_to(value, output, true);
212
224
  output.cat('"');
213
225
  }
214
226
  }
@@ -18,7 +18,7 @@ void Init_fortitude_native_ext() {
18
18
  #define BUF_SIZE 256
19
19
  #define MAX_SUBSTITUTION_LENGTH 6
20
20
 
21
- void fortitude_escaped_strcpy(VALUE rb_output, const char * src) {
21
+ void fortitude_escaped_strcpy(VALUE rb_output, const char * src, int for_attribute_value) {
22
22
  char buf[BUF_SIZE + 1];
23
23
  char* buf_pos = buf;
24
24
  char* max_buf_pos = buf + (BUF_SIZE - MAX_SUBSTITUTION_LENGTH);
@@ -39,29 +39,29 @@ void fortitude_escaped_strcpy(VALUE rb_output, const char * src) {
39
39
  *buf_pos++ = 'm';
40
40
  *buf_pos++ = 'p';
41
41
  *buf_pos++ = ';';
42
- } else if (ch == '<') {
42
+ } else if (ch == '"') {
43
+ *buf_pos++ = '&';
44
+ *buf_pos++ = 'q';
45
+ *buf_pos++ = 'u';
46
+ *buf_pos++ = 'o';
47
+ *buf_pos++ = 't';
48
+ *buf_pos++ = ';';
49
+ } else if (ch == '<' && (! for_attribute_value)) {
43
50
  *buf_pos++ = '&';
44
51
  *buf_pos++ = 'l';
45
52
  *buf_pos++ = 't';
46
53
  *buf_pos++ = ';';
47
- } else if (ch == '>') {
54
+ } else if (ch == '>' && (! for_attribute_value)) {
48
55
  *buf_pos++ = '&';
49
56
  *buf_pos++ = 'g';
50
57
  *buf_pos++ = 't';
51
58
  *buf_pos++ = ';';
52
- } else if (ch == '\'') {
59
+ } else if (ch == '\'' && (! for_attribute_value)) {
53
60
  *buf_pos++ = '&';
54
61
  *buf_pos++ = '#';
55
62
  *buf_pos++ = '3';
56
63
  *buf_pos++ = '9';
57
64
  *buf_pos++ = ';';
58
- } else if (ch == '"') {
59
- *buf_pos++ = '&';
60
- *buf_pos++ = 'q';
61
- *buf_pos++ = 'u';
62
- *buf_pos++ = 'o';
63
- *buf_pos++ = 't';
64
- *buf_pos++ = ';';
65
65
  } else {
66
66
  if (ch == '\0') {
67
67
  break;
@@ -92,11 +92,11 @@ VALUE method_append_escaped_string(VALUE self, VALUE rb_output) {
92
92
  return Qnil;
93
93
  }
94
94
 
95
- fortitude_escaped_strcpy(rb_output, c_self);
95
+ fortitude_escaped_strcpy(rb_output, c_self, 0);
96
96
  return Qnil;
97
97
  }
98
98
 
99
- void fortitude_append_to(VALUE object, VALUE rb_output) {
99
+ void fortitude_append_to(VALUE object, VALUE rb_output, int for_attribute_value) {
100
100
  ID to_s;
101
101
  char buf[25];
102
102
  long value;
@@ -111,11 +111,11 @@ void fortitude_append_to(VALUE object, VALUE rb_output) {
111
111
 
112
112
  switch (TYPE(object)) {
113
113
  case T_STRING:
114
- fortitude_escaped_strcpy(rb_output, RSTRING_PTR(object));
114
+ fortitude_escaped_strcpy(rb_output, RSTRING_PTR(object), for_attribute_value);
115
115
  break;
116
116
 
117
117
  case T_SYMBOL:
118
- fortitude_escaped_strcpy(rb_output, rb_id2name(SYM2ID(object)));
118
+ fortitude_escaped_strcpy(rb_output, rb_id2name(SYM2ID(object)), for_attribute_value);
119
119
  break;
120
120
 
121
121
  case T_ARRAY:
@@ -125,7 +125,7 @@ void fortitude_append_to(VALUE object, VALUE rb_output) {
125
125
  if (i > 0) {
126
126
  rb_str_cat2(rb_output, " ");
127
127
  }
128
- fortitude_append_to(array_element, rb_output);
128
+ fortitude_append_to(array_element, rb_output, for_attribute_value);
129
129
  }
130
130
 
131
131
  case T_NONE:
@@ -140,7 +140,7 @@ void fortitude_append_to(VALUE object, VALUE rb_output) {
140
140
 
141
141
  default:
142
142
  new_string = rb_funcall(object, to_s, 0);
143
- fortitude_escaped_strcpy(rb_output, RSTRING_PTR(new_string));
143
+ fortitude_escaped_strcpy(rb_output, RSTRING_PTR(new_string), for_attribute_value);
144
144
  break;
145
145
  }
146
146
  }
@@ -175,12 +175,12 @@ int fortitude_append_key_and_value(VALUE key, VALUE value, VALUE key_and_value_d
175
175
  switch (TYPE(prefix)) {
176
176
  case T_STRING:
177
177
  new_prefix_as_string = rb_funcall(prefix, dup, 0);
178
- fortitude_append_to(key, new_prefix_as_string);
178
+ fortitude_append_to(key, new_prefix_as_string, 0);
179
179
  break;
180
180
 
181
181
  case T_NIL:
182
182
  new_prefix_as_string = rb_str_new("", 0);
183
- fortitude_append_to(key, new_prefix_as_string);
183
+ fortitude_append_to(key, new_prefix_as_string, 0);
184
184
  break;
185
185
 
186
186
  default:
@@ -212,12 +212,12 @@ int fortitude_append_key_and_value(VALUE key, VALUE value, VALUE key_and_value_d
212
212
  break;
213
213
  }
214
214
 
215
- fortitude_append_to(key, rb_output);
215
+ fortitude_append_to(key, rb_output, 0);
216
216
  if (TYPE(allows_bare_attributes) == T_TRUE) {
217
217
  /* ok */
218
218
  } else {
219
219
  rb_str_cat2(rb_output, "=\"");
220
- fortitude_append_to(key, rb_output);
220
+ fortitude_append_to(key, rb_output, 1);
221
221
  rb_str_cat2(rb_output, "\"");
222
222
  }
223
223
  break;
@@ -238,9 +238,9 @@ int fortitude_append_key_and_value(VALUE key, VALUE value, VALUE key_and_value_d
238
238
  break;
239
239
  }
240
240
 
241
- fortitude_append_to(key, rb_output);
241
+ fortitude_append_to(key, rb_output, 0);
242
242
  rb_str_cat2(rb_output, "=\"");
243
- fortitude_append_to(value, rb_output);
243
+ fortitude_append_to(value, rb_output, 1);
244
244
  rb_str_cat2(rb_output, "\"");
245
245
  break;
246
246
  }