risbn 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -6,21 +6,29 @@ Supports both isbn-10 and isbn-13.
6
6
 
7
7
  Provides a simple (barebones) tool for extracting isbns from pdf and chm files.
8
8
 
9
+ Provides barebones google data integration for retrieving all sorts of information from the isbn.
10
+
9
11
  == Examples:
10
12
 
13
+ require 'isbn'
11
14
  isbn = RISBN.parse_first("Some text with and isbn: ISBN-13: 978-0393317732") # => <RISBN isbn="9780393317732">
12
15
  isbn.valid? # => true
13
16
 
14
17
  require 'risbn/scanner'
15
18
  RISBN::Scanner.scan("some/file.pdf")
16
19
  RISBN::Scanner.scan("some/file.chm")
17
- RISBN::Scanner.scan("some/file.tx")
20
+ RISBN::Scanner.scan("some/file.txt")
18
21
 
19
- == Notes
22
+ require 'risbn/gdata'
23
+ RISBN::GData("978-0393317732").data # <OpenStruct self_url="http://www.google.com/books/feeds/volumes/kom8GwAACAAJ", ...
24
+ RISBN::GData("978-0393317732").data.rating # => 3.0
20
25
 
21
- Currently only works on unix like platforms.
26
+ # ...
27
+
28
+ == Notes
22
29
 
23
- Requires the following tools for scanning files:
30
+ The chm/pdf extraction only works on unix like platforms currently and requires
31
+ the following tools for scanning files:
24
32
 
25
33
  * Poppler for pdf (pdftotext utility)
26
34
  * Archmage for chm
data/Rakefile CHANGED
@@ -5,13 +5,13 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "risbn"
8
- gem.summary = %Q{some utils to handle isbn numbers}
9
- gem.description = %Q{some utils to handle isbn numbers}
8
+ gem.summary = %Q{Utils to handle isbns}
9
+ gem.description = %Q{Utils to handle isbns}
10
10
  gem.email = "EmmanuelOga@gmail.com"
11
11
  gem.homepage = "http://github.com/EmmanuelOga/risbn"
12
12
  gem.authors = ["Emmanuel Oga"]
13
13
  gem.add_development_dependency "rspec", ">= 1.2.9"
14
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ gem.add_dependency "nokogiri"
15
15
  end
16
16
  Jeweler::GemcutterTasks.new
17
17
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/lib/risbn.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  class RISBN
2
- attr_accessor :isbn
2
+ class InvalidISBN < ArgumentError; end
3
+
4
+ attr_reader :isbn
3
5
 
4
6
  # Gross, but good to catch anything even remotely similar to a ISBN.
5
7
  # Later, we can validate to see if it really is a ISBN.
@@ -29,6 +31,10 @@ class RISBN
29
31
  end
30
32
  end
31
33
 
34
+ def validate!
35
+ raise InvalidISBN unless valid?
36
+ end
37
+
32
38
  def to_s
33
39
  isbn
34
40
  end
@@ -62,3 +68,7 @@ class RISBN
62
68
  result == checksum
63
69
  end
64
70
  end
