prophecy 0.0.1

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 (129) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/Overview.md +44 -0
  6. data/README.md +35 -0
  7. data/Rakefile +1 -0
  8. data/bin/kindlegen +18 -0
  9. data/bin/kindlegen.exe +0 -0
  10. data/bin/kindlegen_linux +0 -0
  11. data/bin/kindlegen_mac +0 -0
  12. data/bin/prophecy +4 -0
  13. data/docs/licenses/kindlegen/.empty_directory +0 -0
  14. data/docs/licenses/kindlegen/EULA.txt +61 -0
  15. data/docs/licenses/kindlegen/KindleGen Legal Notices 2009-11-10 Linux.txt +21 -0
  16. data/docs/licenses/kindlegen/KindleGen Legal Notices 2009-11-10 Mac.txt +21 -0
  17. data/docs/licenses/kindlegen/KindleGen OSS Notices 2009-07-29-Windows.txt +19 -0
  18. data/features/assets.feature +14 -0
  19. data/features/book.feature +10 -0
  20. data/features/generator.feature +15 -0
  21. data/features/support/hooks.rb +5 -0
  22. data/features/support/setup.rb +3 -0
  23. data/lib/prophecy/assets/.gitignore +2 -0
  24. data/lib/prophecy/assets/config.rb +20 -0
  25. data/lib/prophecy/assets/epub_template/META-INF/com.apple.ibooks.display-options.xml +6 -0
  26. data/lib/prophecy/assets/epub_template/META-INF/container.xml +6 -0
  27. data/lib/prophecy/assets/epub_template/OEBPS/.gitkeep +0 -0
  28. data/lib/prophecy/assets/epub_template/OEBPS/chapters/.gitkeep +0 -0
  29. data/lib/prophecy/assets/epub_template/OEBPS/content.opf.erb +114 -0
  30. data/lib/prophecy/assets/epub_template/OEBPS/toc.ncx.erb +18 -0
  31. data/lib/prophecy/assets/epub_template/mimetype +1 -0
  32. data/lib/prophecy/assets/fonts/Crimson-Bold.otf +0 -0
  33. data/lib/prophecy/assets/fonts/Crimson-BoldItalic.otf +0 -0
  34. data/lib/prophecy/assets/fonts/Crimson-Italic.otf +0 -0
  35. data/lib/prophecy/assets/fonts/Crimson-Roman.otf +0 -0
  36. data/lib/prophecy/assets/fonts/Crimson-Semibold.otf +0 -0
  37. data/lib/prophecy/assets/fonts/Crimson-SemiboldItalic.otf +0 -0
  38. data/lib/prophecy/assets/fonts/GenBasB.ttf +0 -0
  39. data/lib/prophecy/assets/fonts/GenBasBI.ttf +0 -0
  40. data/lib/prophecy/assets/fonts/GenBasI.ttf +0 -0
  41. data/lib/prophecy/assets/fonts/GenBasR.ttf +0 -0
  42. data/lib/prophecy/assets/fonts/GenBkBasB.ttf +0 -0
  43. data/lib/prophecy/assets/fonts/GenBkBasBI.ttf +0 -0
  44. data/lib/prophecy/assets/fonts/GenBkBasI.ttf +0 -0
  45. data/lib/prophecy/assets/fonts/GenBkBasR.ttf +0 -0
  46. data/lib/prophecy/assets/fonts/GentiumPlus-I.ttf +0 -0
  47. data/lib/prophecy/assets/fonts/GentiumPlus-R.ttf +0 -0
  48. data/lib/prophecy/assets/helpers/check_typos.sh +27 -0
  49. data/lib/prophecy/assets/helpers/helpers.rb +0 -0
  50. data/lib/prophecy/assets/helpers/pali_typos +2 -0
  51. data/lib/prophecy/assets/helpers/sed_chars +5 -0
  52. data/lib/prophecy/assets/helpers/sed_dumb_ebook +18 -0
  53. data/lib/prophecy/assets/helpers/sed_tex2uni +62 -0
  54. data/lib/prophecy/assets/helpers/tex2html.sh +112 -0
  55. data/lib/prophecy/assets/helpers/tex2md.sh +10 -0
  56. data/lib/prophecy/assets/helpers/tidy_quotes +1 -0
  57. data/lib/prophecy/assets/helpers/tidy_quotes.sh +8 -0
  58. data/lib/prophecy/assets/helpers/to-html.sh +9 -0
  59. data/lib/prophecy/assets/latex_template/Makefile +37 -0
  60. data/lib/prophecy/assets/latex_template/anecdote.cls +163 -0
  61. data/lib/prophecy/assets/latex_template/book-core-first.sty +673 -0
  62. data/lib/prophecy/assets/latex_template/book-core-last.sty +40 -0
  63. data/lib/prophecy/assets/latex_template/book_main.tex.erb +31 -0
  64. data/lib/prophecy/assets/latex_template/booklet_main.tex +15 -0
  65. data/lib/prophecy/assets/latex_template/chapters/.gitkeep +0 -0
  66. data/lib/prophecy/assets/latex_template/cover_main.tex +48 -0
  67. data/lib/prophecy/assets/latex_template/mylayout.sty +2 -0
  68. data/lib/prophecy/assets/layouts/page.xhtml.erb +20 -0
  69. data/lib/prophecy/assets/sass/_booktheme.sass +3 -0
  70. data/lib/prophecy/assets/sass/_byronic.sass +263 -0
  71. data/lib/prophecy/assets/sass/_colors.sass +7 -0
  72. data/lib/prophecy/assets/sass/_epub-css-starter-kit.sass +734 -0
  73. data/lib/prophecy/assets/sass/_font-existence.scss +12 -0
  74. data/lib/prophecy/assets/sass/_font-source-sans-pro.scss +75 -0
  75. data/lib/prophecy/assets/sass/_fontfaces.scss +11 -0
  76. data/lib/prophecy/assets/sass/_mixins.sass +4 -0
  77. data/lib/prophecy/assets/sass/print.sass +6 -0
  78. data/lib/prophecy/assets/sass/style-epub.sass +7 -0
  79. data/lib/prophecy/assets/sass/style-mobi-kf8.sass +7 -0
  80. data/lib/prophecy/assets/sass/style-mobi.sass +9 -0
  81. data/lib/prophecy/assets/stylesheets/print.css +3 -0
  82. data/lib/prophecy/assets/stylesheets/style-epub.css +401 -0
  83. data/lib/prophecy/assets/stylesheets/style-mobi-kf8.css +401 -0
  84. data/lib/prophecy/assets/stylesheets/style-mobi.css +317 -0
  85. data/lib/prophecy/assets/webfonts/existence-light.ttf +0 -0
  86. data/lib/prophecy/assets/webfonts/sourcesanspro-bold.ttf +0 -0
  87. data/lib/prophecy/assets/webfonts/sourcesanspro-extralight.ttf +0 -0
  88. data/lib/prophecy/assets/webfonts/sourcesanspro-italic.ttf +0 -0
  89. data/lib/prophecy/assets/webfonts/sourcesanspro-light.ttf +0 -0
  90. data/lib/prophecy/assets/webfonts/sourcesanspro-lightitalic.ttf +0 -0
  91. data/lib/prophecy/assets/webfonts/sourcesanspro-regular.ttf +0 -0
  92. data/lib/prophecy/assets/webfonts-extra/sourcesanspro-bolditalic.ttf +0 -0
  93. data/lib/prophecy/assets/webfonts-extra/sourcesanspro-extralightitalic.ttf +0 -0
  94. data/lib/prophecy/assets/webfonts-extra/sourcesanspro-semibold.ttf +0 -0
  95. data/lib/prophecy/assets/webfonts-extra/sourcesanspro-semibolditalic.ttf +0 -0
  96. data/lib/prophecy/book.rb +281 -0
  97. data/lib/prophecy/chapter.rb +359 -0
  98. data/lib/prophecy/cli.rb +144 -0
  99. data/lib/prophecy/generators/assets.rb +29 -0
  100. data/lib/prophecy/generators/book/.gitignore +7 -0
  101. data/lib/prophecy/generators/book/LICENSE.txt +5 -0
  102. data/lib/prophecy/generators/book/README.md.tt +4 -0
  103. data/lib/prophecy/generators/book/book.yml.tt +55 -0
  104. data/lib/prophecy/generators/book/build/epub/.empty_directory +0 -0
  105. data/lib/prophecy/generators/book/build/latex/.empty_directory +0 -0
  106. data/lib/prophecy/generators/book/build/mobi/.empty_directory +0 -0
  107. data/lib/prophecy/generators/book/epub_mobi.yml +26 -0
  108. data/lib/prophecy/generators/book/example-book.yml +78 -0
  109. data/lib/prophecy/generators/book/images/cover.jpg +0 -0
  110. data/lib/prophecy/generators/book/images/cover.xcf +0 -0
  111. data/lib/prophecy/generators/book/images/publisher-logo.jpg +0 -0
  112. data/lib/prophecy/generators/book/manuscript/glossary.md +7 -0
  113. data/lib/prophecy/generators/book/manuscript/nameless-labyrinth.markdown +34 -0
  114. data/lib/prophecy/generators/book/manuscript/preface.md +5 -0
  115. data/lib/prophecy/generators/book/manuscript/the-sway-of-reason.markdown +22 -0
  116. data/lib/prophecy/generators/book/manuscript/unhuman-massiveness.markdown +27 -0
  117. data/lib/prophecy/generators/book/manuscript/xhtml/.gitkeep +0 -0
  118. data/lib/prophecy/generators/book/manuscript/xhtml/cover.xhtml.erb +21 -0
  119. data/lib/prophecy/generators/book/manuscript/xhtml/titlepage.xhtml.erb +31 -0
  120. data/lib/prophecy/generators/book/manuscript/xhtml/toc.xhtml.erb +16 -0
  121. data/lib/prophecy/generators/new.rb +22 -0
  122. data/lib/prophecy/manifest.rb +72 -0
  123. data/lib/prophecy/version.rb +3 -0
  124. data/lib/prophecy.rb +18 -0
  125. data/prophecy.gemspec +36 -0
  126. data/spec/book_spec.rb +9 -0
  127. data/spec/chapter_spec.rb +0 -0
  128. data/spec/manifest_spec.rb +0 -0
  129. metadata +366 -0
