wedgeio 0.0.1
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 +7 -0
 - data/.gitignore +14 -0
 - data/Gemfile +9 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +49 -0
 - data/Rakefile +9 -0
 - data/lib/roda/plugins/wedge.rb +93 -0
 - data/lib/wedge.rb +238 -0
 - data/lib/wedge/component.rb +321 -0
 - data/lib/wedge/config.rb +128 -0
 - data/lib/wedge/dom.rb +139 -0
 - data/lib/wedge/events.rb +136 -0
 - data/lib/wedge/html.rb +29 -0
 - data/lib/wedge/opal.rb +18 -0
 - data/lib/wedge/plugins/form.rb +431 -0
 - data/lib/wedge/plugins/history.rb +92 -0
 - data/lib/wedge/plugins/location.rb +78 -0
 - data/lib/wedge/plugins/pjax.rb +65 -0
 - data/lib/wedge/plugins/validations.rb +251 -0
 - data/lib/wedge/utilis/blank.rb +133 -0
 - data/lib/wedge/utilis/element.rb +23 -0
 - data/lib/wedge/utilis/hash.rb +77 -0
 - data/lib/wedge/utilis/indifferent_hash.rb +209 -0
 - data/lib/wedge/utilis/methods.rb +25 -0
 - data/lib/wedge/utilis/nokogiri.rb +44 -0
 - data/lib/wedge/utilis/titleize.rb +97 -0
 - data/lib/wedge/utilis/try.rb +106 -0
 - data/lib/wedge/version.rb +3 -0
 - data/test.rb +44 -0
 - data/test/dummy/app.rb +34 -0
 - data/test/dummy/components/bar.rb +14 -0
 - data/test/dummy/components/base.rb +5 -0
 - data/test/dummy/components/root.rb +42 -0
 - data/test/dummy/config.ru +6 -0
 - data/test/dummy/forms/bar.rb +5 -0
 - data/test/dummy/forms/foo.rb +6 -0
 - data/test/test.js +59 -0
 - data/test/test_basic_component.rb +34 -0
 - data/test/test_browserio.rb +13 -0
 - data/test/test_helper.rb +38 -0
 - data/wedge.gemspec +32 -0
 - metadata +236 -0
 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Nokogiri
         
     | 
| 
      
 2 
     | 
    
         
            +
              module XML
         
     | 
| 
      
 3 
     | 
    
         
            +
                class NodeSet
         
     | 
| 
      
 4 
     | 
    
         
            +
                  # fix: this is really shity
         
     | 
| 
      
 5 
     | 
    
         
            +
                  # alias_method :original_to_html, :to_html
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # def to_html *args
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #   original_to_html(*args).gsub('%7B', "{").gsub('%7D', "}")
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # end
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
                class Node
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # fix: this is really shity
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # alias_method :original_to_html, :to_html
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # def to_html *args
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #   original_to_html(*args).gsub('%7B', "{").gsub('%7D', "}")
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  private
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def coerce data # :nodoc:
         
     | 
| 
      
 20 
     | 
    
         
            +
                    if data.class.to_s == 'Wedge::DOM'
         
     | 
| 
      
 21 
     | 
    
         
            +
                      data = data.dom
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    case data
         
     | 
| 
      
 25 
     | 
    
         
            +
                    when XML::NodeSet
         
     | 
| 
      
 26 
     | 
    
         
            +
                      return data
         
     | 
| 
      
 27 
     | 
    
         
            +
                    when XML::DocumentFragment
         
     | 
| 
      
 28 
     | 
    
         
            +
                      return data.children
         
     | 
| 
      
 29 
     | 
    
         
            +
                    when String
         
     | 
| 
      
 30 
     | 
    
         
            +
                      return fragment(data).children
         
     | 
| 
      
 31 
     | 
    
         
            +
                    when Document, XML::Attr
         
     | 
| 
      
 32 
     | 
    
         
            +
                      # unacceptable
         
     | 
| 
      
 33 
     | 
    
         
            +
                    when XML::Node
         
     | 
| 
      
 34 
     | 
    
         
            +
                      return data
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    raise ArgumentError, <<-EOERR
         
     | 
| 
      
 38 
     | 
    
         
            +
            Requires a Node, NodeSet or String argument, and cannot accept a #{data.class}.
         
     | 
