gepub 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -1
- data/.travis.yml +6 -0
- data/README.rdoc +9 -55
- data/bin/gepuber +11 -6
- data/examples/generate_example.rb +52 -0
- data/examples/image1.jpg +0 -0
- data/gepub.gemspec +3 -4
- data/lib/gepub/book.rb +154 -176
- data/lib/gepub/gepuber.rb +6 -2
- data/lib/gepub/item.rb +66 -7
- data/lib/gepub/manifest.rb +78 -0
- data/lib/gepub/meta.rb +119 -0
- data/lib/gepub/metadata.rb +230 -0
- data/lib/gepub/package.rb +232 -0
- data/lib/gepub/spine.rb +112 -0
- data/lib/gepub/version.rb +1 -1
- data/lib/gepub/xml_util.rb +25 -0
- data/lib/gepub.rb +16 -0
- data/spec/example_spec.rb +53 -0
- data/spec/fixtures/epubcheck-3.0b4/COPYING.txt +19 -0
- data/spec/fixtures/epubcheck-3.0b4/README.txt +61 -0
- data/spec/fixtures/epubcheck-3.0b4/epubcheck-3.0b4.jar +0 -0
- data/spec/fixtures/epubcheck-3.0b4/jing_license.txt +12 -0
- data/spec/fixtures/epubcheck-3.0b4/lib/commons-compress-1.2.jar +0 -0
- data/spec/fixtures/epubcheck-3.0b4/lib/cssparser-0.9.6.jar +0 -0
- data/spec/fixtures/epubcheck-3.0b4/lib/jing.jar +0 -0
- data/spec/fixtures/epubcheck-3.0b4/lib/sac-1.3.jar +0 -0
- data/spec/fixtures/epubcheck-3.0b4/lib/saxon9he.jar +0 -0
- data/spec/fixtures/testdata/image1.jpg +0 -0
- data/spec/fixtures/testdata/test.opf +60 -0
- data/spec/gepub_spec.rb +57 -17
- data/spec/gepuber_spec.rb +8 -8
- data/spec/manifest_spec.rb +36 -0
- data/spec/metadata_spec.rb +170 -0
- data/spec/package_spec.rb +98 -0
- data/spec/spine_spec.rb +41 -0
- metadata +53 -23
- data/examples/example.rb +0 -49
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.rdoc
CHANGED
@@ -1,70 +1,24 @@
|
|
1
1
|
= gepub
|
2
|
+
{<img src="https://secure.travis-ci.org/skoji/gepub.png" />}[http://travis-ci.org/skoji/gepub]
|
2
3
|
|
3
4
|
* http://github.com/skoji/gepub
|
4
5
|
|
5
6
|
== DESCRIPTION:
|
6
7
|
|
7
|
-
a
|
8
|
+
a generic EPUB parser/generator library.
|
8
9
|
|
9
10
|
== FEATURES/PROBLEMS:
|
10
11
|
|
11
|
-
* GEPUB::Book provides functionality to create
|
12
|
+
* GEPUB::Book provides functionality to create EPUB file, and parsing EPUB file
|
13
|
+
* from version 0.6, GEPUB::Book will be able handle almost every metadata in EPUB2/EPUB3.
|
14
|
+
.. but is still beta version. Please inform me when you find bugs.
|
12
15
|
|
13
|
-
*
|
14
|
-
* opf: can't specify date with event
|
15
|
-
* opf: unique-identifier's scheme is fixed to 'URL'
|
16
|
-
* ncx: can't nest navPoint elements
|
17
|
-
* ...and many other restrictions
|
18
|
-
|
19
|
-
* GEPUB::Generator has been removed. Use GEPUB::Book instead.
|
16
|
+
* Will provide easy to generate EPUB class, like Nokogiri::XML::Generator.
|
20
17
|
|
21
18
|
== SYNOPSIS:
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
require 'fileutils'
|
26
|
-
|
27
|
-
epubname = "testepub.epub"
|
28
|
-
title = "samplepub"
|
29
|
-
|
30
|
-
epub = GEPUB::Book.new(title)
|
31
|
-
epub.author="the author"
|
32
|
-
epub.publisher="the publisher"
|
33
|
-
epub.date = "2010-11-27"
|
34
|
-
epub.identifier = "http://www.skoji.jp/testepub/2010-06-26"
|
35
|
-
epub.locale = 'ja' #defaults to 'en'
|
36
|
-
|
37
|
-
# create test contents files
|
38
|
-
contents = {}
|
39
|
-
[ 'coverpage', 'chapter1', 'chapter2' ].each {
|
40
|
-
|name|
|
41
|
-
contents[name] = <<EOF
|
42
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
43
|
-
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
|
44
|
-
<head>
|
45
|
-
<title>sample #{name} </title>
|
46
|
-
</head>
|
47
|
-
<body>
|
48
|
-
<h1>#{name}</h1>
|
49
|
-
<p>here comes the contents for #{name}</p>
|
50
|
-
</body>
|
51
|
-
</html>
|
52
|
-
EOF
|
53
|
-
}
|
54
|
-
|
55
|
-
# coverpage won't appear on toc, so do not call addNav
|
56
|
-
epub.add_ordered_item('coverpage.html', StringIO.new(contents['coverpage']))
|
57
|
-
|
58
|
-
chap1 = epub.add_ordered_item("chapter1.html", StringIO.new(contents['chapter1']))
|
59
|
-
epub.add_nav(chap1, 'Chapter 1')
|
60
|
-
chap2 = epub.add_ordered_item("chapter2.html", StringIO.new(contents['chapter2']))
|
61
|
-
epub.add_nav(chap2, 'Chapter 2')
|
62
|
-
|
63
|
-
# GEPUB::Book#add_ordered_item will added on <manifest> and <spine> section.
|
64
|
-
# if you want to add image file, use GEPUB::Book#add_item instead.
|
65
|
-
|
66
|
-
epub.generate_epub(epubname)
|
67
|
-
|
20
|
+
see examples directory.
|
21
|
+
|
68
22
|
== INSTALL:
|
69
23
|
|
70
24
|
* gem install gepub
|
@@ -73,7 +27,7 @@ a good-enough EPUB generator library.
|
|
73
27
|
|
74
28
|
(The New BSD License)
|
75
29
|
|
76
|
-
Copyright (c) 2010-
|
30
|
+
Copyright (c) 2010-2012, KOJIMA Satoshi
|
77
31
|
All rights reserved.
|
78
32
|
|
79
33
|
Redistribution and use in source and binary forms, with or without
|
data/bin/gepuber
CHANGED
@@ -2,17 +2,17 @@ require 'gepub'
|
|
2
2
|
require 'optparse'
|
3
3
|
|
4
4
|
def usage
|
5
|
-
STDERR.print "gepuber [-d destination ] <source-directory>\r\n"
|
5
|
+
STDERR.print "gepuber [-d destination ] [-c configfilename] <source-directory>\r\n"
|
6
6
|
exit 1
|
7
7
|
end
|
8
8
|
|
9
|
-
def srccheck(srcdir)
|
9
|
+
def srccheck(srcdir, configfilename)
|
10
10
|
if !File.exist?(srcdir) || !File.directory?(srcdir)
|
11
11
|
STDERR.print "#{srcdir} is not a directory"
|
12
12
|
exit 1
|
13
13
|
end
|
14
|
-
if !File.exist?(File.join(srcdir,
|
15
|
-
STDERR.print "
|
14
|
+
if !File.exist?(File.join(srcdir, configfilename))
|
15
|
+
STDERR.print "#{configfilename} does not exists in#{srcdir}."
|
16
16
|
exit 1
|
17
17
|
end
|
18
18
|
end
|
@@ -25,6 +25,7 @@ def destcheck(destdir)
|
|
25
25
|
end
|
26
26
|
|
27
27
|
destbasedir = "."
|
28
|
+
configfilename = 'gepuber.conf'
|
28
29
|
|
29
30
|
opt = OptionParser.new
|
30
31
|
|
@@ -34,14 +35,18 @@ opt.on('-d [directory]') { |dir|
|
|
34
35
|
destbasedir = dir
|
35
36
|
}
|
36
37
|
|
38
|
+
opt.on('-c [configfilename]') { |name|
|
39
|
+
configfilename = name
|
40
|
+
}
|
41
|
+
|
37
42
|
destbasedir = File.expand_path(destbasedir)
|
38
43
|
|
39
44
|
srcdir = opt.parse(ARGV)[0]
|
40
|
-
srccheck(srcdir)
|
45
|
+
srccheck(srcdir, configfilename)
|
41
46
|
|
42
47
|
Dir.chdir(srcdir)
|
43
48
|
begin
|
44
|
-
File.open(
|
49
|
+
File.open(configfilename, 'rb') {
|
45
50
|
|io|
|
46
51
|
gepuber = GEPUB::Gepuber.new(eval("#{io.read}"))
|
47
52
|
gepuber.create destbasedir
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'rubygem'
|
3
|
+
require 'gepub'
|
4
|
+
|
5
|
+
book = GEPUB::Book.new
|
6
|
+
book.set_main_id('http:/example.jp/bookid_in_url', 'BookID', 'URL')
|
7
|
+
book.language = 'ja'
|
8
|
+
|
9
|
+
# you can add metadata and its property using block
|
10
|
+
book.add_title('GEPUBサンプル文書', nil, GEPUB::TITLE_TYPE::MAIN) {
|
11
|
+
|title|
|
12
|
+
title.lang = 'ja'
|
13
|
+
title.file_as = 'GEPUB Sample Book'
|
14
|
+
title.display_seq = 1
|
15
|
+
title.add_alternates(
|
16
|
+
'en' => 'GEPUB Sample Book (Japanese)',
|
17
|
+
'el' => 'GEPUB δείγμα (Ιαπωνικά)',
|
18
|
+
'th' => 'GEPUB ตัวอย่าง (ญี่ปุ่น)')
|
19
|
+
}
|
20
|
+
# you can do the same thing using method chain
|
21
|
+
book.add_title('これはあくまでサンプルです',nil, GEPUB::TITLE_TYPE::SUBTITLE).set_display_seq(1).add_alternates('en' => 'this book is just a sample.')
|
22
|
+
book.add_creator('小嶋智') {
|
23
|
+
|creator|
|
24
|
+
creator.display_seq = 1
|
25
|
+
creator.add_alternates('en' => 'KOJIMA Satoshi')
|
26
|
+
}
|
27
|
+
book.add_contributor('電書部').set_display_seq(1).add_alternates('en' => 'Denshobu')
|
28
|
+
book.add_contributor('アサガヤデンショ').set_display_seq(2).add_alternates('en' => 'Asagaya Densho')
|
29
|
+
book.add_contributor('湘南電書鼎談').set_display_seq(3).add_alternates('en' => 'Shonan Densho Teidan')
|
30
|
+
book.add_contributor('電子雑誌トルタル').set_display_seq(4).add_alternates('en' => 'eMagazine Torutaru')
|
31
|
+
|
32
|
+
imgfile = File.join(File.dirname(__FILE__), 'img', 'image1.jpg')
|
33
|
+
File.open(imgfile) do
|
34
|
+
|io|
|
35
|
+
book.add_item('img/image1.jpg',io).cover_image
|
36
|
+
end
|
37
|
+
|
38
|
+
# within ordered block, add_item will be added to spine.
|
39
|
+
book.ordered {
|
40
|
+
book.add_item('text/chap1.xhtml').add_content(StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml"><head><title>c1</title></head><body><p>the first page</p></body></html>')).toc_text('Chapter 1')
|
41
|
+
book.add_item('text/chap1-1.xhtml').add_content(StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml"><head><title>c2</title></head><body><p>the second page</p></body></html>')) # do not appear on table of contents
|
42
|
+
book.add_item('text/chap2.xhtml').add_content(StringIO.new('<html xmlns="http://www.w3.org/1999/xhtml"><head><title>c3</title></head><body><p>the third page</p></body></html>')).toc_text('Chapter 2')
|
43
|
+
# to add nav file:
|
44
|
+
# book.add_item('path/to/nav').add_content(nav_html_content).add_property('nav')
|
45
|
+
}
|
46
|
+
epubname = File.join(File.dirname(__FILE__), 'example_test.epub')
|
47
|
+
|
48
|
+
# if you do not specify your own nav document with add_item,
|
49
|
+
# simple navigation text will be generated in generate_epub.
|
50
|
+
# auto-generated nav file will not appear on spine.
|
51
|
+
book.generate_epub(epubname)
|
52
|
+
|
data/examples/image1.jpg
ADDED
Binary file
|
data/gepub.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["KOJIMA Satoshi"]
|
9
9
|
s.email = ["skoji@mac.com"]
|
10
10
|
s.homepage = %q{http://github.com/skoji/gepub}
|
11
|
-
s.summary = %q{a
|
12
|
-
s.description = %q{
|
11
|
+
s.summary = %q{a generic EPUB parser/generator.}
|
12
|
+
s.description = %q{gepub is a EPUB parser/generator. Generates EPUB2 opf. will support EPUB3 parse/generation}
|
13
13
|
|
14
14
|
s.rubyforge_project = "gepub"
|
15
15
|
|
@@ -19,7 +19,6 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
s.add_development_dependency "rspec", ">= 2"
|
22
|
-
s.add_development_dependency "epubcheck", ">= 0.1.0"
|
23
22
|
s.add_runtime_dependency "nokogiri", ">= 1.5.0"
|
24
|
-
s.add_runtime_dependency "rubyzip", ">= 0.9.
|
23
|
+
s.add_runtime_dependency "rubyzip", ">= 0.9.6"
|
25
24
|
end
|
data/lib/gepub/book.rb
CHANGED
@@ -7,109 +7,134 @@ require 'fileutils'
|
|
7
7
|
|
8
8
|
module GEPUB
|
9
9
|
class Book
|
10
|
-
|
10
|
+
MIMETYPE='mimetype'
|
11
|
+
MIMETYPE_CONTENTS='application/epub+zip'
|
12
|
+
CONTAINER='META-INF/container.xml'
|
13
|
+
ROOTFILE_PATTERN=/^.+\.opf$/
|
14
|
+
CONTAINER_NS='urn:oasis:names:tc:opendocument:xmlns:container'
|
15
|
+
|
16
|
+
def self.rootfile_from_container(rootfile)
|
17
|
+
doc = Nokogiri::XML::Document.parse(rootfile)
|
18
|
+
ns = doc.root.namespaces
|
19
|
+
defaultns = ns.select{ |name, value| value == CONTAINER_NS }.keys[0]
|
20
|
+
doc.css("#{defaultns}|rootfiles > #{defaultns}|rootfile")[0]['full-path']
|
21
|
+
end
|
11
22
|
|
12
|
-
def self.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
def self.parse(io)
|
24
|
+
files = {}
|
25
|
+
package = nil
|
26
|
+
package_path = nil
|
27
|
+
Zip::ZipInputStream::open_buffer(io) {
|
28
|
+
|zis|
|
29
|
+
while entry = zis.get_next_entry
|
30
|
+
if !entry.directory?
|
31
|
+
files[entry.name] = zis.read
|
32
|
+
case entry.name
|
33
|
+
when MIMETYPE then
|
34
|
+
files[MIMETYPE] = nil
|
35
|
+
when CONTAINER then
|
36
|
+
package_path = rootfile_from_container(files[entry.name])
|
37
|
+
files[CONTAINER] = nil
|
38
|
+
when ROOTFILE_PATTERN then
|
39
|
+
package = Package.parse_opf(files[entry.name], entry.name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
if package_path != package.path
|
44
|
+
warn 'inconsistend EPUB file: container says opf is #{package_path}, but actually #{package.path}'
|
45
|
+
end
|
46
|
+
files.each {
|
47
|
+
|k, content|
|
48
|
+
item = package.manifest.item_by_href(k.sub(/^#{package.contents_prefix}/,''))
|
49
|
+
if !item.nil?
|
50
|
+
files[k] = nil
|
51
|
+
item.add_raw_content(content)
|
52
|
+
end
|
53
|
+
}
|
54
|
+
book = Book.new(package.path)
|
55
|
+
book.instance_eval { @package = package; @stray_files = files }
|
56
|
+
book
|
57
|
+
}
|
21
58
|
end
|
22
59
|
|
23
|
-
def initialize(
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@
|
28
|
-
@manifest = []
|
29
|
-
@spine = []
|
60
|
+
def initialize(path='OEBPS/package.opf', attributes = {})
|
61
|
+
if File.extname(path) != '.opf'
|
62
|
+
warn 'GEPUB::Book#new interface changed. You must supply path to package.opf as first argument. If you want to set title, please use GEPUB::Book#title='
|
63
|
+
end
|
64
|
+
@package = Package.new(path, attributes)
|
30
65
|
@toc = []
|
31
|
-
|
32
|
-
@contents_prefix = @contents_prefix + "/" if contents_prefix != ""
|
33
|
-
@itemcount = 0
|
34
|
-
@locale = 'en'
|
35
|
-
@epub_version = 2.1
|
36
|
-
@epub_backword_compat = false
|
37
|
-
end
|
38
|
-
|
39
|
-
def_meta :title
|
40
|
-
def_meta :author, :creator
|
41
|
-
def_meta :contributor
|
42
|
-
def_meta :publisher
|
43
|
-
def_meta :date
|
44
|
-
|
45
|
-
def identifier
|
46
|
-
@main_identifier
|
66
|
+
yield book if block_given?
|
47
67
|
end
|
48
68
|
|
49
|
-
def
|
50
|
-
|
51
|
-
@
|
52
|
-
end
|
53
|
-
|
54
|
-
def setIdentifier(scheme, identfier)
|
55
|
-
@metadata[:identifier] << { :scheme => scheme, :identifier => identifier }
|
69
|
+
def add_nav(item, text, id = nil)
|
70
|
+
warn 'add_nav is deprecated: please use Item#toc_text'
|
71
|
+
@toc.push({ :item => item, :text => text, :id => id})
|
56
72
|
end
|
57
73
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
74
|
+
def add_item(href, io = nil, id = nil, attributes = {})
|
75
|
+
item = @package.add_item(href,io,id,attributes)
|
76
|
+
toc = @toc
|
77
|
+
(class << item;self;end).send(:define_method, :toc_text,
|
78
|
+
Proc.new { |text, id = nil|
|
79
|
+
toc.push(:item => item, :text => text, :id => id)
|
80
|
+
item
|
81
|
+
})
|
82
|
+
yield item if block_given?
|
63
83
|
item
|
64
84
|
end
|
65
85
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
86
|
+
def add_ordered_item(href, io = nil, id = nil, attributes = {})
|
87
|
+
item = @package.add_ordered_item(href,io,id,attributes)
|
88
|
+
toc = @toc
|
89
|
+
(class << item;self;end).send(:define_method, :toc_text,
|
90
|
+
Proc.new { |text, id = nil|
|
91
|
+
toc.push(:item => item, :text => text, :id => id)
|
92
|
+
item
|
93
|
+
})
|
94
|
+
yield item if block_given?
|
73
95
|
item
|
74
96
|
end
|
75
|
-
|
76
|
-
def
|
77
|
-
@
|
78
|
-
end
|
79
|
-
|
80
|
-
def specify_cover_image(item)
|
81
|
-
@metadata[:cover] = item.itemid
|
97
|
+
|
98
|
+
def method_missing(name,*args)
|
99
|
+
@package.send(name, *args)
|
82
100
|
end
|
83
|
-
|
84
|
-
def
|
85
|
-
@
|
101
|
+
|
102
|
+
def ordered(&block)
|
103
|
+
@package.ordered(&block)
|
86
104
|
end
|
87
|
-
|
88
105
|
def generate_epub(path_to_epub)
|
89
106
|
if (@toc.size == 0)
|
90
|
-
@toc << { :item => @spine[0]
|
107
|
+
@toc << { :item => @package.spine.itemref_list[0] }
|
108
|
+
end
|
109
|
+
|
110
|
+
if version.to_f < 3.0 || @package.epub_backward_compat
|
111
|
+
add_item('toc.ncx', StringIO.new(ncx_xml), 'ncx')
|
91
112
|
end
|
92
113
|
|
93
|
-
|
114
|
+
if version.to_f >=3.0
|
115
|
+
@package.metadata.set_lastmodified
|
116
|
+
if @package.manifest.item_list.select {
|
117
|
+
|href, item|
|
118
|
+
(item.properties||[]).member? 'nav'
|
119
|
+
}.size == 0
|
120
|
+
generate_nav_doc
|
121
|
+
end
|
122
|
+
end
|
94
123
|
|
95
124
|
File.delete(path_to_epub) if File.exist?(path_to_epub)
|
96
125
|
Zip::ZipOutputStream::open(path_to_epub) {
|
97
126
|
|epub|
|
98
|
-
|
99
|
-
# create metadata files
|
100
127
|
epub.put_next_entry('mimetype', '', '', Zip::ZipEntry::STORED)
|
101
128
|
epub << "application/epub+zip"
|
102
|
-
|
103
129
|
epub.put_next_entry('META-INF/container.xml')
|
104
130
|
epub << container_xml
|
105
131
|
|
106
|
-
epub.put_next_entry(@
|
132
|
+
epub.put_next_entry(@package.path)
|
107
133
|
epub << opf_xml
|
108
134
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
epub.put_next_entry(@contents_prefix + item.href)
|
135
|
+
@package.manifest.item_list.each {
|
136
|
+
|k, item|
|
137
|
+
epub.put_next_entry(@package.contents_prefix + item.href)
|
113
138
|
epub << item.content
|
114
139
|
}
|
115
140
|
}
|
@@ -120,120 +145,73 @@ module GEPUB
|
|
120
145
|
<?xml version="1.0" encoding="UTF-8"?>
|
121
146
|
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
122
147
|
<rootfiles>
|
123
|
-
<rootfile full-path="#{@
|
148
|
+
<rootfile full-path="#{@package.path}" media-type="application/oebps-package+xml"/>
|
124
149
|
</rootfiles>
|
125
150
|
</container>
|
126
151
|
EOF
|
127
152
|
end
|
128
153
|
|
129
|
-
def
|
130
|
-
|
131
|
-
|
132
|
-
package.add_namespace(nil, 'http://www.idpf.org/2007/opf')
|
133
|
-
package['version'] = '2.0'
|
134
|
-
package['unique-identifier'] = 'BookID'
|
135
|
-
package << metadataelem = Nokogiri::XML::Node.new('metadata', opf)
|
136
|
-
metadataelem.add_namespace('opf', 'http://www.idpf.org/2007/opf')
|
137
|
-
metadataelem.add_namespace('dc', "http://purl.org/dc/elements/1.1/")
|
138
|
-
metadataelem << lang = Nokogiri::XML::Node.new('dc:language', opf)
|
139
|
-
lang.content = @locale
|
140
|
-
@metadata.each { |k,v|
|
141
|
-
if (k == :cover)
|
142
|
-
metadataelem << node = Nokogiri::XML::Node.new("meta", opf)
|
143
|
-
node['name'] = 'cover'
|
144
|
-
node['content'] = v
|
145
|
-
elsif (k == :identifier)
|
146
|
-
v.each {
|
147
|
-
|id|
|
148
|
-
metadataelem << node = Nokogiri::XML::Node.new("dc:#{k}", opf)
|
149
|
-
node.content = id[:identifier]
|
150
|
-
if (id[:main_id])
|
151
|
-
node['id'] = 'BookID'
|
152
|
-
end
|
153
|
-
node['opf:scheme'] = id[:scheme]
|
154
|
-
}
|
155
|
-
elsif (k == :gepub_version)
|
156
|
-
metadataelem << node = Nokogiri::XML::Node.new("meta", opf)
|
157
|
-
node['name'] = 'gepub version'
|
158
|
-
node['content'] = v
|
159
|
-
else
|
160
|
-
metadataelem << node = Nokogiri::XML::Node.new("dc:#{k}",opf)
|
161
|
-
node.content = v
|
162
|
-
end
|
163
|
-
}
|
164
|
-
|
165
|
-
package << manifestelem = Nokogiri::XML::Node.new('manifest', opf)
|
166
|
-
@manifest.each {
|
167
|
-
|item|
|
168
|
-
manifestelem << node = Nokogiri::XML::Node.new("item", opf)
|
169
|
-
node['id'] = "#{item.itemid}"
|
170
|
-
node['href'] = "#{item.href}"
|
171
|
-
node['media-type'] = "#{item.mediatype}"
|
172
|
-
}
|
173
|
-
|
174
|
-
package << spineelem = Nokogiri::XML::Node.new('spine', opf)
|
175
|
-
spineelem['toc'] = 'ncx'
|
154
|
+
def generate_nav_doc(title = 'Table of Contents')
|
155
|
+
add_item('nav.html', StringIO.new(nav_doc(title)), 'nav').add_property('nav')
|
156
|
+
end
|
176
157
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
158
|
+
def nav_doc(title = 'Table of Contents')
|
159
|
+
builder = Nokogiri::XML::Builder.new {
|
160
|
+
|doc|
|
161
|
+
doc.html('xmlns' => "http://www.w3.org/1999/xhtml",'xmlns:epub' => "http://www.idpf.org/2007/ops") {
|
162
|
+
doc.head { doc.text ' ' }
|
163
|
+
doc.body {
|
164
|
+
doc.nav('epub:type' => 'toc', 'id' => 'toc') {
|
165
|
+
doc.h1 "#{title}"
|
166
|
+
doc.ol {
|
167
|
+
@toc.each {
|
168
|
+
|x|
|
169
|
+
doc.li {
|
170
|
+
doc.a({'href' => x[:item].href} ,x[:text])
|
171
|
+
}
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
181
177
|
}
|
182
|
-
|
178
|
+
builder.to_xml
|
183
179
|
end
|
184
|
-
|
185
180
|
|
186
181
|
def ncx_xml
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
nav_point['id'] = "#{x[:item].itemid}"
|
218
|
-
nav_point['playOrder'] = "#{count}"
|
219
|
-
|
220
|
-
nav_label = Nokogiri::XML::Node.new('navLabel', ncx)
|
221
|
-
nav_label << navtxt = Nokogiri::XML::Node.new('text', ncx)
|
222
|
-
navtxt.content = "#{x[:text]}"
|
223
|
-
|
224
|
-
nav_content = Nokogiri::XML::Node.new('content', ncx)
|
225
|
-
if x[:id].nil?
|
226
|
-
nav_content['src'] = "#{x[:item].href}"
|
227
|
-
else
|
228
|
-
nav_content['src'] = "#{x[:item].href}##{x[:id]}"
|
229
|
-
end
|
230
|
-
|
231
|
-
count = count + 1
|
232
|
-
nav_map << nav_point
|
233
|
-
nav_point << nav_label
|
234
|
-
nav_point << nav_content
|
182
|
+
builder = Nokogiri::XML::Builder.new {
|
183
|
+
|xml|
|
184
|
+
xml.ncx('xmlns' => 'http://www.daisy.org/z3986/2005/ncx/', 'version' => '2005-1') {
|
185
|
+
xml.head {
|
186
|
+
xml.meta('name' => 'dtb:uid', 'content' => "#{self.identifier}")
|
187
|
+
xml.meta('name' => 'dtb:depth', 'content' => '1')
|
188
|
+
xml.meta('name' => 'dtb:totalPageCount','content' => '0')
|
189
|
+
xml.meta('name' => 'dtb:maxPageNumber', 'content' => '0')
|
190
|
+
}
|
191
|
+
xml.docTitle {
|
192
|
+
xml.text_ "#{@package.metadata.title}"
|
193
|
+
}
|
194
|
+
count = 1
|
195
|
+
xml.navMap {
|
196
|
+
@toc.each {
|
197
|
+
|x|
|
198
|
+
xml.navPoint('id' => "#{x[:item].itemid}", 'playOrder' => "#{count}") {
|
199
|
+
xml.navLabel {
|
200
|
+
xml.text_ "#{x[:text]}"
|
201
|
+
}
|
202
|
+
if x[:id].nil?
|
203
|
+
xml.content('src' => "#{x[:item].href}")
|
204
|
+
else
|
205
|
+
xml.content('src' => "#{x[:item].href}##{x[:id]}")
|
206
|
+
end
|
207
|
+
}
|
208
|
+
count += 1
|
209
|
+
}
|
210
|
+
}
|
211
|
+
}
|
235
212
|
}
|
236
|
-
|
213
|
+
builder.to_xml
|
237
214
|
end
|
215
|
+
|
238
216
|
end
|
239
217
|
end
|
data/lib/gepub/gepuber.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
module GEPUB
|
4
|
-
class Gepuber
|
4
|
+
class Gepuber
|
5
5
|
class FileProvider
|
6
6
|
include Enumerable
|
7
7
|
def initialize(pattern)
|
@@ -21,8 +21,12 @@ module GEPUB
|
|
21
21
|
|
22
22
|
attr_accessor :texts, :resources, :epubname, :coverimg, :table_of_contents, :provider
|
23
23
|
|
24
|
+
def method_missing(name, *args)
|
25
|
+
@package.send(name, *args)
|
26
|
+
end
|
27
|
+
|
24
28
|
def initialize(param)
|
25
|
-
|
29
|
+
@package = GEPUB::Package.new()
|
26
30
|
param.each {
|
27
31
|
|k,v|
|
28
32
|
self.send "#{k}=", v
|