rpub 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -1
- data/.rspec +0 -1
- data/.travis.yml +3 -4
- data/.yardopts +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +70 -46
- data/Guardfile +6 -0
- data/HISTORY.md +10 -0
- data/README.md +1 -1
- data/Rakefile +7 -2
- data/bin/rpub +64 -1
- data/doc/.gitignore +8 -0
- data/doc/api/Rpub.html +339 -0
- data/doc/api/Rpub/Book.html +983 -0
- data/doc/api/Rpub/Chapter.html +737 -0
- data/doc/api/Rpub/Command.html +356 -0
- data/doc/api/Rpub/Commands.html +117 -0
- data/doc/api/Rpub/Commands/Clean.html +216 -0
- data/doc/api/Rpub/Commands/Compile.html +218 -0
- data/doc/api/Rpub/Commands/Generate.html +242 -0
- data/doc/api/Rpub/Commands/Package.html +230 -0
- data/doc/api/Rpub/Commands/Preview.html +216 -0
- data/doc/api/Rpub/Commands/Stats.html +226 -0
- data/doc/api/Rpub/Compressor.html +687 -0
- data/doc/api/Rpub/Context.html +553 -0
- data/doc/api/Rpub/Document.html +647 -0
- data/doc/api/Rpub/Document/OutlineElement.html +388 -0
- data/doc/api/Rpub/Epub.html +465 -0
- data/doc/api/Rpub/Epub/Container.html +224 -0
- data/doc/api/Rpub/Epub/Content.html +344 -0
- data/doc/api/Rpub/Epub/Cover.html +236 -0
- data/doc/api/Rpub/Epub/HtmlToc.html +240 -0
- data/doc/api/Rpub/Epub/Toc.html +244 -0
- data/doc/api/Rpub/FilesystemSource.html +544 -0
- data/doc/api/Rpub/HashDelegation.html +281 -0
- data/doc/api/Rpub/HashDelegation/ClassMethods.html +175 -0
- data/doc/api/Rpub/MediaType.html +192 -0
- data/doc/api/Rpub/Preview.html +464 -0
- data/doc/api/Rpub/XmlFile.html +457 -0
- data/doc/api/_index.html +405 -0
- data/doc/api/class_list.html +54 -0
- data/doc/api/css/common.css +1 -0
- data/doc/api/css/full_list.css +57 -0
- data/doc/api/css/style.css +339 -0
- data/doc/api/file.HISTORY.html +131 -0
- data/doc/api/file.LICENSE.html +92 -0
- data/doc/api/file.README.html +337 -0
- data/doc/api/file_list.html +62 -0
- data/doc/api/frames.html +26 -0
- data/doc/api/index.html +337 -0
- data/doc/api/js/app.js +219 -0
- data/doc/api/js/full_list.js +178 -0
- data/doc/api/js/jquery.js +4 -0
- data/doc/api/method_list.html +533 -0
- data/doc/api/top-level-namespace.html +112 -0
- data/doc/index.html +312 -0
- data/doc/javascripts/scale.fix.js +17 -0
- data/doc/params.json +1 -0
- data/doc/stylesheets/pygment_trac.css +69 -0
- data/doc/stylesheets/styles.css +255 -0
- data/features/clean.feature +31 -0
- data/features/compile.feature +49 -0
- data/features/embedded_assets.feature +51 -0
- data/features/generate.feature +63 -0
- data/features/layout.feature +41 -0
- data/features/package.feature +30 -0
- data/features/previews.feature +66 -0
- data/features/stats.feature +18 -0
- data/features/step_definitions/general_steps.rb +60 -0
- data/features/styles.feature +33 -0
- data/features/support/env.rb +7 -0
- data/features/table_of_contents.feature +35 -0
- data/lib/rpub.rb +28 -31
- data/lib/rpub/book.rb +9 -16
- data/lib/rpub/chapter.rb +4 -54
- data/lib/rpub/command.rb +32 -0
- data/lib/rpub/commands/clean.rb +4 -49
- data/lib/rpub/commands/compile.rb +4 -49
- data/lib/rpub/commands/generate.rb +10 -67
- data/lib/rpub/commands/package.rb +9 -37
- data/lib/rpub/commands/preview.rb +4 -54
- data/lib/rpub/commands/stats.rb +6 -10
- data/lib/rpub/compressor.rb +3 -3
- data/lib/rpub/context.rb +48 -0
- data/lib/rpub/document.rb +68 -0
- data/lib/rpub/epub.rb +8 -7
- data/lib/rpub/epub/content.rb +9 -30
- data/lib/rpub/epub/cover.rb +1 -8
- data/lib/rpub/epub/html_toc.rb +4 -9
- data/lib/rpub/epub/toc.rb +16 -13
- data/lib/rpub/filesystem_source.rb +47 -0
- data/lib/rpub/media_type.rb +16 -0
- data/lib/rpub/preview.rb +29 -0
- data/lib/rpub/version.rb +1 -1
- data/lib/rpub/xml_file.rb +4 -1
- data/rpub.gemspec +6 -7
- data/spec/rpub/book_spec.rb +45 -45
- data/spec/rpub/chapter_spec.rb +87 -22
- data/spec/rpub/epub/container_spec.rb +3 -5
- data/spec/rpub/epub/content_spec.rb +62 -41
- data/spec/rpub/epub/cover_spec.rb +3 -5
- data/spec/rpub/epub/html_toc_spec.rb +8 -8
- data/spec/rpub/epub/toc_spec.rb +20 -22
- data/spec/rpub_spec.rb +1 -3
- data/spec/spec_helper.rb +28 -0
- data/support/config.yml +1 -0
- data/support/styles.css +3 -3
- metadata +131 -120
- data/lib/rpub/commander.rb +0 -23
- data/lib/rpub/commands/base.rb +0 -33
- data/lib/rpub/commands/help.rb +0 -37
- data/lib/rpub/commands/main.rb +0 -45
- data/lib/rpub/compilation_helpers.rb +0 -73
- data/lib/rpub/subclass_tracker.rb +0 -53
- data/spec/rpub/commands/clean_spec.rb +0 -46
- data/spec/rpub/commands/generate_spec.rb +0 -52
- data/spec/rpub/commands/main_spec.rb +0 -26
- data/spec/rpub/commands/package_spec.rb +0 -33
- data/spec/rpub/commands/preview_spec.rb +0 -43
@@ -0,0 +1,41 @@
|
|
1
|
+
Feature: page layout
|
2
|
+
As an author
|
3
|
+
I want to wrap my content in a template file
|
4
|
+
In order to spice up my book's looks
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a file named "chapter1.md" with:
|
8
|
+
"""
|
9
|
+
# Hello, world
|
10
|
+
"""
|
11
|
+
|
12
|
+
Scenario: default layout
|
13
|
+
When I successfully run `rpub compile`
|
14
|
+
And I successfully run `unzip untitled-book-0.0.0.epub`
|
15
|
+
Then the file "OEBPS/chapter-0-hello-world.html" should contain "<body>"
|
16
|
+
|
17
|
+
Scenario: overriding layout by filename
|
18
|
+
Given a file named "layout.html" with:
|
19
|
+
"""
|
20
|
+
foo
|
21
|
+
<%= @body %>
|
22
|
+
bar
|
23
|
+
"""
|
24
|
+
When I successfully run `rpub compile`
|
25
|
+
And I successfully run `unzip untitled-book-0.0.0.epub`
|
26
|
+
Then the file "OEBPS/chapter-0-hello-world.html" should contain "foo"
|
27
|
+
And the file "OEBPS/chapter-0-hello-world.html" should contain "bar"
|
28
|
+
|
29
|
+
Scenario: overriding layout by option
|
30
|
+
Given a file named "template.html" with:
|
31
|
+
"""
|
32
|
+
foo
|
33
|
+
<%= @body %>
|
34
|
+
bar
|
35
|
+
"""
|
36
|
+
When I successfully run `rpub compile -l template.html`
|
37
|
+
And I successfully run `unzip untitled-book-0.0.0.epub`
|
38
|
+
Then the file "OEBPS/chapter-0-hello-world.html" should contain "foo"
|
39
|
+
And the file "OEBPS/chapter-0-hello-world.html" should contain "bar"
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Feature: packaging
|
2
|
+
As an author
|
3
|
+
I want to package my book and other files into a single archive
|
4
|
+
So I can easily distribute it over the internet
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a basic project
|
8
|
+
|
9
|
+
Scenario: compressing book
|
10
|
+
When I successfully run `rpub package`
|
11
|
+
Then a file named "untitled_book.zip" should exist
|
12
|
+
And the archive "untitled_book.zip" should contain file "untitled-book-0.0.0.epub"
|
13
|
+
|
14
|
+
Scenario: custom package filename
|
15
|
+
Given the default "config.yml" file with "package_file" set to "my_book.zip"
|
16
|
+
When I successfully run `rpub package`
|
17
|
+
Then a file named "my_book.zip" should exist
|
18
|
+
|
19
|
+
Scenario: uncompiled book
|
20
|
+
When I successfully run `rpub package`
|
21
|
+
Then a file named "untitled-book-0.0.0.epub" should exist
|
22
|
+
|
23
|
+
Scenario: help
|
24
|
+
When I successfully run `rpub package -h`
|
25
|
+
Then the output should contain "Compile your ebook to an ePub file and package it into an archive"
|
26
|
+
|
27
|
+
Scenario: additional files
|
28
|
+
When I successfully run `rpub package`
|
29
|
+
Then a file named "untitled_book.zip" should exist
|
30
|
+
And the archive "untitled_book.zip" should contain file "README.md"
|
@@ -0,0 +1,66 @@
|
|
1
|
+
Feature: previews
|
2
|
+
As an author
|
3
|
+
I want to quickly see my words in an HTML file with the final formatting
|
4
|
+
So I can see how my work will look without having to use a special e-reader
|
5
|
+
|
6
|
+
Scenario: when there is no content
|
7
|
+
Given the default "config.yml" file
|
8
|
+
When I successfully run `rpub preview`
|
9
|
+
Then a file named "preview.html" should not exist
|
10
|
+
|
11
|
+
Scenario: concatenating content and styles
|
12
|
+
Given the default "config.yml" file
|
13
|
+
And a file named "chapter1.md" with:
|
14
|
+
"""
|
15
|
+
Content 1
|
16
|
+
"""
|
17
|
+
And a file named "chapter2.md" with:
|
18
|
+
"""
|
19
|
+
Content 2
|
20
|
+
"""
|
21
|
+
When I successfully run `rpub preview`
|
22
|
+
Then a file named "preview.html" should exist
|
23
|
+
And the file "preview.html" should contain:
|
24
|
+
"""
|
25
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
26
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
27
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
28
|
+
"""
|
29
|
+
And the file "preview.html" should contain "Content 1"
|
30
|
+
And the file "preview.html" should contain "Content 2"
|
31
|
+
And the file "preview.html" should contain:
|
32
|
+
"""
|
33
|
+
body {
|
34
|
+
margin: 3%;
|
35
|
+
font-family: Georgia, serif;
|
36
|
+
line-height: 1.4em;
|
37
|
+
}
|
38
|
+
"""
|
39
|
+
|
40
|
+
Scenario: given an explicit filename
|
41
|
+
Given the default "config.yml" file
|
42
|
+
And a file named "chapter1.md" with:
|
43
|
+
"""
|
44
|
+
Content 1
|
45
|
+
"""
|
46
|
+
When I successfully run `rpub preview -o output.html`
|
47
|
+
Then a file named "preview.html" should not exist
|
48
|
+
And a file named "output.html" should exist
|
49
|
+
|
50
|
+
Scenario: given an explicit layout
|
51
|
+
Given the default "config.yml" file
|
52
|
+
And a file named "chapter1.md" with:
|
53
|
+
"""
|
54
|
+
Content 1
|
55
|
+
"""
|
56
|
+
And a file named "layout.html" with:
|
57
|
+
"""
|
58
|
+
Custom layout
|
59
|
+
<%= @body %>
|
60
|
+
"""
|
61
|
+
When I successfully run `rpub preview -l layout.html`
|
62
|
+
Then the file "preview.html" should contain "Custom layout"
|
63
|
+
|
64
|
+
Scenario: getting help
|
65
|
+
When I successfully run `rpub preview -h`
|
66
|
+
Then the stdout should contain "Generate a single-page HTML file"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: text statistics
|
2
|
+
As an author
|
3
|
+
I want to see some stats about my work
|
4
|
+
In order to get a sense of progress
|
5
|
+
|
6
|
+
Scenario: Lorem ipsum
|
7
|
+
Given the default "config.yml" file
|
8
|
+
And a file named "chapter1.md" with:
|
9
|
+
"""
|
10
|
+
Lorem ipsum dolor sit amet"
|
11
|
+
"""
|
12
|
+
When I successfully run `rpub stats`
|
13
|
+
Then the output should contain "5 words"
|
14
|
+
And the output should contain "1 pages"
|
15
|
+
And the output should contain "1 sentences"
|
16
|
+
And the output should contain "5.0 avg sentence length"
|
17
|
+
And the output should contain "ari"
|
18
|
+
And the output should contain "clf"
|
@@ -0,0 +1,60 @@
|
|
1
|
+
def read_support_file(filename)
|
2
|
+
File.read(File.join(SUPPORT_PATH, filename))
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^the default "(.*?)" file$/ do |filename|
|
6
|
+
write_file filename, read_support_file(filename)
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^the default "config.yml" file with "(.*?)" set to "(.*?)"$/ do |key, value|
|
10
|
+
config = YAML.load(read_support_file('config.yml'))
|
11
|
+
value = false if value == 'false'
|
12
|
+
value = value.to_i if value =~ /^\d+$/
|
13
|
+
config[key] = value
|
14
|
+
write_file 'config.yml', YAML.dump(config)
|
15
|
+
end
|
16
|
+
|
17
|
+
Given /^the default "config.yml" file with:$/ do |settings|
|
18
|
+
config = YAML.load(read_support_file('config.yml'))
|
19
|
+
config.merge! settings.rows_hash
|
20
|
+
write_file 'config.yml', YAML.dump(config)
|
21
|
+
end
|
22
|
+
|
23
|
+
Then /^the default file "(.*?)" should exist$/ do |filename|
|
24
|
+
step %Q{a file named "#{filename}" should exist}
|
25
|
+
step %Q{the file "#{filename}" should contain exactly:}, read_support_file(filename)
|
26
|
+
end
|
27
|
+
|
28
|
+
Then /^the archive "(.*?)" should contain file "(.*?)"$/ do |filename, entry|
|
29
|
+
in_current_dir do
|
30
|
+
Zip::File.open(filename, Zip::File::CREATE) do |zipfile|
|
31
|
+
zipfile.get_entry(entry)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Then /^the archive "(.*?)" should not contain file "(.*?)"$/ do |filename, entry|
|
37
|
+
in_current_dir do
|
38
|
+
Zip::File.open(filename, Zip::File::CREATE) do |zipfile|
|
39
|
+
expect(zipfile.find_entry(entry)).to be_nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Given /^a basic project$/ do
|
45
|
+
steps %Q{
|
46
|
+
Given a file named "README.md" with:
|
47
|
+
"""
|
48
|
+
README file
|
49
|
+
"""
|
50
|
+
And the default "layout.html" file
|
51
|
+
And the default "styles.css" file
|
52
|
+
And the default "config.yml" file
|
53
|
+
And a file named "chapter1.md" with:
|
54
|
+
"""
|
55
|
+
# Chapter 1
|
56
|
+
|
57
|
+
Hello, world
|
58
|
+
"""
|
59
|
+
}
|
60
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
Feature: page layout
|
2
|
+
As an author
|
3
|
+
I want to format my text with CSS
|
4
|
+
In order to spice up my book's looks
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a file named "chapter1.md" with:
|
8
|
+
"""
|
9
|
+
Hello, world
|
10
|
+
"""
|
11
|
+
|
12
|
+
Scenario: default styles
|
13
|
+
When I successfully run `rpub compile`
|
14
|
+
Then the archive "untitled-book-0.0.0.epub" should contain file "OEBPS/styles.css"
|
15
|
+
|
16
|
+
Scenario: overriding styles
|
17
|
+
Given a file named "styles.css" with:
|
18
|
+
"""
|
19
|
+
foo bar
|
20
|
+
"""
|
21
|
+
When I successfully run `rpub compile`
|
22
|
+
And I successfully run `unzip untitled-book-0.0.0.epub`
|
23
|
+
Then the file "OEBPS/styles.css" should contain "foo bar"
|
24
|
+
|
25
|
+
Scenario: custom styles
|
26
|
+
Given a file named "formatting.css" with:
|
27
|
+
"""
|
28
|
+
foo bar
|
29
|
+
"""
|
30
|
+
When I successfully run `rpub compile -s formatting.css`
|
31
|
+
And I successfully run `unzip untitled-book-0.0.0.epub`
|
32
|
+
Then the file "OEBPS/styles.css" should contain "foo bar"
|
33
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Feature: automatic table of contents
|
2
|
+
As an author
|
3
|
+
I want to have my table of contents automatically generated
|
4
|
+
So I don't have to do it manually
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a file named "chapter1.md" with:
|
8
|
+
"""
|
9
|
+
# Chapter 1
|
10
|
+
|
11
|
+
## Subheading
|
12
|
+
|
13
|
+
Lorem ipsum
|
14
|
+
"""
|
15
|
+
|
16
|
+
Scenario: skipping human-readable table of contents
|
17
|
+
When I successfully run `rpub compile`
|
18
|
+
And I run `unzip untitled-book-0.0.0.epub`
|
19
|
+
Then a file named "OEBPS/toc.html" should exist
|
20
|
+
And the file "OEBPS/toc.html" should contain "Chapter 1"
|
21
|
+
And the file "OEBPS/toc.html" should contain "Subheading"
|
22
|
+
|
23
|
+
Scenario: human-readable table of contents
|
24
|
+
Given the default "config.yml" file with "toc" set to "false"
|
25
|
+
When I successfully run `rpub compile`
|
26
|
+
And I run `unzip untitled-book-0.0.0.epub`
|
27
|
+
Then the file "OEBPS/toc.html" should not exist
|
28
|
+
|
29
|
+
Scenario: custom table of contents depth
|
30
|
+
Given the default "config.yml" file with "max_level" set to "1"
|
31
|
+
When I successfully run `rpub compile`
|
32
|
+
And I run `unzip untitled-book-0.0.0.epub`
|
33
|
+
Then the file "OEBPS/toc.html" should contain "Chapter 1"
|
34
|
+
And the file "OEBPS/toc.html" should not contain "Subheading"
|
35
|
+
|
data/lib/rpub.rb
CHANGED
@@ -4,29 +4,45 @@ require 'yaml'
|
|
4
4
|
require 'digest'
|
5
5
|
require 'ostruct'
|
6
6
|
require 'erb'
|
7
|
+
require 'forwardable'
|
7
8
|
|
8
9
|
require 'builder'
|
9
10
|
require 'kramdown'
|
10
|
-
require 'zip
|
11
|
+
require 'zip'
|
11
12
|
require 'nokogiri'
|
12
13
|
require 'textstats'
|
13
14
|
require 'typogruby'
|
14
15
|
|
16
|
+
module Rpub
|
17
|
+
GEM_ROOT = File.expand_path('../../', __FILE__)
|
18
|
+
|
19
|
+
# @return [String] full path to a file that was relative to the gem support directory
|
20
|
+
def self.support_file(path)
|
21
|
+
File.join(GEM_ROOT, 'support', path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.source
|
25
|
+
FilesystemSource
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.document_factory
|
29
|
+
Rpub::Document.method(:new)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
15
33
|
require 'rpub/version'
|
16
|
-
require 'rpub/
|
17
|
-
require 'rpub/
|
18
|
-
require 'rpub/
|
19
|
-
require 'rpub/commands/base'
|
20
|
-
require 'rpub/commands/main'
|
21
|
-
require 'rpub/commands/compile'
|
34
|
+
require 'rpub/filesystem_source'
|
35
|
+
require 'rpub/context'
|
36
|
+
require 'rpub/command'
|
22
37
|
require 'rpub/commands/clean'
|
23
|
-
require 'rpub/commands/
|
24
|
-
require 'rpub/commands/package'
|
25
|
-
require 'rpub/commands/help'
|
38
|
+
require 'rpub/commands/compile'
|
26
39
|
require 'rpub/commands/generate'
|
40
|
+
require 'rpub/commands/package'
|
41
|
+
require 'rpub/commands/preview'
|
27
42
|
require 'rpub/commands/stats'
|
28
43
|
require 'rpub/hash_delegation'
|
29
44
|
require 'rpub/book'
|
45
|
+
require 'rpub/preview'
|
30
46
|
require 'rpub/chapter'
|
31
47
|
require 'rpub/compressor'
|
32
48
|
require 'rpub/epub'
|
@@ -36,24 +52,5 @@ require 'rpub/epub/toc'
|
|
36
52
|
require 'rpub/epub/content'
|
37
53
|
require 'rpub/epub/html_toc'
|
38
54
|
require 'rpub/epub/cover'
|
39
|
-
|
40
|
-
|
41
|
-
GEM_ROOT = File.expand_path('../../', __FILE__)
|
42
|
-
|
43
|
-
NoConfiguration = Class.new(StandardError)
|
44
|
-
|
45
|
-
class InvalidSubcommand < StandardError
|
46
|
-
def initialize(subcommand)
|
47
|
-
super "Unknown subcommand: #{subcommand}"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# @return [String] full path to a file that was relative to the gem support directory
|
52
|
-
def self.support_file(path)
|
53
|
-
File.join(GEM_ROOT, 'support', path)
|
54
|
-
end
|
55
|
-
|
56
|
-
KRAMDOWN_OPTIONS = {
|
57
|
-
:coderay_line_numbers => nil
|
58
|
-
}
|
59
|
-
end
|
55
|
+
require 'rpub/media_type'
|
56
|
+
require 'rpub/document'
|
data/lib/rpub/book.rb
CHANGED
@@ -3,25 +3,18 @@ module Rpub
|
|
3
3
|
# ordering, the book metadata from the configuration file and the book output
|
4
4
|
# filename.
|
5
5
|
class Book
|
6
|
+
extend Forwardable
|
6
7
|
include Enumerable
|
7
|
-
include HashDelegation
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
# @return [Hash] The hash of configuration options read from the config.yml file.
|
12
|
-
attr_reader :config
|
9
|
+
def_delegators :@context, :fonts, :config, :layout
|
13
10
|
|
14
11
|
# @return [Array<Chapter>] List of chapters, one for every input markdown file.
|
15
12
|
attr_reader :chapters
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
attr_reader :layout
|
22
|
-
|
23
|
-
def initialize(layout, config = {}, fonts = [])
|
24
|
-
@chapters, @config, @layout, @fonts = [], config, layout, fonts
|
14
|
+
def initialize(context)
|
15
|
+
@chapters = []
|
16
|
+
@context = context
|
17
|
+
@context.chapter_files.each(&method(:<<))
|
25
18
|
end
|
26
19
|
|
27
20
|
def each(&block)
|
@@ -33,11 +26,11 @@ module Rpub
|
|
33
26
|
end
|
34
27
|
|
35
28
|
def has_toc?
|
36
|
-
!!config.
|
29
|
+
!!config.toc
|
37
30
|
end
|
38
31
|
|
39
32
|
def has_cover?
|
40
|
-
!!config.
|
33
|
+
!!config.cover_image
|
41
34
|
end
|
42
35
|
|
43
36
|
def outline
|
@@ -71,7 +64,7 @@ module Rpub
|
|
71
64
|
# @return [String] output filename for epub, based on the book title and
|
72
65
|
# version number.
|
73
66
|
def filename
|
74
|
-
@filename ||= [config
|
67
|
+
@filename ||= [config.title, config.version].join('-').gsub(/[^\w\.]/i, '-').squeeze('-').downcase.chomp('-') + '.epub'
|
75
68
|
end
|
76
69
|
end
|
77
70
|
end
|
data/lib/rpub/chapter.rb
CHANGED
@@ -4,6 +4,9 @@ module Rpub
|
|
4
4
|
# suitable for writing to the epub archive with the appropriate identifiers
|
5
5
|
# to be listed in the epub manifest files.
|
6
6
|
class Chapter
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@document, :images, :outline, :toc, :title, :to_html
|
9
|
+
|
7
10
|
# @return [String] raw textual contents of this chapter
|
8
11
|
attr_reader :content
|
9
12
|
|
@@ -15,12 +18,7 @@ module Rpub
|
|
15
18
|
|
16
19
|
def initialize(content, number, layout)
|
17
20
|
@content, @number, @layout = content, number, layout
|
18
|
-
@document =
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [Kramdown::Element] Toc elements hierarchy
|
22
|
-
def toc
|
23
|
-
Kramdown::Converter::Toc.convert(@document.root).first
|
21
|
+
@document = Rpub.document_factory.call(content, layout)
|
24
22
|
end
|
25
23
|
|
26
24
|
# @return [String] Unique identifier for this chapter.
|
@@ -33,57 +31,9 @@ module Rpub
|
|
33
31
|
@id ||= "chapter-#{number}"
|
34
32
|
end
|
35
33
|
|
36
|
-
# @return [String] content parsed to HTML by the markdown engine.
|
37
|
-
def to_html
|
38
|
-
@to_html ||= Typogruby.improve(@document.to_html)
|
39
|
-
end
|
40
|
-
|
41
34
|
# @return [String] name for the file in the zip to use, based on the title
|
42
35
|
def filename
|
43
36
|
@filename ||= xml_id.to_s + '-' + title.gsub(/[^\w\.]/i, '-').squeeze('-').downcase.chomp('-') + '.html'
|
44
37
|
end
|
45
|
-
|
46
|
-
# Ordered headers for this chapter, each header as an object responding
|
47
|
-
# to #level and #text.
|
48
|
-
#
|
49
|
-
# @return [Array<#text,#level>] list of headers for this chapter
|
50
|
-
def outline
|
51
|
-
@outline ||= elements(:header).map do |element|
|
52
|
-
OpenStruct.new({
|
53
|
-
:level => element.options[:level],
|
54
|
-
:text => element_text(element),
|
55
|
-
:html_id => Kramdown::Converter::Html.send(:new, @document, { :auto_id_prefix => '' }).generate_id(element.options[:raw_text])
|
56
|
-
})
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# @return [Array<String>] list of all image references
|
61
|
-
def images
|
62
|
-
@images ||= elements(:img).map { |e| e.attr['src'] }
|
63
|
-
end
|
64
|
-
|
65
|
-
# @return [String] Text of the first heading in this chapter
|
66
|
-
def title
|
67
|
-
@title ||= begin
|
68
|
-
(heading = outline.first) ? heading.text : 'untitled'
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def element_text(element)
|
75
|
-
elements(:text, element).map { |e| e.value }.join
|
76
|
-
end
|
77
|
-
|
78
|
-
def elements(type, root = @document.root)
|
79
|
-
collector = lambda do |element|
|
80
|
-
element.children.select { |e|
|
81
|
-
e.type == type
|
82
|
-
} + element.children.map { |e|
|
83
|
-
collector.call(e)
|
84
|
-
}.flatten
|
85
|
-
end
|
86
|
-
collector.call(root)
|
87
|
-
end
|
88
38
|
end
|
89
39
|
end
|