kindlerb 1.0.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
- doc_uuid:
2
- title:
3
- author:
4
- publisher:
5
- subject: News
6
- date: 2012-01-04
7
-
1
+ doc_uuid:
2
+ title:
3
+ author:
4
+ publisher:
5
+ subject: News
6
+ date: 2012-01-04
7
+
@@ -1,6 +1,6 @@
1
- #!/usr/bin/env ruby
2
- require 'kindlerb'
3
-
4
- Kindlerb.download
5
-
1
+ #!/usr/bin/env ruby
2
+ require 'kindlerb'
3
+
4
+ Kindlerb.download
5
+
6
6
  puts "Kindlerb is successfully set up!"
@@ -1,25 +1,26 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
-
4
- Gem::Specification.new do |s|
5
- s.name = "kindlerb"
6
- s.version = '1.0.1'
7
- s.platform = Gem::Platform::RUBY
8
- s.required_ruby_version = '>= 2.0.0'
9
-
10
- s.authors = ["Daniel Choi", "Emir Aydin"]
11
- s.email = ["dhchoi@gmail.com", "emir@emiraydin.com"]
12
- s.homepage = "http://github.com/danchoi/kindlerb"
13
- s.summary = %q{Kindle eperiodical generator}
14
- s.description = %q{Kindle eperiodical generator}
15
-
16
- s.rubyforge_project = "kindlerb"
17
-
18
- s.files = `git ls-files`.split("\n")
19
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
- s.require_paths = ["lib"]
22
-
23
- s.add_dependency 'nokogiri'
24
- s.add_dependency 'mustache'
25
- end
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'kindlerb/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "kindlerb"
7
+ s.version = Kindlerb::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.required_ruby_version = '>= 2.0.0'
10
+
11
+ s.authors = ["Daniel Choi", "Emir Aydin"]
12
+ s.email = ["dhchoi@gmail.com", "emir@emiraydin.com"]
13
+ s.homepage = "http://github.com/danchoi/kindlerb"
14
+ s.summary = %q{Kindle eperiodical generator}
15
+ s.description = %q{Kindle eperiodical generator}
16
+
17
+ s.rubyforge_project = "kindlerb"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_dependency 'nokogiri'
25
+ s.add_dependency 'mustache'
26
+ end
@@ -1,232 +1,262 @@
1
- # encoding: utf-8
2
-
3
- # extract nav structure
4
-
5
- require 'pathname'
6
- require 'yaml'
7
- require 'nokogiri'
8
- require 'mustache'
9
- require 'fileutils'
10
-
11
- # monkeypatch
12
- class String
13
- def shorten(max)
14
- length > max ? Array(self[0,max].split(/\s+/)[0..-2]).join(' ') + '...' : self
15
- end
16
- end
17
-
18
- module Kindlerb
19
-
20
- def self.download
21
-
22
- gem_path = Gem::Specification.find_by_name('kindlerb').gem_dir
23
- ext_dir = gem_path + '/ext/'
24
- bin_dir = gem_path + '/bin/'
25
-
26
- # Define Kindlegen download files for different OS's
27
- executable = 'kindlegen'
28
- windows = false
29
- compressed_file = case RbConfig::CONFIG['host_os']
30
- when /mac|darwin/i
31
- extract = 'unzip '
32
- "KindleGen_Mac_i386_v2_9.zip"
33
- when /linux|cygwin/i
34
- extract = 'tar zxf '
35
- "kindlegen_linux_2.6_i386_v2_9.tar.gz"
36
- when /mingw32/i
37
- windows = true
38
- extract = 'unzip '
39
- executable = 'kindlegen.exe'
40
- "kindlegen_win32_v2_9.zip"
41
- else
42
- STDERR.puts "Host OS is not supported!"
43
- exit(1)
44
- end
45
-
46
- url = 'http://kindlegen.s3.amazonaws.com/' + compressed_file
47
-
48
- # Download and extract the Kindlegen file into gem's /etc folder
49
- unless File.directory?(ext_dir)
50
- FileUtils.mkdir_p(ext_dir)
51
- end
52
- system 'curl ' + url + ' -o ' + ext_dir + compressed_file
53
- puts "Kindlegen downloaded: " + ext_dir + compressed_file
54
- FileUtils.cd(ext_dir)
55
- system extract + compressed_file
56
-
57
- # Move the executable into gem's /bin folder
58
- unless File.directory?(bin_dir)
59
- FileUtils.mkdir_p(bin_dir)
60
- end
61
- moved = FileUtils.mv(ext_dir + executable, bin_dir)
62
- puts "Kindlegen extracted to: " + bin_dir
63
- # Clean up ext folder
64
- if moved
65
- FileUtils.rm_rf(ext_dir)
66
- end
67
-
68
- # Give exec permissions to Kindlegen file
69
- exec_file = bin_dir + executable
70
- if windows
71
- cmd = "icacls #{exec_file} /T /C /grant Everyone:(f)"
72
- system cmd
73
- else
74
- FileUtils.chmod 0754, exec_file
75
- end
76
- puts "Execution permissions granted to the user for Kindlegen executable"
77
-
78
- end
79
-
80
- # Returns the full path to executable Kindlegen file
81
- def self.executable
82
-
83
- gem_path = Gem::Specification.find_by_name('kindlerb').gem_dir
84
-
85
- # Different extensions based on OS
86
- kindlegen = case RbConfig::CONFIG['host_os']
87
- when /mac|darwin/i
88
- "kindlegen"
89
- when /linux|cygwin/i
90
- "kindlegen"
91
- when /mingw32/i
92
- "kindlegen.exe"
93
- else
94
- STDERR.puts "Kindlegen is not installed because host OS is not supported!"
95
- exit(1)
96
- end
97
-
98
- exec_path = gem_path + '/bin/' + kindlegen
99
-
100
- return exec_path
101
-
102
- end
103
-
104
- def self.run(target_dir, verbose = false, compression_method = 'c2')
105
-
106
- opf_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/opf.mustache"))
107
- ncx_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/ncx.mustache"))
108
- contents_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/contents.mustache"))
109
- section_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/section.mustache"))
110
- masthead_gif = File.join(File.dirname(__FILE__), '..', "templates/masthead.gif")
111
- cover_gif = File.join(File.dirname(__FILE__), '..', "templates/cover-image.gif")
112
-
113
- Dir.chdir target_dir do
114
- playorder = 1
115
-
116
- images = []
117
- manifest_items = []
118
-
119
- unless File.exist?("_document.yml")
120
-
121
- puts "Usage: kindlerb [target file directory]"
122
-
123
- abort "Missing _document.yml. Your input file tree is not structured correctly. Please read the README."
124
- end
125
-
126
- document = YAML::load_file("_document.yml")
127
-
128
- document[:spine_items] = []
129
- section_html_files = []
130
-
131
- sections = Dir['sections/*'].entries.sort.map.with_index {|section_dir|
132
- c = File.read(Pathname.new(section_dir) + '_section.txt')
133
- c.force_encoding("UTF-8")
134
- section_title = c.strip
135
- articles = Dir[Pathname.new(section_dir) + '*'].entries.select {|x| File.basename(x) !~ /section/}.sort
136
- section_html_files << (section_html_file = (Pathname.new(section_dir) + 'section.html').to_s)
137
- idref = "item-#{section_dir.gsub(/\D/, '')}"
138
-
139
- document[:spine_items] << {:idref => idref}
140
- manifest_items << {
141
- :href => section_html_file,
142
- :media => "application/xhtml+xml",
143
- :idref => idref
144
- }
145
-
146
- s = {
147
- :path => section_dir,
148
- :title => section_title.shorten(40),
149
- :playorder => (playorder += 1),
150
- :idref => idref,
151
- :href => Pathname.new(section_dir) + 'section.html',
152
- :articles => articles.map {|article_file|
153
- doc = Nokogiri::HTML(File.read(article_file, :encoding => 'UTF-8'))
154
- article_images = doc.search("img").map {|img|
155
- mimetype = img[:src] ? "image/#{File.extname(img[:src]).sub('.', '')}" : nil
156
- {:href => img[:src], :mimetype => mimetype}
157
- }
158
- images.push *article_images
159
- title = doc.search("html/head/title").map(&:inner_text).first || "no title"
160
- idref = "item-#{article_file.gsub(/\D/, '')}"
161
- document[:spine_items] << {:idref => idref}
162
- article = {
163
- :file => article_file,
164
- :href => article_file,
165
- :title => title,
166
- :short_title => title.shorten(60),
167
- :author => doc.search("html/head/meta[@name=author]").map{|n|n[:content]}.first,
168
- :description => doc.search("html/head/meta[@name=description]").map{|n|n[:content]}.first,
169
- :playorder => (playorder += 1),
170
- :idref => idref
171
- }
172
- manifest_items << {
173
- :href => article[:file],
174
- :media => "application/xhtml+xml",
175
- :idref => article[:idref]
176
- }
177
- article
178
- }
179
- }
180
-
181
- # Generate the section html
182
- out = Mustache.render section_template, s
183
- File.open(section_html_file, "w") {|f| f.puts out}
184
- s
185
-
186
- }
187
-
188
- document[:first_article] = sections[0][:articles][0]
189
- document['sections'] = sections
190
-
191
-
192
- document[:manifest_items] = manifest_items + images.map.with_index {|img, idx|
193
- {
194
- :href => img[:href],
195
- :media => img[:mimetype],
196
- :idref => "img-%03d" % idx
197
- }
198
- }
199
- document[:cover_mimetype] ||= "image/gif"
200
-
201
- opf = Mustache.render opf_template, document
202
- File.open("kindlerb.opf", "w") {|f| f.puts opf}
203
- puts "Wrote #{target_dir}/kindlerb.opf"
204
-
205
- # NCX
206
- ncx = Mustache.render ncx_template, document
207
- File.open("nav-contents.ncx", "w") {|f| f.puts ncx}
208
- puts "Wrote #{target_dir}/nav-contents.ncx"
209
-
210
- # contents
211
- contents = Mustache.render contents_template, document
212
- File.open("contents.html", "w") {|f| f.puts contents}
213
- puts "Wrote #{target_dir}/contents.html"
214
-
215
- outfile = document['mobi_outfile']
216
- puts "Writing #{outfile}"
217
- cmd = self.executable + "#{' -verbose' if verbose} -#{compression_method} -o #{outfile} kindlerb.opf && echo 'Wrote MOBI to #{outfile}'"
218
- puts cmd
219
- system cmd
220
-
221
- # If the system call returns anything other than nil, the call was successful
222
- # Because Kindlegen completes build successfully with warnings
223
- successful = $?.exitstatus.nil? ? false : true
224
- if successful
225
- return true
226
- else
227
- return false
228
- end
229
-
230
- end
231
- end
232
- end
1
+ # encoding: utf-8
2
+
3
+ # extract nav structure
4
+
5
+ require 'pathname'
6
+ require 'yaml'
7
+ require 'nokogiri'
8
+ require 'mustache'
9
+ require 'fileutils'
10
+ require 'kindlerb/version'
11
+
12
+ # monkeypatch
13
+ class String
14
+ def shorten(max)
15
+ length > max ? Array(self[0,max].split(/\s+/)[0..-2]).join(' ') + '...' : self
16
+ end
17
+ end
18
+
19
+ module Kindlerb
20
+
21
+ def self.download
22
+ # use system kindlegen if available
23
+ if system('kindlegen', out: :close)
24
+ puts "Using system kindlegen"
25
+ return
26
+ end
27
+
28
+ gem_path = Gem::Specification.find_by_name('kindlerb').gem_dir
29
+ ext_dir = gem_path + '/ext/'
30
+ bin_dir = gem_path + '/bin/'
31
+
32
+ # Define Kindlegen download files for different OS's
33
+ executable_filename = 'kindlegen'
34
+ windows = false
35
+ compressed_file = case RbConfig::CONFIG['host_os']
36
+ when /mac|darwin/i
37
+ extract = 'unzip '
38
+ "KindleGen_Mac_i386_v2_9.zip"
39
+ when /linux|cygwin/i
40
+ extract = 'tar zxf '
41
+ "kindlegen_linux_2.6_i386_v2_9.tar.gz"
42
+ when /mingw32/i
43
+ windows = true
44
+ extract = 'unzip '
45
+ executable_filename = 'kindlegen.exe'
46
+ "kindlegen_win32_v2_9.zip"
47
+ else
48
+ STDERR.puts "Host OS is not supported!"
49
+ exit(1)
50
+ end
51
+
52
+ url = 'http://kindlegen.s3.amazonaws.com/' + compressed_file
53
+
54
+ # Download and extract the Kindlegen file into gem's /etc folder
55
+ unless File.directory?(ext_dir)
56
+ FileUtils.mkdir_p(ext_dir)
57
+ end
58
+ system 'curl ' + url + ' -o ' + ext_dir + compressed_file
59
+ puts "Kindlegen downloaded: " + ext_dir + compressed_file
60
+ system extract + ext_dir + compressed_file + ' -d ' + ext_dir
61
+
62
+ # Move the executable_filename into gem's /bin folder
63
+ unless File.directory?(bin_dir)
64
+ FileUtils.mkdir_p(bin_dir)
65
+ end
66
+ moved = FileUtils.mv(ext_dir + executable_filename, bin_dir)
67
+ puts "Kindlegen extracted to: " + bin_dir
68
+ # Clean up ext folder
69
+ if moved
70
+ FileUtils.rm_rf(ext_dir)
71
+ end
72
+
73
+ # Give exec permissions to Kindlegen file
74
+ exec_file = bin_dir + executable_filename
75
+ if windows
76
+ cmd = "icacls #{exec_file} /T /C /grant Everyone:(f)"
77
+ system cmd
78
+ else
79
+ FileUtils.chmod 0754, exec_file
80
+ end
81
+ puts "Execution permissions granted to the user for Kindlegen executable"
82
+
83
+ end
84
+
85
+ # Returns the full path to executable Kindlegen file
86
+ def self.executable
87
+ # use system kindlegen if available
88
+ return 'kindlegen' if system('kindlegen', out: :close)
89
+
90
+ gem_path = Gem::Specification.find_by_name('kindlerb').gem_dir
91
+
92
+ # Different extensions based on OS
93
+ kindlegen = case RbConfig::CONFIG['host_os']
94
+ when /mac|darwin/i
95
+ "kindlegen"
96
+ when /linux|cygwin/i
97
+ "kindlegen"
98
+ when /mingw32/i
99
+ "kindlegen.exe"
100
+ else
101
+ return nil
102
+ end
103
+
104
+ exec_path = gem_path + '/bin/' + kindlegen
105
+
106
+ return exec_path
107
+
108
+ end
109
+
110
+ # Used for users to check whether Kindlerb can work
111
+ def self.kindlegen_available?
112
+ kindlegen = self.executable
113
+ case kindlegen
114
+ when 'kindlegen'
115
+ true
116
+ when String
117
+ File.exist?(kindlegen)
118
+ else
119
+ false
120
+ end
121
+ end
122
+
123
+ def self.run(target_dir, verbose = false, compression_method = 'c2')
124
+ unless self.kindlegen_available?
125
+ STDERR.puts "Kindlegen is not available, install it with `setupkindlerb`"
126
+ exit(1)
127
+ end
128
+
129
+ opf_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/opf.mustache"))
130
+ ncx_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/ncx.mustache"))
131
+ contents_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/contents.mustache"))
132
+ section_template = File.read(File.join(File.dirname(__FILE__), '..', "templates/section.mustache"))
133
+ masthead_gif = File.join(File.dirname(__FILE__), '..', "templates/masthead.gif")
134
+ cover_gif = File.join(File.dirname(__FILE__), '..', "templates/cover-image.gif")
135
+
136
+ playorder = 1
137
+
138
+ images = []
139
+ manifest_items = []
140
+
141
+ base_dir = Pathname.new target_dir
142
+ document_yml = base_dir.join "_document.yml"
143
+
144
+ unless File.exist? document_yml
145
+
146
+ puts "Usage: kindlerb [target file directory]"
147
+
148
+ abort "Missing _document.yml. Your input file tree is not structured correctly. Please read the README."
149
+ end
150
+
151
+ document = YAML::load_file document_yml
152
+
153
+ document[:spine_items] = []
154
+ section_html_files = []
155
+
156
+ sections_all = base_dir.join "sections", "*"
157
+
158
+ sections = Dir[sections_all].entries.sort.map.with_index {|section_dir|
159
+ c = File.read(Pathname.new(section_dir) + '_section.txt')
160
+ c.force_encoding("UTF-8")
161
+ section_title = c.strip
162
+ articles = Dir[Pathname.new(section_dir) + '*'].entries.select {|x| File.basename(x) !~ /section/}.sort
163
+ section_html_files << (section_html_file = (Pathname.new(section_dir) + 'section.html').to_s)
164
+ idref = "item-#{section_dir.gsub(/\D/, '')}"
165
+
166
+ document[:spine_items] << {:idref => idref}
167
+ manifest_items << {
168
+ :href => section_html_file,
169
+ :media => "application/xhtml+xml",
170
+ :idref => idref
171
+ }
172
+
173
+ s = {
174
+ :path => section_dir,
175
+ :title => section_title.shorten(40),
176
+ :playorder => (playorder += 1),
177
+ :idref => idref,
178
+ :href => Pathname.new(section_dir) + 'section.html',
179
+ :articles => articles.map {|article_file|
180
+ doc = Nokogiri::HTML(File.read(article_file, :encoding => 'UTF-8'))
181
+ article_images = doc.search("img").map {|img|
182
+ mimetype = img[:src] ? "image/#{File.extname(img[:src]).sub('.', '')}" : nil
183
+ {:href => img[:src], :mimetype => mimetype}
184
+ }
185
+ images.push *article_images
186
+ title = doc.search("html/head/title").map(&:inner_text).first || "no title"
187
+ idref = "item-#{article_file.gsub(/\D/, '')}"
188
+ document[:spine_items] << {:idref => idref}
189
+ article = {
190
+ :file => article_file,
191
+ :href => article_file,
192
+ :title => title,
193
+ :short_title => title.shorten(60),
194
+ :author => doc.search("html/head/meta[@name=author]").map{|n|n[:content]}.first,
195
+ :description => doc.search("html/head/meta[@name=description]").map{|n|n[:content]}.first,
196
+ :playorder => (playorder += 1),
197
+ :idref => idref
198
+ }
199
+ manifest_items << {
200
+ :href => article[:file],
201
+ :media => "application/xhtml+xml",
202
+ :idref => article[:idref]
203
+ }
204
+ article
205
+ }
206
+ }
207
+
208
+ # Generate the section html
209
+ out = Mustache.render section_template, s
210
+ File.open(section_html_file, "w") {|f| f.puts out}
211
+ s
212
+
213
+ }
214
+
215
+ document[:first_article] = sections[0][:articles][0]
216
+ document['sections'] = sections
217
+
218
+
219
+ document[:manifest_items] = manifest_items + images.map.with_index {|img, idx|
220
+ {
221
+ :href => img[:href],
222
+ :media => img[:mimetype],
223
+ :idref => "img-%03d" % idx
224
+ }
225
+ }
226
+ document[:cover_mimetype] ||= "image/gif"
227
+
228
+ opf = Mustache.render opf_template, document
229
+ opf_path = base_dir.join "kindlerb.opf"
230
+ File.open(opf_path, "w") {|f| f.puts opf}
231
+ puts "Wrote #{target_dir}/kindlerb.opf"
232
+
233
+ # NCX
234
+ ncx = Mustache.render ncx_template, document
235
+ ncx_path = base_dir.join "nav-contents.ncx"
236
+ File.open(ncx_path, "w") {|f| f.puts ncx}
237
+ puts "Wrote #{target_dir}/nav-contents.ncx"
238
+
239
+ # contents
240
+ contents = Mustache.render contents_template, document
241
+ contents_path = base_dir.join "contents.html"
242
+ File.open(contents_path, "w") {|f| f.puts contents}
243
+ puts "Wrote #{target_dir}/contents.html"
244
+
245
+ outfile = document['mobi_outfile']
246
+ infile = base_dir.join "kindlerb.opf"
247
+ puts "Writing #{outfile}"
248
+ cmd = self.executable + "#{' -verbose' if verbose} -#{compression_method} -o #{outfile} #{infile} && echo 'Wrote MOBI to #{outfile}'"
249
+ puts cmd
250
+ system cmd
251
+
252
+ # If the system call returns anything other than nil, the call was successful
253
+ # Because Kindlegen completes build successfully with warnings
254
+ successful = $?.exitstatus.nil? ? false : true
255
+ if successful
256
+ return true
257
+ else
258
+ return false
259
+ end
260
+
261
+ end
262
+ end