former 0.0.2 → 1.0.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.
- data/.ruby-gemset +1 -0
 - data/.ruby-version +1 -0
 - data/README.rdoc +12 -15
 - data/former.gemspec +0 -1
 - data/lib/former/builder.rb +25 -16
 - data/lib/former/element.rb +5 -11
 - data/lib/former/version.rb +1 -1
 - data/test/builder_test.rb +25 -1
 - metadata +6 -20
 
    
        data/.ruby-gemset
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            former
         
     | 
    
        data/.ruby-version
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ruby-1.9.3-p392
         
     | 
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -32,15 +32,14 @@ In this example, we want to be able to edit the location of all links that have 
     | 
|
| 
       32 
32 
     | 
    
         
             
            To produce the input fields from some example input HTML, first create an instance of your parser.
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
34 
     | 
    
         
             
              parsed = Parser.new "<p>some text<a class='important' href='http://alink.com'>some link text<img src='/an/image/path' /></a>last text</p>"
         
     | 
| 
       35 
     | 
    
         
            -
              puts parsed.to_form_html
         
     | 
| 
       36 
35 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
      
 36 
     | 
    
         
            +
            Then, we can get information about the editable fields:
         
     | 
| 
       38 
37 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
               
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
              <input name= 
     | 
| 
      
 38 
     | 
    
         
            +
              parsed.each { |elem| puts "#{elem.node.name} is #{elem.value}" }
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            And, even create an html form from this:
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              parsed.each { |elem| puts "<input name='former_0' type='text' value='#{elem.value}' />" }
         
     | 
| 
       44 
43 
     | 
    
         | 
| 
       45 
44 
     | 
    
         
             
            You can also convert the original html to json:
         
     | 
| 
       46 
45 
     | 
    
         | 
| 
         @@ -61,14 +60,12 @@ Will produce the original html with the new field values: 
     | 
|
| 
       61 
60 
     | 
    
         | 
| 
       62 
61 
     | 
    
         
             
              <p>A New Description<a class='important' href='http://anewlink.com'>some link...
         
     | 
| 
       63 
62 
     | 
    
         | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
      
 63 
     | 
    
         
            +
            If you want finer grained control over what's considered an editable element, you can pass a block in as well to the attr method.  For instance, if you want only text fields that are not empty, you could use:
         
     | 
| 
       65 
64 
     | 
    
         | 
| 
       66 
65 
     | 
    
         
             
              class Parser < Former::Builder
         
     | 
| 
       67 
     | 
    
         
            -
                 
     | 
| 
       68 
     | 
    
         
            -
                attr("img", :src) { |elem, name|
         
     | 
| 
       69 
     | 
    
         
            -
                  # If the src url is a really long bit of text, you could do something like this.
         
     | 
| 
       70 
     | 
    
         
            -
                  # The name is the name (which has the index) necessary to set the value on a GET/POST
         
     | 
| 
       71 
     | 
    
         
            -
                  "<textarea name='#{name}'></textarea>"
         
     | 
| 
       72 
     | 
    
         
            -
                }
         
     | 
| 
       73 
     | 
    
         
            -
                text "p", "a.important"
         
     | 
| 
      
 66 
     | 
    
         
            +
                text("p", "a.important") { |elem| not elem.text.strip.empty? }
         
     | 
| 
       74 
67 
     | 
    
         
             
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              p = Parser.new("<p>\n</p><p>some text</p>").length # this is only 1
         
     | 
| 
      
 70 
     | 
    
         
            +
              p[0] = 'other text'
         
     | 
| 
      
 71 
     | 
    
         
            +
              p.to_html # => '<p>\n</p><p>other text</p>'
         
     | 
    
        data/former.gemspec
    CHANGED
    
    | 
         @@ -14,7 +14,6 @@ Gem::Specification.new do |gem| 
     | 
|
| 
       14 
14 
     | 
    
         
             
              gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
         
     | 
| 
       15 
15 
     | 
    
         
             
              gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
       16 
16 
     | 
    
         
             
              gem.require_paths = ["lib"]
         
     | 
| 
       17 
     | 
    
         
            -
              gem.add_dependency("actionpack", ">= 4.0.3")
         
     | 
| 
       18 
17 
     | 
    
         
             
              gem.add_dependency("nokogiri", ">= 1.6.0")
         
     | 
| 
       19 
18 
     | 
    
         
             
              gem.add_development_dependency("rake")
         
     | 
| 
       20 
