rpub 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -1
  3. data/.rspec +0 -1
  4. data/.travis.yml +3 -4
  5. data/.yardopts +1 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +70 -46
  8. data/Guardfile +6 -0
  9. data/HISTORY.md +10 -0
  10. data/README.md +1 -1
  11. data/Rakefile +7 -2
  12. data/bin/rpub +64 -1
  13. data/doc/.gitignore +8 -0
  14. data/doc/api/Rpub.html +339 -0
  15. data/doc/api/Rpub/Book.html +983 -0
  16. data/doc/api/Rpub/Chapter.html +737 -0
  17. data/doc/api/Rpub/Command.html +356 -0
  18. data/doc/api/Rpub/Commands.html +117 -0
  19. data/doc/api/Rpub/Commands/Clean.html +216 -0
  20. data/doc/api/Rpub/Commands/Compile.html +218 -0
  21. data/doc/api/Rpub/Commands/Generate.html +242 -0
  22. data/doc/api/Rpub/Commands/Package.html +230 -0
  23. data/doc/api/Rpub/Commands/Preview.html +216 -0
  24. data/doc/api/Rpub/Commands/Stats.html +226 -0
  25. data/doc/api/Rpub/Compressor.html +687 -0
  26. data/doc/api/Rpub/Context.html +553 -0
  27. data/doc/api/Rpub/Document.html +647 -0
  28. data/doc/api/Rpub/Document/OutlineElement.html +388 -0
  29. data/doc/api/Rpub/Epub.html +465 -0
  30. data/doc/api/Rpub/Epub/Container.html +224 -0
  31. data/doc/api/Rpub/Epub/Content.html +344 -0
  32. data/doc/api/Rpub/Epub/Cover.html +236 -0
  33. data/doc/api/Rpub/Epub/HtmlToc.html +240 -0
  34. data/doc/api/Rpub/Epub/Toc.html +244 -0
  35. data/doc/api/Rpub/FilesystemSource.html +544 -0
  36. data/doc/api/Rpub/HashDelegation.html +281 -0
  37. data/doc/api/Rpub/HashDelegation/ClassMethods.html +175 -0
  38. data/doc/api/Rpub/MediaType.html +192 -0
  39. data/doc/api/Rpub/Preview.html +464 -0
  40. data/doc/api/Rpub/XmlFile.html +457 -0
  41. data/doc/api/_index.html +405 -0
  42. data/doc/api/class_list.html +54 -0
  43. data/doc/api/css/common.css +1 -0
  44. data/doc/api/css/full_list.css +57 -0
  45. data/doc/api/css/style.css +339 -0
  46. data/doc/api/file.HISTORY.html +131 -0
  47. data/doc/api/file.LICENSE.html +92 -0
  48. data/doc/api/file.README.html +337 -0
  49. data/doc/api/file_list.html +62 -0
  50. data/doc/api/frames.html +26 -0
  51. data/doc/api/index.html +337 -0
  52. data/doc/api/js/app.js +219 -0
  53. data/doc/api/js/full_list.js +178 -0
  54. data/doc/api/js/jquery.js +4 -0
  55. data/doc/api/method_list.html +533 -0
  56. data/doc/api/top-level-namespace.html +112 -0
  57. data/doc/index.html +312 -0
  58. data/doc/javascripts/scale.fix.js +17 -0
  59. data/doc/params.json +1 -0
  60. data/doc/stylesheets/pygment_trac.css +69 -0
  61. data/doc/stylesheets/styles.css +255 -0
  62. data/features/clean.feature +31 -0
  63. data/features/compile.feature +49 -0
  64. data/features/embedded_assets.feature +51 -0
  65. data/features/generate.feature +63 -0
  66. data/features/layout.feature +41 -0
  67. data/features/package.feature +30 -0
  68. data/features/previews.feature +66 -0
  69. data/features/stats.feature +18 -0
  70. data/features/step_definitions/general_steps.rb +60 -0
  71. data/features/styles.feature +33 -0
  72. data/features/support/env.rb +7 -0
  73. data/features/table_of_contents.feature +35 -0
  74. data/lib/rpub.rb +28 -31
  75. data/lib/rpub/book.rb +9 -16
  76. data/lib/rpub/chapter.rb +4 -54
  77. data/lib/rpub/command.rb +32 -0
  78. data/lib/rpub/commands/clean.rb +4 -49
  79. data/lib/rpub/commands/compile.rb +4 -49
  80. data/lib/rpub/commands/generate.rb +10 -67
  81. data/lib/rpub/commands/package.rb +9 -37
  82. data/lib/rpub/commands/preview.rb +4 -54
  83. data/lib/rpub/commands/stats.rb +6 -10
  84. data/lib/rpub/compressor.rb +3 -3
  85. data/lib/rpub/context.rb +48 -0
  86. data/lib/rpub/document.rb +68 -0
  87. data/lib/rpub/epub.rb +8 -7
  88. data/lib/rpub/epub/content.rb +9 -30
  89. data/lib/rpub/epub/cover.rb +1 -8
  90. data/lib/rpub/epub/html_toc.rb +4 -9
  91. data/lib/rpub/epub/toc.rb +16 -13
  92. data/lib/rpub/filesystem_source.rb +47 -0
  93. data/lib/rpub/media_type.rb +16 -0
  94. data/lib/rpub/preview.rb +29 -0
  95. data/lib/rpub/version.rb +1 -1
  96. data/lib/rpub/xml_file.rb +4 -1
  97. data/rpub.gemspec +6 -7
  98. data/spec/rpub/book_spec.rb +45 -45
  99. data/spec/rpub/chapter_spec.rb +87 -22
  100. data/spec/rpub/epub/container_spec.rb +3 -5
  101. data/spec/rpub/epub/content_spec.rb +62 -41
  102. data/spec/rpub/epub/cover_spec.rb +3 -5
  103. data/spec/rpub/epub/html_toc_spec.rb +8 -8
  104. data/spec/rpub/epub/toc_spec.rb +20 -22
  105. data/spec/rpub_spec.rb +1 -3
  106. data/spec/spec_helper.rb +28 -0
  107. data/support/config.yml +1 -0
  108. data/support/styles.css +3 -3
  109. metadata +131 -120
  110. data/lib/rpub/commander.rb +0 -23
  111. data/lib/rpub/commands/base.rb +0 -33
  112. data/lib/rpub/commands/help.rb +0 -37
  113. data/lib/rpub/commands/main.rb +0 -45
  114. data/lib/rpub/compilation_helpers.rb +0 -73
  115. data/lib/rpub/subclass_tracker.rb +0 -53
  116. data/spec/rpub/commands/clean_spec.rb +0 -46
  117. data/spec/rpub/commands/generate_spec.rb +0 -52
  118. data/spec/rpub/commands/main_spec.rb +0 -26
  119. data/spec/rpub/commands/package_spec.rb +0 -33
  120. data/spec/rpub/commands/preview_spec.rb +0 -43