| 
      
 39 
     | 
    
         
            +
            (You probably want to select a node from the Document with at() or search(), or create a new Node via Node.new().)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    EOERR
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Adds String#titleize for creating properly capitalized titles.
         
     | 
| 
      
 3 
     | 
    
         
            +
            # It can be called as Titleize.titleize or "a string".titleize.
         
     | 
| 
      
 4 
     | 
    
         
            +
            #
         
     | 
| 
      
 5 
     | 
    
         
            +
            # titlecase is included as an alias for titleize.
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            # If loaded in a Rails environment, it modifies Inflector.titleize.
         
     | 
| 
      
 8 
     | 
    
         
            +
            module Titleize
         
     | 
| 
      
 9 
     | 
    
         
            +
              SMALL_WORDS = %w{a an and as at but by en for if in of on or the to v v. via vs vs.}
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              extend self
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              # Capitalizes most words to create a nicer looking title string.
         
     | 
| 
      
 14 
     | 
    
         
            +
              #
         
     | 
| 
      
 15 
     | 
    
         
            +
              # The list of "small words" which are not capped comes from
         
     | 
| 
      
 16 
     | 
    
         
            +
              # the New York Times Manual of Style, plus 'vs' and 'v'.
         
     | 
| 
      
 17 
     | 
    
         
            +
              #
         
     | 
| 
      
 18 
     | 
    
         
            +
              #   "notes on a scandal" # => "Notes on a Scandal"
         
     | 
| 
      
 19 
     | 
    
         
            +
              #   "the good german"    # => "The Good German"
         
     | 
| 
      
 20 
     | 
    
         
            +
              def titleize(title)
         
     | 
| 
      
 21 
     | 
    
         
            +
                title = title.dup
         
     | 
| 
      
 22 
     | 
    
         
            +
                title.downcase! unless title[/[[:lower:]]/]  # assume all-caps need fixing
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                phrases(title).map do |phrase|
         
     | 
| 
      
 25 
     | 
    
         
            +
                  words = phrase.split
         
     | 
| 
      
 26 
     | 
    
         
            +
                  words.map do |word|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    def word.capitalize
         
     | 
| 
      
 28 
     | 
    
         
            +
                      # like String#capitalize, but it starts with the first letter
         
     | 
| 
      
 29 
     | 
    
         
            +
                      self.sub(/[[:alpha:]].*/) {|subword| subword.capitalize}
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    case word
         
     | 
| 
      
 33 
     | 
    
         
            +
                    when /[[:alpha:]]\.[[:alpha:]]/  # words with dots in, like "example.com"
         
     | 
| 
      
 34 
     | 
    
         
            +
                      word
         
     | 
| 
      
 35 
     | 
    
         
            +
                    when /[-‑]/  # hyphenated word (regular and non-breaking)
         
     | 
| 
      
 36 
     | 
    
         
            +
                      word.split(/([-‑])/).map do |part|
         
     | 
| 
      
 37 
     | 
    
         
            +
                        SMALL_WORDS.include?(part) ? part : part.capitalize
         
     | 
| 
      
 38 
     | 
    
         
            +
                      end.join
         
     | 
| 
      
 39 
     | 
    
         
            +
                    when /^[[:alpha:]].*[[:upper:]]/ # non-first letter capitalized already
         
     | 
| 
      
 40 
     | 
    
         
            +
                      word
         
     | 
| 
      
 41 
     | 
    
         
            +
                    when /^[[:digit:]]/  # first character is a number
         
     | 
| 
      
 42 
     | 
    
         
            +
                      word
         
     | 
| 
      
 43 
     | 
    
         
            +
                    when words.first, words.last
         
     | 
| 
      
 44 
     | 
    
         
            +
                      word.capitalize
         
     | 
| 
      
 45 
     | 
    
         
            +
                    when *(SMALL_WORDS + SMALL_WORDS.map {|small| small.capitalize })
         
     | 
| 
      
 46 
     | 
    
         
            +
                      word.downcase
         
     | 
| 
      
 47 
     | 
    
         
            +
                    else
         
     | 
| 
      
 48 
     | 
    
         
            +
                      word.capitalize
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end.join(" ")
         
     | 
| 
      
 51 
     | 
    
         
            +
                end.join(" ")
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              # Splits a title into an array based on punctuation.
         
     | 
