eeepub3 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e37fdd0df050b43117eb43439f4f2dba67cc9f96
4
+ data.tar.gz: 7e5a05e05a17afbdcd72c3c3a6ed2269c16c51d9
5
+ SHA512:
6
+ metadata.gz: e1587a96ace135f869eb4494d2c087e5dac8aedf7977140fa1bfe54469e12a3eb3bede7e099823ec7875d60a52d48c6f7af6527d1b859d421c9cb494135f0c97
7
+ data.tar.gz: 43d500fe967d569fbba17c71712eb6dfed33119cb6ca6dffd03c61808b939574659e7ab59d9e6ff07bd10eee880f318e5e179ee44087c8d8f39f12bb1438c5b9
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in eeepub.gemspec
4
+ gemspec
data/LICENSE ADDED
File without changes
@@ -0,0 +1,4 @@
1
+ eeepub3
2
+ =======
3
+
4
+ EPUB3 tools
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.rspec_opts = ['--color']
8
+ end
9
+ rescue LoadError => e
10
+ puts "RSpec not installed"
11
+ end
12
+
13
+ task :default => :spec
14
+
15
+ begin
16
+ require 'yard'
17
+ YARD::Rake::YardocTask.new
18
+ rescue LoadError
19
+ task :yardoc do
20
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "eeepub3"
5
+ s.version = "0.0.1"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["bubaz"]
8
+ s.email = ["s.bubovich@gmail.com"]
9
+ s.homepage = "http://github.com/bubaz/eeepub3"
10
+ s.summary = %q{ePub generator}
11
+ s.description = %q{EeePub is a Ruby ePub generator.}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency "builder"
19
+ s.add_dependency "rubyzip"
20
+ s.add_development_dependency "rspec"
21
+ s.add_development_dependency "nokogiri"
22
+ s.add_development_dependency "rr"
23
+ s.add_development_dependency "simplecov"
24
+ end
@@ -0,0 +1,15 @@
1
+ require 'eeepub/container_item'
2
+ require 'eeepub/opf'
3
+ require 'eeepub/ocf'
4
+ require 'eeepub/ncx'
5
+ require 'eeepub/maker'
6
+ require 'eeepub/easy'
7
+
8
+ module EeePub
9
+ # Make ePub
10
+ #
11
+ # @param [Proc] block the block for initialize EeePub::Maker
12
+ def self.make(&block)
13
+ EeePub::Maker.new(&block)
14
+ end
15
+ end
@@ -0,0 +1,116 @@
1
+ require 'builder'
2
+
3
+ module EeePub
4
+ # Abstract base class for container item of ePub. Provides some helper methods.
5
+ #
6
+ # @abstract
7
+ class ContainerItem
8
+ class << self
9
+
10
+ private
11
+
12
+ # Set default value to attribute
13
+ #
14
+ # @param [Symbol] name the attribute name
15
+ # @param [Object] default the default value
16
+ def default_value(name, default)
17
+ instance_variable_name = "@#{name}"
18
+ define_method(name) do
19
+ self.instance_variable_get(instance_variable_name) ||
20
+ self.instance_variable_set(instance_variable_name, default)
21
+ end
22
+ end
23
+
24
+ # Define alias of attribute accessor
25
+ #
26
+ # @param [Symbol] name the attribute name as alias
27
+ # @param [Symbol] name the attribute name as source
28
+ def attr_alias(name, src)
29
+ alias_method name, src
30
+ alias_method :"#{name}=", :"#{src}="
31
+ end
32
+ end
33
+
34
+ # @param [Hash<Symbol, Object>] values the hash of symbols and objects for attributes
35
+ def initialize(values)
36
+ set_values(values)
37
+ end
38
+
39
+ # Set values for attributes
40
+ #
41
+ # @param [Hash<Symbol, Object>] values the hash of symbols and objects for attributes
42
+ def set_values(values)
43
+ values.each do |k, v|
44
+ self.send(:"#{k}=", v)
45
+ end
46
+ end
47
+
48
+ # Convert to xml of container item
49
+ #
50
+ # @return [String] the xml of container item
51
+ def to_xml
52
+ out = ""
53
+ builder = Builder::XmlMarkup.new(:target => out, :indent => 2)
54
+ builder.instruct!
55
+ build_xml(builder)
56
+ out
57
+ end
58
+
59
+ # Save as container item
60
+ #
61
+ # @param [String] filepath the file path for container item
62
+ def save(filepath)
63
+ File.open(filepath, 'w') do |file|
64
+ file << self.to_xml
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ # Guess media type from file name
71
+ #
72
+ # @param [String] filename the file name
73
+ # @return [String] the media-type
74
+ def guess_media_type(filename)
75
+ ext = File.extname(filename)
76
+ mimes = {
77
+ '.png' => 'image/png',
78
+ '.js' => 'application/x-javascript',
79
+ '.html' => 'application/xhtml+xml',
80
+ '.jpeg' => 'image/jpeg',
81
+ '.jpg' => 'image/jpeg',
82
+ '.gif' => 'image/gif',
83
+ '.svg' => 'image/svg+xml',
84
+ '.ncx' => 'application/x-dtbncx+xml',
85
+ '.css' => 'text/css',
86
+ '.less' => 'text/plain', #explicit not text/css because of validation failure
87
+ '.mp4' => 'video/mp4',
88
+ '.mp3' => 'audio/mpeg',
89
+ '.webm' => 'video/webm',
90
+ '.woff' => 'application/font-woff',
91
+ '.otf' => 'application/vnd.ms-opentype',
92
+ '.ttf' => 'application/vnd.ms-opentype',
93
+ '.eot' => 'application/vnd.ms-opentype',
94
+ '.db' =>'application/octet-stream', #explicit,
95
+ '.nes'=>'text/plain; charset=x-user-defined', #explicit
96
+ '.txt'=>'text/plain'
97
+ }
98
+
99
+ mimes[ext] || 'application/octet-stream'
100
+
101
+ end
102
+
103
+ # Convert options for xml attributes
104
+ #
105
+ # @param [Hash<Symbol, Object>] hash the hash of symbols and objects for xml attributes
106
+ # @return [Hash<String, Object>] the options for xml attributes
107
+ def convert_to_xml_attributes(hash)
108
+ result = {}
109
+ hash.each do |k, v|
110
+ key = k.to_s.gsub('_', '-').to_sym
111
+ result[key] = v
112
+ end
113
+ result
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,100 @@
1
+ require 'tmpdir'
2
+ require 'fileutils'
3
+
4
+ module EeePub
5
+ # The class to make ePub more easily
6
+ #
7
+ # @example
8
+ # epub = EeePub::Easy.new do
9
+ # title 'sample'
10
+ # creator 'jugyo'
11
+ # identifier 'http://example.com/book/foo', :scheme => 'URL'
12
+ # uid 'http://example.com/book/foo'
13
+ # end
14
+ #
15
+ # epub.sections << ['1. foo', <<HTML]
16
+ # <?xml version="1.0" encoding="UTF-8"?>
17
+ # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
18
+ # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
19
+ # <head>
20
+ # <title>foo</title>
21
+ # </head>
22
+ # <body>
23
+ # <p>
24
+ # foo foo foo foo foo foo
25
+ # </p>
26
+ # </body>
27
+ # </html>
28
+ # HTML
29
+ #
30
+ # epub.assets << 'image.png'
31
+ #
32
+ # epub.save('sample.epub')
33
+ class Easy < EeePub::Maker
34
+ attr_reader :sections, :assets
35
+
36
+ # @param [Proc] block the block for initialize
37
+ def initialize(&block)
38
+ @sections = []
39
+ @assets = []
40
+ super
41
+ end
42
+
43
+ # Save as ePub file
44
+ #
45
+ # @param [String] filename the ePub file name to save
46
+ def save(filename)
47
+ Dir.mktmpdir do |dir|
48
+ prepare(dir)
49
+
50
+ NCX.new(
51
+ :uid => @uid,
52
+ :title => @titles[0],
53
+ :nav => @nav
54
+ ).save(File.join(dir, @ncx_file))
55
+
56
+ OPF.new(
57
+ :title => @titles,
58
+ :identifier => @identifiers,
59
+ :creator => @creators,
60
+ :publisher => @publishers,
61
+ :date => @dates,
62
+ :language => @languages,
63
+ :subject => @subjects,
64
+ :description => @descriptions,
65
+ :rights => @rightss,
66
+ :relation => @relations,
67
+ :manifest => @files.map{|i| File.basename(i)},
68
+ :ncx => @ncx_file
69
+ ).save(File.join(dir, @opf_file))
70
+
71
+ OCF.new(
72
+ :dir => dir,
73
+ :container => @opf_file
74
+ ).save(filename)
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def prepare(dir)
81
+ filenames = []
82
+ sections.each_with_index do |section, index|
83
+ filename = File.join(dir, "section_#{index}.html")
84
+ File.open(filename, 'w') { |file| file.write section[1] }
85
+ filenames << filename
86
+ end
87
+
88
+ assets.each do |file|
89
+ FileUtils.cp(file, dir)
90
+ end
91
+
92
+ files(filenames + assets)
93
+ nav(
94
+ [sections, filenames].transpose.map do |section, filename|
95
+ {:label => section[0], :content => File.basename(filename)}
96
+ end
97
+ )
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,156 @@
1
+ require 'tmpdir'
2
+ require 'fileutils'
3
+
4
+ module EeePub
5
+ # The class to make ePub easily
6
+ #
7
+ # Note on unique identifiers:
8
+ #
9
+ # At least one 'identifier' must be the unique identifer represented by the name
10
+ # given to 'uid' and set via the hash option :id => {name}. The default name for
11
+ # uid is 'BookId' and doesn't need to be specified explicitly. If no identifier is
12
+ # marked as the unique identifier, the first one give will be chosen.
13
+ #
14
+ # @example
15
+ # epub = EeePub.make do
16
+ # title 'sample'
17
+ # creator 'jugyo'
18
+ # publisher 'jugyo.org'
19
+ # date '2010-05-06'
20
+ # uid 'BookId'
21
+ # identifier 'http://example.com/book/foo', :scheme => 'URL', :id => 'BookId'
22
+ #
23
+ # files ['/path/to/foo.html', '/path/to/bar.html']
24
+ # nav [
25
+ # {:label => '1. foo', :content => 'foo.html', :nav => [
26
+ # {:label => '1.1 foo-1', :content => 'foo.html#foo-1'}
27
+ # ]},
28
+ # {:label => '1. bar', :content => 'bar.html'}
29
+ # ]
30
+ # end
31
+ # epub.save('sample.epub')
32
+ class Maker
33
+ [
34
+ :title,
35
+ :creator,
36
+ :publisher,
37
+ :date,
38
+ :language,
39
+ :subject,
40
+ :description,
41
+ :rights,
42
+ :relation
43
+ ].each do |name|
44
+ class_eval <<-DELIM
45
+ def #{name}(value)
46
+ @#{name}s ||= []
47
+ @#{name}s << value
48
+ end
49
+ DELIM
50
+ end
51
+
52
+ [
53
+ :uid,
54
+ :files,
55
+ :nav,
56
+ :cover,
57
+ :ncx_file,
58
+ :opf_file,
59
+ :guide
60
+ ].each do |name|
61
+ define_method(name) do |arg|
62
+ instance_variable_set("@#{name}", arg)
63
+ end
64
+ end
65
+
66
+ def identifier(id, options)
67
+ @identifiers ||= []
68
+ @identifiers << {:value => id, :scheme => options[:scheme], :id => options[:id]}
69
+ end
70
+
71
+ # @param [Proc] block the block for initialize
72
+ def initialize(&block)
73
+ @files ||= []
74
+ @nav ||= []
75
+ @ncx_file ||= 'toc.ncx'
76
+ @opf_file ||= 'content.opf'
77
+
78
+ instance_eval(&block) if block_given?
79
+ end
80
+
81
+ # Save as ePub file
82
+ #
83
+ # @param [String] filename the ePub file name to save
84
+ def save(filename)
85
+ create_epub.save(filename)
86
+ end
87
+
88
+ # instead of saving to file, output the file contents.
89
+ # important for serving on-the-fly doc creation from
90
+ # web interface where we don't want to allow file system
91
+ # writes (Heroku, et al.)
92
+ def render
93
+ create_epub.render
94
+ end
95
+
96
+ private
97
+
98
+ def create_epub
99
+ @uid ||= 'BookId'
100
+ unique_identifier = @identifiers.select{ |i| i[:id] == @uid }.first
101
+ unless unique_identifier
102
+ unique_identifier = @identifiers.first
103
+ unique_identifier[:id] = @uid
104
+ end
105
+ dir = Dir.mktmpdir
106
+ @files.each do |file|
107
+ case file
108
+ when String
109
+ FileUtils.cp(file, dir)
110
+ when Hash
111
+ file_path, dir_path = *file.first
112
+ dest_dir = File.join(dir, dir_path)
113
+ FileUtils.mkdir_p(dest_dir)
114
+ FileUtils.cp(file_path, dest_dir)
115
+ end
116
+ end
117
+
118
+ NCX.new(
119
+ :uid => @identifiers.select{ |i| i[:id] == @uid }.first,
120
+ :title => @titles[0],
121
+ :nav => @nav
122
+ ).save(File.join(dir, @ncx_file))
123
+
124
+ OPF.new(
125
+ :title => @titles,
126
+ :unique_identifier => @uid,
127
+ :identifier => @identifiers,
128
+ :creator => @creators,
129
+ :publisher => @publishers,
130
+ :date => @dates,
131
+ :language => @languages,
132
+ :subject => @subjects,
133
+ :description => @descriptions,
134
+ :rights => @rightss,
135
+ :cover => @cover,
136
+ :relation => @relations,
137
+ :manifest => @files.map{|file|
138
+ case file
139
+ when String
140
+ File.basename(file)
141
+ when Hash
142
+ file_path, dir_path = *file.first
143
+ File.join(dir_path, File.basename(file_path))
144
+ end
145
+ },
146
+ :ncx => @ncx_file,
147
+ :guide => @guide
148
+ ).save(File.join(dir, @opf_file))
149
+
150
+ OCF.new(
151
+ :dir => dir,
152
+ :container => @opf_file
153
+ )
154
+ end
155
+ end
156
+ end