kitabu 2.0.0 → 2.0.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +7 -5
- data/lib/kitabu.rb +12 -1
- data/lib/kitabu/cli.rb +1 -1
- data/lib/kitabu/exporter.rb +5 -5
- data/lib/kitabu/{parser.rb → exporter/base.rb} +9 -11
- data/lib/kitabu/exporter/css.rb +24 -0
- data/lib/kitabu/{parser → exporter}/epub.rb +2 -2
- data/lib/kitabu/exporter/html.rb +109 -0
- data/lib/kitabu/{parser → exporter}/mobi.rb +2 -2
- data/lib/kitabu/exporter/pdf.rb +43 -0
- data/lib/kitabu/{parser → exporter}/txt.rb +2 -2
- data/lib/kitabu/footnotes/base.rb +33 -0
- data/lib/kitabu/footnotes/html.rb +52 -0
- data/lib/kitabu/footnotes/pdf.rb +47 -0
- data/lib/kitabu/source_list.rb +73 -0
- data/lib/kitabu/stats.rb +1 -1
- data/lib/kitabu/stream.rb +1 -1
- data/lib/kitabu/toc/html.rb +6 -6
- data/lib/kitabu/version.rb +1 -1
- data/spec/kitabu/exporter/css_spec.rb +16 -0
- data/spec/kitabu/{parser → exporter}/epub_spec.rb +3 -3
- data/spec/kitabu/exporter/html_spec.rb +36 -0
- data/spec/kitabu/{parser → exporter}/mobi_spec.rb +3 -3
- data/spec/kitabu/{parser → exporter}/pdf_spec.rb +3 -3
- data/spec/kitabu/{parser → exporter}/txt_spec.rb +3 -3
- data/spec/kitabu/footnotes/html_spec.rb +67 -0
- data/spec/kitabu/{parser/html_spec.rb → source_list_spec.rb} +5 -34
- data/spec/kitabu/stats_spec.rb +7 -7
- data/templates/templates/styles/pdf.scss +1 -47
- data/templates/text/04_Dynamic_Content.erb +1 -1
- metadata +29 -54
- data/examples/kitabu/output/epub/images/.gitkeep +0 -0
- data/examples/kitabu/output/epub/images/kitabu-icon.png +0 -0
- data/examples/kitabu/output/epub/images/kitabu-icon.svg +0 -19
- data/examples/kitabu/output/epub/images/kitabu-word.png +0 -0
- data/examples/kitabu/output/epub/images/kitabu-word.svg +0 -14
- data/examples/kitabu/output/epub/images/kitabu.png +0 -0
- data/examples/kitabu/output/epub/images/kitabu.svg +0 -20
- data/examples/kitabu/output/epub/section_0.html +0 -266
- data/examples/kitabu/output/epub/section_1.html +0 -246
- data/examples/kitabu/output/epub/section_2.html +0 -520
- data/examples/kitabu/output/epub/section_3.html +0 -282
- data/examples/kitabu/output/epub/section_4.html +0 -276
- data/examples/kitabu/output/epub/styles/epub.css +0 -437
- data/examples/kitabu/output/epub/styles/html.css +0 -712
- data/examples/kitabu/output/epub/styles/pdf.css +0 -840
- data/examples/kitabu/output/epub/styles/print.css +0 -1278
- data/examples/kitabu/output/epub/toc.html +0 -37
- data/examples/kitabu/output/images/.gitkeep +0 -0
- data/examples/kitabu/output/images/kitabu-icon.png +0 -0
- data/examples/kitabu/output/images/kitabu-icon.svg +0 -19
- data/examples/kitabu/output/images/kitabu-word.png +0 -0
- data/examples/kitabu/output/images/kitabu-word.svg +0 -14
- data/examples/kitabu/output/images/kitabu.png +0 -0
- data/examples/kitabu/output/images/kitabu.svg +0 -20
- data/examples/kitabu/output/kitabu.epub +0 -0
- data/examples/kitabu/output/kitabu.html +0 -513
- data/examples/kitabu/output/kitabu.mobi +0 -0
- data/examples/kitabu/output/kitabu.pdf +0 -0
- data/examples/kitabu/output/kitabu.pdf.html +0 -729
- data/examples/kitabu/output/kitabu.print.html +0 -729
- data/examples/kitabu/output/kitabu.print.pdf +0 -0
- data/examples/kitabu/output/kitabu.txt +0 -440
- data/examples/kitabu/output/styles/epub.css +0 -437
- data/examples/kitabu/output/styles/html.css +0 -712
- data/examples/kitabu/output/styles/pdf.css +0 -840
- data/examples/kitabu/output/styles/print.css +0 -1278
- data/lib/kitabu/parser/html.rb +0 -208
- data/lib/kitabu/parser/pdf.rb +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99b16e5ab09105d5dbb28f37ce455d787a62fdee
|
4
|
+
data.tar.gz: dd1b28e6cd2a2d910073d82464d9b1ac235c0660
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c06222c9fd8e790581de00cbc1020a1bb9db90df276a59936cbba614cc0eb6f54c289114eff26289aa9dce89d695861de2abab4e265fdef12f22fc49de14e1f2
|
7
|
+
data.tar.gz: d6e3629e8c61d471788a95455af7f54e92e231e29b74087fa63a4498a1c6846a85371e0471452f713700cf1ad261652ac8d7ab356688c0e8eda928f2f875f1d5
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,9 @@
|
|
4
4
|
[](https://codeclimate.com/github/fnando/kitabu)
|
5
5
|
[](https://codeclimate.com/github/fnando/kitabu)
|
6
6
|
|
7
|
-
|
7
|
+
Kitabu is a framework for creating e-books from Markdown using Ruby. Using Prince PDF generator, you'll be able to get high quality PDFs. Also supports EPUB, Mobi, Text and HTML generation.
|
8
|
+
|
9
|
+
While Prince is too expensive (495USD for a single user license), the free version available at <http://www.princexml.com/download> generates a PDF with a small logo on the first page, which is removed when sent to a printer; you can use it locally for viewing the results immediately. When you're done writing your e-book, you can use [DocRaptor](http://docraptor.com), which have plans starting at $15/mo.
|
8
10
|
|
9
11
|
## Features
|
10
12
|
|
@@ -16,8 +18,8 @@ While Prince is too expensive (495USD for a single user license), the free versi
|
|
16
18
|
|
17
19
|
## Installation
|
18
20
|
|
19
|
-
To install Kitabu, you
|
20
|
-
If you
|
21
|
+
To install Kitabu, you'll need a working Ruby 2.0+ installation.
|
22
|
+
If you're cool with it, just run the following command to install it.
|
21
23
|
|
22
24
|
gem install kitabu
|
23
25
|
|
@@ -119,13 +121,13 @@ You'll want to see your progress eventually; it's time for you to generate the b
|
|
119
121
|
|
120
122
|
Kitabu can generate a Table of Contents (TOC) based on your h2-h6 tags. The h1 tag is discarded because it's meant to be the book title.
|
121
123
|
|
122
|
-
To print the TOC, you need to print a variable called
|
124
|
+
To print the TOC, you need to print a variable called `toc`, using the eRb tag.
|
123
125
|
|
124
126
|
<%= toc %>
|
125
127
|
|
126
128
|
#### Using ERB
|
127
129
|
|
128
|
-
You can also have
|
130
|
+
You can also have `.erb` files. You can mix Markdown and HTML, like the following:
|
129
131
|
|
130
132
|
## This the chapter title
|
131
133
|
|
data/lib/kitabu.rb
CHANGED
@@ -15,6 +15,7 @@ require "thor/group"
|
|
15
15
|
require "yaml"
|
16
16
|
require "cgi"
|
17
17
|
require "erb"
|
18
|
+
require "open3"
|
18
19
|
|
19
20
|
require "redcarpet"
|
20
21
|
require "rouge"
|
@@ -39,8 +40,18 @@ module Kitabu
|
|
39
40
|
require "kitabu/toc"
|
40
41
|
require "kitabu/cli"
|
41
42
|
require "kitabu/markdown"
|
42
|
-
require "kitabu/
|
43
|
+
require "kitabu/source_list"
|
43
44
|
require "kitabu/exporter"
|
45
|
+
require "kitabu/exporter/base"
|
46
|
+
require "kitabu/exporter/html"
|
47
|
+
require "kitabu/exporter/epub"
|
48
|
+
require "kitabu/exporter/mobi"
|
49
|
+
require "kitabu/exporter/pdf"
|
50
|
+
require "kitabu/exporter/txt"
|
51
|
+
require "kitabu/exporter/css"
|
52
|
+
require "kitabu/footnotes/base"
|
53
|
+
require "kitabu/footnotes/html"
|
54
|
+
require "kitabu/footnotes/pdf"
|
44
55
|
require "kitabu/stream"
|
45
56
|
require "kitabu/dependency"
|
46
57
|
require "kitabu/stats"
|
data/lib/kitabu/cli.rb
CHANGED
data/lib/kitabu/exporter.rb
CHANGED
@@ -29,11 +29,11 @@ module Kitabu
|
|
29
29
|
export_txt = [nil, "txt"].include?(options[:only])
|
30
30
|
|
31
31
|
exported = []
|
32
|
-
exported <<
|
33
|
-
exported <<
|
34
|
-
exported <<
|
35
|
-
exported <<
|
36
|
-
exported <<
|
32
|
+
exported << HTML.export(root_dir)
|
33
|
+
exported << PDF.export(root_dir) if export_pdf && Dependency.prince?
|
34
|
+
exported << Epub.export(root_dir) if export_epub
|
35
|
+
exported << Mobi.export(root_dir) if export_mobi && Dependency.kindlegen?
|
36
|
+
exported << Txt.export(root_dir) if export_txt && Dependency.html2text?
|
37
37
|
|
38
38
|
if exported.all?
|
39
39
|
color = :green
|
@@ -1,13 +1,5 @@
|
|
1
|
-
require 'open3'
|
2
|
-
|
3
1
|
module Kitabu
|
4
|
-
|
5
|
-
autoload :HTML , "kitabu/parser/html"
|
6
|
-
autoload :PDF , "kitabu/parser/pdf"
|
7
|
-
autoload :Epub , "kitabu/parser/epub"
|
8
|
-
autoload :Mobi , "kitabu/parser/mobi"
|
9
|
-
autoload :Txt , "kitabu/parser/txt"
|
10
|
-
|
2
|
+
class Exporter
|
11
3
|
class Base
|
12
4
|
# The e-book directory.
|
13
5
|
#
|
@@ -17,8 +9,8 @@ module Kitabu
|
|
17
9
|
#
|
18
10
|
attr_accessor :source
|
19
11
|
|
20
|
-
def self.
|
21
|
-
new(root_dir).
|
12
|
+
def self.export(root_dir)
|
13
|
+
new(root_dir).export
|
22
14
|
end
|
23
15
|
|
24
16
|
def initialize(root_dir)
|
@@ -26,6 +18,12 @@ module Kitabu
|
|
26
18
|
@source = root_dir.join("text")
|
27
19
|
end
|
28
20
|
|
21
|
+
#
|
22
|
+
#
|
23
|
+
def source_list
|
24
|
+
@source_list ||= SourceList.new(root_dir)
|
25
|
+
end
|
26
|
+
|
29
27
|
# Return directory's basename.
|
30
28
|
#
|
31
29
|
def name
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Kitabu
|
2
|
+
class Exporter
|
3
|
+
class CSS < Base
|
4
|
+
attr_reader :root_dir
|
5
|
+
|
6
|
+
def export
|
7
|
+
files = Dir[root_dir.join("templates/styles/*.{scss,sass}").to_s]
|
8
|
+
options = {
|
9
|
+
style: :expanded,
|
10
|
+
line_numbers: true,
|
11
|
+
load_paths: [root_dir.join("templates/styles")]
|
12
|
+
}
|
13
|
+
|
14
|
+
files.each do |file|
|
15
|
+
_, file_name, syntax = *File.basename(file).match(/(.*?)\.(.*?)$/)
|
16
|
+
engine = Sass::Engine.new(File.read(file), options.merge(syntax: syntax.to_sym))
|
17
|
+
target = root_dir.join("output/styles", "#{file_name}.css")
|
18
|
+
FileUtils.mkdir_p(File.dirname(target))
|
19
|
+
File.open(target, "w") {|io| io << engine.render }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Kitabu
|
2
|
-
|
2
|
+
class Exporter
|
3
3
|
class Epub < Base
|
4
4
|
def sections
|
5
5
|
@sections ||= html.css("div.chapter").each_with_index.map do |chapter, index|
|
@@ -20,7 +20,7 @@ module Kitabu
|
|
20
20
|
@html ||= Nokogiri::HTML(html_path.read)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
23
|
+
def export
|
24
24
|
copy_styles!
|
25
25
|
copy_images!
|
26
26
|
set_metadata!
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Kitabu
|
2
|
+
class Exporter
|
3
|
+
class HTML < Base
|
4
|
+
class << self
|
5
|
+
# The footnote index control. We have to manipulate footnotes
|
6
|
+
# because each chapter starts from 1, so we have duplicated references.
|
7
|
+
#
|
8
|
+
attr_accessor :footnote_index
|
9
|
+
end
|
10
|
+
|
11
|
+
# Parse all files and save the parsed content
|
12
|
+
# to <tt>output/book_name.html</tt>.
|
13
|
+
#
|
14
|
+
def export
|
15
|
+
copy_images!
|
16
|
+
export_stylesheets!
|
17
|
+
|
18
|
+
File.open(root_dir.join("output/#{name}.html"), "w") do |file|
|
19
|
+
file << parse_layout(content)
|
20
|
+
end
|
21
|
+
|
22
|
+
true
|
23
|
+
rescue Exception => error
|
24
|
+
handle_error(error)
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def reset_footnote_index!
|
29
|
+
self.class.footnote_index = 1
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return all chapters wrapped in a <tt>div.chapter</tt> tag.
|
33
|
+
#
|
34
|
+
def content
|
35
|
+
String.new.tap do |content|
|
36
|
+
source_list.each_chapter do |files|
|
37
|
+
content << %[<div class="chapter">#{render_chapter(files)}</div>]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
# Render +file+ considering its extension.
|
44
|
+
#
|
45
|
+
def render_file(file)
|
46
|
+
if format(file) == :erb
|
47
|
+
content = render_template(file, config)
|
48
|
+
else
|
49
|
+
content = File.read(file)
|
50
|
+
end
|
51
|
+
|
52
|
+
Kitabu::Markdown.render(content)
|
53
|
+
end
|
54
|
+
|
55
|
+
def format(file)
|
56
|
+
if File.extname(file) == '.erb'
|
57
|
+
:erb
|
58
|
+
else
|
59
|
+
:markdown
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Parse layout file, making available all configuration entries.
|
64
|
+
#
|
65
|
+
def parse_layout(html)
|
66
|
+
toc = TOC::HTML.generate(html)
|
67
|
+
content = Footnotes::HTML.process(toc.content).html.css('html').first.inner_html
|
68
|
+
|
69
|
+
locals = config.merge({
|
70
|
+
content: content,
|
71
|
+
toc: toc.to_html,
|
72
|
+
changelog: render_changelog
|
73
|
+
})
|
74
|
+
|
75
|
+
render_template(root_dir.join("templates/html/layout.erb"), locals)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Render changelog file.
|
79
|
+
# This file can be used to inform any book change.
|
80
|
+
#
|
81
|
+
def render_changelog
|
82
|
+
changelog = Dir[root_dir.join("text/CHANGELOG.*")].first
|
83
|
+
render_file(changelog) if changelog
|
84
|
+
end
|
85
|
+
|
86
|
+
# Render all +files+ from a given chapter.
|
87
|
+
#
|
88
|
+
def render_chapter(files)
|
89
|
+
String.new.tap do |chapter|
|
90
|
+
files.each do |file|
|
91
|
+
chapter << render_file(file) << "\n\n"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Copy images
|
97
|
+
#
|
98
|
+
def copy_images!
|
99
|
+
copy_directory("images", "output/images")
|
100
|
+
end
|
101
|
+
|
102
|
+
# Export all root stylesheets.
|
103
|
+
#
|
104
|
+
def export_stylesheets!
|
105
|
+
Exporter::CSS.new(root_dir).export
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Kitabu
|
2
|
+
class Exporter
|
3
|
+
class PDF < Base
|
4
|
+
def export
|
5
|
+
apply_footnotes!
|
6
|
+
spawn_command ["prince", html_for_pdf.to_s, "-o", pdf_file.to_s]
|
7
|
+
spawn_command ["prince", html_for_print.to_s, "-o", print_file.to_s]
|
8
|
+
end
|
9
|
+
|
10
|
+
def apply_footnotes!
|
11
|
+
html = Footnotes::PDF.process(html_file.read).html
|
12
|
+
create_html_file(html_for_print, html, 'print')
|
13
|
+
create_html_file(html_for_pdf, html, 'pdf')
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_html_file(target, html, class_name)
|
17
|
+
html.css("html").first.set_attribute "class", class_name
|
18
|
+
html.css("link[name=stylesheet]").first.set_attribute "href", "styles/#{class_name}.css"
|
19
|
+
File.open(target, "w") {|f| f << html.to_html }
|
20
|
+
end
|
21
|
+
|
22
|
+
def html_for_pdf
|
23
|
+
root_dir.join("output/#{name}.pdf.html")
|
24
|
+
end
|
25
|
+
|
26
|
+
def html_for_print
|
27
|
+
root_dir.join("output/#{name}.print.html")
|
28
|
+
end
|
29
|
+
|
30
|
+
def html_file
|
31
|
+
root_dir.join("output/#{name}.html")
|
32
|
+
end
|
33
|
+
|
34
|
+
def pdf_file
|
35
|
+
root_dir.join("output/#{name}.pdf")
|
36
|
+
end
|
37
|
+
|
38
|
+
def print_file
|
39
|
+
root_dir.join("output/#{name}.print.pdf")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Kitabu
|
2
|
+
module Footnotes
|
3
|
+
class Base
|
4
|
+
# Set the content that will be modified.
|
5
|
+
attr_accessor :content
|
6
|
+
|
7
|
+
# Set the Nokogiri html object.
|
8
|
+
attr_accessor :html
|
9
|
+
|
10
|
+
# Set the footnote index.
|
11
|
+
attr_reader :footnote_index
|
12
|
+
|
13
|
+
# Process content, fixing footnotes numbering.
|
14
|
+
# Returns a string representing the new markup.
|
15
|
+
#
|
16
|
+
def self.process(content)
|
17
|
+
footnotes = new(content)
|
18
|
+
footnotes.process
|
19
|
+
footnotes
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(content)
|
23
|
+
@content = content
|
24
|
+
@html = Nokogiri::HTML(content)
|
25
|
+
@footnote_index = 1
|
26
|
+
end
|
27
|
+
|
28
|
+
def increment_footnote_index!
|
29
|
+
@footnote_index += 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Kitabu
|
2
|
+
module Footnotes
|
3
|
+
class HTML < Base
|
4
|
+
def process
|
5
|
+
html.css('.chapter').each(&method(:process_chapter))
|
6
|
+
end
|
7
|
+
|
8
|
+
def process_chapter(chapter)
|
9
|
+
footnotes = chapter.css('.footnotes').first
|
10
|
+
return unless footnotes
|
11
|
+
list = footnotes.css('ol').first
|
12
|
+
list.set_attribute 'start', footnote_index
|
13
|
+
|
14
|
+
chapter.css('.footnotes li').each do |footnote|
|
15
|
+
process_footnote(chapter, footnote)
|
16
|
+
increment_footnote_index!
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_footnote(chapter, footnote)
|
21
|
+
current_index = footnote.get_attribute('id').gsub(/[^\d]/m, '')
|
22
|
+
footnote.set_attribute 'id', "fn#{footnote_index}"
|
23
|
+
|
24
|
+
process_links_to_footnote(chapter, current_index)
|
25
|
+
process_rev_links(chapter, current_index)
|
26
|
+
process_ref_elements(chapter, current_index)
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_links_to_footnote(chapter, current_index)
|
30
|
+
chapter.css("a[href='#fn#{current_index}']").each do |link|
|
31
|
+
link.set_attribute 'href', "#fn#{footnote_index}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def process_rev_links(chapter, current_index)
|
36
|
+
chapter.css("a[href='#fnref#{current_index}']").each do |link|
|
37
|
+
link.set_attribute 'href', "#fnref#{footnote_index}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_ref_elements(chapter, current_index)
|
42
|
+
chapter.css("sup[id=fnref#{current_index}]").each_with_index do |sup, index|
|
43
|
+
if index.zero?
|
44
|
+
sup.set_attribute 'id', "fnref#{footnote_index}"
|
45
|
+
else
|
46
|
+
sup.remove_attribute 'id'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|