module Prophecy class Chapter attr_accessor :title, :id, :idref, :lang, :class, :book, :level, :layout, :src, :path, :render_name, :render_path, :href, :type, :linear, :prefix, :postfix, :insert, :section_name, :section_number, :navpoints # Array index corresponds to level, levels index from 0 too. In the # .yml you give the level: N attrib as if they were indexed from 1, # makes more sense there, but we compensate for it in the class. @@section_name = [ "Chapter", ] @@section_number = [ 0, ] @@toc_from_headers = false @@playOrder = 1 @@the_matter = 'frontmatter' def initialize(book, config) @book = book if @book.output_format == 'mobi' unless config['level'].nil? lvl = config['level'].to_i - 1 if lvl > 1 @level = 1 else @level = lvl end else @level = 0 end else if config['level'].nil? @level = 0 else @level = config['level'].to_i - 1 end end if config['the_matter'] @the_matter = config['the_matter'] @@the_matter = config['the_matter'] else @the_matter = @@the_matter end @linear = config['linear'] || nil @src = nil if config.is_a?(String) @src = config elsif config.is_a?(Hash) && config.has_key?('src') @src = config['src'] end ext_for_output = { 'epub' => '.xhtml', 'mobi' => '.xhtml', 'latex' => '.tex', 'web' => '.html' } chapters_dir_for_output = { 'epub' => File.join('OEBPS', 'chapters'), 'mobi' => File.join('OEBPS', 'chapters'), 'latex' => 'chapters', 'web' => 'chapters', } @path = nil @href = nil unless @src.nil? @render_ext = ext_for_output[book.output_format] @path = File.expand_path(File.join( book.format_dir(@src), @src)) @render_name = File.basename(@path).sub(/\.erb$/, '').sub(/\.[^\.]+$/, @render_ext) @render_path = File.expand_path( File.join( self.book.build_dir, chapters_dir_for_output[book.output_format], @render_name ) ) a = Pathname.new(self.render_path) b = Pathname.new(File.expand_path( File.join( self.book.build_dir, chapters_dir_for_output[book.output_format], '..' ) )) @href = a.relative_path_from(b) end @type = config['type'] || nil @title = config['title'] || self.first_header_text || "" @class = config['class'] || "" @class += " #{@type}" if @type @id = config['id'] || 'chapter_' + @title.downcase.gsub(/[^a-z0-9-]/, '-').gsub(/--+/, '-') @lang = config['lang'] || book.lang @prefix = config['prefix'] || nil @postfix = config['postfix'] || nil @insert = config['insert'] || nil if config['section_name'] @@section_name[@level] = config['section_name'] else end if config['section_number'] @@section_number[@level] = config['section_number'].to_i - 1 elsif @@section_number[@level].nil? @@section_number[@level] = 1 elsif !@path.nil? @@section_number[@level] += 1 end @section_name = @@section_name[@level] @section_number = @@section_number[@level] @@toc_from_headers = config['toc_from_headers'] unless config['toc_from_headers'].nil? @navpoints = [] if @path if @@toc_from_headers doc = Nokogiri::HTML(self.to_html) headers = doc.xpath("//*[name()='h1' or name()='h2' or name()='h3' or name()='h4']") headers.each do |h| # skip links ( tag) in header (possibly end- or footnote references) t = "" h.children.select{|i| i.name != 'a'}.each{|s| t += s} @navpoints << { 'text' => CGI.escapeHTML(t), 'src' => "chapters/#{@render_name}##{h.attributes['id']}", 'playOrder' => @@playOrder, 'level' => @level, } @@playOrder += 1 end else @navpoints << { 'text' => @title, 'src' => "chapters/#{@render_name}", 'playOrder' => @@playOrder, 'level' => @level, } @@playOrder += 1 end end if config['layout'].nil? @layout_path = File.join(book.layouts_dir, book.chapter_layout) elsif config['layout'] == 'nil' || config['layout'] == 'none' @layout_path = nil else @layout_path = File.join(book.layouts_dir, config['layout']) end end def idref self.book.manifest.items.select do |i| File.expand_path(i.path) == self.render_path end.first.id end def first_header_text if @path doc = Nokogiri::HTML(self.to_html) h = doc.xpath("//*[name()='h1' or name()='h2' or name()='h3' or name()='h4']").first h.text.strip if h else nil end end def to_guide_reference return "" if @type.nil? ret = " %w{chapter section subsection subsubsection paragraph subparagraph}}).to_latex when '.tex' ret = text when '.erb' template = ERB.new(text) fmt = File.extname(@path.sub(/#{format}$/, '')) ret = self.to_tex(format = fmt, text = template.result(binding)) else warn "Don't know how to render: #{@src}" raise "Error while rendering chapter" end ret end def to_spineitem ret = "#{@title}" end def to_toc_tr ret = "" @navpoints.each do |nav| ret += "\n" # Section name and number ret += "\n" if self.mainmatter? && !@section_name.nil? && !@section_name.empty? ret += "#{@section_name} #{@section_number}" end ret += "\n" # Separator ret += "" if self.mainmatter? && !@section_name.nil? && !@section_name.empty? ret += " · " end ret += "\n" # Title ret += "\n" ret += "#{nav['text']}\n" ret += "\n" ret += "" end ret end def frontmatter? @the_matter == 'frontmatter' end def mainmatter? @the_matter == 'mainmatter' end def backmatter? @the_matter == 'backmatter' end def self.section_name @@section_name end def self.section_name=(a) @@section_name = a end def self.section_number @@section_number end def self.section_number=(a) @@section_number = a end def self.toc_from_headers @@toc_from_headers end def self.toc_from_headers=(b) @@toc_from_headers = b end def self.the_matter @@the_matter end def self.the_matter=(s) @@the_matter = s end def to_s [@title, @path].join(", ") end end end