| 
      
 55 
     | 
    
         
            +
              #
         
     | 
| 
      
 56 
     | 
    
         
            +
              #   "simple title"              # => ["simple title"]
         
     | 
| 
      
 57 
     | 
    
         
            +
              #   "more complicated: titling" # => ["more complicated:", "titling"]
         
     | 
| 
      
 58 
     | 
    
         
            +
              def phrases(title)
         
     | 
| 
      
 59 
     | 
    
         
            +
                phrases = title.scan(/.+?(?:[:.;?!] |$)/).map {|phrase| phrase.strip }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # rejoin phrases that were split on the '.' from a small word
         
     | 
| 
      
 62 
     | 
    
         
            +
                if phrases.size > 1
         
     | 
| 
      
 63 
     | 
    
         
            +
                  phrases[0..-2].each_with_index do |phrase, index|
         
     | 
| 
      
 64 
     | 
    
         
            +
                    if SMALL_WORDS.include?(phrase.split.last.downcase)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      phrases[index] << " " + phrases.slice!(index + 1)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                phrases
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            class String
         
     | 
| 
      
 75 
     | 
    
         
            +
              # Capitalizes most words to create a nicer looking title string.
         
     | 
| 
      
 76 
     | 
    
         
            +
              #
         
     | 
| 
      
 77 
     | 
    
         
            +
              # The list of "small words" which are not capped comes from
         
     | 
| 
      
 78 
     | 
    
         
            +
              # the New York Times Manual of Style, plus 'vs' and 'v'.
         
     | 
| 
      
 79 
     | 
    
         
            +
              #
         
     | 
| 
      
 80 
     | 
    
         
            +
              # titleize is also aliased as titlecase.
         
     | 
| 
      
 81 
     | 
    
         
            +
              #
         
     | 
| 
      
 82 
     | 
    
         
            +
              #   "notes on a scandal" # => "Notes on a Scandal"
         
     | 
| 
      
 83 
     | 
    
         
            +
              #   "the good german"    # => "The Good German"
         
     | 
| 
      
 84 
     | 
    
         
            +
              def titleize(opts={})
         
     | 
| 
      
 85 
     | 
    
         
            +
                # if defined? ActiveSupport
         
     | 
| 
      
 86 
     | 
    
         
            +
                #   ActiveSupport::Inflector.titleize(self, opts)
         
     | 
| 
      
 87 
     | 
    
         
            +
                # else
         
     | 
| 
      
 88 
     | 
    
         
            +
                  Titleize.titleize(self)
         
     | 
| 
      
 89 
     | 
    
         
            +
                # end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
              alias_method :titlecase, :titleize
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              def titleize!
         
     | 
| 
      
 94 
     | 
    
         
            +
                replace(titleize)
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
              alias_method :titlecase!, :titleize!
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,106 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Object
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Invokes the public method whose name goes as first argument just like
         
     | 
| 
      
 3 
     | 
    
         
            +
              # +public_send+ does, except that if the receiver does not respond to it the
         
     | 
| 
      
 4 
     | 
    
         
            +
              # call returns +nil+ rather than raising an exception.
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # This method is defined to be able to write
         
     | 
| 
      
 7 
     | 
    
         
            +
              #
         
     | 
| 
      
 8 
     | 
    
         
            +
              #   @person.try(:name)
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              # instead of
         
     | 
| 
      
 11 
     | 
    
         
            +
              #
         
     | 
| 
      
 12 
     | 
    
         
            +
              #   @person.name if @person
         
     | 
| 
      
 13 
     | 
    
         
            +
              #
         
     | 
| 
      
 14 
     | 
    
         
            +
              # +try+ calls can be chained:
         
     | 
| 
      
 15 
     | 
    
         
            +
              #
         
     | 
| 
      
 16 
     | 
    
         
            +
              #   @person.try(:spouse).try(:name)
         
     | 
| 
      
 17 
     | 
    
         
            +
              #
         
     | 
| 
      
 18 
     | 
    
         
            +
              # instead of
         
     | 
| 
      
 19 
     | 
    
         
            +
              #
         
     | 
| 
      
 20 
     | 
    
         
            +
              #   @person.spouse.name if @person && @person.spouse
         
     | 
| 
      
 21 
     | 
    
         
            +
              #
         
     | 
| 
      
 22 
     | 
    
         
            +
              # +try+ will also return +nil+ if the receiver does not respond to the method:
         
     | 
