forme 2.4.1 → 2.6.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG +18 -0
- data/README.rdoc +46 -4
- data/lib/forme/bs3.rb +1 -1
- data/lib/forme/template.rb +4 -4
- data/lib/forme/transformers/formatter.rb +11 -3
- data/lib/forme/transformers/serializer.rb +1 -1
- data/lib/forme/version.rb +2 -2
- data/lib/forme.rb +4 -10
- data/lib/roda/plugins/forme_erubi_capture.rb +2 -2
- data/lib/roda/plugins/forme_erubi_capture_block.rb +45 -0
- data/lib/roda/plugins/forme_route_csrf.rb +18 -1
- data/lib/roda/plugins/forme_set.rb +15 -2
- data/lib/sequel/plugins/forme.rb +16 -0
- metadata +4 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c0078a295325f1880c32a870466a7e280a0cd324e2f8bf91ea81125bf557d225
         | 
| 4 | 
            +
              data.tar.gz: 120e19dde7e39176a4693a4ab46f7f1c2f4d86265f3de4946af6a1d40f5fd524
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f13bb7fdfaf90be6af18cc67403d4e36f963c6258eeb49bbc4579b356534172fa4d25380f032ef7a80954f532de3a63f67e3ad3a985c0225d4d21db0245fe387
         | 
| 7 | 
            +
              data.tar.gz: 6ec1d4cbee834565239953a12b826b9b190c4f80901b6dc559954c7414889a1c0691e3a16b25dd5d2176a079ae3826a3b9e13bb6c23e323979046af98288208f
         | 
    
        data/CHANGELOG
    CHANGED
    
    | @@ -1,3 +1,21 @@ | |
| 1 | 
            +
            === 2.6.0 (2024-06-18)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Add Roda forme_erubi_capture_block plugin to support erubi/capture_block <%= form do %> <% end %> tags (jeremyevans)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Support :hr as select option value to use a hr tag instead of an option tag (jeremyevans)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Support maxlength and minlength options as attributes for textareas (jeremyevans)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            * Support minlength option as attribute for text inputs (jeremyevans)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            === 2.5.0 (2024-02-13)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            * Add hidden inputs to work with formaction/formmethod support in Roda 3.77+ route_csrf plugin (jeremyevans)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            * Support :formaction option on buttons (jeremyevans)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * Support emit: false option for non-rails template forms allowing block based form use without appending to template (jeremyevans)
         | 
| 18 | 
            +
             | 
| 1 19 | 
             
            === 2.4.1 (2023-09-19)
         | 
| 2 20 |  | 
| 3 21 | 
             
            * Add dependency on bigdecimal, as bigdecimal is moving from standard library to bundled gem in Ruby 3.4 (jeremyevans)
         | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -615,8 +615,8 @@ internally).  +forme_parse+ returns a hash with the following keys: | |
| 615 615 | 
             
                            check that the submitted values for associated objects match one of the
         | 
| 616 616 | 
             
                            options for the input in the form.
         | 
| 617 617 |  | 
| 618 | 
            -
            It is possible to use +forme_set+ for the  | 
| 619 | 
            -
             | 
| 618 | 
            +
            It is possible to use +forme_set+ for the forms it can handle, and use +forme_parse+ and
         | 
| 619 | 
            +
            +set_fields+ for other forms.
         | 
| 620 620 |  | 
| 621 621 | 
             
            === Roda forme_set plugin
         | 
| 622 622 |  | 
| @@ -792,6 +792,7 @@ Forme ships with multiple Roda plugins | |
| 792 792 | 
             
            * forme_set (discussed above)
         | 
| 793 793 | 
             
            * forme
         | 
| 794 794 | 
             
            * forme_route_csrf
         | 
| 795 | 
            +
            * forme_erubi_capture_block
         | 
| 795 796 | 
             
            * forme_erubi_capture
         | 
| 796 797 |  | 
| 797 798 | 
             
            == forme_route_csrf and forme plugins
         | 
| @@ -800,7 +801,7 @@ For new code, it is recommended to use forme_route_csrf, as that uses Roda's rou | |
| 800 801 | 
             
            plugin, which supports more secure request-specific CSRF tokens.  In both cases, usage in ERB
         | 
| 801 802 | 
             
            templates is the same:
         | 