19 
     | 
    
         
             
              gem.add_development_dependency("rdoc")
         
     | 
    
        data/lib/former/builder.rb
    CHANGED
    
    | 
         @@ -9,8 +9,8 @@ module Former 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  @html = Nokogiri::HTML.parse(html)
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                  matches = {}
         
     | 
| 
       12 
     | 
    
         
            -
                  self.class.queries.each  
     | 
| 
       13 
     | 
    
         
            -
                    @html.search(path).each  
     | 
| 
      
 12 
     | 
    
         
            +
                  self.class.queries.each do |path, qs|
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @html.search(path).each do |node| 
         
     | 
| 
       14 
14 
     | 
    
         
             
                      # if all we need is the text, only include text kids
         
     | 
| 
       15 
15 
     | 
    
         
             
                      if qs.length == 1 and qs.first[:query] == :text
         
     | 
| 
       16 
16 
     | 
    
         
             
                        node.traverse { |e| matches[e] = qs if e.text? and not matches.keys.include? e }
         
     | 
| 
         @@ -18,23 +18,29 @@ module Former 
     | 
|
| 
       18 
18 
     | 
    
         
             
                        # otherwise, ignore just text requests
         
     | 
| 
       19 
19 
     | 
    
         
             
                        matches[node] = qs.select { |q| q[:query] != :text }
         
     | 
| 
       20 
20 
     | 
    
         
             
                      end
         
     | 
| 
       21 
     | 
    
         
            -
                     
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
                  @editable = []
         
     | 
| 
       25 
     | 
    
         
            -
                  @html.traverse_prefix  
     | 
| 
       26 
     | 
    
         
            -
                    (matches[e] || []).each  
     | 
| 
       27 
     | 
    
         
            -
                       
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
      
 25 
     | 
    
         
            +
                  @html.traverse_prefix do |e|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    (matches[e] || []).each do |query|
         
     | 
| 
      
 27 
     | 
    
         
            +
                      if query[:block].nil? or query[:block].call(e)
         
     | 
| 
      
 28 
     | 
    
         
            +
                        @editable << Element.new(e, query[:query], @editable.length)
         
     | 
| 
      
 29 
     | 
    
         
            +
                      end
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  
         
     | 
| 
      
 33 
     | 
    
         
            +
                  # if we were given text only (no html), nokogiri will helpfully
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # wrap it in a <p> - but our output should just be text.  So remember.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @nothtml = (@editable.length == 1 and @html.text == html)
         
     | 
| 
       30 
36 
     | 
    
         
             
                end
         
     | 
| 
       31 
37 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                def  
     | 
| 
       33 
     | 
    
         
            -
                  @editable. 
     | 
| 
      
 38 
     | 
    
         
            +
                def length
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @editable.length
         
     | 
| 
       34 
40 
     | 
    
         
             
                end
         
     | 
| 
       35 
41 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                def  
     | 
| 
       37 
     | 
    
         
            -
                  @editable. 
     | 
| 
      
 42 
     | 
    
         
            +
                def each(&block)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @editable.each { |e| block.call(e) }
         
     | 
| 
       38 
44 
     | 
    
         
             
                end
         
     | 
| 
       39 
45 
     | 
    
         | 
| 
       40 
46 
     | 
    
         
             
                def to_json
         
     | 
| 
         @@ -42,12 +48,15 @@ module Former 
     | 
|
| 
       42 
48 
     | 
    
         
             
                end
         
     | 
| 
       43 
49 
     | 
    
         | 
| 
       44 
50 
     | 
    
         
             
                def to_html
         
     | 
| 
       45 
     | 
    
         
            -
                   
     | 
| 
       46 
     | 
    
         
            -
                   
     | 
| 
      
 51 
     | 
    
         
            +
                  return @html.text if @nothtml
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # nokogiri pads w/ html/body elements
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @html.xpath("/html/body").children.map { |c|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    c.serialize(:save_with => Nokogiri::XML::Node::SaveOptions::AS_HTML).strip
         
     | 
| 
      
 55 
     | 
    
         
            +
                  }.join
         
     | 
| 
       47 
56 
     | 
    
         
             
                end
         
     | 
| 
       48 
57 
     | 
    
         | 
| 
       49 
58 
     | 
    
         
             
                def []=(index, value)
         
     | 
| 
       50 
     | 
    
         
            -
                  @editable[index]. 
     | 
| 
      
 59 
     | 
    
         
            +
                  @editable[index].value = value
         
     | 
| 
       51 
60 
     | 
    
         
             
                end
         
     | 
| 
       52 
61 
     | 
    
         | 
| 
       53 