| 
      
 23 
     | 
    
         
            +
              #
         
     | 
| 
      
 24 
     | 
    
         
            +
              #   @person.try(:non_existing_method) # => nil
         
     | 
| 
      
 25 
     | 
    
         
            +
              #
         
     | 
| 
      
 26 
     | 
    
         
            +
              # instead of
         
     | 
| 
      
 27 
     | 
    
         
            +
              #
         
     | 
| 
      
 28 
     | 
    
         
            +
              #   @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
         
     | 
| 
      
 29 
     | 
    
         
            +
              #
         
     | 
| 
      
 30 
     | 
    
         
            +
              # +try+ returns +nil+ when called on +nil+ regardless of whether it responds
         
     | 
| 
      
 31 
     | 
    
         
            +
              # to the method:
         
     | 
| 
      
 32 
     | 
    
         
            +
              #
         
     | 
| 
      
 33 
     | 
    
         
            +
              #   nil.try(:to_i) # => nil, rather than 0
         
     | 
| 
      
 34 
     | 
    
         
            +
              #
         
     | 
| 
      
 35 
     | 
    
         
            +
              # Arguments and blocks are forwarded to the method if invoked:
         
     | 
| 
      
 36 
     | 
    
         
            +
              #
         
     | 
| 
      
 37 
     | 
    
         
            +
              #   @posts.try(:each_slice, 2) do |a, b|
         
     | 
| 
      
 38 
     | 
    
         
            +
              #     ...
         
     | 
| 
      
 39 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 40 
     | 
    
         
            +
              #
         
     | 
| 
      
 41 
     | 
    
         
            +
              # The number of arguments in the signature must match. If the object responds
         
     | 
| 
      
 42 
     | 
    
         
            +
              # to the method the call is attempted and +ArgumentError+ is still raised
         
     | 
| 
      
 43 
     | 
    
         
            +
              # in case of argument mismatch.
         
     | 
| 
      
 44 
     | 
    
         
            +
              #
         
     | 
| 
      
 45 
     | 
    
         
            +
              # If +try+ is called without arguments it yields the receiver to a given
         
     | 
| 
      
 46 
     | 
    
         
            +
              # block unless it is +nil+:
         
     | 
| 
      
 47 
     | 
    
         
            +
              #
         
     | 
| 
      
 48 
     | 
    
         
            +
              #   @person.try do |p|
         
     | 
| 
      
 49 
     | 
    
         
            +
              #     ...
         
     | 
| 
      
 50 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 51 
     | 
    
         
            +
              #
         
     | 
| 
      
 52 
     | 
    
         
            +
              # You can also call try with a block without accepting an argument, and the block
         
     | 
| 
      
 53 
     | 
    
         
            +
              # will be instance_eval'ed instead:
         
     | 
| 
      
 54 
     | 
    
         
            +
              #
         
     | 
| 
      
 55 
     | 
    
         
            +
              #   @person.try { upcase.truncate(50) }
         
     | 
| 
      
 56 
     | 
    
         
            +
              #
         
     | 
| 
      
 57 
     | 
    
         
            +
              # Please also note that +try+ is defined on +Object+. Therefore, it won't work
         
     | 
| 
      
 58 
     | 
    
         
            +
              # with instances of classes that do not have +Object+ among their ancestors,
         
     | 
| 
      
 59 
     | 
    
         
            +
              # like direct subclasses of +BasicObject+. For example, using +try+ with
         
     | 
| 
      
 60 
     | 
    
         
            +
              # +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
         
     | 
| 
      
 61 
     | 
    
         
            +
              # the delegator itself.
         
     | 
| 
      
 62 
     | 
    
         
            +
              def try(*a, &b)
         
     | 
| 
      
 63 
     | 
    
         
            +
                try!(*a, &b) if a.empty? || respond_to?(a.first)
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              # Same as #try, but raises a NoMethodError exception if the receiver is
         
     | 
| 
      
 67 
     | 
    
         
            +
              # not +nil+ and does not implement the tried method.
         
     | 
| 
      
 68 
     | 
    
         
            +
              #
         
     | 
| 
      
 69 
     | 
    
         
            +
              #   "a".try!(:upcase) # => "A"
         
     | 