@@ -0,0 +1,281 @@
1
+
2
+ module Prophecy
3
+
4
+ class Book
5
+
6
+ attr_reader :config, :chapters, :manifest
7
+
8
+ attr_reader :title, :subtitle, :author, :publisher, :publisher_atag,
9
+ :publisher_logo, :book_atag, :isbn, :uuid, :version, :edition,
10
+ :lang, :lang_iso_639_2, :build_dir, :template_dir, :layouts_dir,
11
+ :assets_dir, :tex_dir, :markdown_dir, :xhtml_dir, :chapter_layout,
12
+ :include_assets, :exclude_assets, :toc, :output_format, :bookid,
13
+ :rights, :creator, :subject, :source, :contributors, :cover_image,
14
+ :date, :compile_name
15
+
16
+ def initialize(config)
17
+ @config = config.clone
18
+
19
+ c = config
20
+
21
+ @output_format = c['output_format'] || nil
22
+ @title = c['title'] || "The Title"
23
+ @subtitle = c['subtitle'] || nil
24
+ @author = c['author'] || "The Author"
25
+ @creator = c['creator'] || @author
26
+ @publisher = c['publisher'] || nil
27
+ @publisher_atag = c['publisher_atag'] || nil
28
+ @publisher_logo = c['publisher_logo'] || nil
29
+ @book_atag = c['book_atag'] || nil
30
+ @isbn = c['isbn'] || nil
31
+ @uuid = c['uuid'] || nil
32
+ @version = c['version'] || 'v0.1'
33
+ @edition = c['edition'] || nil
34
+ @lang = c['lang'] || 'en-GB'
35
+ @lang_iso_639_2 = c['lang_iso_639_2'] || @lang.downcase.sub(/-.*$/, '')
36
+ @tex_dir = c['tex_dir'] || find_format_dir('tex')
37
+ @markdown_dir = c['markdown_dir'] || find_format_dir('markdown')
38
+ @xhtml_dir = c['xhtml_dir'] || find_format_dir('xhtml')
39
+ @build_dir = c['build_dir'] || File.join('./build', @output_format)
40
+ @assets_dir = c['assets_dir'] || find_assets_dir
41
+ @template_dir = c['template_dir'] || find_template_dir
42
+ @layouts_dir = c['layouts_dir'] || File.join(@assets_dir, 'layouts')
43
+ @chapter_layout = c['chapter_layout'] || 'page.xhtml.erb'
44
+ @include_assets = format_include_assets(c['include_assets'])
45
+ @exclude_assets = format_exclude_assets(c['exclude_assets'])
46
+ @toc = c['toc'] || nil
47
+ @bookid = c['bookid'] || nil
48
+ @rights = c['rights'] || nil
49
+ @subject = c['subject'] || nil
50
+ @source = c['source'] || nil
51
+ @contributors = c['contributors'] || nil
52
+ @cover_image = c['cover_image'] || nil
53
+ @date = c['date'] || Time.now.strftime("%Y-%m-%d")
54
+
55
+ @compile_name = "#{self.author}-#{self.title}-#{Time.now.strftime("%FT%T")}".gsub(/[^a-zA-Z0-9-]/, '-').gsub(/--*/, '-')
56
+
57
+ @manifest = nil
58
+ @chapters = []
59
+ Chapter.section_name = config['section_names'] if config['section_names']
60
+ if @toc
61
+ @toc.each do |ch|
62
+ if ch.is_a?(String)
63
+ ch = { 'src' => ch }
64
+ end
65
+
66
+ if ch.has_key?('target')
67
+ if ch['target'].include?(@output_format) || ch['target'] == @output_format
68
+ @chapters << Chapter.new(self, ch)
69
+ end
70
+ else
71
+ c = Chapter.new(self, ch)
72
+ @chapters << c unless c.render_path.nil?
73
+ end
74
+ end
75
+ @navpoints = @chapters.flat_map{|c| c.navpoints}
76
+ end
77
+ end
78
+
79
+ def generate_build
80
+ case self.output_format
81
+ when 'epub'
82
+ self.build_epub_mobi
83
+ when 'mobi'
84
+ self.build_epub_mobi
85
+ when 'latex'
86
+ self.build_latex
87
+ else
88
+ warn "Don't know how to build output format: " + self.output_format
89
+ raise "Unknown Output Format Error"
90
+ end
91
+ end
92
+
93
+ def build_latex
94
+ FileUtils.cp_r(File.join(@template_dir, '.'), @build_dir)
95
+ FileUtils.cp_r(@include_assets, @build_dir)
96
+
97
+ # For ERB binding.
98
+ book = self
99
+
100
+ Dir.glob(File.join(@build_dir, '**/*'), File::FNM_DOTMATCH).each do |f|
101
+ if File.extname(f) == '.erb'
102
+ template = ERB.new(IO.read(f))
103
+ text = template.result(binding)
104
+ File.open(f.sub(/\.erb$/, ''), "w"){|file| file << text }
105
+ FileUtils.rm(f)
106
+ end
107
+
108
+ @exclude_assets.each do |ex|
109
+ if File.fnmatch(ex, f) || File.fnmatch(ex, File.basename(f))
110
+ FileUtils.rm(f)
111
+ end
112
+ end
113
+ end
114
+
115
+ @chapters.each do |ch|
116
+ next if ch.src.nil?
117
+ unless File.extname(ch.src) == '.tex'
118
+ File.open(ch.render_path, "w"){|f| f << ch.to_tex }
119
+ end
120
+ end
121
+ end
122
+
123
+ def build_epub_mobi
124
+ FileUtils.cp_r(File.join(@template_dir, '.'), @build_dir)
125
+ FileUtils.cp_r(@include_assets, File.join(@build_dir, 'OEBPS'))
126
+
127
+ content_opf_path = nil
128
+
129
+ # For ERB binding.
130
+ book = self
131
+
132
+ Dir.glob(File.join(@build_dir, '**/*'), File::FNM_DOTMATCH).each do |f|
133
+ if File.extname(f) == '.erb'
134
+ if File.basename(f) == 'content.opf.erb'
135
+ content_opf_path = File.expand_path(f)
136
+ next
137
+ end
138
+ template = ERB.new(IO.read(f))
139
+ text = template.result(binding)
140
+ File.open(f.sub(/\.erb$/, ''), "w"){|file| file << text }
141
+ FileUtils.rm(f)
142
+ end
143
+
144
+ @exclude_assets.each do |ex|
145
+ if File.fnmatch(ex, f) || File.fnmatch(ex, File.basename(f))
146
+ FileUtils.rm(f)
147
+ end
148
+ end
149
+ end
150
+
151
+ @chapters.each do |ch|
152
+ File.open(ch.render_path, "w"){|f| f << ch.to_html }
153
+ end
154
+
155
+ @manifest = Manifest.new(self)
156
+
157
+ # Rendering content.opf.erb at the end.
158
+ unless content_opf_path.nil?
159
+ template = ERB.new(IO.read(content_opf_path))
160
+ text = template.result(binding)
161
+ File.open(content_opf_path.sub(/\.erb$/, ''), "w"){|file| file << text }
162
+ FileUtils.rm(content_opf_path)
163
+ end
164
+ end
165
+
166
+ def format_dir(src)
167
+ case File.extname(src)
168
+ when '.md', '.mkd', '.markdown'
169
+ self.markdown_dir
170
+ when '.tex'
171
+ self.tex_dir
172
+ when '.xhtml'
173
+ self.xhtml_dir
174
+ when '.html'
175
+ self.xhtml_dir
176
+ when '.erb'
177
+ self.format_dir(src.sub(/\.erb$/, ''))
178
+ end
179
+ end
180
+
181
+ def render_navpoints
182
+ ret = ""
183
+ @navpoints.each_with_index do |nav, idx|
184
+ ret += "<navPoint id='nav#{nav['playOrder']}' playOrder='#{nav['playOrder']}'>\n"
185
+ ret += "<navLabel><text>#{nav['text']}</text></navLabel>\n"
186
+ ret += "<content src='#{nav['src']}'/>"
187
+
188
+ next_nav = @navpoints[idx+1]
189
+ if !next_nav.nil? && next_nav['level'] < nav['level']
190
+ d = nav['level'] - next_nav['level'] + 1
191
+ d.times{ ret += "</navPoint>\n" }
192
+ elsif next_nav.nil? || next_nav['level'] == nav['level']
193
+ ret += "</navPoint>\n"
194
+ end
195
+ end
196
+ ret
197
+ end
198
+
199
+ def personal_name_first(lastname_comma_name)
200
+ n = lastname_comma_name.split(/, */)
201
+ "#{n[1]} #{n[0]}"
202
+ end
203
+
204
+ def epub?
205
+ self.output_format == 'epub'
206
+ end
207
+
208
+ def mobi?
209
+ self.output_format == 'mobi'
210
+ end
211
+
212
+ def latex?
213
+ self.output_format == 'latex'
214
+ end
215
+
216
+ private
217
+
218
+ def find_format_dir(format)
219
+ if Dir.exists?("./manuscript/#{format}/")
220
+ "./manuscript/#{format}/"
221
+ else
222
+ './manuscript/'
223
+ end
224
+ end
225
+
226
+ def find_assets_dir
227
+ if Dir.exists?('./assets/')
228
+ File.join('.', 'assets')
229
+ else
230
+ File.join(File.expand_path(File.dirname(__FILE__)), 'assets')
231
+ end
232
+ end
233
+
234
+ def format_include_assets(config_include)
235
+ case (self.output_format)
236
+ when 'epub', 'mobi'
237
+ inc = [
238
+ File.join(self.assets_dir, 'webfonts'),
239
+ File.join('.', 'images'),
240
+ File.join(self.assets_dir, 'stylesheets')
241
+ ]
242
+ when 'latex'
243
+ inc = []
244
+ end
245
+
246
+ if config_include.nil?
247
+ inc
248
+ else
249
+ inc.concat(config_include).uniq
250
+ end
251
+ end
252
+
253
+ def format_exclude_assets(config_exclude)
254
+ case (self.output_format)
255
+ when 'epub'
256
+ ex = [ 'ie.css', 'print.css', 'style-mobi.css', '*.swp', '.gitkeep' ]
257
+ when 'mobi'
258
+ ex = [ 'ie.css', 'print.css', 'style-epub.css', '*.swp', '.gitkeep' ]
259
+ when 'latex'
260
+ ex = []
261
+ end
262
+
263
+ if config_exclude.nil?
264
+ ex
265
+ else
266
+ ex.concat(config_exclude).uniq
267
+ end
268
+ end
269
+
270
+ def find_template_dir
271
+ case (self.output_format)
272
+ when 'epub', 'mobi'
273
+ File.join(self.assets_dir, 'epub_template')
274
+ when 'latex'
275
+ File.join(self.assets_dir, 'latex_template')
276
+ end
277
+ end
278
+
279
+ end
280
+
281
+ end
@@ -0,0 +1,359 @@
1
+
2
+ module Prophecy
3
+
4
+ class Chapter
5
+
6
+ attr_accessor :title, :id, :idref, :lang, :class, :book, :level,
7
+ :layout, :src, :path, :render_name, :render_path, :href, :type,
8
+ :linear, :prefix, :postfix, :insert, :section_name,
9
+ :section_number, :navpoints
10
+
11
+ # Array index corresponds to level, levels index from 0 too. In the
12
+ # .yml you give the level: N attrib as if they were indexed from 1,
13
+ # makes more sense there, but we compensate for it in the class.
14
+
15
+ @@section_name = [ "Chapter", ]
16
+ @@section_number = [ 0, ]
17
+ @@toc_from_headers = false
18
+ @@playOrder = 1
19
+
20
+ @@the_matter = 'frontmatter'
21
+
22
+ def initialize(book, config)
23
+ @book = book
24
+
25
+ if @book.output_format == 'mobi'
26
+ unless config['level'].nil?
27
+ lvl = config['level'].to_i - 1
28
+ if lvl > 1
29
+ @level = 1
30
+ else
31
+ @level = lvl
32
+ end
33
+ else
34
+ @level = 0
35
+ end
36
+ else
37
+ if config['level'].nil?
38
+ @level = 0
39
+ else
40
+ @level = config['level'].to_i - 1
41
+ end
42
+ end
43
+
44
+ if config['the_matter']
45
+ @the_matter = config['the_matter']
46
+ @@the_matter = config['the_matter']
47
+ else
48
+ @the_matter = @@the_matter
49
+ end
50
+
51
+ @linear = config['linear'] || nil
52
+
53
+ @src = nil
54
+ if config.is_a?(String)
55
+ @src = config
56
+ elsif config.is_a?(Hash) && config.has_key?('src')
57
+ @src = config['src']
58
+ end
59
+
60
+ ext_for_output = {
61
+ 'epub' => '.xhtml',
62
+ 'mobi' => '.xhtml',
63
+ 'latex' => '.tex',
64
+ 'web' => '.html'
65
+ }
66
+
67
+ chapters_dir_for_output = {
68
+ 'epub' => File.join('OEBPS', 'chapters'),
69
+ 'mobi' => File.join('OEBPS', 'chapters'),
70
+ 'latex' => 'chapters',
71
+ 'web' => 'chapters',
72
+ }
73
+
74
+ @path = nil
75
+ @href = nil
76
+
77
+ unless @src.nil?
78
+ @render_ext = ext_for_output[book.output_format]
79
+
80
+ @path = File.expand_path(File.join(
81
+ book.format_dir(@src), @src))
82
+ @render_name = File.basename(@path).sub(/\.erb$/, '').sub(/\.[^\.]+$/, @render_ext)
83
+ @render_path = File.expand_path(
84
+ File.join(
85
+ self.book.build_dir,
86
+ chapters_dir_for_output[book.output_format],
87
+ @render_name
88
+ )
89
+ )
90
+
91
+ a = Pathname.new(self.render_path)
92
+ b = Pathname.new(File.expand_path(
93
+ File.join(
94
+ self.book.build_dir,
95
+ chapters_dir_for_output[book.output_format],
96
+ '..'
97
+ )
98
+ ))
99
+ @href = a.relative_path_from(b)
100
+ end
101
+
102
+ @type = config['type'] || nil
103
+ @title = config['title'] || self.first_header_text || ""
104
+ @class = config['class'] || ""
105
+ @class += " #{@type}" if @type
106
+ @id = config['id'] || 'chapter_' + @title.downcase.gsub(/[^a-z0-9-]/, '-').gsub(/--+/, '-')
107
+ @lang = config['lang'] || book.lang
108
+ @prefix = config['prefix'] || nil
109
+ @postfix = config['postfix'] || nil
110
+ @insert = config['insert'] || nil
111
+
112
+ if config['section_name']
113
+ @@section_name[@level] = config['section_name']
114
+ else
115
+ end
116
+ if config['section_number']
117
+ @@section_number[@level] = config['section_number'].to_i - 1
118
+ elsif @@section_number[@level].nil?
119
+ @@section_number[@level] = 1
120
+ elsif !@path.nil?
121
+ @@section_number[@level] += 1
122
+ end
123
+ @section_name = @@section_name[@level]
124
+ @section_number = @@section_number[@level]
125
+
126
+ @@toc_from_headers = config['toc_from_headers'] unless config['toc_from_headers'].nil?
127
+
128
+ @navpoints = []
129
+ if @path
130
+ if @@toc_from_headers
131
+ doc = Nokogiri::HTML(self.to_html)
132
+ headers = doc.xpath("//*[name()='h1' or name()='h2' or name()='h3' or name()='h4']")
133
+ headers.each do |h|
134
+ # skip links (<a href=""> tag) in header (possibly end- or footnote references)
135
+ t = ""
136
+ h.children.select{|i| i.name != 'a'}.each{|s| t += s}
137
+ @navpoints << {
138
+ 'text' => CGI.escapeHTML(t),
139
+ 'src' => "chapters/#{@render_name}##{h.attributes['id']}",
140
+ 'playOrder' => @@playOrder,
141
+ 'level' => @level,
142
+ }
143
+ @@playOrder += 1
144
+ end
145
+ else
146
+ @navpoints << {
147
+ 'text' => @title,
148
+ 'src' => "chapters/#{@render_name}",
149
+ 'playOrder' => @@playOrder,
150
+ 'level' => @level,
151
+ }
152
+ @@playOrder += 1
153
+ end
154
+ end
155
+
156
+ if config['layout'].nil?
157
+ @layout_path = File.join(book.layouts_dir, book.chapter_layout)
158
+ elsif config['layout'] == 'nil' || config['layout'] == 'none'
159
+ @layout_path = nil
160
+ else
161
+ @layout_path = File.join(book.layouts_dir, config['layout'])
162
+ end
163
+ end
164
+
165
+ def idref
166
+ self.book.manifest.items.select do |i|
167
+ File.expand_path(i.path) == self.render_path
168
+ end.first.id
169
+ end
170
+
171
+ def first_header_text
172
+ if @path
173
+ doc = Nokogiri::HTML(self.to_html)
174
+ h = doc.xpath("//*[name()='h1' or name()='h2' or name()='h3' or name()='h4']").first
175
+ h.text.strip if h
176
+ else
177
+ nil
178
+ end
179
+ end
180
+
181
+ def to_guide_reference
182
+ return "" if @type.nil?
183
+ ret = "<reference href='#{@href}' title=\"#{@title.gsub('"', "'")}\""
184
+ ret += " type='#{@type}'"
185
+ ret += " />"
186
+ end
187
+
188
+ def to_html(format = nil, text = nil, layout_path = @layout_path)
189
+ format ||= File.extname(@path)
190
+ text ||= IO.read(@path)
191
+ # for ERB binding
192
+ book = self.book
193
+ chapter = self
194
+
195
+ ret = nil
196
+
197
+ case format
198
+ when '.html', '.xhtml'
199
+ ret = text
200
+ when '.md', '.mkd', '.markdown'
201
+ ret = Kramdown::Document.new(text).to_html
202
+ when '.tex'
203
+ File.open('./temp-chapter.tex', 'w'){|f| f << text }
204
+ r = system 'pandoc --smart --normalize --from=latex --to=html -o ./temp-chapter.xhtml ./temp-chapter.tex'
205
+ warn "WARNING: pandoc returned non-zero for #{self.to_s}" unless r
206
+ ret = IO.read('./temp-chapter.xhtml')
207
+ FileUtils.rm(['./temp-chapter.tex', './temp-chapter.xhtml'])
208
+ when '.erb'
209
+ template = ERB.new(text)
210
+ fmt = File.extname(@path.sub(/#{format}$/, ''))
211
+ return self.to_html(format = fmt, text = template.result(binding))
212
+ else
213
+ warn "Don't know how to render: #{@src}"
214
+ raise "Error while rendering chapter"
215
+ end
216
+
217
+ unless layout_path.nil?
218
+ template = ERB.new(IO.read(layout_path))
219
+ content = ret
220
+ template.result(binding)
221
+ else
222
+ ret
223
+ end
224
+ end
225
+
226
+ def to_tex(format = nil, text = nil, layout_path = @layout_path)
227
+ format ||= File.extname(@path)
228
+ text ||= IO.read(@path)
229
+ # for ERB binding
230
+ book = self.book
231
+ chapter = self
232
+
233
+ ret = nil
234
+
235
+ case format
236
+ when '.html', '.xhtml'
237
+ File.open('./temp-chapter.html', 'w'){|f| f << text }
238
+ system 'pandoc --smart --normalize --chapters --from=html --to=latex -o ./temp-chapter.tex ./temp-chapter.html'
239
+ ret = IO.read('./temp-chapter.tex')
240
+ FileUtils.rm(['./temp-chapter.tex', './temp-chapter.html'])
241
+ when '.md'
242
+ ret = Kramdown::Document.new(text, options = {:latex_headers => %w{chapter section subsection subsubsection paragraph subparagraph}}).to_latex
243
+ when '.tex'
244
+ ret = text
245
+ when '.erb'
246
+ template = ERB.new(text)
247
+ fmt = File.extname(@path.sub(/#{format}$/, ''))
248
+ ret = self.to_tex(format = fmt, text = template.result(binding))
249
+ else
250
+ warn "Don't know how to render: #{@src}"
251
+ raise "Error while rendering chapter"
252
+ end
253
+
254
+ ret
255
+ end
256
+
257
+ def to_spineitem
258
+ ret = "<itemref idref='#{self.idref}' "
259
+ ret += "linear='#{self.linear}'" unless self.linear.nil?
260
+ ret += " />"
261
+ end
262
+
263
+ def to_chapterlist
264
+ return "#{@insert}" if @insert
265
+ ret = ""
266
+ ret += @prefix + "\n" if @prefix
267
+
268
+ if @src
269
+ ret += "% #{@title}\n" unless @title.empty?
270
+ if File.extname(@src) == '.tex'
271
+ ret += "\\input{" + File.join('..', '..', @book.tex_dir, @src) + "}"
272
+ else
273
+ ret += "\\input{#{@href}}"
274
+ end
275
+ end
276
+ ret += "\n" + @postfix if @postfix
277
+ ret
278
+ end
279
+
280
+ def to_toc_li
281
+ "<li><a href='../chapters/#{@render_name}'><span>#{@title}</span></a></li>"
282
+ end
283
+
284
+ def to_toc_tr
285
+ ret = ""
286
+ @navpoints.each do |nav|
287
+ ret += "<tr>\n"
288
+ # Section name and number
289
+ ret += "<td class='section'>\n"
290
+ if self.mainmatter? && !@section_name.nil? && !@section_name.empty?
291
+ ret += "#{@section_name} #{@section_number}"
292
+ end
293
+ ret += "</td>\n"
294
+ # Separator
295
+ ret += "<td class='separator'>"
296
+ if self.mainmatter? && !@section_name.nil? && !@section_name.empty?
297
+ ret += " &middot; "
298
+ end
299
+ ret += "</td>\n"
300
+ # Title
301
+ ret += "<td class='title #{@the_matter}'>\n"
302
+ ret += "<a href='#{File.join('..', 'chapters', File.basename(nav['src']))}'><span>#{nav['text']}</span></a>\n"
303
+ ret += "</td>\n"
304
+ ret += "</tr>"
305
+ end
306
+ ret
307
+ end
308
+
309
+ def frontmatter?
310
+ @the_matter == 'frontmatter'
311
+ end
312
+
313
+ def mainmatter?
314
+ @the_matter == 'mainmatter'
315
+ end
316
+
317
+ def backmatter?
318
+ @the_matter == 'backmatter'
319
+ end
320
+
321
+ def self.section_name
322
+ @@section_name
323
+ end
324
+
325
+ def self.section_name=(a)
326
+ @@section_name = a
327
+ end
328
+
329
+ def self.section_number
330
+ @@section_number
331
+ end
332
+
333
+ def self.section_number=(a)
334
+ @@section_number = a
335
+ end
336
+
337
+ def self.toc_from_headers
338
+ @@toc_from_headers
339
+ end
340
+
341
+ def self.toc_from_headers=(b)
342
+ @@toc_from_headers = b
343
+ end
344
+
345
+ def self.the_matter
346
+ @@the_matter
347
+ end
348
+
349
+ def self.the_matter=(s)
350
+ @@the_matter = s
351
+ end
352
+
353
+ def to_s
354
+ [@title, @path].join(", ")
355
+ end
356
+ end
357
+
358
+ end
359
+