71
+
72
+ def RISBN(text)
73
+ RISBN.parse_first(text)
74
+ end
@@ -0,0 +1,88 @@
1
+ require 'risbn/nokogiri_utils'
2
+ require 'open-uri'
3
+ require 'ostruct'
4
+
5
+ class RISBN
6
+ class GData
7
+ attr_reader :isbn
8
+
9
+ # Provide an RISBN object or a string to be parsed for an ISBN.
10
+ def initialize(isbn)
11
+ risbn = isbn.is_a?(RISBN) ? isbn : RISBN(isbn)
12
+ risbn.validate!
13
+ @isbn = risbn.to_s
14
+ end
15
+
16
+ # google does not allow to access the data directly by isbn
17
+ # so a search is needed first to retrieve the actual google id.
18
+ def search_url
19
+ "http://books.google.com/books/feeds/volumes?q=ISBN#{ isbn }"
20
+ end
21
+
22
+ # performs a google search by isbn to retrieve the actual google book id.
23
+ def entry_url
24
+ @info ||= ( Nokogiri(open(search_url).read) / "entry" / "id" ).inner_text
25
+ end
26
+
27
+ # returns the original book xml from google.
28
+ def xml
29
+ @entry ||= open(entry_url).read
30
+ rescue => e
31
+ raise RuntimeError, "coult not open url: #{entry_url} : \n#{e}"
32
+ end
33
+
34
+ # nokogiri nodes from the xml
35
+ def xml_nodes
36
+ @xml_nodes ||= Nokogiri::XML(xml)
37
+ end
38
+
39
+ # hash representation of the google xml
40
+ def to_hash
41
+ @to_hash ||= RISBN::NokogiriUtils.hash_from_node(xml_nodes)[:entry]
42
+ end
43
+
44
+ # returns an openstruct with a massaged version of the original xml data.
45
+ def data
46
+ return @data if @data
47
+ h, data = to_hash, OpenStruct.new
48
+
49
+ data.creator = h[:creator]
50
+ data.date = h[:date]
51
+ data.description = h[:description]
52
+ data.format = h[:format]
53
+ data.id = h[:id]
54
+ data.identifier = h[:identifier]
55
+ data.language = h[:language]
56
+ data.publisher = h[:publisher]
57
+ data.rating = h[:rating][:attributes][:average].to_f
58
+ data.rating_max = h[:rating][:attributes][:max].to_f
59
+ data.rating_min = h[:rating][:attributes][:min].to_f
60
+ data.subject = h[:subject].map { |s| s.split(/ [\-\/] /) }.flatten.map(&:strip).uniq.sort
61
+ data.title = h[:title].uniq.join(" ")
62
+ data.updated = h[:updated]
63
+ data.category = h[:category]
64
+ data.embeddability = h[:embeddability][:value]
65
+ data.open_access = h[:openAccess][:value]
66
+ data.viewability = h[:viewability][:value]
67
+
68
+ h[:link].each do |link|
69
+ href = link.is_a?(Hash) ? link[:attributes][:href] : link.last[:href]
70
+ rel = link.is_a?(Hash) ? link[:attributes][:rel] : link.last[:rel]
71
+ data.send("#{rel[/thumbnail|info|annotation|alternate|self/]}_url=", href)
72
+ end
73
+
74
+ @data = data
75
+ end
76
+
77
+ end
78
+ end
79
+
80
+ class RISBN
81
+ def gdata
82
+ @gdata ||= RISBN::GData.new(self)
83
+ end
84
+
85
+ def self.GData(isbn)
86
+ RISBN::GData.new(isbn)
87
+ end
88
+ end
@@ -0,0 +1,40 @@
1
+ require 'nokogiri'
2
+
3
+ class RISBN
4
+ module NokogiriUtils
5
+ extend self
6
+
7
+ # http://gist.github.com/370755
8
+ def hash_from_node(node)
9
+ { node.root.name.to_sym => xml_node_to_hash(node.root) }
10
+ end
11
+
12
+ def xml_node_to_hash(node)
13
+ return to_value(node.content.to_s) unless node.element?
14
+
15
+ result_hash = {}
16
+
17
+ node.attributes.each do |key, attr|
18
+ ( result_hash[:attributes] ||= Hash.new )[attr.name.to_sym] = to_value(attr.value)
19
+ end
20
+
21
+ node.children.each do |child|
22
+ result = xml_node_to_hash(child)
23
+
24
+ if child.name == "text"
25
+ return to_value(result) unless child.next_sibling || child.previous_sibling
26
+ else
27
+ key, val = child.name.to_sym, to_value(result)
28
+ result_hash[key] = result_hash.key?(key) ? Array(result_hash[key]).push(val) : val
29
+ end
30
+ end
31
+
32
+ result_hash
33
+ end
34
+
35
+ def to_value(data)
36
+ data.is_a?(String) && data =~ /^\d+$/ ? data.to_i : data
37
+ end
38
+
39
+ end
40
+ end
data/lib/risbn/scanner.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'shellwords'
2
2
  require 'tmpdir'
