former 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
- This will output:
36
+ Then, we can get information about the editable fields:
38
37
 
39
- <input name="former_0" type="text" value="some text" />
40
- <input name="former_1" type="text" value="http://alink.com" />
41
- <input name="former_2" type="text" value="some link text" />
42
- <input name="former_3" type="text" value="/an/image/path" />
43
- <input name="former_4" type="text" value="last text" />
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
- By default, the fields created are input's. If you pass a block to the attr/text class methods, though, you can create your own.
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
- attr "a.important", :href
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")
@@ -9,8 +9,8 @@ module Former
9
9
  @html = Nokogiri::HTML.parse(html)
10
10
 
11
11
  matches = {}
12
- self.class.queries.each { |path, qs|
13
- @html.search(path).each { |node|
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 { |e|
26
- (matches[e] || []).each { |query|
27
- @editable << Element.new(e, query[:query], @editable.length, query[:block])
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 each(&block)
33
- @editable.each { |e| block.call(e) }
38
+ def length
39
+ @editable.length
34
40
  end
35
41
 
36
- def to_form_html
37
- @editable.map(&:to_form_html).join("\n")
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
- # nokogiri pads w/ xhtml/body elements
46
- @html.search("//body").first.children.map(&:to_html).join
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].set_value value
59
+ @editable[index].value = value
51
60
  end
52
61
 
53
62
  # vals should be { :former_0 => 'value', :former_1 => 'value two', ... }
@@ -1,15 +1,12 @@
1
- require 'action_view'
2
1
  require 'json'
3
2
 
4
3
  module Former
5
4
  class Element
6
- include ActionView::Helpers::TagHelper
7
- attr_reader :node, :query, :block
5
+ attr_reader :node, :query
8
6
 
9
- def initialize(node, query, index, block)
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 to_form_html
26
- name = "former_#{@index}"
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 set_value(value)
26
+ def value=(value)
33
27
  if @query == :text
34
28
  @node.content = value
35
29
  else
@@ -1,3 +1,3 @@
1
1
  module Former
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0"
3
3
  end
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 = Parser.new @html_txt
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.2
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-02-27 00:00:00.000000000 Z
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: 4374242057553143574
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: 4374242057553143574
106
+ hash: 4051511182999902248
121
107
  requirements: []
122
108
  rubyforge_project:
123
109
  rubygems_version: 1.8.25