| 802 803 |  | 
| 803 | 
            -
              <% form(@obj, : | 
| 804 | 
            +
              <% form(@obj, action: '/foo') do |f| %>
         | 
| 804 805 | 
             
                <%= f.input(:field) %>
         | 
| 805 806 | 
             
                <% f.tag(:fieldset) do %>
         | 
| 806 807 | 
             
                  <%= f.input(:field_two) %>
         | 
| @@ -810,6 +811,8 @@ templates is the same: | |
| 810 811 | 
             
            The forme_route_csrf plugin's +form+ method supports the following options
         | 
| 811 812 | 
             
            in addition to the default +Forme.form+ options:
         | 
| 812 813 |  | 
| 814 | 
            +
            :emit :: Set to false to not emit implicit tags into template.  This should only be
         | 
| 815 | 
            +
                     used if you are not modifying the template inside the block.
         | 
| 813 816 | 
             
            :csrf :: Set to force whether a CSRF tag should be included.  By default, a CSRF
         | 
| 814 817 | 
             
                     tag is included if the form's method is one of the request methods checked
         | 
| 815 818 | 
             
                     by the Roda route_csrf plugin.
         | 
| @@ -818,10 +821,43 @@ in addition to the default +Forme.form+ options: | |
| 818 821 | 
             
                                           CSRF token unless the Roda route_csrf plugin has been
         | 
| 819 822 | 
             
                                           configured to support non-request specific tokens.
         | 
| 820 823 |  | 
| 824 | 
            +
            The <tt>emit: false</tt> option allows you to do:
         | 
| 825 | 
            +
             | 
| 826 | 
            +
              <%= form(@obj, {action: '/foo'}, emit: false) do |f|
         | 
| 827 | 
            +
                f.input(:field)
         | 
| 828 | 
            +
                f.tag(:fieldset) do
         | 
| 829 | 
            +
                  f.input(:field_two)
         | 
| 830 | 
            +
                end
         | 
| 831 | 
            +
              end %>
         | 
| 832 | 
            +
             | 
| 833 | 
            +
            This is useful if you are calling some method that calls +form+ with a block,
         | 
| 834 | 
            +
            where the resulting entire Forme::Forme object will be literalized into the
         | 
| 835 | 
            +
            template. The form will include the CSRF token and forme_set metadata as appropriate.
         | 
| 836 | 
            +
             | 
| 821 837 | 
             
            The forme plugin does not require any csrf plugin, but will transparently use
         | 
| 822 838 | 
             
            Rack::Csrf if it is available. If Rack::Csrf is available a CSRF tag if the form's
         | 
| 823 839 | 
             
            method is +POST+, with no configuration ability.
         | 
| 824 840 |  | 
| 841 | 
            +
            == forme_erubi_capture_block plugin
         | 
| 842 | 
            +
             | 
| 843 | 
            +
            The forme_erubi_capture_block plugin builds on the forme_route_csrf plugin, but it supports
         | 
| 844 | 
            +
            the erubi/capture_block engine, which allows this syntax:
         | 
| 845 | 
            +
             | 
| 846 | 
            +
              <%= form(@obj, :action=>'/foo') do |f| %>
         | 
| 847 | 
            +
                <%= f.input(:field) %>
         | 
| 848 | 
            +
                <%= f.tag(:fieldset) do %>
         | 
| 849 | 
            +
                  <%= f.input(:field_two) %>
         | 
| 850 | 
            +
                <% end %>
         | 
| 851 | 
            +
              <% end %>
         | 
| 852 | 
            +
             | 
| 853 | 
            +
            If you use the forme_erubi_capture)block plugin, you need to manually set Roda to use the
         | 
| 854 | 
            +
            erubi/capture_block engine, which you can do via:
         | 
| 855 | 
            +
             | 
| 856 | 
            +
              require 'erubi/capture_block'
         | 
| 857 | 
            +
              app.plugin :render, :engine_opts=>{'erb'=>{:engine_class=>Erubi::CaptureBlockEngine}}
         | 
| 858 | 
            +
             | 
| 859 | 
            +
            The forme_erubi_capture plugin requires Erubi 1.13.0+.
         | 
| 860 | 
            +
             | 
| 825 861 | 
             
            == forme_erubi_capture plugin
         | 
| 826 862 |  | 
| 827 863 | 
             
            The forme_erubi_capture plugin builds on the forme_route_csrf plugin, but it supports
         | 