| 
      
 70 
     | 
    
         
            +
              #   nil.try!(:upcase) # => nil
         
     | 
| 
      
 71 
     | 
    
         
            +
              #   123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Fixnum
         
     | 
| 
      
 72 
     | 
    
         
            +
              def try!(*a, &b)
         
     | 
| 
      
 73 
     | 
    
         
            +
                if a.empty? && block_given?
         
     | 
| 
      
 74 
     | 
    
         
            +
                  if b.arity.zero?
         
     | 
| 
      
 75 
     | 
    
         
            +
                    instance_eval(&b)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  else
         
     | 
| 
      
 77 
     | 
    
         
            +
                    yield self
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                else
         
     | 
| 
      
 80 
     | 
    
         
            +
                  public_send(*a, &b)
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
            end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
            class NilClass
         
     | 
| 
      
 86 
     | 
    
         
            +
              # Calling +try+ on +nil+ always returns +nil+.
         
     | 
| 
      
 87 
     | 
    
         
            +
              # It becomes especially helpful when navigating through associations that may return +nil+.
         
     | 
| 
      
 88 
     | 
    
         
            +
              #
         
     | 
| 
      
 89 
     | 
    
         
            +
              #   nil.try(:name) # => nil
         
     | 
| 
      
 90 
     | 
    
         
            +
              #
         
     | 
| 
      
 91 
     | 
    
         
            +
              # Without +try+
         
     | 
| 
      
 92 
     | 
    
         
            +
              #   @person && @person.children.any? && @person.children.first.name
         
     | 
| 
      
 93 
     | 
    
         
            +
              #
         
     | 
| 
      
 94 
     | 
    
         
            +
              # With +try+
         
     | 
| 
      
 95 
     | 
    
         
            +
              #   @person.try(:children).try(:first).try(:name)
         
     | 
| 
      
 96 
     | 
    
         
            +
              def try(*args)
         
     | 
| 
      
 97 
     | 
    
         
            +
                nil
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              # Calling +try!+ on +nil+ always returns +nil+.
         
     | 
| 
      
 101 
     | 
    
         
            +
              #
         
     | 
| 
      
 102 
     | 
    
         
            +
              #   nil.try!(:name) # => nil
         
     | 
| 
      
 103 
     | 
    
         
            +
              def try!(*args)
         
     | 
| 
      
 104 
     | 
    
         
            +
                nil
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
            end
         
     | 
    
        data/test.rb
    ADDED
    
    | 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'awesome_print'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            requires = {
         
     | 
| 
      
 4 
     | 
    
         
            +
              form_plugin: [],
         
     | 
| 
      
 5 
     | 
    
         
            +
              list: [
         
     | 
| 
      
 6 
     | 
    
         
            +
                {
         
     | 
| 
      
 7 
     | 
    
         
            +
                  name: 'claim',
         
     | 
| 
      
 8 
     | 
    
         
            +
                  requires: [
         
     | 
| 
      
 9 
     | 
    
         
            +
                    {name: 'filter_form', requires: [{ name: 'form_plugin', requires: [] }]},
         
     | 
| 
      
 10 
     | 
    
         
            +
                    {name: 'claim_form', requires: []}
         
     | 
| 
      
 11 
     | 
    
         
            +
                  ],
         
     | 
| 
      
 12 
     | 
    
         
            +
                },
         
     | 
| 
      
 13 
     | 
    
         
            +
                {
         
     | 
| 
      
 14 
     | 
    
         
            +
                  name: 'claim_form',
         
     | 
| 
      
 15 
     | 
    
         
            +
                  requires: [
         
     | 
| 
      
 16 
     | 
    
         
            +
                    {name: 'form_plugin', requires: []},
         
     | 
| 
      
 17 
     | 
    
         
            +
                    {name: 'address_form', requires: [{ name: 'form_plugin', requires: [] }]}
         
     | 
| 
      
 18 
     | 
    
         
            +
                  ],
         
     | 
| 
      
 19 
     | 
    
         
            +
                }
         
     | 
| 
      
 20 
     | 
    
         
            +
              ]
         
     | 
| 
      
 21 
     | 
    
         
            +
            }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            $loaded_requires = []
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            def get_requires reqs, requires_array = []
         
     | 
| 
      
 26 
     | 
    
         
            +
              new_reqs = []
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              reqs.each do |r|
         
     | 
