elcamino-microformat 0.0.8

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b953eda6079522b0e0d424163f04636dbe335b4c
4
+ data.tar.gz: b6617bfe82b414dbb901a06079a730b58395421e
5
+ SHA512:
6
+ metadata.gz: e2993d9b04c721e7ca88bc54f9ab350a9279d4e1ce8c2d620b393af6d66829cba7240ceb71f0050e6fe99f9e75093524d81d3c6d5a6e9cb3460f649bf12e6c1f
7
+ data.tar.gz: 07bd2728b89221ddd090d635644fb5fa1c226fd1d7f4e6e0e33acd52c1cc22293aa7f90ba0391aec21522f8fd0195ae2df630b16780e32b6e7bfbca339beced8
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ **.DS_Store
data/.rvmrc ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bash
2
+
3
+ if ! rvm list | grep -q ruby-1.9.3-p194 ; then
4
+ rvm install 1.9.3-p194
5
+ fi
6
+
7
+ rvm 1.9.3-p194@platformq_microformat --create
8
+
9
+ if ! gem list | grep -q bundler ; then
10
+ gem install --no-ri --no-rdoc bundler
11
+ bundle install --without production
12
+ fi
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in microformat.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Platform Q LLC
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.md ADDED
@@ -0,0 +1,55 @@
1
+ # Microformat
2
+
3
+ Reads Microformats from HTML documents
4
+
5
+ [![Build Status][2]][1] [![Code Climate][3]][4]
6
+
7
+ [1]: http://travis-ci.org/platformq/microformat
8
+ [2]: https://secure.travis-ci.org/platformq/microformat.png?branch=master
9
+ [3]: https://codeclimate.com/badge.png
10
+ [4]: https://codeclimate.com/github/platformq/microformat
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem "microformat"
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install microformat
27
+
28
+ ## Usage
29
+
30
+ You can parse a document (or partial document), providing the HTML as a string:
31
+
32
+ ```ruby
33
+ html = "<html>...</html>"
34
+ Microformat.parse(html) # => Microformat::Collection
35
+ ```
36
+
37
+ Or provide a Nokogiri element:
38
+
39
+ ```ruby
40
+ require "nokogiri"
41
+
42
+ html = "<html>...</html>"
43
+ doc = Nokogiri::HTML(html)
44
+ element = doc.css("body")
45
+ Microformat.parse(element)
46
+ # => Microformat::Collection
47
+ ```
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork it
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require "rspec/core/rake_task"
5
+
6
+ desc "Runs all the specs"
7
+ task default: %w(spec)
8
+
9
+ desc "Run specs"
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
12
+ # Put spec opts in a file named .rspec in root
13
+ end
@@ -0,0 +1,11 @@
1
+ require "microformat/version"
2
+ require "microformat/parser"
3
+ require "microformat/review"
4
+ require "microformat/review_aggregate"
5
+ require "microformat/card"
6
+
7
+ module Microformat
8
+ def self.parse(*args)
9
+ Parser.parse(*args)
10
+ end
11
+ end
@@ -0,0 +1,50 @@
1
+ require "microformat/attribute_map"
2
+
3
+ module Microformat
4
+ class Attribute
5
+ attr_reader :name, :options, :attributes
6
+
7
+ def initialize(name, options = {}, &block)
8
+ @name = name
9
+ @options = options
10
+ @attributes ||= {}
11
+ if options[:format]
12
+ @attributes.merge!(options[:format].attribute_definition.attributes)
13
+ end
14
+ block.yield(self) if block_given?
15
+ end
16
+
17
+ def attribute(name, options = {}, &block)
18
+ Attribute.new(name, options, &block).tap do |attribute|
19
+ @attributes.merge!(name.to_sym => attribute)
20
+ end
21
+ end
22
+
23
+ def read_from(document)
24
+ selector = options[:selector] || ".#{@name}"
25
+ sub_document = document.css(selector).first
26
+ value = read_value_from(sub_document)
27
+ AttributeMap.new(self, sub_document, { value: value })
28
+ end
29
+
30
+ def read_value_from(document)
31
+ Array(options[:attribute] || "text").each do |attr|
32
+ if attr == "text"
33
+ return cast((document && document.text) || options[:default], options[:cast])
34
+ elsif document[attr]
35
+ return cast(document && document[attr], options[:cast])
36
+ end
37
+ end
38
+ return options[:default]
39
+ end
40
+
41
+ def cast(value, cast_to = nil)
42
+ value && case cast_to
43
+ when :integer then value.to_s.strip.to_i
44
+ when :decimal then value.to_s.strip.to_f
45
+ when :string then value.to_s.strip
46
+ else value
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,23 @@
1
+ require "microformat/attribute"
2
+ require "microformat/attribute_map"
3
+
4
+ module Microformat
5
+ class AttributeDefinition
6
+ attr_reader :attributes
7
+
8
+ def initialize(&block)
9
+ @attributes ||= {}
10
+ block.yield(self)
11
+ end
12
+
13
+ def attribute(name, options = {}, &block)
14
+ Attribute.new(name, options, &block).tap do |attribute|
15
+ @attributes.merge!(name.to_sym => attribute)
16
+ end
17
+ end
18
+
19
+ def map_to(document)
20
+ AttributeMap.new(self, document)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module Microformat
2
+ class AttributeMap
3
+ attr_reader :definition, :document
4
+
5
+ def initialize(definition, document, values = {})
6
+ @definition = definition
7
+ @document = document
8
+ @values = values
9
+ @attribute_cache = {}
10
+ end
11
+
12
+ def respond_to_missing?(name, public_only = false)
13
+ values_responds_to?(name) ||
14
+ definition_responds_to?(name)
15
+ end
16
+
17
+ def method_missing(name, *args, &block)
18
+ if values_responds_to?(name)
19
+ @values.fetch(name.to_sym)
20
+ elsif @attribute_cache.has_key?(name)
21
+ @attribute_cache[name]
22
+ elsif definition_responds_to?(name)
23
+ attribute = @definition.attributes.fetch(name)
24
+ value = attribute.read_from(document)
25
+ @attribute_cache[name] = value
26
+ else
27
+ super(name)
28
+ end
29
+ end
30
+
31
+ private
32
+ def values_responds_to?(name)
33
+ @values.has_key?(name.to_sym)
34
+ end
35
+
36
+ def definition_responds_to?(name)
37
+ @definition.attributes.has_key?(name.to_sym)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ require "microformat/format"
2
+
3
+ module Microformat
4
+ class Card < Format
5
+ selector ".vcard"
6
+
7
+ attribute_definition do |root|
8
+ root.attribute(:fn, required: true)
9
+ root.attribute(:n) do |n|
10
+ n.attribute(:"honorific-prefix")
11
+ n.attribute(:"given-name")
12
+ n.attribute(:"additional-name")
13
+ n.attribute(:"family-name")
14
+ n.attribute(:"honorific-suffix")
15
+ end
16
+ root.attribute(:nickname)
17
+ root.attribute(:org)
18
+ root.attribute(:photo, cast: :url, attribute: ["href", "src"])
19
+ root.attribute(:url, cast: :url, attribute: "href")
20
+ root.attribute(:email, cast: :email)
21
+ root.attribute(:tel, cast: :tel)
22
+ root.attribute(:categoria)
23
+ root.attribute(:adr) do |adr|
24
+ adr.attribute(:"street-address")
25
+ adr.attribute(:locality)
26
+ adr.attribute(:region)
27
+ adr.attribute(:"postal-code")
28
+ adr.attribute(:"country-name")
29
+ adr.attribute(:district)
30
+ end
31
+ root.attribute(:"bday")
32
+ root.attribute(:"category")
33
+ root.attribute(:"note")
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ require "microformat/selectors"
2
+
3
+ module Microformat
4
+ class Collection < ::Array
5
+ def <<(element)
6
+ # load the first matching format
7
+ format = Selectors.class_matching(element)
8
+ # use the microformat to parse the element
9
+ parsed = format.parse(element)
10
+ # add the parsed object to the array
11
+ super(parsed)
12
+ end
13
+
14
+ def filter(*args)
15
+ classes = Array(args).flatten
16
+ # find the applicable classes
17
+ filtered = select do |object|
18
+ Array(classes).include?(object.class)
19
+ end
20
+ # create a new collection from them
21
+ self.class.new.tap do |collection|
22
+ collection.replace(filtered)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ require "microformat/attribute_definition"
2
+ require "microformat/selectors"
3
+
4
+ module Microformat
5
+ class Format
6
+ def self.selector(selector = nil)
7
+ define_selector(selector) if selector
8
+ @selector
9
+ end
10
+
11
+ def self.attribute_definition(&block)
12
+ @attribute_definition = AttributeDefinition.new(&block) if block_given?
13
+ @attribute_definition
14
+ end
15
+
16
+ def self.parse(document)
17
+ new(document)
18
+ end
19
+
20
+ attr_reader :document
21
+
22
+ def initialize(document)
23
+ @document = document
24
+ end
25
+
26
+ def respond_to_missing?(name, public_only = false)
27
+ attribute_map.respond_to?(name)
28
+ end
29
+
30
+ def method_missing(name)
31
+ if attribute_map.respond_to?(name)
32
+ attribute_map.send(name)
33
+ else
34
+ super(name)
35
+ end
36
+ end
37
+
38
+ private
39
+ def attribute_map
40
+ @attribute_map ||= self.class.attribute_definition.map_to(document)
41
+ end
42
+
43
+ def self.define_selector(selector)
44
+ Selectors.define(selector, self)
45
+ @selector = selector
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,54 @@
1
+ require "nokogiri"
2
+ require "microformat/collection"
3
+ require "microformat/selectors"
4
+
5
+ module Microformat
6
+ class Parser
7
+ def self.parse(doc, options = {})
8
+ # ensure the document is parsed
9
+ unless doc.respond_to?(:css)
10
+ doc = Nokogiri::HTML(doc)
11
+ end
12
+ # return the collection
13
+ new(doc, options).collection
14
+ end
15
+
16
+ attr_reader :doc, :options
17
+
18
+ def initialize(doc, options)
19
+ @doc = doc
20
+ @options = options
21
+ parse(elements)
22
+ end
23
+
24
+ def parse(elements)
25
+ i = 0; while i < [limit, elements.size].min do
26
+ collection << elements[i]
27
+ i += 1
28
+ end
29
+ end
30
+
31
+ def limit
32
+ @limit ||= options[:limit] || Float::INFINITY
33
+ end
34
+
35
+ def selectors
36
+ @selectors ||= Selectors.filter(options[:filter])
37
+ end
38
+
39
+ def collection
40
+ @collection ||= Collection.new
41
+ end
42
+
43
+ private
44
+ def elements
45
+ @elements ||= [].tap do |elements|
46
+ while doc.css(selectors.join(", ")).length > 0
47
+ node = doc.css(selectors.join(", ")).first
48
+ node.remove
49
+ elements.push node
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,19 @@
1
+ require "microformat/format"
2
+ require "microformat/card"
3
+
4
+ module Microformat
5
+ class Review < Format
6
+ selector ".hreview"
7
+
8
+ attribute_definition do |root|
9
+ root.attribute(:summary)
10
+ root.attribute(:type)
11
+ root.attribute(:item, format: Card)
12
+ root.attribute(:reviewer, format: Card)
13
+ root.attribute(:rating, cast: :decimal)
14
+ root.attribute(:description)
15
+ root.attribute(:tags, multiple: true, selector: "[rel='tag']")
16
+ root.attribute(:permalink, selector: "[rel='bookmark']", attribute: "href")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ require "microformat/format"
2
+ require "microformat/card"
3
+
4
+ module Microformat
5
+ class ReviewAggregate < Format
6
+ selector ".hreview-aggregate"
7
+
8
+ attribute_definition do |root|
9
+ root.attribute(:item, format: Card)
10
+ root.attribute(:rating, cast: :decimal)
11
+ root.attribute(:count, cast: :integer)
12
+ root.attribute(:votes, cast: :integer)
13
+ root.attribute(:summary)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ require "singleton"
2
+
3
+ module Microformat
4
+ class Selectors < Hash
5
+ include Singleton
6
+
7
+ def self.class_matching(element)
8
+ # load the CSS classes of the element
9
+ css_classes = element["class"].split(/\s+/).map do |c|
10
+ ".#{c}"
11
+ end
12
+ # loop through the classes
13
+ Array(css_classes).each do |css_class|
14
+ instance.each do |selector, klass|
15
+ if selector == css_class
16
+ return klass
17
+ end
18
+ end
19
+ end
20
+ raise RuntimeError, "No class is defined for any of the selectors: #{css_classes.join(" / ")}"
21
+ end
22
+
23
+ def self.define(selector, klass)
24
+ if instance.has_key?(selector) && instance.fetch(selector) != klass
25
+ raise ArgumentError, "#{instance.fetch(selector).name} has already implemented the selector '#{selector}'"
26
+ else
27
+ instance.merge!(selector => klass)
28
+ end
29
+ end
30
+
31
+ def self.filter(klasses = nil)
32
+ if klasses
33
+ instance.filter(Array(klasses))
34
+ else
35
+ instance.keys
36
+ end
37
+ end
38
+
39
+ def filter(klasses)
40
+ select do |selector, klass|
41
+ Array(klasses).include?(klass)
42
+ end.keys
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module Microformat
2
+ VERSION = "0.0.8"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require "microformat/version"
6
+
7
+ Gem::Specification.new do |s|
8
+ s.authors = ["Ryan Townsend", "Tobias Begalke"]
9
+ s.email = ["ryan@ryantownsend.co.uk", "elcamino@spyz.org"]
10
+ s.description = %q{Reads Microformats from HTML documents}
11
+ s.summary = s.description
12
+ s.homepage = "https://github.com/elcamino/microformat"
13
+
14
+ s.files = `git ls-files`.split($\)
15
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ s.name = "elcamino-microformat"
18
+ s.require_paths = ["lib"]
19
+ s.version = Microformat::VERSION
20
+
21
+ # gems
22
+ s.add_dependency "nokogiri"
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "rspec"
25
+ s.add_development_dependency "simplecov"
26
+ end
@@ -0,0 +1,16 @@
1
+ require "spec_helper"
2
+
3
+ describe Microformat::AttributeDefinition do
4
+ subject { Microformat::AttributeDefinition }
5
+
6
+ describe "#initialize" do
7
+ it "should accept a block of nested attributes" do
8
+ map = subject.new do |map|
9
+ map.attribute(:one)
10
+ map.attribute(:two)
11
+ end
12
+
13
+ expect(map.attributes.size).to eq(2)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe Microformat::Attribute do
4
+ subject { Microformat::Attribute }
5
+
6
+ describe "#initialize" do
7
+ it "should accept a block of nested attributes" do
8
+ attribute = subject.new(:name) do |attr|
9
+ attr.attribute(:one)
10
+ attr.attribute(:two)
11
+ attr.attribute(:three) do |three|
12
+ three.attribute(:four)
13
+ end
14
+ end
15
+
16
+ expect(attribute.attributes.size).to eq(3)
17
+ end
18
+
19
+ it "should set the name" do
20
+ expect(subject.new(:fn).name).to eq(:fn)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ describe Microformat::Collection do
4
+ subject do
5
+ Microformat::Collection.new
6
+ end
7
+
8
+ describe "#<<" do
9
+ it "should parse the element to the collection" do
10
+ selector = ".selector"
11
+ source = %Q(<html><body>
12
+ <div class="#{selector.gsub(/^\./, "")}"></div>
13
+ </body></html>)
14
+ element = Nokogiri::HTML(source).css(selector).first
15
+ parsed = mock("parsed_object")
16
+ format = mock("format")
17
+ format.should_receive(:parse).and_return(parsed)
18
+ Microformat::Selectors.define(selector, format)
19
+ subject << element
20
+ expect(subject).to include parsed
21
+ end
22
+ end
23
+
24
+ describe "#filter" do
25
+ it "should filter the collection down to the specific classes" do
26
+ objects = [Object.new, Hash.new, Array.new]
27
+ subject.replace(objects)
28
+ expect(subject.filter(Hash)).to eq [objects[1]]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+
3
+ module Microformat
4
+ class TestFormat < Microformat::Format; end
5
+ end
6
+
7
+ describe Microformat::Format do
8
+ after(:each) do
9
+ Microformat::Selectors.instance.replace({})
10
+ end
11
+
12
+ describe "::selector" do
13
+ describe "getting the value" do
14
+ it "should return the value" do
15
+ Microformat::TestFormat.selector ".review"
16
+ expect(Microformat::TestFormat.selector).to eq ".review"
17
+ end
18
+ end
19
+
20
+ describe "setting the value" do
21
+ it "should define the selector" do
22
+ Microformat::TestFormat.selector ".review2"
23
+ expect(Microformat::Selectors.instance[".review2"]).to eq Microformat::TestFormat
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "::attribute_definition" do
29
+ describe "setting the value" do
30
+ it "should accept a block and set the map correctly" do
31
+ map = Microformat::TestFormat.attribute_definition do |attr|
32
+ attr.attribute :name
33
+ end
34
+ expect(map.attributes.values.first.name).to eq :name
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "::parse" do
40
+ it "should return and instance of the format using the given document" do
41
+ html = %Q(<html><body>Something</body></html>)
42
+ doc = Nokogiri::HTML(html)
43
+ expect(Microformat::TestFormat.parse(doc).document).to eq doc
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,121 @@
1
+ require "spec_helper"
2
+ require "nokogiri"
3
+
4
+ describe Microformat::Parser do
5
+ describe "::parse" do
6
+ subject do
7
+ Microformat::Parser.parse(doc)
8
+ end
9
+
10
+ before(:each) do
11
+ Microformat::Selectors.instance.replace({})
12
+ [
13
+ Microformat::Card,
14
+ Microformat::Review
15
+ ].each { |klass| klass.selector(klass.selector) }
16
+ end
17
+
18
+ let(:html) do
19
+ %Q(<html><body></body></html>)
20
+ end
21
+
22
+ let(:review_html) do
23
+ %Q(<html><body>
24
+ <div class="hreview">
25
+ <div class="summary">It's good</div>
26
+ <div class="reviewer">
27
+ <p class="fn">Dave</p>
28
+ </div>
29
+ </div>
30
+ </body></html>)
31
+ end
32
+
33
+ let(:nested_review_html) do
34
+ %Q(<html><body>
35
+ <div class="hreview">
36
+ <div class="summary">It's good</div>
37
+ <div class="reviewer">
38
+ <p class="fn">Dave</p>
39
+ <div class="hreview"></div>
40
+ </div>
41
+ </div>
42
+ </body></html>)
43
+ end
44
+
45
+ context "given a HTML string" do
46
+ let(:doc) { html }
47
+
48
+ it "should return an instance of Microformat::Collection" do
49
+ expect(subject).to be_kind_of Microformat::Collection
50
+ end
51
+ end
52
+
53
+ context "given a HTML document" do
54
+ let(:doc) { Nokogiri::HTML(html) }
55
+
56
+ it "should return an instance of Microformat::Collection" do
57
+ expect(subject).to be_kind_of Microformat::Collection
58
+ end
59
+ end
60
+
61
+ context "given a HTML element" do
62
+ let(:doc) { Nokogiri::HTML(html).css("body") }
63
+
64
+ it "should return an instance of Microformat::Collection" do
65
+ expect(subject).to be_kind_of Microformat::Collection
66
+ end
67
+ end
68
+
69
+ context "given a HTML document with a hReview" do
70
+ let(:doc) { Nokogiri::HTML(review_html) }
71
+
72
+ it "should return a collection with one object" do
73
+ expect(subject.size).to eq 1
74
+ end
75
+
76
+ describe "the returned Microformat object" do
77
+ subject do
78
+ Microformat::Parser.parse(doc).first
79
+ end
80
+
81
+ it "should be a Microformat::Review" do
82
+ expect(subject).to be_kind_of(Microformat::Review)
83
+ end
84
+
85
+ it "should return the summary" do
86
+ expect(subject.summary.value).to eq "It's good"
87
+ end
88
+
89
+ it "should return the reviewer's full name" do
90
+ expect(subject.reviewer.fn.value).to eq "Dave"
91
+ end
92
+ end
93
+ end
94
+
95
+ context "given a HTML document with nested microformats" do
96
+ let(:doc) { Nokogiri::HTML(nested_review_html) }
97
+
98
+ it "should return a collection with one object" do
99
+ expect(subject.size).to eq 1
100
+ end
101
+
102
+ describe "the returned Microformat object" do
103
+ subject do
104
+ Microformat::Parser.parse(doc).first
105
+ end
106
+
107
+ it "should be a Microformat::Review" do
108
+ expect(subject).to be_kind_of(Microformat::Review)
109
+ end
110
+
111
+ it "should return the summary" do
112
+ expect(subject.summary.value).to eq "It's good"
113
+ end
114
+
115
+ it "should return the reviewer's full name" do
116
+ expect(subject.reviewer.fn.value).to eq "Dave"
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,92 @@
1
+ require "spec_helper"
2
+
3
+ describe Microformat::Selectors do
4
+ let(:selectors) { Hash.new }
5
+
6
+ subject do
7
+ Microformat::Selectors.instance
8
+ end
9
+
10
+ before(:each) do
11
+ selectors.each do |sel,klass|
12
+ Microformat::Selectors.define(sel, klass)
13
+ end
14
+ end
15
+
16
+ after(:each) do
17
+ Microformat::Selectors.instance.replace({})
18
+ end
19
+
20
+ describe "::instance" do
21
+ it "should always return the same object" do
22
+ expect(subject.class.instance.object_id).to eq subject.class.instance.object_id
23
+ end
24
+ end
25
+
26
+ describe "::define" do
27
+ context "when the selector is already defined" do
28
+ it "should raise an exception" do
29
+ subject.class.define(".hello", Hash)
30
+ expect {
31
+ subject.class.define(".hello", Object)
32
+ }.to raise_error(ArgumentError)
33
+ end
34
+ end
35
+
36
+ context "when redefining the selector" do
37
+ it "should not raise an exception" do
38
+ subject.class.define(".hello", Hash)
39
+ expect {
40
+ subject.class.define(".hello", Hash)
41
+ }.not_to raise_error(ArgumentError)
42
+ end
43
+ end
44
+
45
+ context "when the selector is not defined" do
46
+ it "should add the definition to the hash" do
47
+ subject.class.define(".hello", Hash)
48
+ expect(subject[".hello"]).to eq Hash
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "::class_matching" do
54
+ let(:selectors) do
55
+ {
56
+ ".review" => Object,
57
+ ".card" => Hash
58
+ }
59
+ end
60
+
61
+ it "should return the first class that matches the given selectors" do
62
+ doc = %Q(<html><body>
63
+ <div class="card review"></div>
64
+ </body></html>)
65
+ element = Nokogiri::HTML(doc).css(".card").first
66
+ expect(subject.class.class_matching(element)).to eq Hash
67
+ end
68
+
69
+ context "with no matching selectors" do
70
+ it "should raise an exception" do
71
+ doc = %Q(<html><body>
72
+ <div class="non"></div>
73
+ </body></html>)
74
+ element = Nokogiri::HTML(doc).css(".non").first
75
+ expect {
76
+ subject.class.class_matching(element)
77
+ }.to raise_error(RuntimeError)
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "::filter" do
83
+ let(:selectors) do
84
+ { ".review" => Object }
85
+ end
86
+
87
+ it "should return an array of selectors that match the given classes" do
88
+ expect(subject.class.filter(Object)).to eq [".review"]
89
+ expect(subject.class.filter(Hash)).to eq []
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe Microformat do
4
+ subject { Microformat }
5
+
6
+ describe "::parse" do
7
+ let(:args) { ["one", 2, :three] }
8
+
9
+ before(:each) do
10
+ Microformat::Parser.should_receive(:parse).with(*args).and_return(true)
11
+ end
12
+
13
+ it "should pass args onto the parser" do
14
+ expect(subject.parse(*args)).to be_true
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ require "simplecov"
2
+ SimpleCov.start do
3
+ add_filter "/spec/"
4
+ end
5
+
6
+ require "bundler"
7
+ Bundler.require
8
+
9
+ Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
@@ -0,0 +1,8 @@
1
+ RSpec.configure do |config|
2
+ config.expect_with :rspec do |c|
3
+ c.syntax = :expect
4
+ end
5
+
6
+ config.color_enabled = true
7
+ config.order = :random
8
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elcamino-microformat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.8
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Townsend
8
+ - Tobias Begalke
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-10-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: simplecov
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: Reads Microformats from HTML documents
71
+ email:
72
+ - ryan@ryantownsend.co.uk
73
+ - elcamino@spyz.org
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".rvmrc"
80
+ - ".travis.yml"
81
+ - Gemfile
82
+ - LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - lib/microformat.rb
86
+ - lib/microformat/attribute.rb
87
+ - lib/microformat/attribute_definition.rb
88
+ - lib/microformat/attribute_map.rb
89
+ - lib/microformat/card.rb
90
+ - lib/microformat/collection.rb
91
+ - lib/microformat/format.rb
92
+ - lib/microformat/parser.rb
93
+ - lib/microformat/review.rb
94
+ - lib/microformat/review_aggregate.rb
95
+ - lib/microformat/selectors.rb
96
+ - lib/microformat/version.rb
97
+ - microformat.gemspec
98
+ - spec/microformat/attribute_definition_spec.rb
99
+ - spec/microformat/attribute_spec.rb
100
+ - spec/microformat/collection_spec.rb
101
+ - spec/microformat/format_spec.rb
102
+ - spec/microformat/parser_spec.rb
103
+ - spec/microformat/selectors_spec.rb
104
+ - spec/microformat_spec.rb
105
+ - spec/spec_helper.rb
106
+ - spec/support/env.rb
107
+ homepage: https://github.com/elcamino/microformat
108
+ licenses: []
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.2.2
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Reads Microformats from HTML documents
130
+ test_files:
131
+ - spec/microformat/attribute_definition_spec.rb
132
+ - spec/microformat/attribute_spec.rb
133
+ - spec/microformat/collection_spec.rb
134
+ - spec/microformat/format_spec.rb
135
+ - spec/microformat/parser_spec.rb
136
+ - spec/microformat/selectors_spec.rb
137
+ - spec/microformat_spec.rb
138
+ - spec/spec_helper.rb
139
+ - spec/support/env.rb