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
@@ -1,23 +0,0 @@
1
- module Rpub
2
- # The +Commander+ module is responsible for invoking `Command` objects. This is
3
- # the internal part of the library that is used by the CLI.
4
- #
5
- # The +Commander+ takes a list of arguments, which would typically come from the CLI,
6
- # and tries to look up a +Command+ class. If it cannot find anything, it will invoke
7
- # the {Rpub::Commands::Main} command.
8
- #
9
- # @see Rpub::Commands::Base
10
- # @see Rpub::Commands
11
- module Commander
12
- def invoke(args = [])
13
- subcommand, *options = args
14
- Commands::Base.matching(subcommand).new(options).invoke
15
- rescue SubclassTracker::NoSuchSubclass
16
- Commands::Main.new(args).invoke
17
- rescue NoConfiguration
18
- abort 'The current directory does not look like an rpub project.'
19
- end
20
-
21
- extend self
22
- end
23
- end
@@ -1,33 +0,0 @@
1
- module Rpub
2
- module Commands
3
- class Base
4
- extend SubclassTracker
5
-
6
- attr_reader :options
7
-
8
- def initialize(options = [], stdout = $stdout)
9
- @options, @stdout = options, stdout
10
- end
11
-
12
- def invoke
13
- parser.parse!(options)
14
- end
15
-
16
- def help
17
- puts parser
18
- end
19
-
20
- protected
21
-
22
- def parser
23
- OptionParser.new
24
- end
25
-
26
- private
27
-
28
- def puts(*args)
29
- @stdout.puts(*args)
30
- end
31
- end
32
- end
33
- end
@@ -1,37 +0,0 @@
1
- module Rpub
2
- module Commands
3
- class Help < Base
4
- identifier 'help'
5
-
6
- def invoke
7
- if options.empty?
8
- Main.new.invoke
9
- else
10
- Base.matching(options.shift).new.help
11
- end
12
- end
13
-
14
- private
15
-
16
- def parser
17
- OptionParser.new do |opts|
18
- opts.banner = <<-EOS
19
- Usage: rpub help subcommand
20
-
21
- Describe the usage and options for rpub subcommands.
22
-
23
- Options:
24
- EOS
25
- opts.separator ''
26
- opts.separator 'Generic options:'
27
- opts.separator ''
28
-
29
- opts.on_tail '-h', '--help', 'Display this message' do
30
- puts opts
31
- exit
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,45 +0,0 @@
1
- module Rpub
2
- module Commands
3
- class Main < Base
4
-
5
- def invoke
6
- options << '-h' if options.empty?
7
- super
8
- raise InvalidSubcommand, options[0] unless options.empty?
9
- end
10
-
11
- protected
12
-
13
- def parser
14
- OptionParser.new do |opts|
15
- opts.banner = <<-EOS
16
- Usage: rpub [subcommand] [options]
17
-
18
- Compile multiple Markdown-formatted input files into a machine-readable epub
19
- file for distribution as an ebook.
20
-
21
- Available subcommands:
22
-
23
- compile
24
- preview
25
- clean
26
- package
27
- help
28
- EOS
29
-
30
- opts.separator ''
31
- opts.separator 'Generic options:'
32
- opts.separator ''
33
-
34
- opts.on_tail '-v', '--version', 'Display version information' do
35
- puts "rpub #{Rpub::VERSION}"
36
- end
37
-
38
- opts.on_tail '-h', '--help', 'Display command reference' do
39
- puts opts
40
- end
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,73 +0,0 @@
1
- module Rpub
2
- # Provide a set of helper methods that are used across various commands to
3
- # simplify the compilation process. These methods mostly deal with loading files
4
- # from the current project directory.
5
- module CompilationHelpers
6
-
7
- def concatenated_document
8
- Kramdown::Document.new(
9
- markdown_files.join("\n"),
10
- KRAMDOWN_OPTIONS.merge(:template => layout)
11
- )
12
- end
13
-
14
- # Factory method for {Rpub::Book} objects, loading every markdown file as a
15
- # chapter.
16
- #
17
- # @see #markdown_files
18
- # @return [Rpub::Book]
19
- def create_book
20
- book = Book.new(layout, config, fonts)
21
- markdown_files.each(&book.method(:<<))
22
- book
23
- end
24
-
25
- # All chapter input files loaded into strings. This does not include any of
26
- # the files listed in the +ignore+ configuration key.
27
- #
28
- # @return [Array<String>]
29
- def markdown_files
30
- @markdown_files ||= filter_exceptions(Dir['*.md']).sort.map(&File.method(:read))
31
- end
32
-
33
- # @return [String] path to the current layout file (defaulting to built-in)
34
- def layout
35
- @layout ||= own_or_support_file('layout.html')
36
- end
37
-
38
- # @return [String] path to the current stylesheet file (defaulting to built-in)
39
- def styles
40
- @styles ||= own_or_support_file('styles.css')
41
- end
42
-
43
- # Load the contents of +config.yml+ into a +Hash+ object.
44
- #
45
- # @raise [NoConfiguration] when the config file cannot be found.
46
- # @return [Hash] parsed configuration
47
- def config
48
- @config_file ||= begin
49
- raise NoConfiguration unless File.exist?('config.yml')
50
- YAML.load_file('config.yml') || {}
51
- end
52
- end
53
-
54
- private
55
-
56
- def fonts
57
- @fonts ||= File.read(styles).scan(/url\((?:'|")?([^'")]+\.otf)(?:'|")?\)/i).flatten
58
- end
59
-
60
- def filter_exceptions(filenames)
61
- return filenames unless config.has_key?('ignore')
62
- filenames.reject(&config['ignore'].method(:include?))
63
- end
64
-
65
- def own_or_support_file(filename)
66
- if File.exists?(filename)
67
- filename
68
- else
69
- Rpub.support_file(filename)
70
- end
71
- end
72
- end
73
- end
@@ -1,53 +0,0 @@
1
- module Rpub
2
- # Add tracking of subclasses to an existing class by extending it with
3
- # SubclassTracker.
4
- #
5
- # This allows you to set an identifier in a subclass using the +identifier+
6
- # macro, and find subclasses based on that value.
7
- #
8
- # Example:
9
- #
10
- # class ParentClass
11
- # extend SubclassTracker
12
- # end
13
- #
14
- # class ChildClass < ParentClass
15
- # identifier 'foo'
16
- # end
17
- #
18
- # ParentClass.matching('foo') # => ChildClass
19
- # ParentClass.matching('bar') # => raises SubclassTracker::NoSuchSubclass
20
- #
21
- # Note that you don't HAVE to set an identifier. If you don't, your child
22
- # class will never be found by +#matching+.
23
- module SubclassTracker
24
- class NoSuchSubclass < StandardError
25
- def initialize(subcommand)
26
- super "Unrecognized identifier: #{subcommand}"
27
- end
28
- end
29
-
30
- # Set or return the identifier for this class.
31
- def identifier(id = nil)
32
- return @identifier if id.nil?
33
- @identifier = id
34
- end
35
-
36
- def inherited(child)
37
- @subclasses ||= []
38
- @subclasses << child
39
- super
40
- end
41
-
42
- def each
43
- @subclasses ||= []
44
- @subclasses.each { |subclass| yield subclass }
45
- end
46
-
47
- def matching(identifier)
48
- find { |subclass| subclass.identifier === identifier } or raise NoSuchSubclass, identifier
49
- end
50
-
51
- include Enumerable
52
- end
53
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Rpub::Commands::Clean do
4
- before do
5
- Dir.chdir File.join(FIXTURES_DIRECTORY, 'clean')
6
- end
7
-
8
- after do
9
- FileUtils.touch 'preview.html'
10
- FileUtils.touch 'example.epub'
11
- end
12
-
13
- it 'should remove example.epub file' do
14
- expect {
15
- described_class.new.invoke
16
- }.to remove_file('example.epub')
17
- end
18
-
19
- it 'should remove preview.html file' do
20
- expect {
21
- described_class.new.invoke
22
- }.to remove_file('preview.html')
23
- end
24
-
25
- context 'when in dry run mode' do
26
- let(:buffer) { StringIO.new }
27
- let(:subject) { described_class.new(['-d'], buffer) }
28
-
29
- it 'should print preview.html' do
30
- subject.invoke
31
- buffer.string.should include('preview.html')
32
- end
33
-
34
- it 'should not print non-existant files' do
35
- FileUtils.rm 'preview.html'
36
- subject.invoke
37
- buffer.string.should_not include('preview.html')
38
- end
39
-
40
- it 'should not remove existing files' do
41
- expect {
42
- subject.invoke
43
- }.to_not remove_file('preview.html')
44
- end
45
- end
46
- end
@@ -1,52 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Rpub::Commands::Generate do
4
- let(:buffer) { StringIO.new }
5
- before do
6
- Dir.chdir File.join(FIXTURES_DIRECTORY, 'generate')
7
- end
8
-
9
- after do
10
- File.unlink 'styles.css' if File.exist?('styles.css')
11
- File.unlink 'layout.html' if File.exist?('layout.html')
12
- File.unlink 'config.yml' if File.exist?('config.yml')
13
- end
14
-
15
- context 'given a specific option' do
16
- let(:subject) { described_class.new(['--config'], buffer) }
17
-
18
- it 'should generate one file' do
19
- expect(&subject.method(:invoke)).to create_file('config.yml')
20
- end
21
-
22
- it 'should not generate stylesheet' do
23
- expect(&subject.method(:invoke)).to_not create_file('layout.html', 'styles.css')
24
- end
25
- end
26
-
27
- context 'given a no option' do
28
- let(:subject) { described_class.new(['--no-styles'], buffer) }
29
-
30
- it 'should generate two files' do
31
- expect(&subject.method(:invoke)).to create_file('layout.html', 'config.yml')
32
- end
33
-
34
- it 'should not generate stylesheet' do
35
- expect(&subject.method(:invoke)).to_not create_file('styles.css')
36
- end
37
- end
38
-
39
- context 'given no options' do
40
- let(:subject) { described_class.new([], buffer) }
41
-
42
- it 'should generate three files' do
43
- expect(&subject.method(:invoke)).to create_file('styles.css', 'layout.html', 'config.yml')
44
- end
45
-
46
- it 'should not generate existing files' do
47
- File.open('styles.css', 'w') { |f| f.write 'foo' }
48
- expect(&subject.method(:invoke)).to_not change { File.read('styles.css') }
49
- buffer.string.should include('Not overriding styles.css')
50
- end
51
- end
52
- end
@@ -1,26 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Rpub::Commands::Main do
4
- let(:buffer) { StringIO.new }
5
-
6
- it 'should default to help text' do
7
- described_class.new([], buffer).invoke
8
- buffer.string.should =~ /Display command reference/
9
- end
10
-
11
- it 'should raise error when a subcommand remains' do
12
- expect {
13
- described_class.new(['foo'], buffer).invoke
14
- }.should raise_error(Rpub::InvalidSubcommand)
15
- end
16
-
17
- it 'should print the version number' do
18
- described_class.new(['-v'], buffer).invoke
19
- buffer.string.should =~ /rpub \d+\.\d+\.\d+/
20
- end
21
-
22
- it 'should print help text' do
23
- described_class.new(['-h'], buffer).invoke
24
- buffer.string.should =~ /Display command reference/
25
- end
26
- end
@@ -1,33 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Rpub::Commands::Package do
4
- before do
5
- Dir.chdir File.join(FIXTURES_DIRECTORY, 'package')
6
- end
7
-
8
- after do
9
- File.unlink('package.zip') if File.exist?('package.zip')
10
- File.unlink('untitled-book-0.0.0.epub') if File.exist?('untitled-book-0.0.0.epub')
11
- end
12
-
13
- it 'should generate an archive' do
14
- expect(&subject.method(:invoke)).to create_file('package.zip')
15
- end
16
-
17
- context 'archive file' do
18
- before { described_class.new.invoke }
19
-
20
- let(:subject) do
21
- [].tap do |files|
22
- Zip::ZipInputStream.open('package.zip') do |io|
23
- while entry = io.get_next_entry
24
- files << entry.name
25
- end
26
- end
27
- end
28
- end
29
-
30
- it { should include('README.md') }
31
- it { should include('untitled-book-0.0.0.epub') }
32
- end
33
- end
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Rpub::Commands::Preview do
4
- before do
5
- Dir.chdir File.join(FIXTURES_DIRECTORY, 'preview')
6
- end
7
-
8
- after do
9
- File.unlink 'preview.html' if File.exist?('preview.html')
10
- File.unlink 'foo.bar' if File.exist?('foo.bar')
11
- end
12
-
13
- context 'generated content' do
14
- before { Rpub::Commands::Preview.new.invoke }
15
- let(:subject) { File.read('preview.html') }
16
-
17
- it { should include('<p>foo</p>') }
18
- it { should include('<p>bar</p>') }
19
- it { should match(/foo.*bar/m) }
20
- it { should match(/<head>/) }
21
- it { should match(/<style>/) }
22
- end
23
-
24
- it 'should create new preview file' do
25
- expect {
26
- Rpub::Commands::Preview.new.invoke
27
- }.to create_file('preview.html')
28
- end
29
-
30
- it 'should do nothing when there are no files to preview' do
31
- Dir.chdir File.join(FIXTURES_DIRECTORY, 'no_files')
32
- expect {
33
- Rpub::Commands::Preview.new.invoke
34
- }.to_not create_file('preview.html')
35
- end
36
-
37
- it 'should allow overriding the filename' do
38
- expect {
39
- Rpub::Commands::Preview.new(['-o', 'foo.bar']).invoke
40
- }.to create_file('foo.bar')
41
- end
42
-
43
- end