thepub 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009, 2010 Dmitri Goutnik, Invisible Llama
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.
data/README.markdown ADDED
@@ -0,0 +1,18 @@
1
+ = thepub
2
+
3
+ Nothing more than a direct extraction of [Repub's](http://github.com/invisiblellama/repub) epub module and associated tests.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2010 Dmitri Goutnik, Invisible Llama. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "thepub"
8
+ gem.summary = %Q{Extraction of Repub's epub module and associated tests}
9
+ gem.description = %Q{Extraction of Repub's epub module and associated tests}
10
+ gem.email = "hi@williammelody.com"
11
+ gem.homepage = "http://github.com/autodata/thepub"
12
+ gem.authors = ["Dmitri Goutnik, Invisible Llama", "William Melody"]
13
+ gem.add_development_dependency "thoughtbot-shoulda"
14
+ gem.add_dependency "nokogiri"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ if File.exist?('VERSION')
48
+ version = File.read('VERSION')
49
+ else
50
+ version = ""
51
+ end
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "thepub #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+
3
+ module Thepub
4
+ module Epub
5
+
6
+ # Mixin for stuff that can be added to the ePub package
7
+ #
8
+ module ContainerItem
9
+ attr_accessor :file_path
10
+ attr_accessor :media_type
11
+
12
+ def document?
13
+ ['application/xhtml+xml', 'application/x-dtbook+xml'].include? self.media_type
14
+ end
15
+ end
16
+
17
+ # Wrapper class for ePub items that do not have specialized classes
18
+ # e.g. HTML files, CSSs etc.
19
+ #
20
+ class Item
21
+ include ContainerItem
22
+
23
+ def initialize(file_path, media_type = nil)
24
+ @file_path = file_path.strip
25
+ @media_type = media_type || case @file_path.downcase
26
+ when /.*\.html?$/
27
+ 'application/xhtml+xml'
28
+ when /.*\.css$/
29
+ 'text/css'
30
+ when /.*\.(jpeg|jpg)$/
31
+ 'image/jpeg'
32
+ when /.*\.png$/
33
+ 'image/png'
34
+ when /.*\.gif$/
35
+ 'image/gif'
36
+ when /.*\.svg$/
37
+ 'image/svg+xml'
38
+ when /.*\.ncx$/
39
+ 'application/x-dtbncx+xml'
40
+ when /.*\.opf$/
41
+ 'application/oebps-package+xml'
42
+ else
43
+ raise 'Unknown media type'
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,137 @@
1
+ require 'rubygems'
2
+ require 'builder'
3
+
4
+ module Thepub
5
+ module Epub
6
+
7
+ class NCX
8
+ include ContainerItem
9
+
10
+ def initialize(uid, file_path = 'toc.ncx')
11
+ @file_path = file_path
12
+ @media_type = 'application/x-dtbncx+xml'
13
+ @head = Head.new(uid)
14
+ @doc_title = DocTitle.new('Untitled')
15
+ @nav_map = NavMap.new
16
+ end
17
+
18
+ def title
19
+ @doc_title.text
20
+ end
21
+
22
+ def title=(text)
23
+ @doc_title = DocTitle.new(text)
24
+ end
25
+
26
+ attr_reader :nav_map
27
+
28
+ def to_xml
29
+ out = ''
30
+ builder = Builder::XmlMarkup.new(:target => out)
31
+ builder.instruct!
32
+ builder.declare! :DOCTYPE, :ncx, :PUBLIC, "-//NISO//DTD ncx 2005-1//EN", "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd"
33
+ builder.ncx :xmlns => "http://www.daisy.org/z3986/2005/ncx/", :version => "2005-1" do
34
+ @nav_map.calc_depth_and_play_order
35
+ @head.depth = @nav_map.depth
36
+ @head.to_xml(builder)
37
+ @doc_title.to_xml(builder)
38
+ @nav_map.to_xml(builder)
39
+ end
40
+ out
41
+ end
42
+
43
+ def save
44
+ File.open(@file_path, 'w') do |f|
45
+ f << to_xml
46
+ end
47
+ end
48
+
49
+ class Head < Struct.new(
50
+ :uid
51
+ )
52
+
53
+ attr_accessor :depth
54
+
55
+ def to_xml(builder)
56
+ builder.head do
57
+ builder.meta :name => "dtb:uid", :content => self.uid
58
+ builder.meta :name => "dtb:depth", :content => @depth
59
+ builder.meta :name => "dtb:totalPageCount", :content => 0
60
+ builder.meta :name => "dtb:maxPageNumber", :content => 0
61
+ end
62
+ end
63
+ end
64
+
65
+ class DocTitle < Struct.new(
66
+ :text
67
+ )
68
+
69
+ def to_xml(builder)
70
+ builder.docTitle do
71
+ builder.text self.text
72
+ end
73
+ end
74
+ end
75
+
76
+ class NavPoint < Struct.new(
77
+ :title,
78
+ :src
79
+ )
80
+
81
+ def initialize(title, src, points = nil)
82
+ super(title, src)
83
+ @play_order = 0
84
+ @points = points || []
85
+ end
86
+
87
+ attr_accessor :play_order
88
+ attr_accessor :points
89
+
90
+ def to_xml(builder)
91
+ builder.navPoint :id => point_id(@play_order), :playOrder => @play_order do
92
+ builder.navLabel do
93
+ builder.text self.title
94
+ end
95
+ builder.content :src => self.src
96
+ @points.each { |point| point.to_xml(builder) }
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def point_id(play_order)
103
+ "navPoint-#{play_order}"
104
+ end
105
+ end
106
+
107
+ class NavMap < NavPoint
108
+
109
+ def initialize
110
+ super(nil, nil)
111
+ @depth = 1
112
+ end
113
+
114
+ attr_reader :depth
115
+
116
+ def calc_depth_and_play_order
117
+ play_order = 0
118
+ l = lambda do |points, depth|
119
+ @depth = depth if depth > @depth
120
+ points.each do |pt|
121
+ pt.play_order = (play_order += 1)
122
+ l.call(pt.points, depth + 1) unless pt.points.empty?
123
+ end
124
+ end
125
+ l.call(@points, @depth = 1)
126
+ end
127
+
128
+ def to_xml(builder)
129
+ builder.navMap do
130
+ @points.each { |point| point.to_xml(builder) }
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ end
137
+ end
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'builder'
4
+
5
+ module Thepub
6
+ module Epub
7
+
8
+ # OEBPS Container Format (OCF) 1.0 wrapper
9
+ # (see http://www.idpf.org/ocf/ocf1.0/download/ocf10.htm)
10
+ #
11
+ class OCF
12
+
13
+ def initialize
14
+ @items = []
15
+ end
16
+
17
+ attr_reader :items
18
+
19
+ def <<(item)
20
+ if item.kind_of? ContainerItem
21
+ @items << item
22
+ elsif item.is_a? String
23
+ @items << Item.new(item)
24
+ else
25
+ raise "Unsupported item class: #{item.class}"
26
+ end
27
+ end
28
+
29
+ def to_xml
30
+ out = ''
31
+ builder = Builder::XmlMarkup.new(:target => out)
32
+ builder.instruct!
33
+ builder.container :xmlns => "urn:oasis:names:tc:opendocument:xmlns:container", :version => "1.0" do
34
+ builder.rootfiles do
35
+ @items.each do |item|
36
+ builder.rootfile 'full-path' => item.file_path, 'media-type' => item.media_type
37
+ end
38
+ end
39
+ end
40
+ out
41
+ end
42
+
43
+ def save
44
+ meta_inf = 'META-INF'
45
+ FileUtils.mkdir_p(meta_inf)
46
+ File.open(File.join(meta_inf, 'container.xml'), 'w') do |f|
47
+ f << to_xml
48
+ end
49
+ end
50
+
51
+ def zip(output_path)
52
+ File.open('mimetype', 'w') do |f|
53
+ f << 'application/epub+zip'
54
+ end
55
+ # mimetype has to be first in the archive
56
+ %x(zip -X9 \"#{output_path}\" mimetype)
57
+ %x(zip -Xr9D \"#{output_path}\" * -xi mimetype)
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,137 @@
1
+ require 'rubygems'
2
+ require 'builder'
3
+
4
+ module Thepub
5
+ module Epub
6
+
7
+ # Open Packaging Format (OPF) 2.0 wrapper
8
+ # (see http://www.idpf.org/2007/opf/OPF_2.0_final_spec.html)
9
+ #
10
+ class OPF
11
+ include ContainerItem
12
+
13
+ def initialize(uid, file_path = 'package.opf')
14
+ @file_path = file_path
15
+ @media_type = 'application/oebps-package+xml'
16
+ @metadata = Metadata.new('Untitled', 'en', uid, Date.today.to_s)
17
+ @items = []
18
+ @ncx = nil
19
+ end
20
+
21
+ class Metadata < Struct.new(
22
+ :title,
23
+ :language,
24
+ :identifier,
25
+ :date,
26
+ :subject,
27
+ :description,
28
+ :relation,
29
+ :creator,
30
+ :publisher,
31
+ :rights
32
+ )
33
+
34
+ def to_xml(builder)
35
+ builder.metadata 'xmlns:dc' => "http://purl.org/dc/elements/1.1/",
36
+ 'xmlns:dcterms' => "http://purl.org/dc/terms/",
37
+ 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
38
+ 'xmlns:opf' => "http://www.idpf.org/2007/opf" do
39
+ # Required elements
40
+ builder.dc :title do
41
+ builder << self.title
42
+ end
43
+ builder.dc :language, 'xsi:type' => "dcterms:RFC3066" do
44
+ builder << self.language
45
+ end
46
+ builder.dc :identifier, :id => 'dcidid', 'opf:scheme' => 'URI' do
47
+ builder << self.identifier
48
+ end
49
+ # Optional elements
50
+ builder.dc :subject do
51
+ builder << self.subject
52
+ end if self.subject
53
+ builder.dc :description do
54
+ builder << self.description
55
+ end if self.description
56
+ builder.dc :relation do
57
+ builder << self.relation
58
+ end if self.relation
59
+ builder.dc :creator do # TODO: roles
60
+ builder << self.creator
61
+ end if self.creator
62
+ builder.dc :publisher do
63
+ builder << self.publisher
64
+ end if self.publisher
65
+ builder.dc :date do
66
+ builder << self.date.to_s
67
+ end if self.date
68
+ builder.dc :rights do
69
+ builder << self.rights
70
+ end if self.rights
71
+ end
72
+ end
73
+ end
74
+
75
+ attr_reader :metadata
76
+ attr_reader :items
77
+
78
+ def <<(item)
79
+ if item.kind_of? NCX
80
+ @ncx = item
81
+ elsif item.kind_of? ContainerItem
82
+ @items << item
83
+ elsif item.is_a? String
84
+ @items << Item.new(item)
85
+ else
86
+ raise "Unsupported item class: #{item.class}"
87
+ end
88
+ end
89
+
90
+ def to_xml
91
+ out = ''
92
+ builder = Builder::XmlMarkup.new(:target => out)
93
+ builder.instruct!
94
+ builder.package :xmlns => "http://www.idpf.org/2007/opf",
95
+ 'unique-identifier' => "dcidid",
96
+ 'version' => "2.0" do
97
+ @metadata.to_xml(builder)
98
+ manifest_to_xml(builder)
99
+ spine_to_xml(builder)
100
+ end
101
+ out
102
+ end
103
+
104
+ def save
105
+ File.open(@file_path, 'w') do |f|
106
+ f << to_xml
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ def item_id(index)
113
+ "item-#{index + 1}"
114
+ end
115
+
116
+ def manifest_to_xml(builder)
117
+ builder.manifest do
118
+ # NCX has fixed id
119
+ builder.item :id => 'ncx', :href => @ncx.file_path, 'media-type' => @ncx.media_type if @ncx
120
+ @items.each_with_index do |item, index|
121
+ builder.item :id => item_id(index), :href => item.file_path, 'media-type' => item.media_type
122
+ end
123
+ end
124
+ end
125
+
126
+ def spine_to_xml(builder)
127
+ # toc attribute points to the NCX item in manifest
128
+ builder.spine :toc => 'ncx' do
129
+ @items.each_with_index do |item, index|
130
+ builder.itemref :idref => item_id(index) if item.document?
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ end
137
+ end
@@ -0,0 +1,4 @@
1
+ require 'thepub/epub/container_item'
2
+ require 'thepub/epub/ocf'
3
+ require 'thepub/epub/opf'
4
+ require 'thepub/epub/ncx'
data/lib/thepub.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'nokogiri'
2
+ require 'thepub/epub'
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'thepub'
8
+
9
+ class Test::Unit::TestCase
10
+ end
data/test/test_ncx.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ class TestToc < Test::Unit::TestCase
4
+ def test_toc_create
5
+ ncx = Thepub::Epub::NCX.new('some-ncx')
6
+ s = ncx.to_xml
7
+ #p s
8
+ doc = Nokogiri::XML.parse(s)
9
+ assert_equal('some-ncx', doc.at("//xmlns:meta[@name='dtb:uid']")['content'])
10
+ assert_equal('1', doc.at("//xmlns:meta[@name='dtb:depth']")['content'])
11
+ assert_equal('0', doc.at("//xmlns:meta[@name='dtb:totalPageCount']")['content'])
12
+ assert_equal('0', doc.at("//xmlns:meta[@name='dtb:maxPageNumber']")['content'])
13
+ assert_equal('Untitled', doc.at("//xmlns:docTitle/xmlns:text").inner_text)
14
+ assert_not_nil(doc.at('//xmlns:navMap'))
15
+ end
16
+
17
+ def test_nav_map
18
+ ncx = Thepub::Epub::NCX.new('some-ncx')
19
+ ncx.nav_map.points << Thepub::Epub::NCX::NavPoint.new('Intro', 'intro.html')
20
+ ncx.nav_map.points << Thepub::Epub::NCX::NavPoint.new('Chapter 1', 'chapter-1.html')
21
+ ncx.nav_map.points << Thepub::Epub::NCX::NavPoint.new('Chapter 2', 'chapter-2.html')
22
+ ncx.nav_map.points[2].points << Thepub::Epub::NCX::NavPoint.new('Chapter 2-1', 'chapter-2-1.html')
23
+ ncx.nav_map.points << Thepub::Epub::NCX::NavPoint.new('Glossary', 'glossary.html')
24
+ ncx.nav_map.points[1].points << Thepub::Epub::NCX::NavPoint.new('Chapter 1-1', 'chapter-1-1.html')
25
+ ncx.nav_map.points[1].points << Thepub::Epub::NCX::NavPoint.new('Chapter 1-2', 'chapter-1-2.html')
26
+ s = ncx.to_xml
27
+ #p s
28
+ doc = Nokogiri::XML.parse(s)
29
+ assert_equal(4, doc.xpath('//xmlns:navMap/xmlns:navPoint').size)
30
+ assert_equal('2', doc.at("//xmlns:meta[@name='dtb:depth']")['content'])
31
+ assert_equal('1', doc.at('//xmlns:navMap/xmlns:navPoint[position()=1]')['playOrder'])
32
+ assert_equal('2', doc.at('//xmlns:navMap/xmlns:navPoint[position()=2]')['playOrder'])
33
+ assert_equal('3', doc.at('//xmlns:navMap/xmlns:navPoint[position()=2]/xmlns:navPoint[position()=1]')['playOrder'])
34
+ assert_equal('5', doc.at('//xmlns:navMap/xmlns:navPoint[position()=3]')['playOrder'])
35
+ assert_equal('navPoint-2', doc.at('//xmlns:navMap/xmlns:navPoint[position()=2]')['id'])
36
+ assert_equal('Chapter 1', doc.at('//xmlns:navMap/xmlns:navPoint[position()=2]/xmlns:navLabel/xmlns:text').inner_text)
37
+ assert_equal('chapter-1.html', doc.at('//xmlns:navMap/xmlns:navPoint[position()=2]/xmlns:content')['src'])
38
+ assert_equal(7, doc.xpath('//xmlns:navMap//xmlns:navPoint').size)
39
+ end
40
+ end
data/test/test_ocf.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class TestContainer < Test::Unit::TestCase
4
+ def test_container_create
5
+ container = Thepub::Epub::OCF.new
6
+ container << 'test.html'
7
+ container << Thepub::Epub::OPF.new('12345')
8
+ s = container.to_xml
9
+ #p s
10
+ doc = Nokogiri::XML.parse(s)
11
+ assert_not_nil(doc.at('rootfile'))
12
+ assert_equal('test.html', doc.at('rootfile[1]')['full-path'])
13
+ assert_equal('application/xhtml+xml', doc.at('rootfile[1]')['media-type'])
14
+ assert_equal('package.opf', doc.at('rootfile[2]')['full-path'])
15
+ assert_equal('application/oebps-package+xml', doc.at('rootfile[2]')['media-type'])
16
+ end
17
+
18
+ def test_container_create_fail
19
+ assert_raise(RuntimeError) do
20
+ # unknown mime type
21
+ container = Thepub::Epub::OCF.new
22
+ container << 'blah.blah'
23
+ end
24
+ end
25
+ end
data/test/test_opf.rb ADDED
@@ -0,0 +1,63 @@
1
+ require 'test_helper'
2
+
3
+ class TestContent < Test::Unit::TestCase
4
+ def test_create
5
+ opf = Thepub::Epub::OPF.new('some-opf')
6
+ s = opf.to_xml
7
+ doc = Nokogiri::XML.parse(s)
8
+ #p doc
9
+
10
+ metadata = doc.at('metadata')
11
+ assert_not_nil(metadata)
12
+ assert_equal('some-opf', metadata.xpath('dc:identifier', 'xmlns:dc' => "http://purl.org/dc/elements/1.1/").inner_text)
13
+ assert_equal('Untitled', metadata.xpath('dc:title', 'xmlns:dc' => "http://purl.org/dc/elements/1.1/").inner_text)
14
+ assert_equal('en', metadata.xpath('dc:language', 'xmlns:dc' => "http://purl.org/dc/elements/1.1/").inner_text)
15
+ assert_equal(Date.today.to_s, metadata.xpath('dc:date', 'xmlns:dc' => "http://purl.org/dc/elements/1.1/").inner_text)
16
+ end
17
+
18
+ def test_manifest_create
19
+ opf = Thepub::Epub::OPF.new('some-opf')
20
+ opf << Thepub::Epub::NCX.new('some-ncx')
21
+ s = opf.to_xml
22
+ doc = Nokogiri::XML.parse(s)
23
+ #p doc
24
+
25
+ manifest = doc.at('manifest')
26
+ assert_not_nil(manifest)
27
+ assert_equal(1, manifest.children.size)
28
+ assert_equal('ncx', manifest.at('item[@href="toc.ncx"]')['id'])
29
+ assert_not_nil(doc.at('spine'))
30
+ assert_equal(0, doc.xpath('spine/item').size)
31
+ end
32
+
33
+ def test_manifest_and_spine_items
34
+ opf = Thepub::Epub::OPF.new('some-opf')
35
+ opf << 'style.css'
36
+ opf << 'more-style.css'
37
+ opf << ' logo.jpg '
38
+ opf << 'intro.html'
39
+ opf << ' image.png'
40
+ opf << 'picture.jpeg '
41
+ opf << Thepub::Epub::NCX.new('some-ncx')
42
+ opf << 'chapter-1.html'
43
+ opf << 'glossary.html'
44
+ s = opf.to_xml
45
+ doc = Nokogiri::HTML(s)
46
+ #p doc
47
+
48
+ manifest = doc.at('manifest')
49
+ assert_not_nil(manifest)
50
+ assert_equal(2, manifest.xpath('item[@media-type="text/css"]').size)
51
+ assert_equal(2, manifest.search('item[@media-type="image/jpeg"]').size)
52
+ assert_equal(1, manifest.search('item[@media-type="image/png"]').size)
53
+ # NCX is first and always has id = 'ncx'
54
+ assert_equal('ncx', manifest.at('./item[position()=1]')['id'])
55
+
56
+ spine = doc.at('spine')
57
+ # attribute toc has and id of NCX manifest item
58
+ assert_equal('ncx', spine['toc'])
59
+ assert_equal(3, spine.search('itemref').size)
60
+ assert_equal('item-4', spine.at('./itemref[position()=1]')['idref'])
61
+ assert_equal('item-8', spine.at('./itemref[position()=3]')['idref'])
62
+ end
63
+ end
data/thepub.gemspec ADDED
@@ -0,0 +1,66 @@
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{thepub}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dmitri Goutnik, Invisible Llama", "William Melody"]
12
+ s.date = %q{2010-02-01}
13
+ s.description = %q{Extraction of Repub's epub module and associated tests}
14
+ s.email = %q{hi@williammelody.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.markdown",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/thepub.rb",
27
+ "lib/thepub/epub.rb",
28
+ "lib/thepub/epub/container_item.rb",
29
+ "lib/thepub/epub/ncx.rb",
30
+ "lib/thepub/epub/ocf.rb",
31
+ "lib/thepub/epub/opf.rb",
32
+ "test/test_helper.rb",
33
+ "test/test_ncx.rb",
34
+ "test/test_ocf.rb",
35
+ "test/test_opf.rb",
36
+ "thepub.gemspec"
37
+ ]
38
+ s.homepage = %q{http://github.com/autodata/thepub}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.5}
42
+ s.summary = %q{Extraction of Repub's epub module and associated tests}
43
+ s.test_files = [
44
+ "test/test_helper.rb",
45
+ "test/test_ncx.rb",
46
+ "test/test_ocf.rb",
47
+ "test/test_opf.rb"
48
+ ]
49
+
50
+ if s.respond_to? :specification_version then
51
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
55
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
56
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
57
+ else
58
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
59
+ s.add_dependency(%q<nokogiri>, [">= 0"])
60
+ end
61
+ else
62
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
63
+ s.add_dependency(%q<nokogiri>, [">= 0"])
64
+ end
65
+ end
66
+
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thepub
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Dmitri Goutnik, Invisible Llama
8
+ - William Melody
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2010-02-01 00:00:00 -06:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: thoughtbot-shoulda
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: nokogiri
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ version:
36
+ description: Extraction of Repub's epub module and associated tests
37
+ email: hi@williammelody.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - LICENSE
44
+ - README.markdown
45
+ files:
46
+ - .document
47
+ - .gitignore
48
+ - LICENSE
49
+ - README.markdown
50
+ - Rakefile
51
+ - VERSION
52
+ - lib/thepub.rb
53
+ - lib/thepub/epub.rb
54
+ - lib/thepub/epub/container_item.rb
55
+ - lib/thepub/epub/ncx.rb
56
+ - lib/thepub/epub/ocf.rb
57
+ - lib/thepub/epub/opf.rb
58
+ - test/test_helper.rb
59
+ - test/test_ncx.rb
60
+ - test/test_ocf.rb
61
+ - test/test_opf.rb
62
+ - thepub.gemspec
63
+ has_rdoc: true
64
+ homepage: http://github.com/autodata/thepub
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options:
69
+ - --charset=UTF-8
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.5
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Extraction of Repub's epub module and associated tests
91
+ test_files:
92
+ - test/test_helper.rb
93
+ - test/test_ncx.rb
94
+ - test/test_ocf.rb
95
+ - test/test_opf.rb