gepub 0.5.0 → 0.6.0
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.
- 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
|