| 
      
 29 
     | 
    
         
            +
                if r[:requires].any?
         
     | 
| 
      
 30 
     | 
    
         
            +
                  get_requires(r[:requires], requires_array)
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                unless $loaded_requires.include? r[:name]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  $loaded_requires << r[:name]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  new_reqs         << r[:name]
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              requires_array << new_reqs if new_reqs.any?
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              requires_array
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            ap get_requires requires[:list]
         
     | 
    
        data/test/dummy/app.rb
    ADDED
    
    | 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'wedge'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'roda'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'pry'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'awesome_print'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ROOT_PATH = File.dirname(__FILE__)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            class DummyApp < Roda
         
     | 
| 
      
 10 
     | 
    
         
            +
              plugin :wedge, {
         
     | 
| 
      
 11 
     | 
    
         
            +
                scope: self,
         
     | 
| 
      
 12 
     | 
    
         
            +
                plugins: [:form]
         
     | 
| 
      
 13 
     | 
    
         
            +
              }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              plugin :assets, {
         
     | 
| 
      
 16 
     | 
    
         
            +
                group_subdirs: false,
         
     | 
| 
      
 17 
     | 
    
         
            +
                path: ROOT_PATH,
         
     | 
| 
      
 18 
     | 
    
         
            +
                css_dir: '',
         
     | 
| 
      
 19 
     | 
    
         
            +
                js_dir: ''
         
     | 
| 
      
 20 
     | 
    
         
            +
              }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              route do |r|
         
     | 
| 
      
 23 
     | 
    
         
            +
                r.wedge_assets
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                r.root do
         
     | 
| 
      
 26 
     | 
    
         
            +
                  wedge(:root, :js).display
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            Dir["#{ROOT_PATH}/forms/*.rb"].sort.each { |file| require file }
         
     | 
| 
      
 32 
     | 
    
         
            +
            Dir["#{ROOT_PATH}/components/*.rb"].sort.each { |file| require file }
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            Wedge.cache # cache files on app load
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'base' unless RUBY_ENGINE == 'opal'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class DummyApp
         
     | 
| 
      
 4 
     | 
    
         
            +
              class RootComponent < BaseComponent
         
     | 
| 
      
 5 
     | 
    
         
            +
                config.name :root
         
     | 
| 
      
 6 
     | 
    
         
            +
                config.html <<-HTML
         
     | 
| 
      
 7 
     | 
    
         
            +
                  <!DOCTYPE html>
         
     | 
| 
      
 8 
     | 
    
         
            +
                  <html>
         
     | 
| 
      
 9 
     | 
    
         
            +
                    <head>
         
     | 
| 
      
 10 
     | 
    
         
            +
                      <script src="//code.jquery.com/jquery-1.11.2.js"></script>
         
     | 
| 
      
 11 
     | 
    
         
            +
                      #{Wedge.script_tag}
         
     | 
| 
      
 12 
     | 
    
         
            +
                    </head>
         
     | 
| 
      
 13 
     | 
    
         
            +
                    <body>
         
     | 
| 
      
 14 
     | 
    
         
            +
                      <div id='foo'>bar</div>
         
     | 
| 
      
 15 
     | 
    
         
            +
                    </body>
         
     | 
| 
      
 16 
     | 
    
         
            +
                  </html>
         
     | 
| 
      
 17 
     | 
    
         
            +
                HTML
         
     | 
| 
      
 18 
     | 
    
         
            +
                config.dom do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  dom.find('body') << assets(:js)
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
                config.requires :base, :bar, :foo_form, :pjax_plugin
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def display
         
     | 
| 
      
 24 
     | 
    
         
            +
                  if server?
         
     | 
| 
      
 25 
     | 
    
         
            +
                    dom
         
     | 
| 
      
 26 
     | 
    
         
            +
                  else
         
     | 
| 
      
 27 
     | 
    
         
            +
                    el = Element['<div>']
         
     | 
| 
      
 28 
     | 
    
         
            +
                    el.html 'foo'
         
     | 
| 
      
 29 
     | 
    
         
            +
                    dom.find('#foo').before el
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                on :ready do
         
     | 
| 
      
 34 
     | 
    
         
            +
                  puts 'dom ready'
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                on :click, '#foo' do |el|
         
     | 
| 
      
 38 
     | 
    
         
            +
                  el.after '<div>bar</div>'
         
     | 
