kitabu 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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