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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +7 -5
  5. data/lib/kitabu.rb +12 -1
  6. data/lib/kitabu/cli.rb +1 -1
  7. data/lib/kitabu/exporter.rb +5 -5
  8. data/lib/kitabu/{parser.rb → exporter/base.rb} +9 -11
  9. data/lib/kitabu/exporter/css.rb +24 -0
  10. data/lib/kitabu/{parser → exporter}/epub.rb +2 -2
  11. data/lib/kitabu/exporter/html.rb +109 -0
  12. data/lib/kitabu/{parser → exporter}/mobi.rb +2 -2
  13. data/lib/kitabu/exporter/pdf.rb +43 -0
  14. data/lib/kitabu/{parser → exporter}/txt.rb +2 -2
  15. data/lib/kitabu/footnotes/base.rb +33 -0
  16. data/lib/kitabu/footnotes/html.rb +52 -0
  17. data/lib/kitabu/footnotes/pdf.rb +47 -0
  18. data/lib/kitabu/source_list.rb +73 -0
  19. data/lib/kitabu/stats.rb +1 -1
  20. data/lib/kitabu/stream.rb +1 -1
  21. data/lib/kitabu/toc/html.rb +6 -6
  22. data/lib/kitabu/version.rb +1 -1
  23. data/spec/kitabu/exporter/css_spec.rb +16 -0
  24. data/spec/kitabu/{parser → exporter}/epub_spec.rb +3 -3
  25. data/spec/kitabu/exporter/html_spec.rb +36 -0
  26. data/spec/kitabu/{parser → exporter}/mobi_spec.rb +3 -3
  27. data/spec/kitabu/{parser → exporter}/pdf_spec.rb +3 -3
  28. data/spec/kitabu/{parser → exporter}/txt_spec.rb +3 -3
  29. data/spec/kitabu/footnotes/html_spec.rb +67 -0
  30. data/spec/kitabu/{parser/html_spec.rb → source_list_spec.rb} +5 -34
  31. data/spec/kitabu/stats_spec.rb +7 -7
  32. data/templates/templates/styles/pdf.scss +1 -47
  33. data/templates/text/04_Dynamic_Content.erb +1 -1
  34. metadata +29 -54
  35. data/examples/kitabu/output/epub/images/.gitkeep +0 -0
  36. data/examples/kitabu/output/epub/images/kitabu-icon.png +0 -0
  37. data/examples/kitabu/output/epub/images/kitabu-icon.svg +0 -19
  38. data/examples/kitabu/output/epub/images/kitabu-word.png +0 -0
  39. data/examples/kitabu/output/epub/images/kitabu-word.svg +0 -14
  40. data/examples/kitabu/output/epub/images/kitabu.png +0 -0
  41. data/examples/kitabu/output/epub/images/kitabu.svg +0 -20
  42. data/examples/kitabu/output/epub/section_0.html +0 -266
  43. data/examples/kitabu/output/epub/section_1.html +0 -246
  44. data/examples/kitabu/output/epub/section_2.html +0 -520
  45. data/examples/kitabu/output/epub/section_3.html +0 -282
  46. data/examples/kitabu/output/epub/section_4.html +0 -276
  47. data/examples/kitabu/output/epub/styles/epub.css +0 -437
  48. data/examples/kitabu/output/epub/styles/html.css +0 -712
  49. data/examples/kitabu/output/epub/styles/pdf.css +0 -840
  50. data/examples/kitabu/output/epub/styles/print.css +0 -1278
  51. data/examples/kitabu/output/epub/toc.html +0 -37
  52. data/examples/kitabu/output/images/.gitkeep +0 -0
  53. data/examples/kitabu/output/images/kitabu-icon.png +0 -0
  54. data/examples/kitabu/output/images/kitabu-icon.svg +0 -19
  55. data/examples/kitabu/output/images/kitabu-word.png +0 -0
  56. data/examples/kitabu/output/images/kitabu-word.svg +0 -14
  57. data/examples/kitabu/output/images/kitabu.png +0 -0
  58. data/examples/kitabu/output/images/kitabu.svg +0 -20
  59. data/examples/kitabu/output/kitabu.epub +0 -0
  60. data/examples/kitabu/output/kitabu.html +0 -513
  61. data/examples/kitabu/output/kitabu.mobi +0 -0
  62. data/examples/kitabu/output/kitabu.pdf +0 -0
  63. data/examples/kitabu/output/kitabu.pdf.html +0 -729
  64. data/examples/kitabu/output/kitabu.print.html +0 -729
  65. data/examples/kitabu/output/kitabu.print.pdf +0 -0
  66. data/examples/kitabu/output/kitabu.txt +0 -440
  67. data/examples/kitabu/output/styles/epub.css +0 -437
  68. data/examples/kitabu/output/styles/html.css +0 -712
  69. data/examples/kitabu/output/styles/pdf.css +0 -840
  70. data/examples/kitabu/output/styles/print.css +0 -1278
  71. data/lib/kitabu/parser/html.rb +0 -208
  72. data/lib/kitabu/parser/pdf.rb +0 -88
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc4c26926c9593f2b8e97479bafef553a97adad2
4
- data.tar.gz: 388956fdff69380c6bc9d5698ab6b37851f92fba
3
+ metadata.gz: 99b16e5ab09105d5dbb28f37ce455d787a62fdee
4
+ data.tar.gz: dd1b28e6cd2a2d910073d82464d9b1ac235c0660
5
5
  SHA512:
