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
|