epub-maker 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: 151508171923e54e7fff1950f2faceedab975568
4
+ data.tar.gz: 1343fe1b022341d99765ebc1a46a9261fb0339c7
5
+ SHA512:
6
+ metadata.gz: 6261ffcbc75632d75188ee109c544d46955a9917f3b817a8dd2df8d0edceca530ee4b436bf4347e14a7d6d3f9610333eed8420da22d608da78b4f8357f9ce6b8
7
+ data.tar.gz: de1a958a0ec211d11e82eac5f3e59bcde89b84da93bb5cb0faadc9f1a4b48ec8ef94551ff44c18edc715dff7a89fa060b7430108ba3b48c5f994aa01c4d6fd41
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ deps
19
+ *~
@@ -0,0 +1,4 @@
1
+ 0.0.1
2
+ ------
3
+
4
+ * Initial release!
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'epub-parser', path: '../epub-parser'
7
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012, 2013 KITAITI Makoto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,154 @@
1
+ EPUB Maker
2
+ ==========
3
+
4
+ This library supports making and editing EPUB books
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'epub-maker'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install epub-maker
20
+
21
+ Usage
22
+ -----
23
+
24
+ ### Library ###
25
+
26
+ require 'epub/maker'
27
+
28
+ EPUB::Maker.make path/to/generated/book.epub do |book|
29
+ book.make_ocf do |ocf|
30
+ ocf.make_container do |container|
31
+ container.make_rootfile full_path: 'OPS/content.opf'
32
+ end
33
+ end
34
+
35
+ book.make_package do |package|
36
+ package.dir = 'rtl'
37
+
38
+ package.make_metadata do |metadata|
39
+ metadata.title = 'Sample eBook'
40
+ metadata.language = 'ja'
41
+ end
42
+
43
+ package.make_manifest do |manifest|
44
+ Pathname.glob("#{@fixture_dir}/OPS/*.{xhtml,xml}").each_with_index do |content_path, index|
45
+ manifest.make_item do |item|
46
+ item.id = "item-#{index + 1}"
47
+ href = content_path.relative_path_from(@fixture_dir + File.dirname(book.rootfile_path))
48
+ item.href = Addressable::URI.parse(href.to_s)
49
+ item.media_type = case content_path.extname
50
+ when '.xhtml' then 'application/xhtml+xml'
51
+ when '.png' then 'image/png'
52
+ end
53
+ item.content_file = (@fixture_dir + item.entry_name).to_path
54
+ item.properties << 'nav' if content_path.basename.to_path == 'nav.xhtml'
55
+ end
56
+ end
57
+
58
+ package.make_spine do |spine|
59
+ spine.page_progression_direction = 'rtl'
60
+
61
+ package.manifest.items.select(&:xhtml?).each do |item|
62
+ spine.make_itemref do |itemref|
63
+ itemref.item = item
64
+ itemref.linear = true
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ For structure of EPUB book, see [EPUB Parser's documentation][epub-parser-doc].
73
+
74
+ ### Rake task ###
75
+
76
+ **CAUTION**: Still work in progress. File path to require and API will be modified in the future.
77
+
78
+ require 'epub/maker/task'
79
+
80
+ DIR = 'path/to/dir/holding/contents'
81
+ EPUB::Maker::Task.new @epub_name do |task|
82
+ task.titles = ['EPUB Maker Rake Example']
83
+
84
+ task.base_dir = DIR
85
+
86
+ task.files.include "#{task.base_dir}/**/*"
87
+ task.files.exclude {|entry| ! File.file? entry}
88
+
89
+ task.rootfile = "#{DIR}/OPS/contents.opf"
90
+ task.make_rootfiles = true
91
+
92
+ task.resources = task.files.dup
93
+ task.resources.exclude /\.opf/
94
+ task.resources.exclude /META\-INF/
95
+
96
+ task.navs.include 'OPS/nav.xhtml'
97
+ task.media_types = {"#{DIR}/OPS/slideshow.xml" => 'application/x-demo-slideshow'}
98
+
99
+ task.spine = task.resources.dup
100
+ task.spine.exclude /OPS\/impl\.xhtml\z/
101
+ task.spine.exclude /\.xml\z/
102
+
103
+ task.bindings = {'application/x-demo-slideshow' => "#{DIR}/OPS/impl.xhtml"}
104
+ end
105
+
106
+ ### In-place editing
107
+
108
+ require 'epub/maker'
109
+
110
+ book = EPUB::Parser.parse('path/to/book.epub')
111
+ book.resources.select(&:xhtml?).each do |item|
112
+ doc = item.content_document.nokogiri
113
+ title = doc/'title'
114
+ title.content += ' - Additional Title such like book title'
115
+ item.content = doc.to_xml
116
+ item.save
117
+ end
118
+
119
+ Shortcut:
120
+
121
+ book.resources.select(&:xhtml?).each do |item|
122
+ item.edit_with_nokogiri do |doc| # Nokogiri::XML::Document is passed to block
123
+ doc.search('img').each do |img|
124
+ img['alt'] = '' if img['alt'].nil?
125
+ end
126
+ end # item.content = doc.to_xml is called automatically
127
+ end # item.save is called automatically
128
+
129
+ For APIs of parsed EPUB book, see [EPUB Parser's documentation][epub-parser-doc].
130
+
131
+ [epub-parser-doc]: http://rubydoc.info/gems/epub-parser/frames
132
+
133
+ Requirements
134
+ ------------
135
+ * Ruby 2.0 or later
136
+ * C compiler to build zipruby and Nokogiri gems
137
+
138
+ Todo
139
+ ----
140
+ * Refine Rake task
141
+
142
+ Recent Changes
143
+ --------------
144
+ ### 0.0.1
145
+ * Initial release!
146
+
147
+ Contributing
148
+ ------------
149
+
150
+ 1. Fork it
151
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
152
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
153
+ 4. Push to the branch (`git push origin my-new-feature`)
154
+ 5. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ require 'rake/testtask'
2
+ require 'rake/clean'
3
+ require 'yard'
4
+ require "bundler/gem_tasks"
5
+
6
+ task :default => :test
7
+
8
+ CLEAN.include 'README.html'
9
+
10
+ Rake::TestTask.new
11
+ YARD::Rake::YardocTask.new
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'epub-maker'
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'epub/maker/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "epub-maker"
8
+ gem.version = EPUB::Maker::VERSION
9
+ gem.authors = ["KITAITI Makoto"]
10
+ gem.email = ["KitaitiMakoto@gmail.com"]
11
+ gem.description = %q{This library supports making and editing EPUB books}
12
+ gem.summary = %q{EPUB Maker}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.files.delete '"test/fixtures/book/OPS/\343\203\253\343\203\274\343\203\210\343\203\225\343\202\241\343\202\244\343\203\253.opf"'
17
+ gem.files.push('test/fixtures/book/OPS/ルートファイル.opf')
18
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ["lib"]
21
+ gem.required_ruby_version = '>= 2.0.0'
22
+
23
+ gem.add_runtime_dependency 'zipruby'
24
+ gem.add_runtime_dependency 'epub-parser', '>= 0.1.5'
25
+ gem.add_runtime_dependency 'pathname-common_prefix'
26
+ gem.add_runtime_dependency 'mime-types'
27
+ gem.add_runtime_dependency 'ruby-uuid'
28
+ gem.add_runtime_dependency 'archive-zip'
29
+ gem.add_runtime_dependency 'rake'
30
+
31
+ gem.add_development_dependency 'test-unit-full'
32
+ gem.add_development_dependency 'epubcheck'
33
+ gem.add_development_dependency 'epzip'
34
+ gem.add_development_dependency 'simplecov'
35
+ gem.add_development_dependency 'pry'
36
+ gem.add_development_dependency 'pry-doc'
37
+ gem.add_development_dependency 'yard'
38
+ gem.add_development_dependency 'redcarpet'
39
+ gem.add_development_dependency 'gem-man'
40
+ gem.add_development_dependency 'ronn'
41
+ end
@@ -0,0 +1,113 @@
1
+ require 'pathname'
2
+ require 'pathname/common_prefix'
3
+ require 'fileutils'
4
+ require 'tmpdir'
5
+ require 'time'
6
+ require 'uuid'
7
+ require 'archive/zip'
8
+ require 'epub'
9
+ require 'epub/constants'
10
+ require 'epub/book'
11
+ require 'epub/parser'
12
+ require "epub/maker/version"
13
+ require 'epub/maker/ocf'
14
+ require 'epub/maker/publication'
15
+ require 'epub/maker/content_document'
16
+
17
+ module EPUB
18
+ module Maker
19
+ class << self
20
+ # @param path [Pathname|#to_path|String]
21
+ # @todo Add option whether mv blocks or not when file locked already
22
+ # @todo Timeout when file shared-locked long time
23
+ def make(path)
24
+ path = Pathname(path) unless path.kind_of? Pathname
25
+ book = EPUB::Book.new
26
+ Pathname.mktmpdir 'epub-maker' do |dir|
27
+ temp_path = dir/path.basename
28
+ mimetype = dir/'mimetype'
29
+ mimetype.write EPUB::MediaType::EPUB
30
+ Archive::Zip.open temp_path.to_path, :w do |archive|
31
+ file = Archive::Zip::Entry.from_file(mimetype.to_path, compression_codec: Archive::Zip::Codec::Store)
32
+ archive.add_entry file
33
+ end
34
+
35
+ Zip::Archive.open temp_path.to_path do |archive|
36
+ yield book if block_given?
37
+ book.save archive
38
+ end
39
+
40
+ path.open 'wb' do |file|
41
+ raise "File locked by other process: #{path}" unless file.flock File::LOCK_SH|File::LOCK_NB
42
+ ($VERBOSE ? ::FileUtils::Verbose : ::FileUtils).move temp_path.to_path, path.to_path
43
+ end
44
+ end
45
+ book
46
+
47
+ # validate
48
+ # build_xml
49
+ # archive
50
+ end
51
+ end
52
+ end
53
+
54
+ def make_ocf
55
+ self.ocf = OCF.new
56
+ ocf.make do |ocf|
57
+ yield ocf if block_given?
58
+ end
59
+ ocf
60
+ end
61
+
62
+ def make_package
63
+ self.package = Publication::Package.new
64
+ package.make do |package|
65
+ yield package if block_given?
66
+ end
67
+ package
68
+ end
69
+
70
+ # @param archive [Zip::Archive]
71
+ def save(archive)
72
+ ocf.save archive
73
+ package.save archive
74
+ resources.each do |item|
75
+ item.save archive
76
+ end
77
+ end
78
+ end
79
+
80
+ class Pathname
81
+ class << self
82
+ # @overload mktmpdir(prefix_suffix=nil, tmpdir=nil)
83
+ # @param prefix_suffix [String|nil] see Dir.mktmpdir
84
+ # @param tmpdir [String|nil] see Dir.mktmpdir
85
+ # @return [Pathname] path to temporary directory
86
+ # @overload mktmpdir(prefix_suffix=nil, tmpdir=nil)
87
+ # @param prefix_suffix [String|nil] see Dir.mktmpdir
88
+ # @param tmpdir [String|nil] see Dir.mktmpdir
89
+ # @yieldparam dir [Pathname] path to temporary directory
90
+ # @return value of given block
91
+ def mktmpdir(prefix_suffix=nil, tmpdir=nil)
92
+ if block_given?
93
+ Dir.mktmpdir prefix_suffix, tmpdir do |dir|
94
+ yield new(dir)
95
+ end
96
+ else
97
+ new(Dir.mktmpdir(prefix_suffix, tmpdir))
98
+ end
99
+ end
100
+ end
101
+
102
+ def write(string, mode='w', perm=0666)
103
+ open mode, perm do |file|
104
+ file << string
105
+ end
106
+ end
107
+
108
+ def remove_entry_secure
109
+ FileUtils.remove_entry_secure to_path
110
+ end
111
+
112
+ alias / +
113
+ end
@@ -0,0 +1,36 @@
1
+ require 'epub/content_document'
2
+
3
+ module EPUB
4
+ module ContentDocument
5
+ class Navigation
6
+ def to_xml(options={:encoding => 'UTF-8'})
7
+ Nokogiri::XML::Builder.new(options) {|xml|
8
+ xml.html('xmlns' => EPUB::NAMESPACES['xhtml'], 'xmlns:epub' => EPUB::NAMESPACES['epub']) {
9
+ xml.head {
10
+ xml.title_ 'Table of Contents'
11
+ }
12
+ xml.body {
13
+ navigations.each do |navigation|
14
+ xml.nav_('epub:type' => navigation.type) {
15
+ unless navigation.items.empty?
16
+ xml.ol {
17
+ navigation.items.each do |item|
18
+ xml.li {
19
+ if item.href
20
+ xml.a item.text, 'href' => item.href
21
+ else
22
+ xml.span_ item.text
23
+ end
24
+ }
25
+ end
26
+ }
27
+ end
28
+ }
29
+ end
30
+ }
31
+ }
32
+ }.to_xml
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,60 @@
1
+ require 'epub/ocf'
2
+
3
+ # @todo Use refinement
4
+ module EPUB
5
+ class OCF
6
+ DIRECTORY = 'META-INF'
7
+
8
+ def make
9
+ yield self if block_given?
10
+ self
11
+ end
12
+
13
+ # @param archive [Zip::Archive] path to archive file
14
+ def save(archive)
15
+ self.container.save archive if self.container
16
+ end
17
+
18
+ # @overload make_container
19
+ # @return [Container]
20
+ # @overload make_container
21
+ # @return [Container]
22
+ # @yield [container] if block given
23
+ # @yieldparam [Container]
24
+ def make_container
25
+ self.container = Container.new
26
+ yield container if block_given?
27
+ container
28
+ end
29
+
30
+ class Container
31
+ def to_xml(options={:encoding => 'UTF-8'})
32
+ Nokogiri::XML::Builder.new(options) {|xml|
33
+ xml.container('xmlns' => EPUB::NAMESPACES['ocf'], 'version' => '1.0') {
34
+ xml.rootfiles {
35
+ rootfiles.each do |rootfile|
36
+ xml.rootfile('full-path' => rootfile.full_path,
37
+ 'media-type' => rootfile.media_type)
38
+ end
39
+ }
40
+ }
41
+ }.to_xml
42
+ end
43
+
44
+ # @param archive [Zip::Archive]
45
+ def save(archive)
46
+ archive.add_buffer File.join(DIRECTORY, Container::FILE), to_xml
47
+ end
48
+
49
+ # @option full_path [String|nil] full path to package document file in container such like "OPS/content.opf"
50
+ # @option media_type [String] media type
51
+ # @yield [Rootfile] rootfile
52
+ def make_rootfile(full_path: nil, media_type: EPUB::MediaType::ROOTFILE)
53
+ rootfile = Rootfile.new(full_path, media_type)
54
+ @rootfiles << rootfile
55
+ yield rootfile if block_given?
56
+ rootfile
57
+ end
58
+ end
59
+ end
60
+ end