| @@ -856,7 +892,8 @@ It allows you to use the following API in your erb templates: | |
| 856 892 | 
             
              <% end %>
         | 
| 857 893 |  | 
| 858 894 | 
             
            In order to this to work transparently, the ERB outvar needs to be <tt>@_out_buf</tt> (this is the
         | 
| 859 | 
            -
            default in Sinatra).
         | 
| 895 | 
            +
            default in Sinatra).  The Sinatra extension also supports the <tt>emit: false</tt> option to not
         | 
| 896 | 
            +
            directly modify the related template (see example in the Roda section for usage).
         | 
| 860 897 |  | 
| 861 898 | 
             
            = Rails Support
         | 
| 862 899 |  | 
| @@ -966,6 +1003,8 @@ Creates a select tag, containing option tags specified by the :options option. | |
| 966 1003 | 
             
                        array, uses the first entry of the array as the text of the option, and
         | 
| 967 1004 | 
             
                        the last entry of the array as the value of the option. If the last entry
         | 
| 968 1005 | 
             
                        of the array is a hash, uses the hash as the attributes for the option.
         | 
| 1006 | 
            +
                        If the option value is +:hr+, uses an hr tag (allowed in recent versions of
         | 
| 1007 | 
            +
                        the HTML standard).
         | 
| 969 1008 | 
             
            :selected :: The value that should be selected.  Any options that are equal to
         | 
| 970 1009 | 
             
                         this value (or included in this value if a multiple select box),
         | 
| 971 1010 | 
             
                         are set to selected.
         | 
| @@ -997,6 +1036,8 @@ Creates a textarea tag.  Options: | |
| 997 1036 |  | 
| 998 1037 | 
             
            :cols :: The number of columns in the text area.
         | 
| 999 1038 | 
             
            :rows :: The number of rows in the text area.
         | 
| 1039 | 
            +
            :maxlength :: Use the maxlength attribute on the tag
         | 
| 1040 | 
            +
            :minlength :: Use the minlength attribute on the tag
         | 
| 1000 1041 |  | 
| 1001 1042 | 
             
            == all others
         | 
| 1002 1043 |  | 
| @@ -1005,6 +1046,7 @@ as text and password, as well as newer HTML5 inputs such as number or email. Opt | |
| 1005 1046 |  | 
| 1006 1047 | 
             
            :size :: Uses the size attribute on the tag
         | 
| 1007 1048 | 
             
            :maxlength :: Use the maxlength attribute on the tag
         | 
| 1049 | 
            +
            :minlength :: Use the minlength attribute on the tag
         | 
| 1008 1050 |  | 
| 1009 1051 | 
             
            == Form options
         | 
| 1010 1052 |  | 
    
        data/lib/forme/bs3.rb
    CHANGED
    
    | @@ -356,7 +356,7 @@ module Forme | |
| 356 356 | 
             
                      case tag.attr[:type].to_sym
         | 
| 357 357 | 
             
                      when :checkbox, :radio, :hidden
         | 
| 358 358 | 
             
                        # .form-control class causes rendering problems, so remove if found
         | 
| 359 | 
            -
                        tag.attr[:class].gsub | 
| 359 | 
            +
                        tag.attr[:class] = tag.attr[:class].gsub(/\s*form-control\s*/,'') if tag.attr[:class]
         | 
| 360 360 | 
             
                        tag.attr[:class] = nil if tag.attr[:class] && tag.attr[:class].empty?
         | 
| 361 361 |  | 
| 362 362 | 
             
                      when :file
         | 
    
        data/lib/forme/template.rb
    CHANGED
    
    | @@ -72,9 +72,9 @@ module Forme | |
| 72 72 | 
             
                  private
         | 
| 73 73 |  | 
| 74 74 | 
             
                  def _forme_form(obj, attr, opts, &block)
         | 
| 75 | 
            -
                    if  | 
| 75 | 
            +
                    if block && opts[:emit] != false
         | 
| 76 76 | 
             
                      erb_form = buffer = offset = nil
         | 
| 77 | 
            -
                       | 
| 77 | 
            +
                      form_block = proc do
         | 
| 78 78 | 
             
                        wrapped_form = erb_form.instance_variable_get(:@form)
         | 
| 79 79 | 
             
                        buffer = wrapped_form.to_s
         | 
| 80 80 | 
             
                        offset = buffer.length
         | 
