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
data/lib/rpub/command.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rpub
|
2
|
+
class Command
|
3
|
+
attr_reader :args, :options
|
4
|
+
|
5
|
+
def initialize(args, options)
|
6
|
+
@args, @options = args, options
|
7
|
+
run
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def run
|
13
|
+
raise 'Must be implemented by subclass'
|
14
|
+
end
|
15
|
+
|
16
|
+
def book
|
17
|
+
@book ||= Book.new(context)
|
18
|
+
end
|
19
|
+
|
20
|
+
def context
|
21
|
+
@context ||= Context.new({
|
22
|
+
:layout => options.layout,
|
23
|
+
:styles => options.styles,
|
24
|
+
:config => options.config
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
def source
|
29
|
+
@source ||= Rpub.source
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/rpub/commands/clean.rb
CHANGED
@@ -1,54 +1,9 @@
|
|
1
1
|
module Rpub
|
2
2
|
module Commands
|
3
|
-
class Clean <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def invoke
|
9
|
-
super
|
10
|
-
remove create_book.filename
|
11
|
-
remove 'preview.html'
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def parser
|
17
|
-
OptionParser.new do |opts|
|
18
|
-
opts.banner = <<-EOS
|
19
|
-
Usage: rpub clean [-d]'
|
20
|
-
|
21
|
-
Clean up all generated files, such as the standard generated .epub
|
22
|
-
file, package files and preview files.
|
23
|
-
|
24
|
-
Options:
|
25
|
-
EOS
|
26
|
-
|
27
|
-
opts.separator ''
|
28
|
-
|
29
|
-
opts.on '-d', '--dry-run', 'Dry-run: only list files to be removed' do
|
30
|
-
@dry_run = true
|
31
|
-
end
|
32
|
-
|
33
|
-
opts.separator ''
|
34
|
-
opts.separator 'Generic options:'
|
35
|
-
opts.separator ''
|
36
|
-
|
37
|
-
opts.on_tail '-h', '--help', 'Display this message' do
|
38
|
-
puts opts
|
39
|
-
exit
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def remove(filename)
|
45
|
-
if File.exist?(filename)
|
46
|
-
unless @dry_run
|
47
|
-
File.unlink(filename)
|
48
|
-
else
|
49
|
-
puts filename
|
50
|
-
end
|
51
|
-
end
|
3
|
+
class Clean < Command
|
4
|
+
def run
|
5
|
+
source.remove book.filename, options.dryrun
|
6
|
+
source.remove 'preview.html', options.dryrun
|
52
7
|
end
|
53
8
|
end
|
54
9
|
end
|
@@ -1,54 +1,9 @@
|
|
1
1
|
module Rpub
|
2
2
|
module Commands
|
3
|
-
class Compile <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def invoke
|
9
|
-
super
|
10
|
-
book = create_book
|
11
|
-
Compressor.open(book.filename) do |zip|
|
12
|
-
Epub.new(book, File.read(styles)).manifest_in(zip)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def parser
|
19
|
-
OptionParser.new do |opts|
|
20
|
-
opts.banner = <<-EOS
|
21
|
-
Usage: rpub compile [options]
|
22
|
-
|
23
|
-
Compile your Markdown-formatted input files to a valid .epub output
|
24
|
-
file using the options described in config.yml. This will use the
|
25
|
-
layout.html and styles.css files in your project directory if
|
26
|
-
present.
|
27
|
-
|
28
|
-
Options:
|
29
|
-
EOS
|
30
|
-
opts.separator ''
|
31
|
-
|
32
|
-
opts.on '-l', '--layout FILENAME', 'Specify an explicit layout file to use' do |filename|
|
33
|
-
@layout = filename
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.on '-s', '--styles FILENAME', 'Specify an explicit stylesheet file to use' do |filename|
|
37
|
-
@styles = filename
|
38
|
-
end
|
39
|
-
|
40
|
-
opts.on '-c', '--config FILENAME', 'Specify an explicit configuration file to use' do |filename|
|
41
|
-
@config_file = filename
|
42
|
-
end
|
43
|
-
|
44
|
-
opts.separator ''
|
45
|
-
opts.separator 'Generic options:'
|
46
|
-
opts.separator ''
|
47
|
-
|
48
|
-
opts.on_tail '-h', '--help', 'Display this message' do
|
49
|
-
puts opts
|
50
|
-
exit
|
51
|
-
end
|
3
|
+
class Compile < Command
|
4
|
+
def run
|
5
|
+
Rpub::Compressor.open(book.filename) do |zip|
|
6
|
+
Rpub::Epub.new(book, source.read(context.styles)).manifest_in(zip)
|
52
7
|
end
|
53
8
|
end
|
54
9
|
end
|
@@ -1,78 +1,21 @@
|
|
1
1
|
module Rpub
|
2
2
|
module Commands
|
3
|
-
class Generate <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
super
|
8
|
-
@all = true
|
9
|
-
end
|
10
|
-
|
11
|
-
def invoke
|
12
|
-
super
|
13
|
-
|
14
|
-
if (@styles.nil? && @all) || (!@styles.nil? && @styles)
|
15
|
-
write_file Rpub.support_file('styles.css')
|
3
|
+
class Generate < Command
|
4
|
+
def run
|
5
|
+
all = [options.styles, options.layout, options.config].all? do |b|
|
6
|
+
b.nil? || b == false
|
16
7
|
end
|
17
8
|
|
18
|
-
if (
|
19
|
-
|
9
|
+
if (options.styles.nil? && all) || (!options.styles.nil? && options.styles)
|
10
|
+
source.write 'styles.css', source.read(Rpub.support_file('styles.css'))
|
20
11
|
end
|
21
12
|
|
22
|
-
if (
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def write_file(file)
|
30
|
-
output_file = File.basename(file)
|
31
|
-
if File.exist?(output_file)
|
32
|
-
puts "Not overriding #{output_file}"
|
33
|
-
return
|
34
|
-
end
|
35
|
-
File.open(output_file, 'w') do |f|
|
36
|
-
f.write File.read(file)
|
13
|
+
if (options.layout.nil? && all) || (!options.layout.nil? && options.layout)
|
14
|
+
source.write 'layout.html', source.read(Rpub.support_file('layout.html'))
|
37
15
|
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def parser
|
41
|
-
OptionParser.new do |opts|
|
42
|
-
opts.banner = <<-EOS
|
43
|
-
Usage: rpub generate [-slach]
|
44
|
-
|
45
|
-
Generate one or more standard files to get started with a new project. By
|
46
|
-
default an entire skeleton project is generated, but by passing the -s, -l, -c
|
47
|
-
options you can generate just a single file.
|
48
|
-
|
49
|
-
Options:
|
50
|
-
EOS
|
51
|
-
opts.separator ' '
|
52
|
-
|
53
|
-
opts.on '-s', '--[no-]styles', 'Generate default stylesheet' do |v|
|
54
|
-
@all = false if v
|
55
|
-
@styles = v
|
56
|
-
end
|
57
|
-
|
58
|
-
opts.on '-l', '--[no-]layout', 'Generate default HTML layout' do |v|
|
59
|
-
@all = false if v
|
60
|
-
@layout = v
|
61
|
-
end
|
62
|
-
|
63
|
-
opts.on '-c', '--[no-]config', 'Generate default configuration' do |v|
|
64
|
-
@all = false if v
|
65
|
-
@config = v
|
66
|
-
end
|
67
|
-
|
68
|
-
opts.separator ''
|
69
|
-
opts.separator 'Generic options:'
|
70
|
-
opts.separator ''
|
71
16
|
|
72
|
-
|
73
|
-
|
74
|
-
exit
|
75
|
-
end
|
17
|
+
if (options.config.nil? && all) || (!options.config.nil? && options.config)
|
18
|
+
source.write 'config.yml', source.read(Rpub.support_file('config.yml'))
|
76
19
|
end
|
77
20
|
end
|
78
21
|
end
|
@@ -1,42 +1,14 @@
|
|
1
1
|
module Rpub
|
2
2
|
module Commands
|
3
|
-
class Package <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
Compressor.open(config.fetch('package_file')) do |zip|
|
13
|
-
zip.store_file create_book.filename, File.read(create_book.filename)
|
14
|
-
config.fetch('package') { [] }.each do |file|
|
15
|
-
zip.compress_file file, File.read(file)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def parser
|
23
|
-
OptionParser.new do |opts|
|
24
|
-
opts.banner = <<-EOS
|
25
|
-
Usage: rpub package
|
26
|
-
|
27
|
-
Compile your ebook to an ePub file and package it into an archive together with
|
28
|
-
optional other files for easy distibution. You might want to include a README
|
29
|
-
file, a license or other promotion material.
|
30
|
-
|
31
|
-
Options:
|
32
|
-
EOS
|
33
|
-
opts.separator ''
|
34
|
-
opts.separator 'Generic options:'
|
35
|
-
opts.separator ''
|
36
|
-
|
37
|
-
opts.on_tail '-h', '--help', 'Display this message' do
|
38
|
-
puts opts
|
39
|
-
exit
|
3
|
+
class Package < Command
|
4
|
+
def run
|
5
|
+
Compile.new(args, options)
|
6
|
+
if context.config.package_file
|
7
|
+
Rpub::Compressor.open(context.config.package_file) do |zip|
|
8
|
+
zip.store_file book.filename, source.read(book.filename)
|
9
|
+
Array(context.config.package).each do |file|
|
10
|
+
zip.compress_file file, source.read(file)
|
11
|
+
end
|
40
12
|
end
|
41
13
|
end
|
42
14
|
end
|
@@ -1,59 +1,9 @@
|
|
1
1
|
module Rpub
|
2
2
|
module Commands
|
3
|
-
class Preview <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(*args)
|
9
|
-
super
|
10
|
-
@filename = 'preview.html'
|
11
|
-
end
|
12
|
-
|
13
|
-
def invoke
|
14
|
-
super
|
15
|
-
return unless markdown_files.any?
|
16
|
-
File.open(@filename, 'w') do |f|
|
17
|
-
f.write move_styles_inline(Typogruby.improve(concatenated_document.to_html))
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def move_styles_inline(html)
|
24
|
-
style_block = %Q{<style>\n#{File.read(styles)}\n</style>}
|
25
|
-
html.gsub %r{</head>}, style_block + "\n</head>"
|
26
|
-
end
|
27
|
-
|
28
|
-
def parser
|
29
|
-
OptionParser.new do |opts|
|
30
|
-
opts.banner = <<-EOS
|
31
|
-
Usage: rpub preview [options]
|
32
|
-
|
33
|
-
Generate a single-page HTML file for easy previewing of your content with the
|
34
|
-
layout and styles used when generating .epub files. By default, the output
|
35
|
-
file will be named "preview.html".
|
36
|
-
|
37
|
-
Options:
|
38
|
-
EOS
|
39
|
-
opts.separator ''
|
40
|
-
opts.on '-l', '--layout FILENAME', 'Specify an explicit layout file to use' do |filename|
|
41
|
-
@layout = filename
|
42
|
-
end
|
43
|
-
|
44
|
-
opts.on '-o', '--output FILENAME', 'Specify an explicit output file' do |filename|
|
45
|
-
@filename = filename
|
46
|
-
end
|
47
|
-
|
48
|
-
opts.separator ''
|
49
|
-
opts.separator 'Generic options:'
|
50
|
-
opts.separator ''
|
51
|
-
|
52
|
-
opts.on_tail '-h', '--help', 'Display this message' do
|
53
|
-
puts opts
|
54
|
-
exit
|
55
|
-
end
|
56
|
-
end
|
3
|
+
class Preview < Command
|
4
|
+
def run
|
5
|
+
options.default :output => 'preview.html'
|
6
|
+
source.force_write options.output, Rpub::Preview.new(context, source).formatted
|
57
7
|
end
|
58
8
|
end
|
59
9
|
end
|
data/lib/rpub/commands/stats.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
1
|
module Rpub
|
2
2
|
module Commands
|
3
|
-
class Stats <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def invoke
|
8
|
-
super
|
9
|
-
text = Nokogiri::HTML(concatenated_document.to_html).xpath('//text()').to_s
|
3
|
+
class Stats < Command
|
4
|
+
def run
|
5
|
+
text = Rpub::Preview.new(context, source).text
|
10
6
|
puts "#{text.words.size} words"
|
11
|
-
puts "#{text.words.size / 500} pages"
|
7
|
+
puts "#{(text.words.size.to_f / 500).ceil} pages"
|
12
8
|
puts "#{text.sentences} sentences"
|
13
9
|
puts "#{text.avg_sentence_length} avg sentence length"
|
14
|
-
puts "
|
15
|
-
puts "
|
10
|
+
puts format("%.2f ari", text.ari)
|
11
|
+
puts format("%.2f clf", text.clf)
|
16
12
|
end
|
17
13
|
end
|
18
14
|
end
|
data/lib/rpub/compressor.rb
CHANGED
@@ -17,7 +17,7 @@ module Rpub
|
|
17
17
|
|
18
18
|
# @param [String] filename of the archive to write to disk
|
19
19
|
def initialize(filename)
|
20
|
-
@zip = Zip::
|
20
|
+
@zip = Zip::OutputStream.new(filename)
|
21
21
|
end
|
22
22
|
|
23
23
|
# Close the zip stream and write the file to disk.
|
@@ -30,7 +30,7 @@ module Rpub
|
|
30
30
|
# @param [String] filename under the which the data should be stored
|
31
31
|
# @param [#to_s] content to be compressed
|
32
32
|
def store_file(filename, content)
|
33
|
-
zip.put_next_entry filename, nil, nil, Zip::
|
33
|
+
zip.put_next_entry filename, nil, nil, Zip::Entry::STORED, Zlib::NO_COMPRESSION
|
34
34
|
zip.write content.to_s
|
35
35
|
end
|
36
36
|
|
@@ -39,7 +39,7 @@ module Rpub
|
|
39
39
|
# @param [String] filename under the which the data should be stored
|
40
40
|
# @param [#to_s] content to be compressed
|
41
41
|
def compress_file(filename, content)
|
42
|
-
zip.put_next_entry filename, nil, nil, Zip::
|
42
|
+
zip.put_next_entry filename, nil, nil, Zip::Entry::DEFLATED, Zlib::BEST_COMPRESSION
|
43
43
|
zip.write content.to_s
|
44
44
|
end
|
45
45
|
end
|
data/lib/rpub/context.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Rpub
|
2
|
+
class Context
|
3
|
+
include Rpub.source
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@config_file = options[:config]
|
7
|
+
@layout = options[:layout]
|
8
|
+
@styles = options[:styles]
|
9
|
+
end
|
10
|
+
|
11
|
+
def config
|
12
|
+
@config ||= OpenStruct.new(YAML.load_file(config_file) || {})
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [String] path to the current layout file (defaulting to built-in)
|
16
|
+
def layout
|
17
|
+
@layout ||= own_or_support_file('layout.html')
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String] path to the current stylesheet file (defaulting to built-in)
|
21
|
+
def styles
|
22
|
+
@styles ||= own_or_support_file('styles.css')
|
23
|
+
end
|
24
|
+
|
25
|
+
def fonts
|
26
|
+
@fonts ||= read(styles).scan(/url\((?:'|")?([^'")]+\.[ot]tf)(?:'|")?\)/i).flatten
|
27
|
+
end
|
28
|
+
|
29
|
+
# All chapter input files loaded into strings. This does not include any of
|
30
|
+
# the files listed in the +ignore+ configuration key.
|
31
|
+
#
|
32
|
+
# @return [Array<String>]
|
33
|
+
def chapter_files
|
34
|
+
@chapter_files ||= filter_exceptions(source_files).sort.map(&method(:read))
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def config_file
|
40
|
+
@config_file ||= own_or_support_file('config.yml')
|
41
|
+
end
|
42
|
+
|
43
|
+
def filter_exceptions(filenames)
|
44
|
+
return filenames unless config.ignore
|
45
|
+
filenames.reject(&config.ignore.method(:include?))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|