kindler 0.1.7 → 0.1.8
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.
- 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:
|