former 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ docs
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in former.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Brian Muller
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,68 @@
1
+ = Former
2
+
3
+ Former turns an html string into a set of editable fields. For instance, if you want to give users the ability to edit certain parts of pregenerated HTML (like the href's of a's), this gem makes it easy to create the form and handle user input.
4
+
5
+ == Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'former'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install former
18
+
19
+ == Usage
20
+ First, create a new parser that extends Builder class.
21
+
22
+ class Parser < Former::Builder
23
+ attr "a.important", :href
24
+ attr "img", :src
25
+ text "p", "a.important"
26
+ end
27
+
28
+ In this example, we want to be able to edit the location of all links that have a class of "important", the location of all images, and the text in any paragraphs or important links.
29
+
30
+ To produce the input fields from some example input HTML, first create an instance of your parser.
31
+
32
+ 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>"
33
+ puts parsed.to_form_html
34
+
35
+ This will output:
36
+
37
+ <input name="former_0" type="text" value="some text" />
38
+ <input name="former_1" type="text" value="http://alink.com" />
39
+ <input name="former_2" type="text" value="some link text" />
40
+ <input name="former_3" type="text" value="/an/image/path" />
41
+ <input name="former_4" type="text" value="last text" />
42
+
43
+ You can then set fields individually or as a group (with, say, the params from a POST/GET):
44
+
45
+ parsed[0] = "A New Description"
46
+ parsed[1] = "http://anewlink.com"
47
+ # or...
48
+ parsed.set_values :former_0 => "A New Description", :former_1 => "http://anewlink.com"
49
+
50
+ When the new values have been set, you can spit out the new HTML version:
51
+
52
+ puts parsed.to_html
53
+
54
+ Will produce the original html with the new field values:
55
+
56
+ <p>A New Description<a class='important' href='http://anewlink.com'>some link...
57
+
58
+ 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.
59
+
60
+ class Parser < Former::Builder
61
+ attr "a.important", :href
62
+ attr("img", :src) { |elem, name|
63
+ # If the src url is a really long bit of text, you could do something like this.
64
+ # The name is the name (which has the index) necessary to set the value on a GET/POST
65
+ "<textarea name='#{name}'></textarea>"
66
+ }
67
+ text "p", "a.important"
68
+ end
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rdoc/task'
3
+ require 'rake/testtask'
4
+
5
+ task :default => [:test]
6
+
7
+ RDoc::Task.new("doc") { |rdoc|
8
+ rdoc.title = "Former - convert HTML to input forms for editable values"
9
+ rdoc.rdoc_dir = 'docs'
10
+ rdoc.rdoc_files.include('README.rdoc')
11
+ rdoc.rdoc_files.include('lib/**/*.rb')
12
+ }
13
+
14
+ desc "Run all unit tests"
15
+ Rake::TestTask.new("test") { |t|
16
+ t.libs << "lib"
17
+ t.test_files = FileList['test/*.rb']
18
+ t.verbose = true
19
+ }
data/former.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'former/version'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "former"
7
+ gem.version = Former::VERSION
8
+ gem.authors = ["Brian Muller"]
9
+ gem.email = ["bamuller@gmail.com"]
10
+ gem.description = "Converts HTML to form fields for editing values in the HTML"
11
+ gem.summary = "Converts HTML to form fields for editing values in the HTML"
12
+ gem.homepage = "http://github.com/opbandit/former"
13
+ gem.files = `git ls-files`.split($/)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.require_paths = ["lib"]
17
+ gem.add_dependency("actionpack", ">= 3.2.0")
18
+ gem.add_dependency("nokogiri", ">= 1.5.6")
19
+ gem.add_development_dependency("rake")
20
+ gem.add_development_dependency("rdoc")
21
+ end
@@ -0,0 +1,65 @@
1
+ require 'nokogiri'
2
+
3
+ module Former
4
+ class Builder
5
+ attr_reader :editable
6
+
7
+ def initialize(html)
8
+ @html = Nokogiri::HTML.parse(html)
9
+
10
+ matches = {}
11
+ @@queries.each { |path, qs|
12
+ @html.search(path).each { |node|
13
+ # if all we need is the text, only include text kids
14
+ if qs.length == 1 and qs.first[:query] == :text
15
+ node.traverse { |e| matches[e] = qs if e.text? and not matches.keys.include? e }
16
+ else
17
+ # otherwise, ignore just text requests
18
+ matches[node] = qs.select { |q| q[:query] != :text }
19
+ end
20
+ }
21
+ }
22
+
23
+ @editable = []
24
+ @html.traverse_prefix { |e|
25
+ (matches[e] || []).each { |query|
26
+ @editable << Element.new(e, query[:query], @editable.length, query[:block])
27
+ }
28
+ }
29
+ end
30
+
31
+ def each(&block)
32
+ @editable.each { |e| block.call(e) }
33
+ end
34
+
35
+ def to_form_html
36
+ @editable.map { |e| e.to_form_html }.join("\n")
37
+ end
38
+
39
+ def to_html
40
+ # nokogiri pads w/ xhtml/body elements
41
+ @html.search("//body").first.children.first.to_html
42
+ end
43
+
44
+ def []=(index, value)
45
+ @editable[index].set_value value
46
+ end
47
+
48
+ # vals should be { :former_0 => 'value', :former_1 => 'value two', ... }
49
+ def set_values(vals)
50
+ vals.each { |key, value|
51
+ self[key.to_s.split('_').last.to_i] = value
52
+ }
53
+ end
54
+
55
+ def self.attr(elem, attr, &block)
56
+ @@queries ||= {}
57
+ @@queries[elem] ||= []
58
+ @@queries[elem] << { :query => attr, :block => block }
59
+ end
60
+
61
+ def self.text(*elems, &block)
62
+ elems.each { |elem| attr(elem, :text, &block) }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,34 @@
1
+ require 'action_view'
2
+
3
+ module Former
4
+ class Element
5
+ include ActionView::Helpers::TagHelper
6
+ attr_reader :node, :query, :block
7
+
8
+ def initialize(node, query, index, block)
9
+ @node = node
10
+ @query = query
11
+ @block = block
12
+ @index = index
13
+ end
14
+
15
+ def to_form_html
16
+ name = "former_#{@index}"
17
+ return @block.call(@node, name) unless @block.nil?
18
+ value = (@query == :text) ? @node.text : @node[@query]
19
+ tag(:input, :type => 'text', :name => name, :value => value)
20
+ end
21
+
22
+ def set_value(value)
23
+ if @query == :text
24
+ @node.content = value
25
+ else
26
+ @node[@query] = value
27
+ end
28
+ end
29
+
30
+ def to_html
31
+ @node.to_html
32
+ end
33
+ end
34
+ end
data/lib/former/ext.rb ADDED
@@ -0,0 +1,10 @@
1
+ module Nokogiri
2
+ module XML
3
+ class Node
4
+ def traverse_prefix(&block)
5
+ block.call(self)
6
+ children.each{ |j| j.traverse_prefix(&block) }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Former
2
+ VERSION = "0.0.1"
3
+ end
data/lib/former.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "former/version"
2
+ require "former/builder"
3
+ require "former/element"
4
+ require "former/ext"
@@ -0,0 +1,31 @@
1
+ require 'test/unit'
2
+ require 'former'
3
+
4
+ class Parser < Former::Builder
5
+ attr "a.important", :href
6
+ attr("img", :src)
7
+ text "p", "a.important"
8
+ end
9
+
10
+ class BuilderTest < Test::Unit::TestCase
11
+ def setup
12
+ @html_txt = '<p>some text<a class="important" href="http://alink.com">some link text<img src="/an/image/path"></a>last text</p>'
13
+ @parser = Parser.new @html_txt
14
+ puts @parser.to_form_html
15
+ end
16
+
17
+ def test_parsing
18
+ assert_equal @parser.editable.length, 5
19
+ end
20
+
21
+ def test_building
22
+ assert_equal @parser.to_html, @html_txt
23
+ new_html_txt = '<p>some new text<a class="important" href="http://alink.com">some link text<img src="/an/image/path"></a>last text</p>'
24
+ @parser[0] = "some new text"
25
+ assert_equal @parser.to_html, new_html_txt
26
+
27
+ # now set it back
28
+ @parser.set_values :former_0 => "some text"
29
+ @parser = Parser.new @html_txt
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: former
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Brian Muller
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2013-02-19 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: actionpack
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.2.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: nokogiri
28
+ requirement: &id002 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.6
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ requirement: &id003 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: rdoc
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id004
59
+ description: Converts HTML to form fields for editing values in the HTML
60
+ email:
61
+ - bamuller@gmail.com
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files: []
67
+
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.rdoc
73
+ - Rakefile
74
+ - former.gemspec
75
+ - lib/former.rb
76
+ - lib/former/builder.rb
77
+ - lib/former/element.rb
78
+ - lib/former/ext.rb
79
+ - lib/former/version.rb
80
+ - test/builder_test.rb
81
+ homepage: http://github.com/opbandit/former
82
+ licenses: []
83
+
84
+ post_install_message:
85
+ rdoc_options: []
86
+
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: -2404963171909705179
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ hash: -2404963171909705179
104
+ segments:
105
+ - 0
106
+ version: "0"
107
+ requirements: []
108
+
109
+ rubyforge_project:
110
+ rubygems_version: 1.8.24
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: Converts HTML to form fields for editing values in the HTML
114
+ test_files:
115
+ - test/builder_test.rb