3
- require 'iconv'
4
3
 
5
4
  class RISBN
6
5
 
@@ -0,0 +1,3 @@
1
+ class RISBN
2
+ VERSION = "0.3.0"
3
+ end
data/risbn.gemspec ADDED
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{risbn}
8
+ s.version = "0.3.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Emmanuel Oga"]
12
+ s.date = %q{2010-04-19}
13
+ s.description = %q{Utils to handle isbns}
14
+ s.email = %q{EmmanuelOga@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/risbn.rb",
27
+ "lib/risbn/gdata.rb",
28
+ "lib/risbn/nokogiri_utils.rb",
29
+ "lib/risbn/scanner.rb",
30
+ "lib/risbn/version.rb",
31
+ "risbn.gemspec",
32
+ "spec/fixtures/book.xml",
33
+ "spec/gdata_spec.rb",
34
+ "spec/risbn_spec.rb",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/EmmanuelOga/risbn}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.6}
41
+ s.summary = %q{Utils to handle isbns}
42
+ s.test_files = [
43
+ "spec/spec_helper.rb",
44
+ "spec/gdata_spec.rb",
45
+ "spec/risbn_spec.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
54
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
57
+ s.add_dependency(%q<nokogiri>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
61
+ s.add_dependency(%q<nokogiri>, [">= 0"])
62
+ end
63
+ end
64
+
@@ -0,0 +1,52 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+ <entry xmlns="http://www.w3.org/2005/Atom" xmlns:gbs="http://schemas.google.com/books/2008" xmlns:dc="http://purl.org/dc/terms" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005">
3
+ <id>http://www.google.com/books/feeds/volumes/VOS6IlCsuU4C</id>
4
+ <updated>2010-04-19T14:35:30.000Z</updated>
5
+ <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/books/2008#volume"/>
6
+ <title type="text">JavaScript</title>
7
+ <link rel="http://schemas.google.com/books/2008/thumbnail" type="image/x-unknown" href="http://bks8.books.google.com/books?id=VOS6IlCsuU4C&amp;printsec=frontcover&amp;img=1&amp;zoom=5&amp;edge=curl&amp;sig=ACfU3U3gH3x5RUB3-HuSK5bnyrSJqYRtlQ&amp;source=gbs_gdata"/>
8
+ <link rel="http://schemas.google.com/books/2008/info" type="text/html" href="http://books.google.com/books?id=VOS6IlCsuU4C&amp;ie=ISO-8859-1&amp;source=gbs_gdata"/>
9
+ <link rel="http://schemas.google.com/books/2008/annotation" type="application/atom+xml" href="http://www.google.com/books/feeds/users/me/volumes"/>
10
+ <link rel="alternate" type="text/html" href="http://books.google.com/books?id=VOS6IlCsuU4C&amp;ie=ISO-8859-1"/>
11
+ <link rel="self" type="application/atom+xml" href="http://www.google.com/books/feeds/volumes/VOS6IlCsuU4C"/>
12
+ <gbs:embeddability value="http://schemas.google.com/books/2008#embeddable"/>
13
+ <gbs:openAccess value="http://schemas.google.com/books/2008#disabled"/>
14
+ <gd:rating min="1" max="5" average="4.19"/>
15
+ <gbs:viewability value="http://schemas.google.com/books/2008#view_partial"/>
16
+ <dc:creator>David Flanagan</dc:creator>
17
+ <dc:date>2006</dc:date>
18
+ <dc:description>This Fifth Edition is completely revised and expanded to cover JavaScript as it is used in today's Web 2.0 applications. This book is both an example-driven programmer's guide and a keep-on-your-desk reference, with new chapters that explain everything you need to know to get the most out of JavaScript, including: Scripted HTTP and Ajax XML processing Client-side graphics using the canvas tag Namespaces in JavaScript--essential when writing complex programs Classes, closures, persistence, Flash, and JavaScript embedded in Java applications Part I explains the core JavaScript language in detail. If you are new to JavaScript, it will teach you the language. If you are already a JavaScript programmer, Part I will sharpen your skills and deepen your understanding of the language. Part II explains the scripting environment provided by web browsers, with a focus on DOM scripting with unobtrusive JavaScript. The broad and deep coverage of client-side JavaScript is illustrated with many sophisticated examples that demonstrate how to: Generate a table of contents for an HTML document Display DHTML animations Automate form validation Draw dynamic pie charts Make HTML elements draggable Define keyboard shortcuts for web applications Create Ajax-enabled tool tips Use XPath and XSLT on XML documents loaded with Ajax And much more Part III is a complete reference for core JavaScript. It documents every class, object, constructor, method, function, property, and constant defined by JavaScript 1.5 and ECMAScript Version 3. Part IV is a reference for client-side JavaScript, covering legacy web browser APIs, the standard Level 2 DOM API, and emerging standards such as the XMLHttpRequestobject and the canvas tag. More than 300,000 JavaScript programmers around the world have made this their indispensable reference book for building JavaScript applications. ""A must-have reference for expert JavaScript programmers...well-organized and detailed."" -- Brendan Eich, creator of JavaScript</dc:description>
19
+ <dc:format>Dimensions 17.8x24.0x5.2 cm</dc:format>
20
+ <dc:format>1028 pages</dc:format>
21
+ <dc:format>book</dc:format>
22
+ <dc:identifier>VOS6IlCsuU4C</dc:identifier>
23
+ <dc:identifier>ISBN:0596101996</dc:identifier>
24
+ <dc:identifier>ISBN:9780596101992</dc:identifier>
25
+ <dc:language>en</dc:language>
26
+ <dc:publisher>O'Reilly Media, Inc.</dc:publisher>
27
+ <dc:subject>JavaScript (Computer program language)</dc:subject>
28
+ <dc:subject>Web servers</dc:subject>
29
+ <dc:subject>Object-oriented programming (Computer science)</dc:subject>
30
+ <dc:subject>Web servers</dc:subject>
31
+ <dc:subject>JavaScript (Computer program language)</dc:subject>
32
+ <dc:subject>Object-oriented programming (Computer science)</dc:subject>
33
+ <dc:subject>Ajax (Web site development technology)</dc:subject>
34
+ <dc:subject>Scripting languages (Computer science)</dc:subject>
35
+ <dc:subject>Computers / Programming Languages / JavaScript &amp; VBScript</dc:subject>
36
+ <dc:subject>Computers / General</dc:subject>
37
+ <dc:subject>Computers / Interactive &amp; Multimedia</dc:subject>
38
+ <dc:subject>Computers / Internet / General</dc:subject>
39
+ <dc:subject>Computers / Internet / Browsers</dc:subject>
40
+ <dc:subject>Computers / Internet / Hardware</dc:subject>
41
+ <dc:subject>Computers / Internet / Security</dc:subject>
42
+ <dc:subject>Computers / Internet / Web Page Design</dc:subject>
43
+ <dc:subject>Computers / Internet / World Wide Web</dc:subject>
44
+ <dc:subject>Computers / Programming / Software Development</dc:subject>
45
+ <dc:subject>Computers / Programming Languages / General</dc:subject>
46
+ <dc:subject>Computers / Programming Languages / HTML</dc:subject>
47
+ <dc:subject>Computers / Programming Languages / Java</dc:subject>
48
+ <dc:subject>Computers / Programming Languages / XML</dc:subject>
49
+ <dc:subject>Computers / Programming Languages / Java</dc:subject>
50
+ <dc:title>JavaScript</dc:title>
51
+ <dc:title>the definitive guide</dc:title>
52
+ </entry>
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe RISBN::GData do
4
+ it "can create a gdata instance from a string" do
5
+ RISBN::GData("9780596101992").should be_an_instance_of(RISBN::GData)
6
+ end
7
+
8
+ it "can create a gdata instance from a RISBN" do
9
+ RISBN("9780596101992").gdata.should be_an_instance_of(RISBN::GData)
10
+ RISBN::GData(RISBN("9780596101992")).should be_an_instance_of(RISBN::GData)
11
+ end
12
+
13
+ it "raises Invalid ISBN if apropriate" do
14
+ expect { RISBN::GData("6660596101992") }.to raise_exception(RISBN::InvalidISBN)
15
+ expect { RISBN("6660596101992").gdata }.to raise_exception(RISBN::InvalidISBN)
16
+ expect { RISBN::GData(RISBN("6660596101992")) }.to raise_exception(RISBN::InvalidISBN)
17
+ end
18
+
19
+ context "retrieving gdata" do
20
+ before do
21
+ @isbn = RISBN("9780596101992")
22
+ @isbn.gdata.stub!(:xml).and_return(File.read(GDATA_FIXTURE_PATH))
23
+ end
24
+
25
+ it "returns an OpenStruct" do
26
+ @isbn.gdata.data.should be_an_instance_of(OpenStruct)
27
+ end
28
+
29
+ it "maps the attributes of the hash form of google response to an struct" do
30
+ additional_keys = [:open_access, :rating_max, :rating_min, :thumbnail_url,
31
+ :info_url, :annotation_url, :alternate_url, :self_url]
32
+
33
+ ( @isbn.gdata.to_hash.keys.uniq - [:link, :openAccess] + additional_keys).each do |key|
34
+ @isbn.gdata.data.should respond_to(key)
35
+ end
36
+ end
37
+ end
38
+ end
data/spec/risbn_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe RISBN do
4
4
  it "parses isbn numbers from a line of text" do
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'rubygems'
3
4
  require 'risbn'
5
+ require 'risbn/gdata'
4
6
  require 'spec'
5
7
  require 'spec/autorun'
6
8
 
9
+ GDATA_FIXTURE_PATH = File.join(File.dirname(__FILE__), 'fixtures', 'book.xml')
10
+
7
11
  Spec::Runner.configure do |config|
8
-
9
12
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: risbn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Emmanuel Oga
@@ -9,20 +14,36 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-02-24 00:00:00 -03:00
17
+ date: 2010-04-19 00:00:00 -03:00
13
18
  default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: rspec
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 2
30
+ - 9
23
31
  version: 1.2.9
24
- version:
25
- description: some utils to handle isbn numbers
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: nokogiri
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ description: Utils to handle isbns
26
47
  email: EmmanuelOga@gmail.com
27
48
  executables: []
28
49
 
@@ -39,7 +60,13 @@ files:
39
60
  - Rakefile
40
61
  - VERSION
41
62
  - lib/risbn.rb
63
+ - lib/risbn/gdata.rb
64
+ - lib/risbn/nokogiri_utils.rb
42
65
  - lib/risbn/scanner.rb
66
+ - lib/risbn/version.rb
67
+ - risbn.gemspec
68
+ - spec/fixtures/book.xml
69
+ - spec/gdata_spec.rb
43
70
  - spec/risbn_spec.rb
44
71
  - spec/spec_helper.rb
45
72
  has_rdoc: true
@@ -55,21 +82,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
82
  requirements:
56
83
  - - ">="
57
84
  - !ruby/object:Gem::Version
85
+ segments:
86
+ - 0
58
87
  version: "0"
59
- version:
60
88
  required_rubygems_version: !ruby/object:Gem::Requirement
61
89
  requirements:
62
90
  - - ">="
63
91
  - !ruby/object:Gem::Version
92
+ segments:
93
+ - 0
64
94
  version: "0"
65
- version:
66
95
  requirements: []
67
96
 
68
97
  rubyforge_project:
69
- rubygems_version: 1.3.5
98
+ rubygems_version: 1.3.6
70
99
  signing_key:
71
100
  specification_version: 3
72
- summary: some utils to handle isbn numbers
101
+ summary: Utils to handle isbns
73
102
  test_files:
74
103
  - spec/spec_helper.rb
104
+ - spec/gdata_spec.rb
75
105
  - spec/risbn_spec.rb