@@ -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
@@ -1,54 +1,9 @@
1
1
  module Rpub
2
2
  module Commands
3
- class Clean < Base
4
- include CompilationHelpers
5
-
6
- identifier 'clean'
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 < Base
4
- include CompilationHelpers
5
-
6
- identifier 'compile'
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 < Base
4
- identifier 'generate'
5
-
6
- def initialize(*args)
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 (@layout.nil? && @all) || (!@layout.nil? && @layout)
19
- write_file Rpub.support_file('layout.html')
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 (@config.nil? && @all) || (!@config.nil? && @config)
23
- write_file Rpub.support_file('config.yml')
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
- opts.on_tail '-h', '--help', 'Display this message' do
73
- puts opts
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 < Base
4
- include CompilationHelpers
5
-
6
- identifier 'package'
7
-
8
- def invoke
9
- super
10
- Compile.new(options).invoke
11
- return unless config.has_key?('package_file')
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 < Base
4
- include CompilationHelpers
5
-
6
- identifier 'preview'
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
@@ -1,18 +1,14 @@
1
1
  module Rpub
2
2
  module Commands
3
- class Stats < Base
4
- identifier 'stats'
5
- include CompilationHelpers
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 "#{text.ari} ari"
15
- puts "#{text.clf} clf"
10
+ puts format("%.2f ari", text.ari)
11
+ puts format("%.2f clf", text.clf)
16
12
  end
17
13
  end
18
14
  end
@@ -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::ZipOutputStream.new(filename)
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::ZipEntry::STORED, Zlib::NO_COMPRESSION
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::ZipEntry::DEFLATED, Zlib::BEST_COMPRESSION
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
@@ -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