Class: Peregrin::Zhook
- Inherits:
-
Object
- Object
- Peregrin::Zhook
- Defined in:
- lib/formats/zhook.rb
Direct Known Subclasses
Defined Under Namespace
Classes: ConvertUtilityMissing, FileNotFound, IndexHTMLRootHasId, MissingCoverPNG, MissingIndexHTML, NotAZipArchive, ValidationError, WrongExtension
Constant Summary collapse
- FORMAT =
"Zhook"
- FILE_EXT =
".zhook"
- INDEX_PATH =
"index.html"
- COVER_PATH =
"cover.png"
- BODY_XPATH =
'/html/body'
- HEAD_XPATH =
'/html/head'
Class Method Summary collapse
-
.read(path) ⇒ Object
Unzips the file at path, generates a simple book object, passes to new.
-
.validate(path) ⇒ Object
Raises an exception if file at path is not a valid Zhook.
Instance Method Summary collapse
-
#initialize(book) ⇒ Zhook
constructor
Stitches together components of the internal book.
-
#to_book(options = {}) ⇒ Object
Returns the internal book object.
-
#write(path) ⇒ Object
Writes the internal book object to a .zhook file at the given path.
Constructor Details
#initialize(book) ⇒ Zhook
Stitches together components of the internal book.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/formats/zhook.rb', line 63 def initialize(book) @book = book if @book.components.length > 1 stitch_components(@book) end consolidate_properties(@book) @book.chapters = outline_book(index) @book.cover ||= ( @book.resources.detect { |r| r.src == COVER_PATH } || @book.add_resource(COVER_PATH) ) end |
Class Method Details
.read(path) ⇒ Object
Unzips the file at path, generates a simple book object, passes to new.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/formats/zhook.rb', line 41 def self.read(path) validate(path) book = Peregrin::Book.new Zip::Archive.open(path) { |zf| book.add_component(INDEX_PATH, zf.content(INDEX_PATH)) zf.each { |entry| ze = entry.name book.add_resource(ze) unless ze == INDEX_PATH || entry.directory? } } book.read_resource_proc = lambda { |resource| Zip::Archive.open(path) { |zipfile| zipfile.content(resource.src) } } extract_properties_from_index(book) new(book) end |
.validate(path) ⇒ Object
Raises an exception if file at path is not a valid Zhook. Otherwise returns true.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/formats/zhook.rb', line 14 def self.validate(path) raise FileNotFound.new(path) unless File.file?(path) raise WrongExtension.new(path) unless File.extname(path) == FILE_EXT begin zf = Zip::Archive.open(path) rescue raise NotAZipArchive.new(path) end unless zf.find(INDEX_PATH) raise MissingIndexHTML.new(path) end unless zf.find(COVER_PATH) raise MissingCoverPNG.new(path) end doc = Nokogiri::HTML::Document.parse(zf.content(INDEX_PATH), nil, 'UTF-8') raise IndexHTMLRootHasId.new(path) if doc.root['id'] ensure zf.close if zf end |
Instance Method Details
#to_book(options = {}) ⇒ Object
Returns the internal book object.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/formats/zhook.rb', line 100 def to_book( = {}) bk = @book.deep_clone # XPath => URI mapping tools cmpt_xpaths = [] boilerplate_rel_links = '<link rel="start" href="cover.html" />' + '<link rel="contents" href="toc.html" />' # Componentizing. if [:componentize] componentizer = Peregrin::Componentizer.new(index) componentizer.process(index.root.at_css('body')) bk.components = componentizer.component_xpaths.collect { |xpath| cmpt_xpaths.push(xpath) doc = componentizer.generate_component(xpath) Peregrin::Component.new(uri_for_xpath(xpath, cmpt_xpaths), doc) } # Add rel links and convert to html string boilerplate_rel_links << '<link rel="first" href="'+bk.components.first.src+'" />' + '<link rel="last" href="'+bk.components.last.src+'" />' bk.components.each_with_index { |cmpt, i| head = cmpt.contents.at_xpath(HEAD_XPATH) prev_path = bk.components[i-1].src if (i-1) >= 0 next_path = bk.components[i+1].src if (i+1) < bk.components.size head.add_child(boilerplate_rel_links) head.add_child('<link rel="prev" href="'+prev_path+'" />') if prev_path head.add_child('<link rel="next" href="'+next_path+'" />') if next_path cmpt.contents = htmlize(cmpt.contents) } else cmpt_xpaths.push(BODY_XPATH) bk.components.clear bk.add_component(uri_for_xpath(BODY_XPATH), htmlize(index)) end # Outlining. bk.chapters = outline_book(index, cmpt_xpaths) if [:componentize] # Table of Contents doc = Nokogiri::HTML::Builder.new(:encoding => 'UTF-8') { |html| curse = lambda { |children| parts = children.collect { |chp| chp.empty_leaf? ? nil : [chp.title, chp.src, chp.children] }.compact html.ol { parts.each { |part| html.li { html.a(part[0], :href => part[1]) curse.call(part[2]) if part[2].any? } } } if parts.any? } curse.call(bk.chapters) }.doc if doc.root toc_doc = componentizer.generate_document(doc.root) toc_doc.at_xpath(HEAD_XPATH).add_child(boilerplate_rel_links) bk.add_component( "toc.html", htmlize(toc_doc), nil, :linear => "no", :guide => "Table of Contents", :guide_type => "toc" ) end # List of Illustrations figures = index.css('figure[id], div.figure[id]') if figures.any? doc = Nokogiri::HTML::Builder.new(:encoding => 'UTF-8') { |html| html.ol { figures.each { |fig| next unless = fig.at_css('figcaption, .figcaption') n = fig while n && n.respond_to?(:parent) break if cmpt_uri = uri_for_xpath(n.path, cmpt_xpaths) n = n.parent end next unless cmpt_uri html.li { html.a(.content, :href => "#{cmpt_uri}##{fig['id']}") } } } }.doc loi_doc = componentizer.generate_document(doc.root) loi_doc.at_xpath(HEAD_XPATH).add_child(boilerplate_rel_links) bk.add_component( "loi.html", htmlize(loi_doc), nil, :linear => "no", :guide => "List of Illustrations", :guide_type => "loi" ) end # Cover doc = Nokogiri::HTML::Builder.new(:encoding => 'UTF-8') { |html| html.div(:id => "cover") { html.img(:src => bk.cover.src, :alt => bk.property_for("title")) } }.doc cover_doc = componentizer.generate_document(doc.root) cover_doc.at_xpath(HEAD_XPATH).add_child(boilerplate_rel_links) bk.components.unshift( Peregrin::Component.new( "cover.html", htmlize(cover_doc), nil, :linear => "no", :guide => "Cover", :guide_type => "cover" ) ) end bk end |
#write(path) ⇒ Object
Writes the internal book object to a .zhook file at the given path.
83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/formats/zhook.rb', line 83 def write(path) File.unlink(path) if File.exists?(path) Zip::Archive.open(path, Zip::CREATE) { |zipfile| zipfile.add_buffer(INDEX_PATH, htmlize(index)) @book.resources.each { |resource| zipfile.add_buffer(resource.src, @book.read_resource(resource)) } unless @book.cover.src == COVER_PATH zipfile.add_buffer(COVER_PATH, to_png_data(@book.cover)) end } path end |