| @@ -83,9 +83,9 @@ module Forme | |
| 83 83 | 
             
                        offset = buffer.length
         | 
| 84 84 | 
             
                      end
         | 
| 85 85 |  | 
| 86 | 
            -
                      f, attr,  | 
| 86 | 
            +
                      f, attr, form_block = _forme_wrapped_form_class.form_args(obj, attr, opts, &form_block)
         | 
| 87 87 | 
             
                      erb_form = _forme_form_class.new(f, self)
         | 
| 88 | 
            -
                      erb_form.form(attr, & | 
| 88 | 
            +
                      erb_form.form(attr, &form_block)
         | 
| 89 89 | 
             
                      erb_form.emit(buffer[offset, buffer.length])
         | 
| 90 90 | 
             
                    else
         | 
| 91 91 | 
             
                      _forme_wrapped_form_class.form(obj, attr, opts, &block)
         | 
| @@ -178,7 +178,7 @@ module Forme | |
| 178 178 | 
             
                # with the type attribute set to input.
         | 
| 179 179 | 
             
                def _format_input(type)
         | 
| 180 180 | 
             
                  @attr[:type] = type
         | 
| 181 | 
            -
                  copy_options_to_attributes([:size, :maxlength])
         | 
| 181 | 
            +
                  copy_options_to_attributes([:size, :maxlength, :minlength])
         | 
| 182 182 | 
             
                  tag(:input)
         | 
| 183 183 | 
             
                end
         | 
| 184 184 |  | 
| @@ -268,10 +268,16 @@ module Forme | |
| 268 268 | 
             
                  ret
         | 
| 269 269 | 
             
                end
         | 
| 270 270 |  | 
| 271 | 
            +
                # Formats a submit input.  Respects :formaction option.
         | 
| 272 | 
            +
                def format_submit
         | 
| 273 | 
            +
                  copy_options_to_attributes([:formaction])
         | 
| 274 | 
            +
                  _format_input(:submit)
         | 
| 275 | 
            +
                end
         | 
| 276 | 
            +
             | 
| 271 277 | 
             
                # Formats a textarea.  Respects the following options:
         | 
| 272 278 | 
             
                # :value :: Sets value as the child of the textarea.
         | 
| 273 279 | 
             
                def format_textarea
         | 
| 274 | 
            -
                  copy_options_to_attributes([:cols, :rows])
         | 
| 280 | 
            +
                  copy_options_to_attributes([:cols, :rows, :maxlength, :minlength])
         | 
| 275 281 | 
             
                  if val = @attr.delete(:value)
         | 
| 276 282 | 
             
                    tag(:textarea, @attr, [val])
         | 
| 277 283 | 
             
                  else
         | 
| @@ -446,7 +452,9 @@ module Forme | |
| 446 452 |  | 
| 447 453 | 
             
                  os.map do |x|
         | 
| 448 454 | 
             
                    attr = {}
         | 
| 449 | 
            -
                    if  | 
| 455 | 
            +
                    if x == :hr
         | 
| 456 | 
            +
                      next form._tag(:hr, {})
         | 
| 457 | 
            +
                    elsif tm
         | 
| 450 458 | 
             
                      text = x.send(tm)
         | 
| 451 459 | 
             
                      val = x.send(vm) if vm
         | 
| 452 460 | 
             
                    elsif x.is_a?(Array)
         | 
| @@ -9,7 +9,7 @@ module Forme | |
| 9 9 | 
             
                Forme.register_transformer(:serializer, :default, new)
         | 
| 10 10 |  | 
| 11 11 | 
             
                # Which tags are self closing (such tags ignore children).
         | 
| 12 | 
            -
                SELF_CLOSING = [:img, :input]
         | 
| 12 | 
            +
                SELF_CLOSING = [:img, :input, :hr]
         | 
| 13 13 |  | 
| 14 14 | 
             
                # Serialize the tag object to an html string.  Supports +Tag+ instances,
         | 
| 15 15 | 
             
                # +Input+ instances (recursing into +call+ with the result of formatting the input),
         | 
    
        data/lib/forme/version.rb
    CHANGED
    
    | @@ -6,11 +6,11 @@ module Forme | |
| 6 6 | 
             
              MAJOR = 2
         | 
| 7 7 |  | 
| 8 8 | 
             
              # The minor version of Forme, updated for new feature releases of Forme.
         | 
| 9 | 
            -
              MINOR =  | 
| 9 | 
            +
              MINOR = 6
         | 
| 10 10 |  | 
| 11 11 | 
             
              # The patch version of Forme, updated only for bug fixes from the last
         | 
| 12 12 | 
             
              # feature release.
         | 
| 13 | 
            -
              TINY =  | 
| 13 | 
            +
              TINY = 0
         | 
| 14 14 |  | 
| 15 15 | 
             
              # Version constant, use <tt>Forme.version</tt> instead.
         | 
| 16 16 | 
             
              VERSION = "#{MAJOR}.#{MINOR}.#{TINY}".freeze
         | 
    
        data/lib/forme.rb
    CHANGED
    
    | @@ -25,16 +25,10 @@ module Forme | |
| 25 25 | 
             
                rescue LoadError
         | 
| 26 26 | 
             
                  ESCAPE_TABLE = {'&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => '''}.freeze
         | 
| 27 27 | 
             
                  ESCAPE_TABLE.each_value(&:freeze)
         | 
| 28 | 
            -
                   | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                     | 
| 32 | 
            -
                      value.to_s.gsub(/[&<>"']/, ESCAPE_TABLE)
         | 
| 33 | 
            -
                    end
         | 
| 34 | 
            -
                  else
         | 
| 35 | 
            -
                    def self.h(value)
         | 
| 36 | 
            -
                      value.to_s.gsub(/[&<>"']/){|s| ESCAPE_TABLE[s]}
         | 
| 37 | 
            -
                    end
         | 
| 28 | 
            +
                  # Escape the following characters with their HTML/XML
         | 
| 29 | 
            +
                  # equivalents.
         | 
| 30 | 
            +
                  def self.h(value)
         | 
| 31 | 
            +
                    value.to_s.gsub(/[&<>"']/, ESCAPE_TABLE)
         | 
| 38 32 | 
             
                  end
         | 
| 39 33 | 
             
                end
         | 
| 40 34 | 
             
              end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            # frozen-string-literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative '../../forme/template'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class Roda
         | 
| 6 | 
            +
              module RodaPlugins
         | 
| 7 | 
            +
                module FormeErubiCaptureBlock
         | 
| 8 | 
            +
                  def self.load_dependencies(app)
         | 
| 9 | 
            +
                    app.plugin :forme_route_csrf
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  class Form < ::Forme::Template::Form
         | 
| 13 | 
            +
                    %w'inputs tag subform'.each do |meth|
         | 
| 14 | 
            +
                      class_eval(<<-END, __FILE__, __LINE__+1)
         | 
| 15 | 
            +
                        def #{meth}(*)
         | 
| 16 | 
            +
                          if block_given?
         | 
| 17 | 
            +
                            @scope.instance_variable_get(@scope.render_opts[:template_opts][:outvar]).capture{super}
         | 
| 18 | 
            +
                          else
         | 
| 19 | 
            +
                            super
         | 
| 20 | 
            +
                          end
         | 
| 21 | 
            +
                        end
         | 
| 22 | 
            +
                      END
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  module InstanceMethods
         | 
| 27 | 
            +
                    def _forme_form(obj, attr, opts, &block)
         | 
| 28 | 
            +
                      if block && opts[:emit] != false
         | 
| 29 | 
            +
                        instance_variable_get(render_opts[:template_opts][:outvar]).capture{super}
         | 
| 30 | 
            +
                      else
         | 
| 31 | 
            +
                        super
         | 
| 32 | 
            +
                      end
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    private
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def _forme_form_class
         | 
| 38 | 
            +
                      Form
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                register_plugin(:forme_erubi_capture_block, FormeErubiCaptureBlock)
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| @@ -36,7 +36,7 @@ class Roda | |
| 36 36 | 
             
                      end
         | 
| 37 37 |  | 
| 38 38 | 
             
                      if apply_csrf
         | 
| 39 | 
            -
                        token = if opts.fetch(:use_request_specific_token){use_request_specific_csrf_tokens?}
         | 
| 39 | 
            +
                        token = if use_request_specific_token = opts.fetch(:use_request_specific_token){use_request_specific_csrf_tokens?}
         | 
| 40 40 | 
             
                          csrf_token(csrf_path(attr[:action]), method)
         | 
| 41 41 | 
             
                        else
         | 
| 42 42 | 
             
                          csrf_token
         | 
| @@ -46,6 +46,23 @@ class Roda | |
| 46 46 | 
             
                        opts[:_before] = lambda do |form|
         | 
| 47 47 | 
             
                          form.tag(:input, :type=>:hidden, :name=>csrf_field, :value=>token)
         | 
| 48 48 | 
             
                        end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                        if use_request_specific_token && (formaction_field = csrf_options[:formaction_field])
         | 
| 51 | 
            +
                          formactions = opts[:formactions] = []
         | 
| 52 | 
            +
                          formaction_tokens = opts[:formaction_tokens] = {}
         | 
| 53 | 
            +
                          _after = opts[:_after]
         | 
| 54 | 
            +
                          opts[:formaction_csrfs] = [formaction_field, formaction_tokens]
         | 
| 55 | 
            +
                          formaction_field = csrf_options[:formaction_field]
         | 
| 56 | 
            +
                          opts[:_after] = lambda do |form|
         | 
| 57 | 
            +
                            formactions.each do |action, method|
         | 
| 58 | 
            +
                              path = csrf_path(action)
         | 
| 59 | 
            +
                              fa_token = csrf_token(path, method)
         | 
| 60 | 
            +
                              formaction_tokens[path] = fa_token
         | 
| 61 | 
            +
                              form.tag(:input, :type=>:hidden, :name=>"#{formaction_field}[#{path}]", :value=>fa_token)
         | 
| 62 | 
            +
                            end
         | 
| 63 | 
            +
                            _after.call(form) if _after
         | 
| 64 | 
            +
                          end
         | 
| 65 | 
            +
                        end
         | 
| 49 66 | 
             
                      end
         | 
| 50 67 | 
             
                    end
         | 
| 51 68 | 
             
                  end
         | 
| @@ -7,7 +7,7 @@ class Roda | |
| 7 7 | 
             
              module RodaPlugins
         | 
| 8 8 | 
             
                module FormeSet
         | 
| 9 9 | 
             
                  # Require the forme_route_csrf plugin.
         | 
| 10 | 
            -
                  def self.load_dependencies(app,  | 
| 10 | 
            +
                  def self.load_dependencies(app, opts = nil, &_)
         | 
| 11 11 | 
             
                    app.plugin :forme_route_csrf 
         | 
| 12 12 | 
             
                  end
         | 
| 13 13 |  | 
| @@ -102,7 +102,9 @@ class Roda | |
| 102 102 | 
             
                    def _forme_form_options(obj, attr, opts)
         | 
| 103 103 | 
             
                      super
         | 
| 104 104 |  | 
| 105 | 
            +
                      _after = opts[:_after]
         | 
| 105 106 | 
             
                      opts[:_after] = lambda do |form|
         | 
| 107 | 
            +
                        _after.call(form) if _after
         | 
| 106 108 | 
             
                        if (obj = form.opts[:obj]) && obj.respond_to?(:forme_inputs) && (forme_inputs = obj.forme_inputs)
         | 
| 107 109 | 
             
                          columns = []
         | 
| 108 110 | 
             
                          valid_values = {}
         | 
| @@ -129,6 +131,9 @@ class Roda | |
| 129 131 | 
             
                          data['columns'] = columns
         | 
| 130 132 | 
             
                          data['namespaces'] = form.opts[:namespace]
         | 
| 131 133 | 
             
                          data['csrf'] = form.opts[:csrf]
         | 
| 134 | 
            +
                          if (formactions = form.opts[:formaction_csrfs]) && !formactions[1].empty?
         | 
| 135 | 
            +
                            data['formaction_csrfs'] = formactions
         | 
| 136 | 
            +
                          end
         | 
| 132 137 | 
             
                          data['valid_values'] = valid_values unless valid_values.empty?
         | 
| 133 138 | 
             
                          data['form_version'] = form.opts[:form_version] if form.opts[:form_version]
         | 
| 134 139 |  | 
| @@ -154,8 +159,16 @@ class Roda | |
| 154 159 |  | 
| 155 160 | 
             
                      data = JSON.parse(data)
         | 
| 156 161 | 
             
                      csrf_field, hmac_csrf_value = data['csrf']
         | 
| 162 | 
            +
                      formaction_csrf_field, formaction_values = data['formaction_csrfs']
         | 
| 163 | 
            +
             | 
| 157 164 | 
             
                      if csrf_field
         | 
| 158 | 
            -
                         | 
| 165 | 
            +
                        formaction_params = params[formaction_csrf_field]
         | 
| 166 | 
            +
                        if formaction_csrf_field && (formaction_params = params[formaction_csrf_field]).is_a?(Hash) && (csrf_value = formaction_params[request.path])
         | 
| 167 | 
            +
                          hmac_csrf_value = formaction_values[request.path]
         | 
| 168 | 
            +
                        else
         | 
| 169 | 
            +
                          csrf_value = params[csrf_field].to_s
         | 
| 170 | 
            +
                        end
         | 
| 171 | 
            +
             | 
| 159 172 | 
             
                        hmac_csrf_value = hmac_csrf_value.to_s
         | 
| 160 173 | 
             
                        unless Rack::Utils.secure_compare(csrf_value.ljust(hmac_csrf_value.length), hmac_csrf_value) && csrf_value.length == hmac_csrf_value.length
         | 
| 161 174 | 
             
                          return _forme_parse_error(:csrf_mismatch, obj)
         | 
    
        data/lib/sequel/plugins/forme.rb
    CHANGED
    
    | @@ -17,6 +17,22 @@ module Sequel # :nodoc: | |
| 17 17 | 
             
                  # that use a <tt>Sequel::Model</tt> instance as the form's
         | 
| 18 18 | 
             
                  # +obj+.
         | 
| 19 19 | 
             
                  module SequelForm
         | 
| 20 | 
            +
                    # If the form has the :formactions option and the button has the
         | 
| 21 | 
            +
                    # formaction option or attribute, append the action and method
         | 
| 22 | 
            +
                    # for this button to the formactions. This is used by the
         | 
| 23 | 
            +
                    # Roda forme_route_csrf and forme_set plugins so that formaction
         | 
| 24 | 
            +
                    # can work as expected.
         | 
| 25 | 
            +
                    def button(opts={})
         | 
| 26 | 
            +
                      if opts.is_a?(Hash) && (formactions = self.opts[:formactions]) &&
         | 
| 27 | 
            +
                          (formaction = opts[:formaction] || ((attr = opts[:attr]) && (attr[:formaction] || attr['formaction'])))
         | 
| 28 | 
            +
                        formmethod = opts[:formmethod] ||
         | 
| 29 | 
            +
                          ((attr = opts[:attr]) && (attr[:formmethod] || attr['formmethod'])) ||
         | 
| 30 | 
            +
                          ((attr = form_tag_attributes) && (attr[:method] || attr['method']))
         | 
| 31 | 
            +
                        formactions << [formaction, formmethod]
         | 
| 32 | 
            +
                      end
         | 
| 33 | 
            +
                      super
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 20 36 | 
             
                    # Use the post method by default for Sequel forms, unless
         | 
| 21 37 | 
             
                    # overridden with the :method attribute.
         | 
| 22 38 | 
             
                    def form(attr={}, &block)
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: forme
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2. | 
| 4 | 
            +
              version: 2.6.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Jeremy Evans
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2024-06-18 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bigdecimal
         | 
| @@ -203,6 +203,7 @@ files: | |
| 203 203 | 
             
            - lib/forme/version.rb
         | 
| 204 204 | 
             
            - lib/roda/plugins/forme.rb
         | 
| 205 205 | 
             
            - lib/roda/plugins/forme_erubi_capture.rb
         | 
| 206 | 
            +
            - lib/roda/plugins/forme_erubi_capture_block.rb
         | 
| 206 207 | 
             
            - lib/roda/plugins/forme_route_csrf.rb
         | 
| 207 208 | 
             
            - lib/roda/plugins/forme_set.rb
         | 
| 208 209 | 
             
            - lib/sequel/plugins/forme.rb
         | 
| @@ -239,7 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 239 240 | 
             
                - !ruby/object:Gem::Version
         | 
| 240 241 | 
             
                  version: '0'
         | 
| 241 242 | 
             
            requirements: []
         | 
| 242 | 
            -
            rubygems_version: 3. | 
| 243 | 
            +
            rubygems_version: 3.5.9
         | 
| 243 244 | 
             
            signing_key:
         | 
| 244 245 | 
             
            specification_version: 4
         | 
| 245 246 | 
             
            summary: HTML forms library
         |