62 
     | 
    
         
             
                # vals should be { :former_0 => 'value', :former_1 => 'value two', ... }
         
     | 
    
        data/lib/former/element.rb
    CHANGED
    
    | 
         @@ -1,15 +1,12 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'action_view'
         
     | 
| 
       2 
1 
     | 
    
         
             
            require 'json'
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
3 
     | 
    
         
             
            module Former
         
     | 
| 
       5 
4 
     | 
    
         
             
              class Element
         
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
       7 
     | 
    
         
            -
                attr_reader :node, :query, :block
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :node, :query
         
     | 
| 
       8 
6 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                def initialize(node, query, index 
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(node, query, index)
         
     | 
| 
       10 
8 
     | 
    
         
             
                  @node = node
         
     | 
| 
       11 
9 
     | 
    
         
             
                  @query = query
         
     | 
| 
       12 
     | 
    
         
            -
                  @block = block
         
     | 
| 
       13 
10 
     | 
    
         
             
                  @index = index
         
     | 
| 
       14 
11 
     | 
    
         
             
                end
         
     | 
| 
       15 
12 
     | 
    
         | 
| 
         @@ -22,14 +19,11 @@ module Former 
     | 
|
| 
       22 
19 
     | 
    
         
             
                  h.to_json
         
     | 
| 
       23 
20 
     | 
    
         
             
                end
         
     | 
| 
       24 
21 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                def  
     | 
| 
       26 
     | 
    
         
            -
                   
     | 
| 
       27 
     | 
    
         
            -
                  return @block.call(@node, name) unless @block.nil?
         
     | 
| 
       28 
     | 
    
         
            -
                  value = (@query == :text) ? @node.text : @node[@query]
         
     | 
| 
       29 
     | 
    
         
            -
                  tag(:input, :type => 'text', :name => name, :value => value)
         
     | 
| 
      
 22 
     | 
    
         
            +
                def value
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @query == :text ? @node.content : @node[@query]
         
     | 
| 
       30 
24 
     | 
    
         
             
                end
         
     | 
| 
       31 
25 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                def  
     | 
| 
      
 26 
     | 
    
         
            +
                def value=(value)
         
     | 
| 
       33 
27 
     | 
    
         
             
                  if @query == :text
         
     | 
| 
       34 
28 
     | 
    
         
             
                    @node.content = value
         
     | 
| 
       35 
29 
     | 
    
         
             
                  else
         
     | 
    
        data/lib/former/version.rb
    CHANGED
    
    
    
        data/test/builder_test.rb
    CHANGED
    
    | 
         @@ -13,12 +13,36 @@ class AllTextParser < Former::Builder 
     | 
|
| 
       13 
13 
     | 
    
         
             
              text
         
     | 
| 
       14 
14 
     | 
    
         
             
            end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
      
 16 
     | 
    
         
            +
            class AllTextParserNotBlank < Former::Builder
         
     | 
| 
      
 17 
     | 
    
         
            +
              attr "a.important", :href
         
     | 
| 
      
 18 
     | 
    
         
            +
              attr("img", :src)
         
     | 
| 
      
 19 
     | 
    
         
            +
              text { |e| not e.text.strip.empty? }
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
       16 
22 
     | 
    
         
             
            class BuilderTest < Test::Unit::TestCase
         
     | 
| 
       17 
23 
     | 
    
         
             
              def setup
         
     | 
| 
       18 
24 
     | 
    
         
             
                @html_txt = '<p>some text<a class="important" href="http://alink.com">some link text<img src="/an/image/path"></a>last text</p>'
         
     | 
| 
       19 
25 
     | 
    
         
             
                @parser = Parser.new @html_txt
         
     | 
| 
       20 
26 
     | 
    
         
             
              end
         
     | 
| 
       21 
27 
     | 
    
         | 
| 
      
 28 
     | 
    
         
            +
              def test_ignore_blank_fields
         
     | 
| 
      
 29 
     | 
    
         
            +
                p = AllTextParserNotBlank.new "<p>\n</p><h1>  </h1><p> some text </p>"
         
     | 
| 
      
 30 
     | 
    
         
            +
                assert_equal p.length, 1
         
     | 
| 
      
 31 
     | 
    
         
            +
                p[0] = "other text"
         
     | 
| 
      
 32 
     | 
    
         
            +
                assert_equal "<p>\n</p><h1>  </h1><p>other text</p>", p.to_html
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                p = AllTextParserNotBlank.new "<p>\n</p><h1>  </h1> some text <p></p>"
         
     | 
| 
      
 35 
     | 
    
         
            +
                assert_equal p.length, 1
         
     | 
| 
      
 36 
     | 
    
         
            +
                p[0] = "other text"
         
     | 
| 
      
 37 
     | 
    
         
            +
                assert_equal "<p>\n</p><h1>  </h1>other text<p></p>", p.to_html
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              def test_nohtml
         
     | 
| 
      
 41 
     | 
    
         
            +
                p = Parser.new "some text that is long, and contains stuff!"
         
     | 
| 
      
 42 
     | 
    
         
            +
                p.set_values :former_0 => "some other text"
         
     | 
| 
      
 43 
     | 
    
         
            +
                assert_equal p.to_html, "some other text"
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       22 
46 
     | 
    
         
             
              def test_parsing
         
     | 
| 
       23 
47 
     | 
    
         
             
                assert_equal @parser.editable.length, 5
         
     | 
| 
       24 
48 
     | 
    
         | 
| 
         @@ -42,6 +66,6 @@ class BuilderTest < Test::Unit::TestCase 
     | 
|
| 
       42 
66 
     | 
    
         | 
| 
       43 
67 
     | 
    
         
             
                # now set it back
         
     | 
| 
       44 
68 
     | 
    
         
             
                @parser.set_values :former_0 => "some text"
         
     | 
| 
       45 
     | 
    
         
            -
                @parser 
     | 
| 
      
 69 
     | 
    
         
            +
                assert_equal @parser.to_html, @html_txt
         
     | 
| 
       46 
70 
     | 
    
         
             
              end
         
     | 
| 
       47 
71 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: former
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.0.0
         
     | 
| 
       5 
5 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
         @@ -9,24 +9,8 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2014- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2014-03-08 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
     | 
    
         
            -
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
     | 
    
         
            -
              name: actionpack
         
     | 
| 
       16 
     | 
    
         
            -
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       17 
     | 
    
         
            -
                none: false
         
     | 
| 
       18 
     | 
    
         
            -
                requirements:
         
     | 
| 
       19 
     | 
    
         
            -
                - - ! '>='
         
     | 
| 
       20 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       21 
     | 
    
         
            -
                    version: 4.0.3
         
     | 
| 
       22 
     | 
    
         
            -
              type: :runtime
         
     | 
| 
       23 
     | 
    
         
            -
              prerelease: false
         
     | 
| 
       24 
     | 
    
         
            -
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       25 
     | 
    
         
            -
                none: false
         
     | 
| 
       26 
     | 
    
         
            -
                requirements:
         
     | 
| 
       27 
     | 
    
         
            -
                - - ! '>='
         
     | 
| 
       28 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       29 
     | 
    
         
            -
                    version: 4.0.3
         
     | 
| 
       30 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       31 
15 
     | 
    
         
             
              name: nokogiri
         
     | 
| 
       32 
16 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -83,6 +67,8 @@ extensions: [] 
     | 
|
| 
       83 
67 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       84 
68 
     | 
    
         
             
            files:
         
     | 
| 
       85 
69 
     | 
    
         
             
            - .gitignore
         
     | 
| 
      
 70 
     | 
    
         
            +
            - .ruby-gemset
         
     | 
| 
      
 71 
     | 
    
         
            +
            - .ruby-version
         
     | 
| 
       86 
72 
     | 
    
         
             
            - Gemfile
         
     | 
| 
       87 
73 
     | 
    
         
             
            - LICENSE.txt
         
     | 
| 
       88 
74 
     | 
    
         
             
            - README.rdoc
         
     | 
| 
         @@ -108,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       108 
94 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       109 
95 
     | 
    
         
             
                  segments:
         
     | 
| 
       110 
96 
     | 
    
         
             
                  - 0
         
     | 
| 
       111 
     | 
    
         
            -
                  hash:  
     | 
| 
      
 97 
     | 
    
         
            +
                  hash: 4051511182999902248
         
     | 
| 
       112 
98 
     | 
    
         
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
       113 
99 
     | 
    
         
             
              none: false
         
     | 
| 
       114 
100 
     | 
    
         
             
              requirements:
         
     | 
| 
         @@ -117,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       117 
103 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       118 
104 
     | 
    
         
             
                  segments:
         
     | 
| 
       119 
105 
     | 
    
         
             
                  - 0
         
     | 
| 
       120 
     | 
    
         
            -
                  hash:  
     | 
| 
      
 106 
     | 
    
         
            +
                  hash: 4051511182999902248
         
     | 
| 
       121 
107 
     | 
    
         
             
            requirements: []
         
     | 
| 
       122 
108 
     | 
    
         
             
            rubyforge_project: 
         
     | 
| 
       123 
109 
     | 
    
         
             
            rubygems_version: 1.8.25
         
     |