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
@@ -0,0 +1,47 @@
|
|
1
|
+
module Kitabu
|
2
|
+
module Footnotes
|
3
|
+
class PDF < Base
|
4
|
+
def process
|
5
|
+
remove_duplicated_attributes
|
6
|
+
html.css(".chapter").each(&method(:process_chapter))
|
7
|
+
end
|
8
|
+
|
9
|
+
def remove_duplicated_attributes
|
10
|
+
# https://github.com/sparklemotion/nokogiri/issues/339
|
11
|
+
html.css('html').first.tap do |element|
|
12
|
+
next unless element
|
13
|
+
element.delete('xmlns')
|
14
|
+
element.delete('xml:lang')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def process_chapter(chapter)
|
19
|
+
chapter.css('.footnotes li').each do |footnote|
|
20
|
+
process_footnote(chapter, footnote)
|
21
|
+
increment_footnote_index!
|
22
|
+
end
|
23
|
+
|
24
|
+
chapter.css('.footnotes').each(&:remove)
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_footnote(chapter, footnote)
|
28
|
+
# Remove rev links
|
29
|
+
footnote.css('[rev=footnote]').map(&:remove)
|
30
|
+
|
31
|
+
# Create an element for storing the footnote description
|
32
|
+
description = Nokogiri::XML::Node.new('span', Nokogiri::HTML::DocumentFragment.parse(''))
|
33
|
+
description.set_attribute 'class', 'footnote'
|
34
|
+
description.inner_html = footnote.css('p').map(&:inner_html).join("\n")
|
35
|
+
|
36
|
+
# Find ref based on footnote's id
|
37
|
+
fn_id = footnote.get_attribute('id')
|
38
|
+
|
39
|
+
refs = chapter.css("a[href='##{fn_id}']").each do |ref|
|
40
|
+
sup = ref.parent
|
41
|
+
sup.after(description)
|
42
|
+
sup.remove
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Kitabu
|
2
|
+
class SourceList
|
3
|
+
# List of directories that should be skipped.
|
4
|
+
#
|
5
|
+
IGNORE_DIR = %w[. .. .svn .git]
|
6
|
+
|
7
|
+
# Files that should be skipped.
|
8
|
+
#
|
9
|
+
IGNORE_FILES = /^(CHANGELOG|TOC)\..*?$/
|
10
|
+
|
11
|
+
# List of recognized extensions.
|
12
|
+
#
|
13
|
+
EXTENSIONS = %w[md erb]
|
14
|
+
|
15
|
+
attr_reader :root_dir
|
16
|
+
attr_reader :source
|
17
|
+
|
18
|
+
def initialize(root_dir)
|
19
|
+
@root_dir = root_dir
|
20
|
+
@source = root_dir.join('text')
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
#
|
25
|
+
def each_chapter(&block)
|
26
|
+
files_grouped_by_chapter.each(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def files_grouped_by_chapter
|
30
|
+
entries.each_with_object([]) do |entry, buffer|
|
31
|
+
files = chapter_files(entry)
|
32
|
+
buffer << files unless files.empty?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def chapter_files(entry)
|
37
|
+
# Chapters can be files outside a directory.
|
38
|
+
if File.file?(entry)
|
39
|
+
[entry]
|
40
|
+
else
|
41
|
+
Dir["#{entry}/**/*.{#{EXTENSIONS.join(",")}}"].sort
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return a list of all recognized files.
|
46
|
+
#
|
47
|
+
def entries
|
48
|
+
Dir.entries(source).sort.each_with_object([]) do |entry, buffer|
|
49
|
+
buffer << source.join(entry) if valid_entry?(entry)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Check if path is a valid entry.
|
54
|
+
# Files/directories that start with a dot or underscore will be skipped.
|
55
|
+
#
|
56
|
+
def valid_entry?(entry)
|
57
|
+
entry !~ /^(\.|_)/ && (valid_directory?(entry) || valid_file?(entry))
|
58
|
+
end
|
59
|
+
|
60
|
+
# Check if path is a valid directory.
|
61
|
+
#
|
62
|
+
def valid_directory?(entry)
|
63
|
+
File.directory?(source.join(entry)) && !IGNORE_DIR.include?(File.basename(entry))
|
64
|
+
end
|
65
|
+
|
66
|
+
# Check if path is a valid file.
|
67
|
+
#
|
68
|
+
def valid_file?(entry)
|
69
|
+
ext = File.extname(entry).gsub(/\./, "").downcase
|
70
|
+
File.file?(source.join(entry)) && EXTENSIONS.include?(ext) && entry !~ IGNORE_FILES
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/kitabu/stats.rb
CHANGED
data/lib/kitabu/stream.rb
CHANGED
data/lib/kitabu/toc/html.rb
CHANGED
@@ -48,9 +48,9 @@ module Kitabu
|
|
48
48
|
|
49
49
|
def tag(node) # :nodoc:
|
50
50
|
toc << {
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
51
|
+
level: node.name.gsub(/[^\d]/, "").to_i,
|
52
|
+
text: node.text,
|
53
|
+
permalink: node["id"]
|
54
54
|
}
|
55
55
|
end
|
56
56
|
|
@@ -58,9 +58,9 @@ module Kitabu
|
|
58
58
|
#
|
59
59
|
def to_hash
|
60
60
|
{
|
61
|
-
:
|
62
|
-
:
|
63
|
-
:
|
61
|
+
content: content,
|
62
|
+
html: to_html,
|
63
|
+
toc: toc
|
64
64
|
}
|
65
65
|
end
|
66
66
|
|
data/lib/kitabu/version.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Kitabu::Exporter::CSS do
|
4
|
+
let(:root) { SPECDIR.join("support/mybook") }
|
5
|
+
|
6
|
+
before do
|
7
|
+
Kitabu::Exporter::CSS.export(root)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "generates css files" do
|
11
|
+
expect(root.join("output/styles/epub.css")).to be_file
|
12
|
+
expect(root.join("output/styles/pdf.css")).to be_file
|
13
|
+
expect(root.join("output/styles/print.css")).to be_file
|
14
|
+
expect(root.join("output/styles/html.css")).to be_file
|
15
|
+
end
|
16
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Kitabu::
|
3
|
+
describe Kitabu::Exporter::Epub do
|
4
4
|
let(:root) { SPECDIR.join("support/mybook") }
|
5
5
|
|
6
6
|
before do
|
7
|
-
Kitabu::
|
8
|
-
Kitabu::
|
7
|
+
Kitabu::Exporter::HTML.export(root)
|
8
|
+
Kitabu::Exporter::Epub.export(root)
|
9
9
|
end
|
10
10
|
|
11
11
|
it "generates e-pub" do
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Kitabu::Exporter::HTML do
|
4
|
+
let(:root) { SPECDIR.join("support/mybook") }
|
5
|
+
let(:format) { described_class.new(root) }
|
6
|
+
|
7
|
+
context "when generating HTML" do
|
8
|
+
let(:file) { SPECDIR.join("support/mybook/output/mybook.html") }
|
9
|
+
let(:html) { File.read(file) }
|
10
|
+
before { format.export }
|
11
|
+
|
12
|
+
it "keeps html file around" do
|
13
|
+
expect(file).to be_file
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has several chapters" do
|
17
|
+
expect(html).to have_tag("div.chapter", 3)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "uses config file" do
|
21
|
+
expect(html).to have_tag("div.imprint p", "Copyright (C) 2010 John Doe.")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "renders changelog" do
|
25
|
+
expect(html).to have_tag("div.changelog h2", "Revisions")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "renders erb" do
|
29
|
+
expect(html).to have_tag("h2", "ERB")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "renders erb blocks" do
|
33
|
+
expect(html).to have_tag("div.note.info > p", "This is a note!")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Kitabu::
|
3
|
+
describe Kitabu::Exporter::Mobi, kindlegen: Kitabu::Dependency.kindlegen? do
|
4
4
|
let(:root) { SPECDIR.join("support/mybook") }
|
5
5
|
|
6
6
|
before do
|
7
|
-
Kitabu::
|
8
|
-
Kitabu::
|
7
|
+
Kitabu::Exporter::HTML.export(root)
|
8
|
+
Kitabu::Exporter::Mobi.export(root)
|
9
9
|
end
|
10
10
|
|
11
11
|
it "generates mobi" do
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Kitabu::
|
3
|
+
describe Kitabu::Exporter::PDF, prince: Kitabu::Dependency.prince? do
|
4
4
|
let(:root) { SPECDIR.join("support/mybook") }
|
5
5
|
|
6
6
|
before do
|
7
|
-
Kitabu::
|
8
|
-
Kitabu::
|
7
|
+
Kitabu::Exporter::HTML.new(root).export
|
8
|
+
Kitabu::Exporter::PDF.new(root).export
|
9
9
|
end
|
10
10
|
|
11
11
|
it "creates html with css identifier" do
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Kitabu::
|
3
|
+
describe Kitabu::Exporter::Txt, html2text: Kitabu::Dependency.html2text? do
|
4
4
|
let(:root) { SPECDIR.join("support/mybook") }
|
5
5
|
|
6
6
|
before do
|
7
|
-
Kitabu::
|
8
|
-
Kitabu::
|
7
|
+
Kitabu::Exporter::HTML.export(root)
|
8
|
+
Kitabu::Exporter::Txt.export(root)
|
9
9
|
end
|
10
10
|
|
11
11
|
it "generates text file" do
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Kitabu::Footnotes::HTML do
|
4
|
+
let(:footnotes) {
|
5
|
+
Kitabu::Markdown.render <<-MARKDOWN.strip_heredoc
|
6
|
+
ohai[^1] and kthxbai[^2]
|
7
|
+
|
8
|
+
ohai[^1] again.
|
9
|
+
|
10
|
+
[^1]: Hello
|
11
|
+
[^2]: OK, thanks. Bye!
|
12
|
+
MARKDOWN
|
13
|
+
}
|
14
|
+
|
15
|
+
let(:content) {
|
16
|
+
<<-HTML.strip_heredoc
|
17
|
+
<div class="chapter">
|
18
|
+
#{footnotes}
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="chapter">
|
22
|
+
#{footnotes}
|
23
|
+
</div>
|
24
|
+
HTML
|
25
|
+
}
|
26
|
+
|
27
|
+
let(:html) {
|
28
|
+
Kitabu::Footnotes::HTML.process(content).html
|
29
|
+
}
|
30
|
+
|
31
|
+
let(:chapter1) { html.css('.chapter:first-of-type').first }
|
32
|
+
let(:chapter2) { html.css('.chapter:last-of-type').first }
|
33
|
+
|
34
|
+
it 'sets starting index' do
|
35
|
+
expect(chapter1).to have_tag('.footnotes ol[start="1"]')
|
36
|
+
expect(chapter2).to have_tag('.footnotes ol[start="3"]')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'sets footnotes id' do
|
40
|
+
html.css('.footnotes li').to_enum(:each).with_index(1) do |footnote, index|
|
41
|
+
expect(footnote.get_attribute('id')).to eq("fn#{index}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'removes id from existing <sup>' do
|
46
|
+
expect(chapter1).to have_tag('sup:not([id])', count: 1)
|
47
|
+
expect(chapter2).to have_tag('sup:not([id])', count: 1)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'sets <sup> id' do
|
51
|
+
expect(chapter1).to have_tag('sup', count: 3)
|
52
|
+
expect(chapter1).to have_tag('sup[id=fnref1]', count: 1)
|
53
|
+
expect(chapter1).to have_tag('sup[id=fnref2]', count: 1)
|
54
|
+
|
55
|
+
expect(chapter2).to have_tag('sup', count: 3)
|
56
|
+
expect(chapter2).to have_tag('sup[id=fnref3]', count: 1)
|
57
|
+
expect(chapter2).to have_tag('sup[id=fnref4]', count: 1)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'sets footnote link-back' do
|
61
|
+
expect(chapter1).to have_tag('.footnotes li:nth-child(1) a[rev=footnote][href="#fnref1"]')
|
62
|
+
expect(chapter1).to have_tag('.footnotes li:nth-child(2) a[rev=footnote][href="#fnref2"]')
|
63
|
+
|
64
|
+
expect(chapter2).to have_tag('.footnotes li:nth-child(1) a[rev=footnote][href="#fnref3"]')
|
65
|
+
expect(chapter2).to have_tag('.footnotes li:nth-child(2) a[rev=footnote][href="#fnref4"]')
|
66
|
+
end
|
67
|
+
end
|
@@ -1,11 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Kitabu::
|
3
|
+
describe Kitabu::SourceList do
|
4
4
|
let(:root) { SPECDIR.join("support/mybook") }
|
5
|
+
let(:format) { Kitabu::Exporter::HTML.new(root) }
|
6
|
+
let(:entries) { source_list.entries }
|
5
7
|
let(:source) { root.join("text") }
|
6
|
-
let(:parser) { described_class.new(root) }
|
7
|
-
let(:entries) { parser.entries }
|
8
8
|
let(:relative) { entries.collect {|e| e.to_s.gsub(/^#{Regexp.escape(source.to_s)}\//, "")} }
|
9
|
+
subject(:source_list) { Kitabu::SourceList.new(root) }
|
9
10
|
|
10
11
|
context "when filtering entries" do
|
11
12
|
it "skips dot directories" do
|
@@ -37,34 +38,4 @@ describe Kitabu::Parser::HTML do
|
|
37
38
|
expect(relative.fourth).to be_nil
|
38
39
|
end
|
39
40
|
end
|
40
|
-
|
41
|
-
context "when generating HTML" do
|
42
|
-
let(:file) { SPECDIR.join("support/mybook/output/mybook.html") }
|
43
|
-
let(:html) { File.read(file) }
|
44
|
-
before { parser.parse }
|
45
|
-
|
46
|
-
it "keeps html file around" do
|
47
|
-
expect(file).to be_file
|
48
|
-
end
|
49
|
-
|
50
|
-
it "has several chapters" do
|
51
|
-
expect(html).to have_tag("div.chapter", 3)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "uses config file" do
|
55
|
-
expect(html).to have_tag("div.imprint p", "Copyright (C) 2010 John Doe.")
|
56
|
-
end
|
57
|
-
|
58
|
-
it "renders changelog" do
|
59
|
-
expect(html).to have_tag("div.changelog h2", "Revisions")
|
60
|
-
end
|
61
|
-
|
62
|
-
it "renders erb" do
|
63
|
-
expect(html).to have_tag("h2", "ERB")
|
64
|
-
end
|
65
|
-
|
66
|
-
it "renders erb blocks" do
|
67
|
-
expect(html).to have_tag("div.note.info > p", "This is a note!")
|
68
|
-
end
|
69
|
-
end
|
70
41
|
end
|
data/spec/kitabu/stats_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Kitabu::Stats do
|
4
4
|
let(:root_dir) { double("root dir").as_null_object }
|
5
|
-
let(:
|
5
|
+
let(:format) { double("format").as_null_object }
|
6
6
|
let(:content) { "" }
|
7
7
|
subject(:stats) { Kitabu::Stats.new(root_dir) }
|
8
8
|
|
@@ -11,18 +11,18 @@ describe Kitabu::Stats do
|
|
11
11
|
}
|
12
12
|
|
13
13
|
context "getting content" do
|
14
|
-
it "
|
15
|
-
expect(Kitabu::
|
14
|
+
it "generates content" do
|
15
|
+
expect(Kitabu::Exporter::HTML)
|
16
16
|
.to receive(:new)
|
17
17
|
.with(root_dir)
|
18
|
-
.and_return(
|
18
|
+
.and_return(format)
|
19
19
|
|
20
20
|
Kitabu::Stats.new(root_dir).content
|
21
21
|
end
|
22
22
|
|
23
|
-
it "returns
|
24
|
-
allow(Kitabu::
|
25
|
-
allow(
|
23
|
+
it "returns content" do
|
24
|
+
allow(Kitabu::Exporter::HTML).to receive_message_chain(:new).and_return(format)
|
25
|
+
allow(format).to receive_message_chain(:content).and_return("some content")
|
26
26
|
|
27
27
|
expect(Kitabu::Stats.new(root_dir).content).to eql("some content")
|
28
28
|
end
|