6
- metadata.gz: 4f4bbbd287feb60d0c0a0ced3f1bf1a1d9945d51b217f137b2e65cb3c356a9a56117ed077a6e836a4b4af83f262bad8a0fcd712820d3770bd14d78ac0e8f6e1a
7
- data.tar.gz: 34d1ae48a3b6071e9b63595c37724816e445ba22896d013d204fe3f7caae2f1936dfdbdf841410c0ff257d5a6d06740dd817944fb3e8676ffe8b8e54b820d078
6
+ metadata.gz: c06222c9fd8e790581de00cbc1020a1bb9db90df276a59936cbba614cc0eb6f54c289114eff26289aa9dce89d695861de2abab4e265fdef12f22fc49de14e1f2
7
+ data.tar.gz: d6e3629e8c61d471788a95455af7f54e92e231e29b74087fa63a4498a1c6846a85371e0471452f713700cf1ad261652ac8d7ab356688c0e8eda928f2f875f1d5
@@ -1,6 +1,6 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## v2.0.0
4
4
 
5
5
  - Remove support for different markdown processors; now using Redcarpet.
6
6
  - Remove support for other file types like textile and html.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kitabu (2.0.0)
4
+ kitabu (2.0.1)
5
5
  activesupport
6
6
  eeepub-with-cover-support
7
7
  i18n
data/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
  [![Code Climate](https://codeclimate.com/github/fnando/kitabu/badges/gpa.svg)](https://codeclimate.com/github/fnando/kitabu)
5
5
  [![Test Coverage](https://codeclimate.com/github/fnando/kitabu/badges/coverage.svg)](https://codeclimate.com/github/fnando/kitabu)
6
6
 
7
- 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.
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, youll need a working Ruby 1.9+ installation.
20
- If youre cool with it, just run the following command to install it.
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 +toc+, using the eRb tag.
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 .erb files. You can mix Markdown and HTML, like the following:
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
 
@@ -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/parser"
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"
@@ -80,7 +80,7 @@ module Kitabu
80
80
  def permalinks
81
81
  inside_ebook!
82
82
 
83
- html = Kitabu::Parser::HTML.new(root_dir).content
83
+ html = Kitabu::Exporter::HTML.new(root_dir).content
84
84
  toc = Kitabu::TOC::HTML.generate(html)
85
85
 
86
86
  toc.toc.each do |options|
@@ -29,11 +29,11 @@ module Kitabu
29
29
  export_txt = [nil, "txt"].include?(options[:only])
30
30
 
31
31
  exported = []
32
- exported << Parser::HTML.parse(root_dir)
33
- exported << Parser::PDF.parse(root_dir) if export_pdf && Dependency.prince?
34
- exported << Parser::Epub.parse(root_dir) if export_epub
35
- exported << Parser::Mobi.parse(root_dir) if export_mobi && Dependency.kindlegen?
36
- exported << Parser::Txt.parse(root_dir) if export_txt && Dependency.html2text?
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
- module Parser
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.parse(root_dir)
21
- new(root_dir).parse
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
- module Parser
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 parse
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
@@ -1,7 +1,7 @@
1
1
  module Kitabu
2
- module Parser
2
+ class Exporter
3
3
  class Mobi < Base
4
- def parse
4
+ def export
5
5
  spawn_command ["kindlegen", epub_file.to_s]
6
6
  true
7
7
  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
@@ -1,7 +1,7 @@
1
1
  module Kitabu
2
- module Parser
2
+ class Exporter
3
3
  class Txt < Base
4
- def parse
4
+ def export
5
5
  spawn_command ["html2text", "-style", "pretty", "-nobs", "-o", txt_file.to_s, html_file.to_s]
6
6
  end
7
7
 
@@ -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