epubber 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +58 -0
- data/Rakefile +9 -0
- data/epubber.gemspec +23 -0
- data/lib/epubber/generator.rb +63 -0
- data/lib/epubber/generators/chapters.rb +20 -0
- data/lib/epubber/generators/content.rb +10 -0
- data/lib/epubber/generators/endnotes.rb +14 -0
- data/lib/epubber/generators/generator.rb +29 -0
- data/lib/epubber/generators/introduction.rb +14 -0
- data/lib/epubber/generators/static.rb +21 -0
- data/lib/epubber/generators/toc.rb +13 -0
- data/lib/epubber/models/book.rb +87 -0
- data/lib/epubber/models/chapter.rb +26 -0
- data/lib/epubber/models/concerns/has_chapters.rb +23 -0
- data/lib/epubber/models/concerns/has_endnotes.rb +17 -0
- data/lib/epubber/models/concerns/has_introduction.rb +17 -0
- data/lib/epubber/models/endnotes.rb +16 -0
- data/lib/epubber/models/introduction.rb +16 -0
- data/lib/epubber/services/compressor.rb +45 -0
- data/lib/epubber/services/persistance.rb +35 -0
- data/lib/epubber/services/template.rb +27 -0
- data/lib/epubber/version.rb +3 -0
- data/lib/epubber.rb +12 -0
- data/lib/templates/META-INF/com.apple.ibooks.display-options.xml +6 -0
- data/lib/templates/META-INF/container.xml +6 -0
- data/lib/templates/OEBPS/Styles/style.css +16 -0
- data/lib/templates/OEBPS/Text/acknowledgements.xhtml +15 -0
- data/lib/templates/OEBPS/Text/chapter.xhtml +16 -0
- data/lib/templates/OEBPS/Text/cover.xhtml +21 -0
- data/lib/templates/OEBPS/Text/dedication.xhtml +15 -0
- data/lib/templates/OEBPS/Text/endnotes.xhtml +16 -0
- data/lib/templates/OEBPS/Text/foreword.xhtml +15 -0
- data/lib/templates/OEBPS/Text/frontmatter.xhtml +15 -0
- data/lib/templates/OEBPS/Text/introduction.xhtml +16 -0
- data/lib/templates/OEBPS/Text/toc.xhtml +37 -0
- data/lib/templates/OEBPS/content.opf +180 -0
- data/lib/templates/OEBPS/toc.ncx +79 -0
- data/lib/templates/mimetype +1 -0
- data/test/test_epubber.rb +31 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 42daf1a5cfc9933d3bbccdffd13be03d45b585e4
|
4
|
+
data.tar.gz: b349d1f7b7ea333a6ceb4d470dbce023daba2534
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 424d892bfbc55f533d5c921b8884441a3f342388d99be0241694d9912ef6def42c7cf8b33456a0d305506bbbccf409ed55be0a80e26e65d56f1164d6273fd2e9
|
7
|
+
data.tar.gz: 53fd7dd832c3baea3aba7008a8f7b3f167e1002f4a7ad0f32d57b34f79f6a2893305d6d1df7d490e710944d355256c878eb764de65c89a7fc3305b5f5fba91a5
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Federico Ramirez
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Epubber
|
2
|
+
This gem allows you to easily build EPUB files programatically.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'epubber'
|
9
|
+
```
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install epubber
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
Epubber's DSL is rather simple:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
path = Epubber.generate do
|
24
|
+
title 'My First EPUB book'
|
25
|
+
author 'Ramirez, Federico'
|
26
|
+
description 'This is an example EPUB'
|
27
|
+
url 'http://my-url.com'
|
28
|
+
|
29
|
+
chapter do
|
30
|
+
title 'Chapter 1'
|
31
|
+
content '<p>This is some content!</p>'
|
32
|
+
end
|
33
|
+
|
34
|
+
chapter do
|
35
|
+
title 'Chapter 2'
|
36
|
+
content '<p>Some more content this is.</p>'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Now the `path` variable contains the full path of the generated EPUB file.
|
41
|
+
# Defaults to `#{title}.epub`
|
42
|
+
```
|
43
|
+
|
44
|
+
You can configure the generator
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
path = Epubber.generate filename: 'some-file.epub', workspace: '/tmp' do
|
48
|
+
# Ebook code here...
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
## Contributing
|
53
|
+
|
54
|
+
1. Fork it ( https://github.com/gosukiwi/epubber/fork )
|
55
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
56
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
57
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
58
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/epubber.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'epubber/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "epubber"
|
8
|
+
spec.version = Epubber::VERSION
|
9
|
+
spec.authors = ["Federico Ramirez"]
|
10
|
+
spec.email = ["fedra.arg@gmail.com"]
|
11
|
+
spec.summary = %q{Generate EPUB files programatically}
|
12
|
+
#spec.description = %q{TODO: Write a longer description. Optional.}
|
13
|
+
spec.homepage = "https://github.com/gosukiwi/epubber"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'epubber/generators/chapters'
|
2
|
+
require 'epubber/generators/content'
|
3
|
+
require 'epubber/generators/toc'
|
4
|
+
require 'epubber/generators/introduction'
|
5
|
+
require 'epubber/generators/static'
|
6
|
+
require 'epubber/generators/endnotes'
|
7
|
+
require 'epubber/services/persistance'
|
8
|
+
require 'epubber/services/compressor'
|
9
|
+
|
10
|
+
# Given a book and a place to work in, generates all required EPUB files
|
11
|
+
class Epubber::Generator
|
12
|
+
attr_reader :working_dir, :book, :filename
|
13
|
+
def initialize(book: book, filename: filename, working_dir: working_dir)
|
14
|
+
@book = book
|
15
|
+
@filename = filename || "#{book.title}.epub"
|
16
|
+
@working_dir = working_dir || '/tmp/epubber'
|
17
|
+
@persistance = Epubber::Services::Persistance.new File.join(@working_dir, 'workspace')
|
18
|
+
@generators = []
|
19
|
+
|
20
|
+
register_generators book: book, persistance: @persistance
|
21
|
+
end
|
22
|
+
|
23
|
+
def register_generators(params)
|
24
|
+
add_generator Epubber::Generators::Content.new(params)
|
25
|
+
add_generator Epubber::Generators::Introduction.new(params)
|
26
|
+
add_generator Epubber::Generators::Toc.new(params)
|
27
|
+
add_generator Epubber::Generators::Chapters.new(params)
|
28
|
+
add_generator Epubber::Generators::Static.new(params)
|
29
|
+
add_generator Epubber::Generators::Endnotes.new(params)
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate
|
33
|
+
@generators.each { |generator| generator.generate }
|
34
|
+
pack
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def clean_tmp
|
40
|
+
@persistance.clean
|
41
|
+
end
|
42
|
+
|
43
|
+
def compressor
|
44
|
+
Epubber::Services::Compressor.new
|
45
|
+
end
|
46
|
+
|
47
|
+
def compress
|
48
|
+
file = File.join working_dir, "#{filename}"
|
49
|
+
dir = File.join working_dir, 'workspace'
|
50
|
+
compressor.compress dir, file
|
51
|
+
return file
|
52
|
+
end
|
53
|
+
|
54
|
+
def pack
|
55
|
+
path = compress
|
56
|
+
clean_tmp
|
57
|
+
return path
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_generator(generator)
|
61
|
+
@generators << generator
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'epubber/generators/generator'
|
2
|
+
|
3
|
+
module Epubber::Generators
|
4
|
+
class Chapters < Generator
|
5
|
+
def generate
|
6
|
+
compiled_template = template.compile 'OEBPS/Text/chapter.xhtml'
|
7
|
+
book.chapters.each do |chapter|
|
8
|
+
generate_chapter compiled_template, chapter
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def generate_chapter(compiled_template, chapter)
|
15
|
+
context = chapter.contextify
|
16
|
+
content = compiled_template.render context
|
17
|
+
persist file: "OEBPS/Text/chapter#{context['id']}.xhtml", content: content
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'epubber/generators/generator'
|
2
|
+
|
3
|
+
module Epubber::Generators
|
4
|
+
class Content < Generator
|
5
|
+
def generate
|
6
|
+
content = template.parse file: 'OEBPS/content.opf', context: book_context
|
7
|
+
persist file: 'OEBPS/content.opf', content: content
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'epubber/generators/generator'
|
2
|
+
|
3
|
+
module Epubber::Generators
|
4
|
+
class Endnotes < Generator
|
5
|
+
def generate
|
6
|
+
# Because this is an optional generator, don't do anything if there's no
|
7
|
+
# introduction in the book
|
8
|
+
return if book.endnotes.nil?
|
9
|
+
|
10
|
+
content = template.parse file: 'OEBPS/Text/endnotes.xhtml', context: book_context
|
11
|
+
persist file: 'OEBPS/Text/endnotes.xhtml', content: content
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'epubber/services/template'
|
2
|
+
|
3
|
+
module Epubber::Generators
|
4
|
+
class Generator
|
5
|
+
attr_reader :book, :persistance
|
6
|
+
def initialize(book: book, persistance: persistance)
|
7
|
+
@book = book
|
8
|
+
@persistance = persistance
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def book_context
|
14
|
+
{ 'book' => book.contextify }
|
15
|
+
end
|
16
|
+
|
17
|
+
def template
|
18
|
+
Epubber::Services::Template.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def template_path(file)
|
22
|
+
template.path file
|
23
|
+
end
|
24
|
+
|
25
|
+
def persist(file: file, content: content)
|
26
|
+
persistance.persist file: file, content: content
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'epubber/generators/generator'
|
2
|
+
|
3
|
+
module Epubber::Generators
|
4
|
+
class Introduction < Generator
|
5
|
+
def generate
|
6
|
+
# Because this is an optional generator, don't do anything if there's no
|
7
|
+
# introduction in the book
|
8
|
+
return if book.introduction.nil?
|
9
|
+
|
10
|
+
content = template.parse file: 'OEBPS/Text/introduction.xhtml', context: book_context
|
11
|
+
persist file: 'OEBPS/Text/introduction.xhtml', content: content
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'epubber/generators/generator'
|
2
|
+
|
3
|
+
module Epubber::Generators
|
4
|
+
class Static < Generator
|
5
|
+
def generate
|
6
|
+
files = ['mimetype', 'META-INF/container.xml', 'META-INF/com.apple.ibooks.display-options.xml',
|
7
|
+
'OEBPS/Text/cover.xhtml', 'OEBPS/Styles/style.css']
|
8
|
+
files.each do |file|
|
9
|
+
copy file
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
# Get the file from the template and copy it unchanged
|
16
|
+
def copy(file)
|
17
|
+
content = File.open(template_path(file)).read
|
18
|
+
persist file: file, content: content
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'epubber/generators/generator'
|
2
|
+
|
3
|
+
module Epubber::Generators
|
4
|
+
class Toc < Generator
|
5
|
+
def generate
|
6
|
+
content = template.parse file: 'OEBPS/toc.ncx', context: book_context
|
7
|
+
persist file: 'OEBPS/toc.ncx', content: content
|
8
|
+
|
9
|
+
content = template.parse file: 'OEBPS/Text/toc.xhtml', context: book_context
|
10
|
+
persist file: 'OEBPS/Text/toc.xhtml', content: content
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'epubber/models/concerns/has_chapters'
|
3
|
+
require 'epubber/models/concerns/has_introduction'
|
4
|
+
require 'epubber/models/concerns/has_endnotes'
|
5
|
+
|
6
|
+
# Represents a book with it's chapters.
|
7
|
+
module Epubber::Models
|
8
|
+
class Book
|
9
|
+
# Related models and their DSL goodies
|
10
|
+
include Epubber::Models::Concerns::HasChapters
|
11
|
+
include Epubber::Models::Concerns::HasIntroduction
|
12
|
+
include Epubber::Models::Concerns::HasEndnotes
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@title = not_specified
|
16
|
+
@author = not_specified
|
17
|
+
@description = not_specified
|
18
|
+
@publisher = not_specified
|
19
|
+
@language = 'en'
|
20
|
+
@url = not_specified
|
21
|
+
# LIST / OF / SUBJECTS => https://www.bisg.org/complete-bisac-subject-headings-2014-edition
|
22
|
+
@subjects = 'NON000000 NON-CLASSIFIABLE'
|
23
|
+
@isbn = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def title(text = nil)
|
27
|
+
return @title if text.nil?
|
28
|
+
@title = text
|
29
|
+
end
|
30
|
+
|
31
|
+
def author(text)
|
32
|
+
@author = text
|
33
|
+
end
|
34
|
+
|
35
|
+
def publisher(text)
|
36
|
+
@publisher = text
|
37
|
+
end
|
38
|
+
|
39
|
+
def description(text)
|
40
|
+
@description = text
|
41
|
+
end
|
42
|
+
|
43
|
+
def language(lang)
|
44
|
+
@language = lang
|
45
|
+
end
|
46
|
+
|
47
|
+
def url(url)
|
48
|
+
@url = url
|
49
|
+
end
|
50
|
+
|
51
|
+
def subjects(subjects)
|
52
|
+
@subjects = subjects
|
53
|
+
end
|
54
|
+
|
55
|
+
def isbn(isbn)
|
56
|
+
@isbn = isbn
|
57
|
+
end
|
58
|
+
|
59
|
+
# Return a hash which can be used as a template's context
|
60
|
+
def contextify
|
61
|
+
context = {
|
62
|
+
# Attributes
|
63
|
+
"title" => @title,
|
64
|
+
"author" => @author,
|
65
|
+
"description" => @description,
|
66
|
+
"publisher" => @publisher,
|
67
|
+
"language" => @language,
|
68
|
+
"url" => @url,
|
69
|
+
"subjects" => @subjects,
|
70
|
+
"uuid" => ::SecureRandom.uuid,
|
71
|
+
"isbn" => @isbn
|
72
|
+
}
|
73
|
+
|
74
|
+
# Related models
|
75
|
+
context["chapters"] = contextified_chapters
|
76
|
+
context["introduction"] = contextified_introduction
|
77
|
+
context["endnotes"] = contextified_endnotes
|
78
|
+
return context
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
def not_specified
|
84
|
+
'Not specified'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Represents a book's chapter
|
2
|
+
module Epubber::Models
|
3
|
+
class Chapter
|
4
|
+
def initialize
|
5
|
+
@id = 0
|
6
|
+
@title = 'Not specified'
|
7
|
+
@content = '<p>Not specified</p>'
|
8
|
+
end
|
9
|
+
|
10
|
+
def id(idx)
|
11
|
+
@id = idx
|
12
|
+
end
|
13
|
+
|
14
|
+
def title(text)
|
15
|
+
@title = text
|
16
|
+
end
|
17
|
+
|
18
|
+
def content(text)
|
19
|
+
@content = text
|
20
|
+
end
|
21
|
+
|
22
|
+
def contextify
|
23
|
+
{ 'id' => @id, 'title' => @title, 'content' => @content }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'epubber/models/chapter'
|
2
|
+
|
3
|
+
module Epubber::Models::Concerns
|
4
|
+
module HasChapters
|
5
|
+
def chapters
|
6
|
+
@chapters ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
# Add chapter
|
10
|
+
def chapter(&block)
|
11
|
+
chapter = Epubber::Models::Chapter.new
|
12
|
+
chapter.instance_eval &block
|
13
|
+
chapter.id(chapters.count + 1)
|
14
|
+
chapters << chapter
|
15
|
+
end
|
16
|
+
|
17
|
+
def contextified_chapters
|
18
|
+
chapters.map do |chapter|
|
19
|
+
chapter.contextify
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'epubber/models/endnotes'
|
2
|
+
|
3
|
+
module Epubber::Models::Concerns
|
4
|
+
module HasEndnotes
|
5
|
+
def endnotes(&block)
|
6
|
+
@endnotes ||= nil
|
7
|
+
return @endnotes unless block_given?
|
8
|
+
@endnotes = Epubber::Models::Endnotes.new
|
9
|
+
@endnotes.instance_eval &block
|
10
|
+
end
|
11
|
+
|
12
|
+
def contextified_endnotes
|
13
|
+
return nil if endnotes.nil?
|
14
|
+
return endnotes.contextify
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'epubber/models/introduction'
|
2
|
+
|
3
|
+
module Epubber::Models::Concerns
|
4
|
+
module HasIntroduction
|
5
|
+
def introduction(&block)
|
6
|
+
@introduction ||= nil
|
7
|
+
return @introduction unless block_given?
|
8
|
+
@introduction = Epubber::Models::Introduction.new
|
9
|
+
@introduction.instance_eval &block
|
10
|
+
end
|
11
|
+
|
12
|
+
def contextified_introduction
|
13
|
+
return nil if introduction.nil?
|
14
|
+
return introduction.contextify
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Represents a book's introduction
|
2
|
+
module Epubber::Models
|
3
|
+
class Endnotes
|
4
|
+
def initialize
|
5
|
+
@content = '<p>Not specified</p>'
|
6
|
+
end
|
7
|
+
|
8
|
+
def content(content)
|
9
|
+
@content = content
|
10
|
+
end
|
11
|
+
|
12
|
+
def contextify
|
13
|
+
{ 'content' => @content }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Represents a book's introduction
|
2
|
+
module Epubber::Models
|
3
|
+
class Introduction
|
4
|
+
def initialize
|
5
|
+
@content = '<p>Not specified</p>'
|
6
|
+
end
|
7
|
+
|
8
|
+
def content(content)
|
9
|
+
@content = content
|
10
|
+
end
|
11
|
+
|
12
|
+
def contextify
|
13
|
+
{ 'content' => @content }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'zip'
|
2
|
+
|
3
|
+
module Epubber::Services
|
4
|
+
class Compressor
|
5
|
+
def compress(dir, file)
|
6
|
+
FileUtils.rm file if File.exists?(file)
|
7
|
+
generator = ZipFileGenerator.new dir, file
|
8
|
+
generator.write
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Helper class to create the actual zip file
|
13
|
+
class ZipFileGenerator
|
14
|
+
# Initialize with the directory to zip and the location of the output archive.
|
15
|
+
def initialize(inputDir, outputFile)
|
16
|
+
@inputDir = inputDir
|
17
|
+
@outputFile = outputFile
|
18
|
+
end
|
19
|
+
|
20
|
+
# Zip the input directory.
|
21
|
+
def write()
|
22
|
+
entries = Dir.entries(@inputDir); entries.delete("."); entries.delete("..")
|
23
|
+
io = Zip::File.open(@outputFile, Zip::File::CREATE);
|
24
|
+
|
25
|
+
writeEntries(entries, "", io)
|
26
|
+
io.close();
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def writeEntries(entries, path, io)
|
32
|
+
entries.each { |e|
|
33
|
+
zipFilePath = path == "" ? e : File.join(path, e)
|
34
|
+
diskFilePath = File.join(@inputDir, zipFilePath)
|
35
|
+
if File.directory?(diskFilePath)
|
36
|
+
io.mkdir(zipFilePath)
|
37
|
+
subdir =Dir.entries(diskFilePath); subdir.delete("."); subdir.delete("..")
|
38
|
+
writeEntries(subdir, zipFilePath, io)
|
39
|
+
else
|
40
|
+
io.get_output_stream(zipFilePath) { |f| f.puts(File.open(diskFilePath, "rb").read())}
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Epubber::Services
|
2
|
+
class Persistance
|
3
|
+
attr_reader :workspace
|
4
|
+
def initialize(workspace)
|
5
|
+
@workspace = workspace
|
6
|
+
end
|
7
|
+
|
8
|
+
# Persist a file into the working directory with the spcified contents.
|
9
|
+
# The file argument is the relative path to the new file, eg: test/chapters/file.xhtml
|
10
|
+
def persist(file: file, content: content)
|
11
|
+
create_path_for file
|
12
|
+
write file, content
|
13
|
+
end
|
14
|
+
|
15
|
+
# Remove the working directory, thus cleaning the file system
|
16
|
+
def clean
|
17
|
+
FileUtils.remove_dir workspace, true
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def write(file, content)
|
23
|
+
File.write path(file), content
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_path_for(file)
|
27
|
+
dir = File.dirname path(file)
|
28
|
+
FileUtils.mkdir_p dir unless File.directory?(dir)
|
29
|
+
end
|
30
|
+
|
31
|
+
def path(file)
|
32
|
+
File.join workspace, file
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
|
3
|
+
module Epubber::Services
|
4
|
+
class Template
|
5
|
+
# Compiles and renderes a template file in the given context
|
6
|
+
def parse(file: file, context: context)
|
7
|
+
compile(file).render context
|
8
|
+
end
|
9
|
+
|
10
|
+
# Compiles a file and returns a template instance ready to be rendered
|
11
|
+
def compile(file)
|
12
|
+
Liquid::Template.parse load(file)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the full path for a given template file
|
16
|
+
def path(file)
|
17
|
+
File.join File.dirname(__FILE__), '../../templates/', file
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
# Opens a file from disk located inside ./templates
|
23
|
+
def load(file)
|
24
|
+
File.open(path(file)).read
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/epubber.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "epubber/version"
|
2
|
+
require "epubber/models/book"
|
3
|
+
require "epubber/generator"
|
4
|
+
|
5
|
+
module Epubber
|
6
|
+
def self.generate(filename: filename = nil, working_dir: working_dir = nil, &block)
|
7
|
+
book = Epubber::Models::Book.new
|
8
|
+
book.instance_eval &block
|
9
|
+
generator = Epubber::Generator.new book: book, working_dir: working_dir, filename: filename
|
10
|
+
generator.generate
|
11
|
+
end
|
12
|
+
end
|