| 
      
 39 
     | 
    
         
            +
                  trigger :clicked_foo
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
    
        data/test/test.js
    ADDED
    
    | 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            var page = require('webpage').create();
         
     | 
| 
      
 2 
     | 
    
         
            +
            page.settings.localToRemoteUrlAccessEnabled = true;
         
     | 
| 
      
 3 
     | 
    
         
            +
            page.settings.resourceTimeout = 1000;
         
     | 
| 
      
 4 
     | 
    
         
            +
            // page.content = "<!doctype html>\n<html>\n<head>\new<script type=\"text/javascript\" src=\"https://code.jquery.com/jquery-1.11.2.min.js\"></script>\n</head>\n<body>\n<div id=\"foo\">bar<div>\n</body>\n</html>";
         
     | 
| 
      
 5 
     | 
    
         
            +
            var content = '<!doctype html>';
         
     | 
| 
      
 6 
     | 
    
         
            +
            content += '<html><head>';
         
     | 
| 
      
 7 
     | 
    
         
            +
            content += '<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.min.js"></script>';
         
     | 
| 
      
 8 
     | 
    
         
            +
            content += '</head><body>';
         
     | 
| 
      
 9 
     | 
    
         
            +
            content += '<h1 id="foo">bar</h1>';
         
     | 
| 
      
 10 
     | 
    
         
            +
            content += '</body></html>';
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            // page.content = "<div id='foo'>bar</div>";
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            page.onConsoleMessage = function(msg) {
         
     | 
| 
      
 15 
     | 
    
         
            +
              console.log(msg);
         
     | 
| 
      
 16 
     | 
    
         
            +
            };
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            page.onResourceTimeout = function(a) {
         
     | 
| 
      
 19 
     | 
    
         
            +
              phantom.exit(1);
         
     | 
| 
      
 20 
     | 
    
         
            +
            };
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            page.onError = function(msg, trace) {
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              var msgStack = ['ERROR: ' + msg];
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              if (trace && trace.length) {
         
     | 
| 
      
 27 
     | 
    
         
            +
                msgStack.push('TRACE:');
         
     | 
| 
      
 28 
     | 
    
         
            +
                trace.forEach(function(t) {
         
     | 
| 
      
 29 
     | 
    
         
            +
                  msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
         
     | 
| 
      
 30 
     | 
    
         
            +
                });
         
     | 
| 
      
 31 
     | 
    
         
            +
              }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              console.log(msgStack.join('\n'));
         
     | 
| 
      
 34 
     | 
    
         
            +
              phantom.exit();
         
     | 
| 
      
 35 
     | 
    
         
            +
            };
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            phantom.onError = function(msg, trace) {
         
     | 
| 
      
 38 
     | 
    
         
            +
              var msgStack = ['PHANTOM ERROR: ' + msg];
         
     | 
| 
      
 39 
     | 
    
         
            +
              if (trace && trace.length) {
         
     | 
| 
      
 40 
     | 
    
         
            +
                msgStack.push('TRACE:');
         
     | 
| 
      
 41 
     | 
    
         
            +
                trace.forEach(function(t) {
         
     | 
| 
      
 42 
     | 
    
         
            +
                  msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function +')' : ''));
         
     | 
| 
      
 43 
     | 
    
         
            +
                });
         
     | 
| 
      
 44 
     | 
    
         
            +
              }
         
     | 
| 
      
 45 
     | 
    
         
            +
              console.log(msgStack.join('\n'));
         
     | 
| 
      
 46 
     | 
    
         
            +
              phantom.exit();
         
     | 
| 
      
 47 
     | 
    
         
            +
            };
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            page.content = content
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            page.onLoadFinished = function() {
         
     | 
| 
      
 52 
     | 
    
         
            +
              page.evaluate(function() {
         
     | 
| 
      
 53 
     | 
    
         
            +
                console.log($('#foo').html());
         
     | 
| 
      
 54 
     | 
    
         
            +
              });
         
     | 
| 
      
 55 
     | 
    
         
            +
              phantom.exit();
         
     | 
| 
      
 56 
     | 
    
         
            +
            };
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            // page.includeJs("http://code.jquery.com/jquery-1.11.2.min.js", function(){
         
     | 
| 
      
 59 
     | 
    
         
            +
            // });
         
     |