jm81-dm-filters 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,7 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ .project
7
+ .loadpath
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jared Morgan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ dm-filters
2
+ ==========
3
+
4
+ This module enables a property in a DataMapper::Resource class to be filtered on
5
+ save into another property, using per-row and/or per-property filters.
6
+
7
+ To use in a model:
8
+
9
+ include Filters::Resource
10
+
11
+ The syntax when defining a property is:
12
+
13
+ property :prop_name, :filter => {
14
+ :to => :filtered_prop,
15
+ :with => :filter_column,
16
+ :default => "DefaultFilter"
17
+ }
18
+
19
+ (:with and :default are optional, though at least one should be specified.)
20
+
21
+ See Filters::AVAILABLE_FILTERS for some filter options. Additional filters
22
+ may be defined in this constant Hash.
23
+
24
+ If the properties in :to and :with have not yet been defined, they will be
25
+ defined automatically. Hence, if want to specify any options with this, they
26
+ should be defined before to filtered property.
27
+
28
+ ##Installation
29
+
30
+ To install the gem:
31
+
32
+ gem sources -a http://gems.github.com
33
+ sudo gem install jm81-dm-filters
34
+
35
+ To require:
36
+
37
+ gem 'jm81-dm-filters'
38
+ require 'dm-filters'
39
+
40
+ ##Copyright
41
+
42
+ Copyright (c) 2009 Jared Morgan. See LICENSE for details.
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "dm-filters"
8
+ gem.summary = %Q{TODO}
9
+ gem.email = "jmorgan@morgancreative.net"
10
+ gem.homepage = "http://github.com/jm81/dm-filters"
11
+ gem.authors = ["Jared Morgan"]
12
+ gem.add_dependency('dm-core')
13
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ end
15
+
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ require 'spec/rake/spectask'
21
+ Spec::Rake::SpecTask.new(:spec) do |spec|
22
+ spec.libs << 'lib' << 'spec'
23
+ spec.spec_files = FileList['spec/**/*_spec.rb']
24
+ end
25
+
26
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.pattern = 'spec/**/*_spec.rb'
29
+ spec.rcov = true
30
+ end
31
+
32
+
33
+ task :default => :spec
34
+
35
+ require 'rake/rdoctask'
36
+ Rake::RDocTask.new do |rdoc|
37
+ if File.exist?('VERSION.yml')
38
+ config = YAML.load(File.read('VERSION.yml'))
39
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
40
+ else
41
+ version = ""
42
+ end
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "dm-filters #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
49
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,141 @@
1
+ require 'rubygems'
2
+
3
+ # This module enables a property to be filtered on save into another property,
4
+ # using per-row and/or per-property filters. The syntax when defining a property
5
+ # is:
6
+ # property :prop_name, :filter => {:to => :filtered_prop, :with => :filter_column, :default => "DefaultFilter"}
7
+ # (:with and :default are optional, though at least one should be specified.)
8
+ #
9
+ # If the properties in :to and :with have not yet been defined, they will be
10
+ # defined automatically. Hence, if want to specify any options with this, they
11
+ # should be defined before to filtered property.
12
+
13
+ module Filters
14
+
15
+ # A hash, with each entry of the form:
16
+ # Filter name (used in +filters+ property) =>
17
+ # Array of two elements Arrays representing classes that can process this
18
+ # filter. Elements are: [ argument_for_require, class_name ].
19
+ # Classes are assumed to respond to +to_html+.
20
+ AVAILABLE_FILTERS = {
21
+ 'Smartypants' => [['rubypants', 'RubyPants']],
22
+ 'Markdown' => [['rdiscount', 'RDiscount'], ['bluecloth', 'BlueCloth']],
23
+ 'Textile' => [['redcloth', 'RedCloth']],
24
+ 'BibleML' => [[File.dirname(__FILE__) + '/filters/bible_ml', 'BibleML']],
25
+ 'Linebreaker' => [[File.dirname(__FILE__) + '/filters/linebreaker', 'Linebreaker']],
26
+ }
27
+
28
+ def self.process(filters, content)
29
+ return content if filters.nil?
30
+
31
+ filters = filters.split(';') if filters.kind_of?(String)
32
+ filters.each do |name|
33
+ filter = get_filter(name)
34
+ next unless filter
35
+ content = filter.new(content).to_html
36
+ end
37
+ content
38
+ end
39
+
40
+ def self.get_filter(name)
41
+ name = name.strip.camel_case
42
+ info = AVAILABLE_FILTERS[name]
43
+ return(nil) unless info
44
+
45
+ # Try to find loaded class
46
+ info.each do |c|
47
+ return Object.const_get(c[1]) if Object.const_defined?(c[1])
48
+ end
49
+
50
+ # Try to require a class
51
+ info.each do |c|
52
+ begin
53
+ require(c[0])
54
+ return Object.const_get(c[1])
55
+ rescue LoadError
56
+ # Try next
57
+ end
58
+ end
59
+
60
+ return nil
61
+ end
62
+
63
+ # Filters::Resource can be included in a model to enable the
64
+ # :filtered_to => (name of other property) option for +properties+.
65
+ # This adds a property name "filters", which is a semi-colon delimited list
66
+ # of filters through which to process the original property.
67
+ module Resource
68
+ class << self
69
+ def included(klass) # Set a few 'magic' properties
70
+ klass.extend(ClassMethods)
71
+ klass.before :save, :process_filters
72
+ end
73
+ end
74
+
75
+ # Process and filters for @filtered_properties.
76
+ def process_filters
77
+ return if self.class.filtered_properties.nil?
78
+ self.class.filtered_properties.each do |f|
79
+ if attribute_dirty?(f[:name])
80
+ filters = nil
81
+ if !f[:with].blank?
82
+ if f[:with].kind_of?(Symbol)
83
+ filters = self.__send__(f[:with])
84
+ else
85
+ filters = f[:with]
86
+ end
87
+ end
88
+ if filters.blank?
89
+ filters = f[:default]
90
+ end
91
+ if filters == :site
92
+ filters = self.site.__send__("#{self.class.name.snake_case}_filter")
93
+ end
94
+ attribute_set(f[:to], Filters.process(filters, self.__send__(f[:name])))
95
+ end
96
+ end
97
+ end
98
+
99
+ module ClassMethods
100
+ # Override DataMapper's +property+ class method to accept as an option
101
+ # +filter+. +filter+ Hash with the following pairs:
102
+ # - +:to+ - Name of property to filter to; this should not be explicitly
103
+ # declared as a property.
104
+ # - +:with+ - Either 1) Name of the property (as a symbol) that designates
105
+ # filter (does not need to be explicitly declared as a property) or
106
+ # 2) A semi-colon delimited String represented filters to use (or an
107
+ # Array of strings).
108
+ # - +:default+ - A semi-colon delimited String represented filters to use
109
+ # (or an Array of strings) if the filter column is blank.
110
+ def property(name, type, options = {})
111
+ if filter = options.delete(:filter)
112
+ @filtered_properties ||= []
113
+ @filtered_properties << filter.merge({:name => name})
114
+ begin
115
+ self.properties[filter[:to].to_s]
116
+ rescue
117
+ self.property(filter[:to], type)
118
+ end
119
+ if filter[:with].kind_of?(Symbol)
120
+ begin
121
+ self.properties[filter[:with].to_s]
122
+ rescue
123
+ self.property(filter[:with], String)
124
+ end
125
+ end
126
+ end
127
+
128
+ super(name, type, options)
129
+ end
130
+
131
+ def filtered_properties
132
+ begin
133
+ # This is to work with STI models. It's not a very good solution.
134
+ @filtered_properties || self.superclass.filtered_properties
135
+ rescue
136
+ nil
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,244 @@
1
+ require 'rexml/document'
2
+ require 'open-uri'
3
+ require 'rubypants'
4
+ require 'rdiscount'
5
+
6
+ class BibleML
7
+
8
+ VERSION_IDS = {
9
+ 'cev' => 46,
10
+ 'niv' => 31,
11
+ 'nasb' => 49,
12
+ 'message' => 65,
13
+ 'amp' => 45,
14
+ 'nlt' => 51,
15
+ '21st century kjv' => 48,
16
+ 'asv' => 8,
17
+ 'darby' => 16,
18
+ 'douay-rheims' => 63,
19
+ 'esv' => 47,
20
+ 'holman' => 77,
21
+ 'kjv' => 9,
22
+ 'ncv' => 78,
23
+ 'nkjv' => 50,
24
+ 'new life' => 74,
25
+ 'wycliffe' => 53,
26
+ "young" => 15
27
+ }
28
+
29
+ def initialize(input)
30
+ @xml = REXML::Document.new("<fg:body xmlns:fg='http://fromgenesis.org'>#{input}</fg:body>")
31
+ end
32
+
33
+ def to_html
34
+ txt = self.
35
+ primary_passage.
36
+ strip_comments.
37
+ block_quotes.
38
+ inline_quotes.
39
+ wikipedia_links.
40
+ to_s
41
+ txt = RubyPants.new(txt).to_html
42
+ txt = RDiscount.new(txt).to_html
43
+ end
44
+
45
+ # Convert fg:pp tags to Primary Passage links
46
+ # and set primary passage book and chapter from
47
+ # last fg:pp tag.
48
+ def primary_passage
49
+ @xml.elements.each("//fg:pp") do | pp_el |
50
+ ref = pp_el.attributes['p']
51
+ ref_link = REXML::Element.new("a")
52
+ ref_link.add_attribute('href', bg_link(ref))
53
+ ref_link.text = "Read #{ref}"
54
+ pp_el.parent.insert_after(pp_el, ref_link)
55
+
56
+ marker = REXML::Text.new(" |\n")
57
+ pp_el.parent.insert_after(ref_link, marker)
58
+
59
+ chapter = pp_el.attributes['p'].split(":")[0]
60
+ chapter_link = REXML::Element.new("a")
61
+ chapter_link.add_attribute('href', bg_link(chapter))
62
+ chapter_link.text = "Full Chapter"
63
+ pp_el.parent.insert_after(marker, chapter_link)
64
+
65
+ pp_el.parent.delete_element(pp_el)
66
+
67
+ m = chapter.match(/(.*)\s(\d+)\Z/)
68
+ @passage_book = m[1]
69
+ @passage_chapter = m[2]
70
+ end
71
+
72
+ self
73
+ end
74
+
75
+ # Strip fg:cm tags
76
+ def strip_comments
77
+ @xml = REXML::Document.new(@xml.to_s.gsub(/\<\/?fg\:cm([^>]*)>/, ''))
78
+ self
79
+ end
80
+
81
+ # Convent fg:bq tags to block quotes with reference
82
+ def block_quotes
83
+ @xml.elements.each("//fg:bq") do | bq_el |
84
+ blockquote = REXML::Element.new("blockquote")
85
+
86
+ if bq_el.has_elements? || bq_el.has_text?
87
+ bq_el.children.each do | child |
88
+ blockquote << child
89
+ end
90
+ else
91
+ blockquote << REXML::Text.new(get_passage(bq_el.attributes['p'], bq_el.attributes['v']))
92
+ end
93
+
94
+ blockquote << REXML::Text.new("\n")
95
+ blockquote << REXML::Element.new("br")
96
+ blockquote << REXML::Text.new("\n(")
97
+ blockquote << reference_a(bq_el.attributes['p'], bq_el.attributes['v'])
98
+ blockquote << REXML::Text.new(")\n")
99
+
100
+ bq_el.parent.replace_child(bq_el, blockquote)
101
+ end
102
+ self
103
+ end
104
+
105
+ # Convent fg:iq tags to inline quotes with reference
106
+ def inline_quotes
107
+ @xml.elements.each("//fg:iq") do | iq_el |
108
+ quote = REXML::Element.new("span")
109
+
110
+ quote << REXML::Text.new("\"")
111
+
112
+ if iq_el.has_elements? || iq_el.has_text?
113
+ iq_el.children.each do | child |
114
+ quote << child
115
+ end
116
+ else
117
+ quote << REXML::Text.new(get_passage(iq_el.attributes['p'], iq_el.attributes['v']))
118
+ end
119
+
120
+ quote << REXML::Text.new("\" (")
121
+ quote << reference_a(iq_el.attributes['p'], iq_el.attributes['v'])
122
+ quote << REXML::Text.new(")\n")
123
+
124
+ iq_el.parent.replace_child(iq_el, quote)
125
+ end
126
+ self
127
+ end
128
+
129
+ def wikipedia_links
130
+ @xml.elements.each("//fg:wp") do | wp_el |
131
+ a = REXML::Element.new("a")
132
+
133
+ a.add_attribute('href', "http://en.wikipedia.org/wiki/#{wp_el.attributes['a']}")
134
+ if wp_el.has_elements? || wp_el.has_text?
135
+ wp_el.children.each do | child |
136
+ a << child
137
+ end
138
+ else
139
+ a << REXML::Text.new(wp_el.attributes['a'])
140
+ end
141
+
142
+ wp_el.parent.replace_child(wp_el, a)
143
+ end
144
+ self
145
+ end
146
+
147
+ def fill_missing_text
148
+ @xml.elements.each("//fg:pp") do | pp_el |
149
+ chapter = pp_el.attributes['p'].split(":")[0]
150
+ m = chapter.match(/(.*)\s(\d+)\Z/)
151
+ @passage_book = m[1]
152
+ @passage_chapter = m[2]
153
+ end
154
+
155
+ @xml.elements.each("//fg:iq") do | q_el |
156
+ unless q_el.has_elements? || q_el.has_text?
157
+ q_el << REXML::Text.new(get_passage(q_el.attributes['p'], q_el.attributes['v']))
158
+ end
159
+ end
160
+
161
+ @xml.elements.each("//fg:bq") do | q_el |
162
+ unless q_el.has_elements? || q_el.has_text?
163
+ psg = get_passage(q_el.attributes['p'], q_el.attributes['v'])
164
+ psg = wordwrap(" " + psg) + "\n"
165
+ q_el << REXML::Text.new(psg)
166
+ end
167
+ end
168
+ self
169
+ end
170
+
171
+ # Based on http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/10655
172
+ def wordwrap(txt)
173
+ txt.gsub(/\t/," ").
174
+ gsub(/\"/,"&quot;").
175
+ gsub(/\'/,"&apos;").
176
+ gsub(/.{1,78}(?:\s|\Z)/){($& + 5.chr).
177
+ gsub(/\n\005/,"\n ").
178
+ gsub(/\005/,"\n ")}.
179
+ gsub(/&quot;/, "\"").
180
+ gsub(/&apos;/, "\'")
181
+ end
182
+
183
+ class << self
184
+ def fill_missing_text(input)
185
+ new(input).fill_missing_text.to_s
186
+ end
187
+ end
188
+
189
+ def to_s
190
+ @xml.to_s.gsub(/<\/?fg:body[^>]*>/, '')
191
+ end
192
+
193
+ # Add book and chapter information to shorthand references
194
+ def expand_reference(ref)
195
+ ref.strip!
196
+ if ref.match(/\A(\d+-?\d*)\Z/) # Just verse(s) given
197
+ "#{@passage_book} #{@passage_chapter}:#{ref}"
198
+ elsif ref.match(/\A(\d+):(\d+-?\d*)\Z/) # Just chapter and verse(s) given
199
+ "#{@passage_book} #{ref}"
200
+ else
201
+ ref
202
+ end
203
+ end
204
+
205
+ # Generate 'a' element for reference link
206
+ def reference_a(ref, version = nil, label = nil)
207
+ ref = expand_reference(ref)
208
+
209
+ unless label
210
+ label = ref
211
+ label += ", #{version}" if version
212
+ end
213
+
214
+ ref_link = REXML::Element.new("a")
215
+ ref_link.add_attribute('href', bg_link(ref, version))
216
+ ref_link.text = label
217
+
218
+ ref_link
219
+ end
220
+
221
+ def bg_link(ref, version = nil)
222
+ ref = expand_reference(ref)
223
+
224
+ ln = "http://www.biblegateway.com/passage/?search=" + ref.downcase.gsub(/\s/, "%20")
225
+ ln += ";&version=#{VERSION_IDS[version.downcase]};" if version
226
+ ln
227
+ end
228
+
229
+ def get_passage(ref, version = "NASB")
230
+ xhtml = open(bg_link(ref, version)) do |f|
231
+ html = f.read.split('<div class="result-text-style-normal">')[1]
232
+ html = html.split(/<\/?div/)[0]
233
+ REXML::Document.new("<body>#{html}</body>")
234
+ end
235
+
236
+ xhtml.root.elements.delete_all("//h4")
237
+ xhtml.root.elements.delete_all("//h5")
238
+ xhtml.root.elements.delete_all("//span")
239
+ xhtml.root.elements.delete_all("//sup")
240
+ xhtml.root.elements.delete_all("//br")
241
+
242
+ xhtml.to_s.gsub(/<\/?body>/, '').gsub(/<\/?p\/?>/, '').gsub('&nbsp;', ' ').squeeze(" ").gsub(/ \" /, ' "')
243
+ end
244
+ end
@@ -0,0 +1,14 @@
1
+ # This filter just replaces single newlines with "<br />" tags.
2
+ class Linebreaker
3
+
4
+ def initialize(input)
5
+ @input = input
6
+ end
7
+
8
+ def to_html
9
+ @input.
10
+ gsub(/(\S)\n(\S)/, "\\1<br />\n\\2").
11
+ gsub(/(\S)\r\n(\S)/, "\\1<br />\n\\2")
12
+ end
13
+
14
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Filters do
4
+ describe "#process" do
5
+ before(:each) do
6
+ @filter_one = mock("Filter 1")
7
+ @filter_two = mock("Filter 2")
8
+ @processor_one, @processor_two = mock("Processor 1"), mock("Processor 2")
9
+ @processed_one, @processed_two = mock("Processed 1"), mock("Processed 2")
10
+ end
11
+
12
+ it "should process through each filter" do
13
+ Filters.should_receive(:get_filter).with("FilterOne").and_return(@filter_one)
14
+ @filter_one.should_receive(:new).with("content").and_return(@processor_one)
15
+ @processor_one.should_receive(:to_html).and_return(@processed_one)
16
+ Filters.should_receive(:get_filter).with(" FilterTwo").and_return(@filter_two)
17
+ @filter_two.should_receive(:new).with(@processed_one).and_return(@processor_two)
18
+ @processor_two.should_receive(:to_html).and_return(@processed_two)
19
+ Filters.process("FilterOne; FilterTwo", "content").should == @processed_two
20
+ end
21
+ end
22
+
23
+ describe "#get_filter" do
24
+ it "should return nil if name not found in AVAILABLE_FILTERS" do
25
+ Filters.get_filter("neverafilter").should be_nil
26
+ end
27
+
28
+ it "should return a filter if it's constant is defined" do
29
+ red_cloth = mock('RedCloth')
30
+ Object.should_receive(:const_defined?).with('RedCloth').and_return(true)
31
+ Object.should_receive(:const_get).with('RedCloth').and_return(red_cloth)
32
+ Filters.get_filter("Textile").should be(red_cloth)
33
+ end
34
+
35
+ it "should attempt to require an undefined filter" do
36
+ red_cloth = mock('RedCloth')
37
+ Object.should_receive(:const_defined?).with('RedCloth').and_return(false)
38
+ Filters.should_receive(:require).with('redcloth').and_return(true)
39
+ Object.should_receive(:const_get).with('RedCloth').and_return(red_cloth)
40
+ Filters.get_filter("Textile").should be(red_cloth)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,106 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/filters/bible_ml')
3
+
4
+ describe BibleML do
5
+
6
+ it "should convert a fg:bq element to a block quote" do
7
+ BibleML.new('<p>1</p><fg:bq p="Exodus 5:1-5" v="ESV">quote <span>hi</span></fg:bq><p>2</p>').
8
+ block_quotes.
9
+ to_s.should ==
10
+ "<p>1</p><blockquote>quote <span>hi</span>\n<br/>\n" +
11
+ "(<a href='http://www.biblegateway.com/passage/?search=exodus%205:1-5;&amp;version=47;'>Exodus 5:1-5, ESV</a>)" +
12
+ "\n</blockquote><p>2</p>"
13
+ end
14
+
15
+ it "should fill in text of an empty fg:bq element" do
16
+ BibleML.new('<fg:bq p="Exodus 5:2-3" v="CEV" />').
17
+ block_quotes.
18
+ to_s.should ==
19
+ "<blockquote>\n &quot;Who is this LORD and why should I obey him?&quot; the king replied. &quot;I refuse to let you and your people go!&quot; " +
20
+ "They answered, &quot;The LORD God of the Hebrews, has appeared to us. Please let us walk three days into the desert " +
21
+ "where we can offer sacrifices to him. If you don&apos;t, he may strike us down with terrible troubles or with war.&quot; \n" +
22
+ "<br/>\n" +
23
+ "(<a href='http://www.biblegateway.com/passage/?search=exodus%205:2-3;&amp;version=46;'>Exodus 5:2-3, CEV</a>)" +
24
+ "\n</blockquote>"
25
+ end
26
+
27
+ it "should assume book and chapter based on bg:pp if ommitted" do
28
+ convertor = BibleML.new('<fg:pp p="Exodus 5:1-5" />').primary_passage
29
+ convertor.expand_reference("7").should == "Exodus 5:7"
30
+ convertor.expand_reference("7-10").should == "Exodus 5:7-10"
31
+ convertor.expand_reference("6:7").should == "Exodus 6:7"
32
+ convertor.expand_reference("6:7-10").should == "Exodus 6:7-10"
33
+ convertor.expand_reference("John 6:7").should == "John 6:7"
34
+ convertor.expand_reference("John 6:7-10").should == "John 6:7-10"
35
+ end
36
+
37
+ it "should convert a fg:iq element to an inline quote" do
38
+ BibleML.new('<p>this is a <fg:iq p="1 Peter 1:2" v="Young">inline quote</fg:iq></p>').
39
+ inline_quotes.
40
+ to_s.should ==
41
+ "<p>this is a <span>&quot;inline quote&quot; " +
42
+ "(<a href='http://www.biblegateway.com/passage/?search=1%20peter%201:2;&amp;version=15;'>1 Peter 1:2, Young</a>)" +
43
+ "\n</span></p>"
44
+ end
45
+
46
+ it "should fill in text of an empty fg:iq element" do
47
+ BibleML.new('<p><fg:iq p="1 Peter 1:2" v="Young" /></p>').
48
+ inline_quotes.
49
+ to_s.should ==
50
+ "<p><span>&quot;\n according to a foreknowledge of God the Father, in sanctification of the Spirit, " +
51
+ "to obedience and sprinkling of the blood of Jesus Christ: Grace to you and peace be multiplied! &quot; " +
52
+ "(<a href='http://www.biblegateway.com/passage/?search=1%20peter%201:2;&amp;version=15;'>1 Peter 1:2, Young</a>)" +
53
+ "\n</span></p>"
54
+ end
55
+
56
+ it "should strip fg:cm tags" do
57
+ BibleML.new('test <fg:cm p="Genesis 11:10-11">comment</fg:cm> test2').
58
+ strip_comments.
59
+ to_s.should ==
60
+ "test comment test2"
61
+ end
62
+
63
+ it "should convert fg:pp tag to Primary Passage links" do
64
+ BibleML.new('<fg:pp p="Exodus 5:1-5" />').
65
+ primary_passage.
66
+ to_s.should ==
67
+ "<a href='http://www.biblegateway.com/passage/?search=exodus%205:1-5'>Read Exodus 5:1-5</a> |\n" +
68
+ "<a href='http://www.biblegateway.com/passage/?search=exodus%205'>Full Chapter</a>"
69
+ end
70
+
71
+ it "should create link from reference with verses" do
72
+ BibleML.new('').bg_link("Genesis 1:10").should ==
73
+ "http://www.biblegateway.com/passage/?search=genesis%201:10"
74
+ end
75
+
76
+ it "should create link from reference without verses" do
77
+ BibleML.new('').bg_link("Genesis 1").should ==
78
+ "http://www.biblegateway.com/passage/?search=genesis%201"
79
+ end
80
+
81
+ it "should convert version names to biblegateway.com ids" do
82
+ BibleML::VERSION_IDS['niv'].should == 31
83
+ BibleML::VERSION_IDS['cev'].should == 46
84
+ end
85
+
86
+ it "should convert an fg:wp element to a wikipedia link" do
87
+ BibleML.new('<fg:wp a="Bible">the Bible</fg:wp>').
88
+ wikipedia_links.
89
+ to_s.should ==
90
+ "<a href='http://en.wikipedia.org/wiki/Bible'>the Bible</a>"
91
+ end
92
+
93
+ it "should convert fixture (full document)" do
94
+ input = File.read(File.dirname(__FILE__) + "/fixtures/gen11/input.xml")
95
+ output = File.read(File.dirname(__FILE__) + "/fixtures/gen11/output.xml")
96
+ output.gsub!("\r\n", "\n") # Just in case I run specs in git repo in Windows
97
+ BibleML.new(input).to_html.should == output
98
+ end
99
+
100
+ it "should convert only missing text" do
101
+ BibleML::fill_missing_text('<p><fg:iq p="1 Peter 1:2" v="Young" /></p>').
102
+ should ==
103
+ "<p><fg:iq v='Young' p='1 Peter 1:2'>\n according to a foreknowledge of God the Father, in sanctification of the Spirit, " +
104
+ "to obedience and sprinkling of the blood of Jesus Christ: Grace to you and peace be multiplied! </fg:iq></p>"
105
+ end
106
+ end
@@ -0,0 +1,16 @@
1
+ <fg:pp p="Genesis 11:10-20" />
2
+
3
+ <fg:bq p="Genesis 11:10-14" v="NASB" />
4
+
5
+ <fg:cm p="Genesis 11:10-11">This passage tells us something.</fg:cm>
6
+ <fg:cm p="Genesis 11:12-14">Now these verses elaborate</fg:cm>
7
+
8
+ <fg:bq p="Genesis 11:15-20" v="CEV">
9
+ Already quoted.
10
+ </fg:bq>
11
+
12
+ <fg:cm p="Genesis 11:15-18">
13
+ This comment <fg:iq p="Genesis 11:20" v="NIV">quotes a verse</fg:iq>
14
+ This comment quotes a verse to fill in
15
+ <fg:iq p="Genesis 11:21" v="NIV" />
16
+ </fg:cm>
@@ -0,0 +1,27 @@
1
+ <p><a href='http://www.biblegateway.com/passage/?search=genesis%2011:10-20'>Read Genesis 11:10-20</a> |
2
+ <a href='http://www.biblegateway.com/passage/?search=genesis%2011'>Full Chapter</a></p>
3
+
4
+ <blockquote>
5
+ These are the records of the generations of Shem. Shem was one hundred years old, and became the father of Arpachshad two years after the flood; and Shem lived five hundred years after he became the father of Arpachshad, and he had other sons and daughters. Arpachshad lived thirty-five years, and became the father of Shelah; and Arpachshad lived four hundred and three years after he became the father of Shelah, and he had other sons and daughters. Shelah lived thirty years, and became the father of Eber;
6
+ <br/>
7
+ (<a href='http://www.biblegateway.com/passage/?search=genesis%2011:10-14;&amp;version=49;'>Genesis 11:10-14, NASB</a>)
8
+ </blockquote>
9
+
10
+
11
+ <p>This passage tells us something.
12
+ Now these verses elaborate</p>
13
+
14
+ <blockquote>
15
+ Already quoted.
16
+
17
+ <br/>
18
+ (<a href='http://www.biblegateway.com/passage/?search=genesis%2011:15-20;&amp;version=46;'>Genesis 11:15-20, CEV</a>)
19
+ </blockquote>
20
+
21
+
22
+ <p> This comment <span>&quot;quotes a verse&quot; (<a href='http://www.biblegateway.com/passage/?search=genesis%2011:20;&amp;version=31;'>Genesis 11:20, NIV</a>)
23
+ </span>
24
+ This comment quotes a verse to fill in
25
+ <span>&quot;
26
+ And after he became the father of Serug, Reu lived 207 years and had other sons and daughters.&quot; (<a href='http://www.biblegateway.com/passage/?search=genesis%2011:21;&amp;version=31;'>Genesis 11:21, NIV</a>)
27
+ </span></p>
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/filters/linebreaker')
3
+
4
+ describe Linebreaker do
5
+
6
+ it "should convert single line breaks to <br> tags" do
7
+ Linebreaker.new("abc\n\ndef\nghi").to_html.should ==
8
+ "abc\n\ndef<br />\nghi"
9
+ end
10
+
11
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'dm-core'
3
+
4
+ class MockContent
5
+ include DataMapper::Resource
6
+ include Filters::Resource
7
+
8
+ property :html, Text
9
+ property :filters, String
10
+ end
11
+
12
+ describe Filters::Resource do
13
+ describe ".property" do
14
+ before(:each) do
15
+ @model = MockContent
16
+ @props = @model.properties
17
+ end
18
+
19
+ it "should add :to property if not defined" do
20
+ @model.property(:body, String, :filter => {:to => :html2, :with => "Markdown"})
21
+ MockContent.properties['html2'].should be_kind_of(DataMapper::Property)
22
+ end
23
+
24
+ it "should not add :with property if not defined" do
25
+ @model.property(:body, String, :filter => {:to => :html, :with => :filters2})
26
+ MockContent.properties['filters2'].should be_kind_of(DataMapper::Property)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ require 'dm-filters'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jm81-dm-filters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jared Morgan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-09 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: dm-core
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: jmorgan@morgancreative.net
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.md
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.md
39
+ - Rakefile
40
+ - VERSION
41
+ - lib/dm-filters.rb
42
+ - lib/filters/bible_ml.rb
43
+ - lib/filters/linebreaker.rb
44
+ - spec/dm-filters_spec.rb
45
+ - spec/filters/bible_ml_spec.rb
46
+ - spec/filters/fixtures/gen11/input.xml
47
+ - spec/filters/fixtures/gen11/output.xml
48
+ - spec/filters/linebreaker_spec.rb
49
+ - spec/filters_resource_spec.rb
50
+ - spec/spec_helper.rb
51
+ has_rdoc: false
52
+ homepage: http://github.com/jm81/dm-filters
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --charset=UTF-8
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.2.0
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: TODO
77
+ test_files:
78
+ - spec/dm-filters_spec.rb
79
+ - spec/filters/bible_ml_spec.rb
80
+ - spec/filters/linebreaker_spec.rb
81
+ - spec/filters_resource_spec.rb
82
+ - spec/spec_helper.rb