kindler 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/Readme.md +17 -6
- data/features/basic.feature +0 -0
- data/features/dsl.feature +8 -0
- data/features/step_definitions/basic_step.rb +0 -0
- data/features/step_definitions/dsl_step.rb +0 -0
- data/lib/kindler/railtie.rb +1 -1
- data/lib/kindler/version.rb +1 -1
- data/lib/kindler.rb +303 -299
- data/spec/cases/generator_spec.rb +93 -55
- data/spec/spec_helper.rb +15 -0
- metadata +12 -4
data/Gemfile
CHANGED
data/Readme.md
CHANGED
@@ -1,9 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#### 2.that's all
|
1
|
+
## Todo
|
2
|
+
* support inner reference, inner link can take to that article
|
4
3
|
|
4
|
+
## Is this gem is what you want?
|
5
|
+
There is a alternative gem called [kindlerb](https://github.com/danchoi/kindlerb) can generate mobi books, the gem is also used
|
6
|
+
for the website [KindleFeeder](http://kindlefeeder.com/) which is build by [Daniel Choi](http://danielchoi.com/software).
|
5
7
|
|
6
|
-
|
8
|
+
If you like to generate mobi book by some html files, you have to conform to the structure which author provide. But if you just
|
9
|
+
want to generate mobi book in the fly, then you should try this gem.
|
10
|
+
|
11
|
+
BTW, we share the same internal way to generating mobi book by [KindleGen 2](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000234621).
|
12
|
+
|
13
|
+
## Prerequisite
|
14
|
+
### 1.kindlegen execute file from amazon
|
15
|
+
### 2.that's all
|
16
|
+
|
17
|
+
## Installation
|
7
18
|
```ruby
|
8
19
|
gem 'kindler'
|
9
20
|
```
|
@@ -13,10 +24,10 @@ or
|
|
13
24
|
```ruby
|
14
25
|
gem 'kindler',:git=>'git@github.com:29decibel/kindler.git'
|
15
26
|
```
|
16
|
-
|
27
|
+
## A kindle mobi book generator
|
17
28
|
which receive a couple of urls then output one mobi file
|
18
29
|
|
19
|
-
|
30
|
+
## Usage
|
20
31
|
```ruby
|
21
32
|
title = 'my_first_mobi_book'
|
22
33
|
book = Kindler::Book.new :title=>title,:author=>'mike'
|
File without changes
|
File without changes
|
File without changes
|
data/lib/kindler/railtie.rb
CHANGED
data/lib/kindler/version.rb
CHANGED
data/lib/kindler.rb
CHANGED
@@ -8,330 +8,334 @@ require_relative 'kindler/railtie' if defined?(Rails)
|
|
8
8
|
require_relative "kindler/version"
|
9
9
|
|
10
10
|
module Kindler
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
class Book
|
12
|
+
class KindlerError < StandardError;end
|
13
|
+
attr_accessor :title,:author,:pages,:pages_by_section,:local_images,:mobi_type
|
14
|
+
TMP_DIR = 'kindler_generated_mobi'
|
15
|
+
DEFAULT_SECTION = "All Pages"
|
16
|
+
PAGE_ATTRIBUTES = %w(wrap title author content section)
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
18
|
+
# availabel options
|
19
|
+
# @param options [Hash]
|
20
|
+
# @option title [String] book title
|
21
|
+
# @option output_dir [String] directory want to generate
|
22
|
+
# @option debug [Boolean] whether puts debug infos
|
23
|
+
# @option keep_image [Boolean] whether keep images, default to true
|
24
|
+
def initialize(options={})
|
25
|
+
@output_dir = options[:output_dir] || './'
|
26
|
+
@keep_image = options[:keep_image] || true
|
27
|
+
@debug = options[:debug]
|
28
|
+
@title = options[:title] || ''
|
29
|
+
@author = options[:author] || 'unknown'
|
30
|
+
@mobi_type = options[:mobi_type] || :magzine
|
31
|
+
@pages = []
|
32
|
+
@local_images = []
|
33
|
+
@pages_by_section = {}
|
34
|
+
raise KindlerError.new("must provide the book title ") unless title
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
37
|
+
def add_page(options={})
|
38
|
+
raise KindlerError.new('must provide title when add page') unless options[:title]
|
39
|
+
page = options.reject{|k,v| PAGE_ATTRIBUTES.include?(k)}
|
40
|
+
page[:wrap] ||= true
|
41
|
+
page[:section] ||= DEFAULT_SECTION
|
42
|
+
page[:count] = pages.count + 1
|
43
|
+
page[:file_name] = "#{page[:count].to_s.rjust(3,'0')}.html"
|
44
|
+
page[:author] = 'unknown' if (page[:author]==nil or page[:author]=='')
|
45
|
+
# escape special chars
|
46
|
+
page[:title] = CGI::escapeHTML(page[:title])
|
47
|
+
page[:author] = CGI::escapeHTML(page[:author])
|
48
|
+
pages << page
|
49
|
+
debug pages
|
50
|
+
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
52
|
+
def generate
|
53
|
+
make_generated_dirs
|
54
|
+
localize_images if @keep_image
|
55
|
+
# reorder count index
|
56
|
+
if magzine?
|
57
|
+
sectionize_pages
|
58
|
+
end
|
59
|
+
generate_toc
|
60
|
+
generate_opf
|
61
|
+
generate_ncx
|
62
|
+
write_to_disk
|
63
|
+
kindlegen
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
66
|
+
def sectionize_pages
|
67
|
+
self.pages.each do |page|
|
68
|
+
pages_by_section[page[:section]] ||= []
|
69
|
+
pages_by_section[page[:section]] << page
|
70
|
+
end
|
71
|
+
self.pages = pages_by_section.values.flatten
|
72
|
+
self.pages.each_with_index do |page,index|
|
73
|
+
page[:count] = index + 1
|
74
|
+
page[:file_name] = "#{page[:count].to_s.rjust(3,'0')}.html"
|
75
|
+
end
|
76
|
+
end
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
# check mobi file is generated already
|
79
|
+
def generated?
|
80
|
+
File.exist? "#{tmp_dir}/#{valid_title}.mobi"
|
81
|
+
end
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
83
|
+
private
|
84
|
+
# make sure kindlegen is installed
|
85
|
+
# you can use "sudo brew install " to install it
|
86
|
+
def kindlegen
|
87
|
+
debug 'begin generate mobi'
|
88
|
+
system("kindlegen #{tmp_dir}/#{valid_title}.opf ")
|
89
|
+
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
91
|
+
# generate contents.html
|
92
|
+
def generate_toc
|
93
|
+
contents = <<-CODE
|
94
|
+
<html>
|
95
|
+
<head>
|
96
|
+
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
|
97
|
+
<title>Table of Contents</title>
|
98
|
+
</head>
|
99
|
+
<body>
|
100
|
+
<h1>Contents</h1>
|
101
|
+
<h4>Main section</h4>
|
102
|
+
<ul>
|
103
|
+
CODE
|
104
|
+
files_count = 1
|
105
|
+
pages.each do |page|
|
106
|
+
contents << "<li><a href='#{files_count.to_s.rjust(3,'0')}.html'>#{page[:title]}</a></li>"
|
107
|
+
files_count += 1
|
108
|
+
end
|
109
|
+
# append footer
|
110
|
+
contents << "</ul></body></html>"
|
111
111
|
|
112
|
-
|
113
|
-
|
112
|
+
@toc = contents
|
113
|
+
end
|
114
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
|
-
|
115
|
+
# generate ncx , which is navigation
|
116
|
+
def generate_ncx
|
117
|
+
contents = <<-NCX
|
118
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
119
|
+
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
|
120
|
+
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="en-US">
|
121
|
+
<head>
|
122
|
+
<meta name="dtb:uid" content="#{title}"/>
|
123
|
+
<meta name="dtb:depth" content="1"/>
|
124
|
+
<meta name="dtb:totalPageCount" content="0"/>
|
125
|
+
<meta name="dtb:maxPageNumber" content="0"/>
|
126
|
+
</head>
|
127
|
+
<docTitle>
|
128
|
+
<text>#{title}</text>
|
129
|
+
</docTitle>
|
130
|
+
<docAuthor>
|
131
|
+
<text>#{author}</text>
|
132
|
+
</docAuthor>
|
133
|
+
<navMap>
|
134
|
+
NCX
|
135
|
+
contents << (magzine? ? magzine_ncx : flat_ncx)
|
136
|
+
contents << "</navMap></ncx>"
|
137
|
+
@ncx = contents
|
138
|
+
end
|
139
139
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
140
|
+
def flat_ncx
|
141
|
+
contents = ''
|
142
|
+
files_count = 2
|
143
|
+
pages.each do |page|
|
144
|
+
nav_point = <<-NAV
|
145
|
+
<navPoint id="navpoint-#{files_count}" playOrder="#{files_count}">
|
146
|
+
<navLabel><text>#{page[:title]}</text></navLabel>
|
147
|
+
<content src="#{(files_count-1).to_s.rjust(3,'0')}.html"/>
|
148
|
+
</navPoint>
|
149
|
+
NAV
|
150
|
+
contents << nav_point
|
151
|
+
files_count += 1
|
152
|
+
end
|
153
|
+
contents
|
154
|
+
end
|
155
155
|
|
156
|
-
|
157
|
-
|
156
|
+
def magzine_ncx
|
157
|
+
contents = ''
|
158
158
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
159
|
+
contents << <<-MAG
|
160
|
+
<navPoint playOrder="0" class="periodical" id="periodical">
|
161
|
+
<navLabel>
|
162
|
+
<text>Table of Contents</text>
|
163
|
+
</navLabel>
|
164
|
+
<content src="contents.html"/>
|
165
165
|
|
166
|
-
|
166
|
+
MAG
|
167
167
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
168
|
+
play_order = 1
|
169
|
+
@pages_by_section.each do |section,pages|
|
170
|
+
next if pages.count==0
|
171
|
+
# add section header
|
172
|
+
contents << <<-SECHEADER
|
173
|
+
<navPoint playOrder="#{play_order}" class="section" id="#{section}">
|
174
|
+
<navLabel>
|
175
|
+
<text>#{section}</text>
|
176
|
+
</navLabel>
|
177
|
+
<content src="#{pages.first[:file_name]}"/>
|
178
|
+
SECHEADER
|
179
179
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
180
|
+
play_order += 1
|
181
|
+
# add pages nav
|
182
|
+
pages.each do |page|
|
183
|
+
contents << <<-PAGE
|
184
|
+
<navPoint playOrder="#{play_order}" class="article" id="item-#{page[:count].to_s.rjust(3,'0')}">
|
185
|
+
<navLabel>
|
186
|
+
<text>#{page[:title]}</text>
|
187
|
+
</navLabel>
|
188
|
+
<content src="#{page[:file_name]}"/>
|
189
|
+
<mbp:meta name="description">#{page[:title]}</mbp:meta>
|
190
|
+
<mbp:meta name="author">#{page[:author]}</mbp:meta>
|
191
|
+
</navPoint>
|
192
|
+
PAGE
|
193
|
+
play_order += 1
|
194
|
+
end
|
195
|
+
# add section footer
|
196
|
+
contents << "</navPoint>"
|
197
|
+
end
|
198
|
+
contents << "</navPoint>"
|
199
|
+
end
|
200
200
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
201
|
+
def magzine_meta
|
202
|
+
<<-META
|
203
|
+
<x-metadata>
|
204
|
+
<output content-type="application/x-mobipocket-subscription-magazine" encoding="utf-8"/>
|
205
|
+
</x-metadata>
|
206
|
+
META
|
207
|
+
end
|
208
208
|
|
209
|
-
|
210
|
-
|
211
|
-
|
209
|
+
def magzine?
|
210
|
+
@mobi_type == :magzine
|
211
|
+
end
|
212
212
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
213
|
+
# generate the opf, manifest of book,including all articles and images and css
|
214
|
+
def generate_opf
|
215
|
+
contents = <<-HTML
|
216
|
+
<?xml version='1.0' encoding='utf-8'?>
|
217
|
+
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="#{title}">
|
218
|
+
<metadata>
|
219
|
+
<dc-metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
|
220
|
+
<dc:title>#{title}</dc:title>
|
221
|
+
<dc:language>en-gb</dc:language>
|
222
|
+
<meta content="cover-image" name="cover"/>
|
223
|
+
<dc:creator>Kindler- 29decibel</dc:creator>
|
224
|
+
<dc:publisher>Kindler- 29decibel</dc:publisher>
|
225
|
+
<dc:subject>News</dc:subject>
|
226
|
+
<dc:identifier id="#{title}">#{title}</dc:identifier>
|
227
|
+
<dc:date>#{Time.now.to_date}</dc:date>
|
228
|
+
<dc:description>Kindler generated book</dc:description>
|
229
|
+
</dc-metadata>
|
230
|
+
#{magzine? ? magzine_meta : ''}
|
231
|
+
</metadata>
|
232
|
+
<manifest>
|
233
|
+
HTML
|
234
|
+
files_count = 1
|
235
|
+
pages.each do |page|
|
236
|
+
doc_id = files_count.to_s.rjust(3,'0')
|
237
|
+
contents << "<item href='#{doc_id}.html' media-type='application/xhtml+xml' id='#{doc_id}'/>"
|
238
|
+
files_count += 1
|
239
|
+
end
|
240
|
+
contents << "<item href='contents.html' media-type='application/xhtml+xml' id='contents'/>"
|
241
|
+
contents << "<item href='nav-contents.ncx' media-type='application/x-dtbncx+xml' id='nav-contents'/>"
|
242
|
+
contents << "</manifest>"
|
243
|
+
contents << "<spine toc='nav-contents'>"
|
244
|
+
contents << "<itemref idref='contents'/>"
|
245
|
+
files_count = 1
|
246
|
+
pages.each do |page|
|
247
|
+
contents << "<itemref idref='#{files_count.to_s.rjust(3,'0')}'/>"
|
248
|
+
files_count += 1
|
249
|
+
end
|
250
|
+
contents << "</spine><guide><reference href='contents.html' type='toc' title='Table of Contents'/></guide></package>"
|
251
|
+
@opf = contents
|
252
|
+
end
|
253
253
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
254
|
+
def localize_images
|
255
|
+
images_count = 1
|
256
|
+
pages.each do |page|
|
257
|
+
article = Nokogiri::HTML(page[:content])
|
258
|
+
article.css('img').each do |img|
|
259
|
+
begin
|
260
|
+
image_remote_address = img.attr('src')
|
261
|
+
unless image_remote_address.start_with?('http')
|
262
|
+
image_remote_address = "http://#{URI(url).host}#{image_remote_address}"
|
263
|
+
end
|
264
|
+
image_local_address = File.join(tmp_dir,"#{images_count}#{File.extname(image_remote_address)}")
|
265
|
+
# download images
|
266
|
+
debug "begin fetch image #{image_remote_address}"
|
267
|
+
debug "save to #{image_local_address}"
|
268
|
+
File.open(image_local_address,'wb') do |f|
|
269
|
+
f.write open(image_remote_address).read
|
270
|
+
end
|
271
|
+
debug 'Image saved'
|
272
|
+
# replace local url address
|
273
|
+
img.attributes['src'].value = "#{images_count}#{File.extname(image_remote_address)}"
|
274
|
+
page[:content] = article.inner_html
|
275
|
+
# add to manifest
|
276
|
+
local_images << "#{images_count}#{File.extname(image_remote_address)}"
|
277
|
+
images_count += 1
|
278
|
+
rescue Exception => e
|
279
|
+
debug "got error when fetch and save image: #{e}"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
284
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
285
|
+
# html file path
|
286
|
+
def file_path(file_name)
|
287
|
+
"#{tmp_dir}/#{file_name}"
|
288
|
+
end
|
289
289
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
290
|
+
# wrap readable contents with in html format
|
291
|
+
def html_wrap(title,content)
|
292
|
+
result = ''
|
293
|
+
result << '<html><head>'
|
294
|
+
result << "<meta content='text/html; charset=utf-8' http-equiv='Content-Type'/>"
|
295
|
+
result << '</head><body>'
|
296
|
+
result << "<h3>#{title}</h3>"
|
297
|
+
result << content
|
298
|
+
result << '</body></html>'
|
299
|
+
end
|
300
300
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
301
|
+
# the dir path to generated files
|
302
|
+
def tmp_dir
|
303
|
+
File.join @output_dir,"#{TMP_DIR}_#{valid_title}"
|
304
|
+
end
|
305
305
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
FileUtils.mkdir_p tmp_dir unless File.exist?(tmp_dir)
|
310
|
-
end
|
306
|
+
def valid_title
|
307
|
+
@v_title ||= @title.gsub(' ','_')
|
308
|
+
end
|
311
309
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
files_count = 1
|
318
|
-
pages.each do |page|
|
319
|
-
File.open(file_path(page[:file_name]),'wb') do |f|
|
320
|
-
content_to_write = page[:wrap] ? html_wrap(page[:title],page[:content]) : page[:content]
|
321
|
-
debug "here is the page #{page[:title]} need to write"
|
322
|
-
debug content_to_write
|
323
|
-
f.write content_to_write
|
324
|
-
end
|
325
|
-
files_count += 1
|
326
|
-
end
|
310
|
+
# create dirs of generated files
|
311
|
+
def make_generated_dirs
|
312
|
+
FileUtils.rm_rf tmp_dir if File.exist?(tmp_dir)
|
313
|
+
FileUtils.mkdir_p tmp_dir unless File.exist?(tmp_dir)
|
314
|
+
end
|
327
315
|
|
328
|
-
|
316
|
+
def write_to_disk
|
317
|
+
File.open("#{tmp_dir}/nav-contents.ncx",'wb') { |f| f.write @ncx }
|
318
|
+
File.open(file_path('contents.html'),'wb') {|f| f.write @toc }
|
319
|
+
File.open("#{tmp_dir}/#{valid_title}.opf",'wb') {|f| f.write @opf}
|
320
|
+
# make html files
|
321
|
+
files_count = 1
|
322
|
+
pages.each do |page|
|
323
|
+
File.open(file_path(page[:file_name]),'wb') do |f|
|
324
|
+
content_to_write = page[:wrap] ? html_wrap(page[:title],page[:content]) : page[:content]
|
325
|
+
debug "here is the page #{page[:title]} need to write"
|
326
|
+
debug content_to_write
|
327
|
+
f.write content_to_write
|
328
|
+
end
|
329
|
+
files_count += 1
|
330
|
+
end
|
329
331
|
|
330
|
-
|
331
|
-
return unless @debug
|
332
|
-
Rails.logger.info(str) if defined?(Rails)
|
333
|
-
puts str
|
334
|
-
end
|
332
|
+
end
|
335
333
|
|
336
|
-
|
334
|
+
def debug(str)
|
335
|
+
return unless @debug
|
336
|
+
Rails.logger.info(str) if defined?(Rails)
|
337
|
+
puts str
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
337
341
|
end
|
@@ -1,58 +1,96 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
describe "Mobi
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
2
|
+
describe "Mobi book file generator" do
|
3
|
+
|
4
|
+
DIR_PREFIX = "kindler_generated_mobi_"
|
5
|
+
|
6
|
+
it "should have the title,author property" do
|
7
|
+
title = 'first-book'
|
8
|
+
author = 'mike'
|
9
|
+
book = Kindler::Book.new :title=>title,:author=>author,:debug=>true
|
10
|
+
book.title.should == title
|
11
|
+
book.author.should == author
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have the generated dir contains book infos" do
|
15
|
+
title = 'first-book'
|
16
|
+
author = 'mike'
|
17
|
+
book = Kindler::Book.new :title=>title,:author=>author,:debug=>true
|
18
|
+
book.generate
|
19
|
+
book.should be_generated
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should contains the contents.html and ncx file" do
|
23
|
+
title = 'first-book'
|
24
|
+
author = 'mike'
|
25
|
+
book = Kindler::Book.new :title=>title,:author=>author,:debug=>true
|
26
|
+
book.add_page :title=>'page1',:author=>'mike1',:content=>'this is the page 1',:wrap=>true
|
27
|
+
File.should be_exist("./#{DIR_PREFIX}#{title}/contents.html")
|
28
|
+
File.should be_exist("./#{DIR_PREFIX}#{title}/nav-contents.ncx")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "contents file should include the page" do
|
32
|
+
title = 'first-book'
|
33
|
+
author = 'mike'
|
34
|
+
book = Kindler::Book.new :title=>title,:author=>author,:debug=>true
|
35
|
+
book.add_page :title=>'page1',:author=>'mike1',:content=>'this is the page 1',:wrap=>true
|
36
|
+
book.generate
|
37
|
+
contents = File.open("./#{DIR_PREFIX}#{title}/contents.html").readlines
|
38
|
+
contents.count.should > 0
|
39
|
+
contents.select {|a| a.include?("001.html")}.count.should > 0
|
40
|
+
book.should be_generated
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should not generate a mobi book" do
|
44
|
+
title = 'good_book'
|
45
|
+
book = Kindler::Book.new :title=>title,:author=>'mike',:debug=>true
|
46
|
+
book.add_page :title=>'page1',:author=>'mike1',:content=>'this is the page 1',:wrap=>true
|
47
|
+
book.add_page :title=>'page2',:author=>'mike1',:content=>'this is the page 2',:wrap=>true
|
48
|
+
book.add_page :title=>'page3',:author=>'mike1',:content=>'this is the page 3',:wrap=>true
|
49
|
+
book.generate
|
50
|
+
book.should be_generated
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should generate book contains images" do
|
54
|
+
title = 'book_with_image'
|
55
|
+
book = Kindler::Book.new :title=>title,:author=>'mike',:debug=>true
|
56
|
+
book.add_page :title=>'page1',:author=>'mike1',:content=>'this is the page 1',:wrap=>true
|
57
|
+
book.add_page :title=>'page2',:author=>'mike1',:content=>'this is the page 2',:wrap=>true
|
58
|
+
book.add_page :title=>'page3',:author=>'mike1',:content=>'<img src="http://media2.glamour-sales.com.cn/media/catalog/category/Stroili_banner_02.jpg"></img>this is the page 3',:wrap=>true
|
59
|
+
book.generate
|
60
|
+
book.should be_generated
|
61
|
+
File.should be_exist("./#{DIR_PREFIX}#{title}/1.jpg")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "can access pages information before generate" do
|
65
|
+
title = 'test_contents'
|
66
|
+
book = Kindler::Book.new :title=>title,:author=>'mike',:debug=>true
|
67
|
+
book.add_page :title=>'love page1',:author=>'mike1',:content=>'this is the love page1',:section => 'love'
|
68
|
+
book.add_page :title=>'love page2',:author=>'mike1',:content=>'this is the love page2',:section => 'love'
|
69
|
+
book.add_page :title=>'hate page1',:author=>'mike1',:content=>'this is the hate page1',:section => 'hate'
|
70
|
+
book.add_page :title=>'love page3',:author=>'mike1',:content=>'this is the love page3',:section => 'love'
|
71
|
+
book.pages.count.should == 4
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
it "should have two sections" do
|
76
|
+
title = 'test_contents'
|
77
|
+
book = Kindler::Book.new :title=>title,:author=>'mike',:debug=>true
|
78
|
+
book.add_page :title=>'love page1',:author=>'mike1',:content=>'this is the love page1',:section => 'love'
|
79
|
+
book.add_page :title=>'love page2',:author=>'mike1',:content=>'this is the love page2',:section => 'love'
|
80
|
+
book.add_page :title=>'hate page1',:author=>'mike1',:content=>'this is the hate page1',:section => 'hate'
|
81
|
+
book.add_page :title=>'love page3',:author=>'mike1',:content=>'this is the love page3',:section => 'love'
|
82
|
+
book.generate
|
83
|
+
book.should be_generated
|
84
|
+
book.pages_by_section.count.should == 2
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should generate books given title contains space" do
|
88
|
+
title = 'title with space'
|
89
|
+
book = Kindler::Book.new :title=>title,:author=>'mike',:debug=>true
|
90
|
+
book.add_page :title=>'page1',:author=>'mike1',:content=>'this is the page 1',:wrap=>true
|
91
|
+
book.add_page :title=>'page2',:author=>'mike1',:content=>'this is the page 2',:wrap=>true
|
92
|
+
book.generate
|
93
|
+
book.should be_generated
|
94
|
+
end
|
57
95
|
|
58
96
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,4 +4,19 @@ rescue LoadError
|
|
4
4
|
puts 'Although not required, bundler is recommended for running the tests.'
|
5
5
|
end
|
6
6
|
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.mock_with :rspec
|
9
|
+
config.color_enabled = true
|
10
|
+
|
11
|
+
config.before(:each) do
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
config.before(:each, :type => :controller) do
|
16
|
+
end
|
17
|
+
|
18
|
+
config.after(:all) do
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
7
22
|
require 'kindler'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kindler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-04-06 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
16
|
-
requirement: &
|
16
|
+
requirement: &2160828000 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2160828000
|
25
25
|
description: kindler is a rubygem allow you to generate kindle mobi book very easily
|
26
26
|
email:
|
27
27
|
- mike.d.1984@gmail.com
|
@@ -34,6 +34,10 @@ files:
|
|
34
34
|
- Guardfile
|
35
35
|
- Rakefile
|
36
36
|
- Readme.md
|
37
|
+
- features/basic.feature
|
38
|
+
- features/dsl.feature
|
39
|
+
- features/step_definitions/basic_step.rb
|
40
|
+
- features/step_definitions/dsl_step.rb
|
37
41
|
- kindler.gemspec
|
38
42
|
- lib/kindler.rb
|
39
43
|
- lib/kindler/railtie.rb
|
@@ -65,6 +69,10 @@ signing_key:
|
|
65
69
|
specification_version: 3
|
66
70
|
summary: kindler is a rubygem allow you to generate kindle mobi book very easily
|
67
71
|
test_files:
|
72
|
+
- features/basic.feature
|
73
|
+
- features/dsl.feature
|
74
|
+
- features/step_definitions/basic_step.rb
|
75
|
+
- features/step_definitions/dsl_step.rb
|
68
76
|
- spec/cases/generator_spec.rb
|
69
77
|
- spec/spec_helper.rb
|
70
78
|
has_rdoc:
|