rpub 0.4.0 → 0.5.0

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.
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,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&nbsp;1"
30
+ And the file "preview.html" should contain "Content&nbsp;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&nbsp;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,7 @@
1
+ require 'aruba/cucumber'
2
+ require 'zip'
3
+ SUPPORT_PATH = File.expand_path(File.join(*%w[.. .. .. support]), __FILE__)
4
+
5
+ Before do
6
+ @aruba_timeout_seconds = 5
7
+ end
@@ -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
+
@@ -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/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/subclass_tracker'
17
- require 'rpub/commander'
18
- require 'rpub/compilation_helpers'
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/preview'
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
- module Rpub
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'
@@ -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
- delegate_to_hash :config
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
- # @return [Array<String>] all the fonts referred to in the stylesheet
18
- attr_reader :fonts
19
-
20
- # @return [String] the path the layout HTML file to use to wrap the chapter in.
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.fetch('toc') { false }
29
+ !!config.toc
37
30
  end
38
31
 
39
32
  def has_cover?
40
- !!config.fetch('cover_image') { false }
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['title'], config['version']].join('-').gsub(/[^\w\.]/i, '-').squeeze('-').downcase.chomp('-') + '.epub'
67
+ @filename ||= [config.title, config.version].join('-').gsub(/[^\w\.]/i, '-').squeeze('-').downcase.chomp('-') + '.epub'
75
68
  end
76
69
  end
77
70
  end
@@ -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 = Kramdown::Document.new(content, KRAMDOWN_OPTIONS.merge(:template => layout))
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