kindler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ kindler_generated*
19
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'rspec'
5
+ # Testing infrastructure
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+
9
+ if RUBY_PLATFORM =~ /darwin/
10
+ # OS X integration
11
+ gem "ruby_gntp"
12
+ gem "rb-fsevent", "~> 0.4.3.1"
13
+ end
14
+ end
15
+
16
+ gem "ruby-readability",:git=>'https://github.com/iterationlabs/ruby-readability.git', :require => 'readability'
17
+ gem 'mini_magick'
18
+
19
+ # Specify your gem's dependencies in kindler.gemspec
20
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+ guard 'rspec', :version => 2 do
4
+ watch(%r{^spec/.+_spec\.rb$})
5
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
6
+ watch('spec/spec_helper.rb') { "spec" }
7
+ end
8
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/Readme.md ADDED
@@ -0,0 +1,26 @@
1
+ ### Todo
2
+ 1.show images within page
3
+ 2.support magzine like format
4
+
5
+ ### A kindle mobi book generator
6
+ which receive a couple of urls then output one mobi file
7
+
8
+ ### Command Line Use [Todo]
9
+ kindler url1 url2 url3 url4 -o test.mobi
10
+
11
+ outputs : test.mobi
12
+
13
+ ### Api use
14
+ ```ruby
15
+ # generate my book
16
+ book = Kindler::Book.new ({:urls=>["http://blog.farmostwood.net/643.html",
17
+ "http://www.ifanr.com/69878","http://www.oneplus.info/archives/455"],
18
+ :title=>'Test_book',:author=>'mike'})
19
+ # you will get my_book.mobi file
20
+ book.generate 'my_book'
21
+ ```
22
+
23
+
24
+ Hope you love it !
25
+
26
+
data/kindler.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/kindler/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["dongbin.li"]
6
+ gem.email = ["mike.d.1984@gmail.com"]
7
+ gem.description = %q{a simple gem to generate kindle mobi book}
8
+ gem.summary = %q{a simple gem to generate kindle mobi book}
9
+ gem.homepage = "https://github.com/29decibel/kindler"
10
+
11
+ gem.rubyforge_project = "kindler"
12
+ gem.add_dependency 'mini_magick'
13
+ gem.add_dependency 'ruby-readability'
14
+
15
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ gem.files = `git ls-files`.split("\n")
17
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ gem.name = "kindler"
19
+ gem.require_paths = ["lib"]
20
+ gem.version = Kindler::VERSION
21
+ end
@@ -0,0 +1,7 @@
1
+ module Kindler
2
+ module HtmlGenerator
3
+ def g_html
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Kindler
2
+ class Railtie < Rails::Railtie
3
+ config.after_initialize do
4
+ # do nothing
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Kindler
2
+ module TocGenerator
3
+ def g_toc
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Kindler
2
+ VERSION = "0.0.1"
3
+ end
data/lib/kindler.rb ADDED
@@ -0,0 +1,254 @@
1
+ require "kindler/version"
2
+ require "readability"
3
+ require "open-uri"
4
+ # require 'mini_magick'
5
+ require 'kindler/railtie' if defined?(Rails)
6
+
7
+ module Kindler
8
+ class Book
9
+ class KindlerError < StandardError;end
10
+ attr_accessor :urls,:title,:author
11
+ TMP_DIR = 'kindler_generated_mobi'
12
+
13
+ # availabel options
14
+ # @param options [Hash]
15
+ # @option urls [Array] urls to generate
16
+ # @option title [String] book title
17
+ # @option output_dir [String] directory want to generate
18
+ def initialize(options={})
19
+ @urls = options[:urls] || {}
20
+ @title = options[:title] || ''
21
+ @output_dir = options[:output_dir] || './'
22
+ raise KindlerError.new("urls option could not be empty") if @urls.empty?
23
+ @author = options[:author] || ''
24
+ @doc_infos = {}
25
+ # init doc infos by url
26
+ @urls.each {|url| @doc_infos[url]= {} }
27
+ end
28
+
29
+ # add url to book
30
+ # @param url [String] url to add to book
31
+ # @param options [Hash]
32
+ # @option section [Symbol] indicate which section the url belongs to,if not empty the book will be generated with magzine style
33
+ def add_url(url,options={})
34
+ return if @doc_infos[url]
35
+ @urls << url
36
+ @doc_infos[url] = {}
37
+ end
38
+
39
+ # generate books by given urls
40
+ def generate(title='')
41
+ make_generated_dirs
42
+ # generate
43
+ generate_html
44
+ generate_toc
45
+ generate_opf
46
+ generate_ncx
47
+ kindlegen
48
+ # clear
49
+ end
50
+
51
+ # check mobi file is generated already
52
+ def mobi_generated?
53
+ File.exist? "#{tmp_dir}/#{@title}.mobi"
54
+ end
55
+
56
+ private
57
+ # make sure kindlegen is installed
58
+ # you can use "sudo brew install " to install it
59
+ def kindlegen
60
+ puts 'begin generate mobi'
61
+ system("kindlegen #{tmp_dir}/#{@title}.opf ")
62
+ end
63
+
64
+ def generate_toc
65
+ contents = <<-CODE
66
+ <html>
67
+ <head>
68
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
69
+ <title>Table of Contents</title>
70
+ </head>
71
+ <body>
72
+ <h1>Contents</h1>
73
+ <h4>Main section</h4>
74
+ <ul>
75
+ CODE
76
+ files_count = 1
77
+ @doc_infos.each do |url,infos|
78
+ contents << "<li><a href='#{files_count.to_s.rjust(3,'0')}.html'>#{infos[:title]}</a></li>"
79
+ files_count += 1
80
+ end
81
+ # append footer
82
+ contents << "</ul></body></html>"
83
+ File.open(file_path('contents'),'w') do |f|
84
+ f.puts contents
85
+ end
86
+ end
87
+
88
+ # generate ncx , which is navigation
89
+ def generate_ncx
90
+ contents = <<-NCX
91
+ <?xml version="1.0" encoding="UTF-8"?>
92
+ <!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
93
+ <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="en-US">
94
+ <head>
95
+ <meta name="dtb:uid" content="#{@title}"/>
96
+ <meta name="dtb:depth" content="1"/>
97
+ <meta name="dtb:totalPageCount" content="0"/>
98
+ <meta name="dtb:maxPageNumber" content="0"/>
99
+ </head>
100
+ <docTitle>
101
+ <text>#{@title}</text>
102
+ </docTitle>
103
+ <docAuthor>
104
+ <text>#{@author}</text>
105
+ </docAuthor>
106
+ <navMap>
107
+ NCX
108
+ # this navPoint seems not useful
109
+ # contents << <<-NAV
110
+ # <navPoint id="navpoint-1" playOrder="1">
111
+ # <navLabel><text>Table Of Contents</text></navLabel>
112
+ # <content src="contents.html"/>
113
+ # </navPoint>
114
+ # NAV
115
+ ####################### periodocal , magzine like format #########################
116
+ # <navPoint playOrder="0" class="periodical" id="periodical">
117
+ # <mbp:meta-img src="masthead.gif" name="mastheadImage"/>
118
+ # <navLabel>
119
+ # <text>Table of Contents</text>
120
+ # </navLabel>
121
+ # <content src="contents.html"/>
122
+ # <navPoint playOrder="1" class="section" id="Main-section">
123
+ # <navLabel>
124
+ # <text>Main section</text>
125
+ # </navLabel>
126
+ # <content src="001.html"/>
127
+ # <navPoint playOrder="2" class="article" id="item-001">
128
+ # <navLabel>
129
+ # <text>Nick Clegg and David Cameron agree key changes on NHS plans</text>
130
+ # </navLabel>
131
+ # <content src="001.html"/>
132
+ # <mbp:meta name="description">Deputy PM tells Andrew Marr show that GPs should not be forced to sign up to new commissioning consortiums</mbp:meta>
133
+ # <mbp:meta name="author">Nicholas Watt and Denis Campbell</mbp:meta>
134
+ # </navPoint>
135
+ # ####################################################################################
136
+ files_count = 2
137
+ @doc_infos.each do |url,infos|
138
+ nav_point = <<-NAV
139
+ <navPoint id="navpoint-#{files_count}" playOrder="#{files_count}">
140
+ <navLabel><text>#{infos[:title]}</text></navLabel>
141
+ <content src="#{(files_count-1).to_s.rjust(3,'0')}.html"/>
142
+ </navPoint>
143
+ NAV
144
+ contents << nav_point
145
+ files_count += 1
146
+ end
147
+ contents << "</navMap></ncx>"
148
+ File.open("#{tmp_dir}/nav-contents.ncx",'w') { |f| f.puts contents }
149
+ end
150
+
151
+ # generate the opf, manifest of book,including all articles and images and css
152
+ def generate_opf
153
+ # mark mobi as magzine format
154
+ # <x-metadata>
155
+ # <output content-type="application/x-mobipocket-subscription-magazine" encoding="utf-8"/>
156
+ # </x-metadata>
157
+ contents = <<-HTML
158
+ <?xml version='1.0' encoding='utf-8'?>
159
+ <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="#{@title}">
160
+ <metadata>
161
+ <dc-metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
162
+ <dc:title>#{@title}</dc:title>
163
+ <dc:language>en-gb</dc:language>
164
+ <meta content="cover-image" name="cover"/>
165
+ <dc:creator>Kindler- 29decibel</dc:creator>
166
+ <dc:publisher>Kindler- 29decibel</dc:publisher>
167
+ <dc:subject>News</dc:subject>
168
+ <dc:identifier id="#{@title}">#{@title}</dc:identifier>
169
+ <dc:date>#{Time.now.to_date}/dc:date>
170
+ <dc:description>Kindler generated book</dc:description>
171
+ </dc-metadata>
172
+ </metadata>
173
+ <manifest>
174
+ HTML
175
+ files_count = 1
176
+ @doc_infos.each do |url,infos|
177
+ doc_id = files_count.to_s.rjust(3,'0')
178
+ contents << "<item href='#{doc_id}.html' media-type='application/xhtml+xml' id='#{doc_id}'/>"
179
+ files_count += 1
180
+ end
181
+ contents << "<item href='contents.html' media-type='application/xhtml+xml' id='contents'/>"
182
+ contents << "<item href='nav-contents.ncx' media-type='application/x-dtbncx+xml' id='nav-contents'/>"
183
+ contents << "</manifest>"
184
+ contents << "<spine toc='nav-contents'>"
185
+ contents << "<itemref idref='contents'/>"
186
+ files_count = 1
187
+ @doc_infos.each do |url,infos|
188
+ contents << "<itemref idref='#{files_count.to_s.rjust(3,'0')}'/>"
189
+ files_count += 1
190
+ end
191
+ contents << "</spine><guide><reference href='contents.html' type='toc' title='Table of Contents'/></guide></package>"
192
+ File.open("#{tmp_dir}/#{@title}.opf",'w') {|f| f.puts contents}
193
+ end
194
+
195
+ # generate every url to article in readable format
196
+ def generate_html
197
+ @doc_infos.each do |url,infos|
198
+ article = readable_article(url)
199
+ # puts article.images
200
+ infos[:content] = html_wrap(article.title,article.content)
201
+ infos[:title] = article.title
202
+ end
203
+ # make html files
204
+ files_count = 1
205
+ @doc_infos.each do |url,infos|
206
+ File.open(file_path(files_count.to_s.rjust(3,'0')),'w') do |f|
207
+ f.puts infos[:content]
208
+ end
209
+ files_count += 1
210
+ end
211
+ end
212
+
213
+ # html file path
214
+ def file_path(file_name)
215
+ "#{tmp_dir}/#{file_name}.html"
216
+ end
217
+
218
+ # wrap readable contents with in html format
219
+ def html_wrap(title,content)
220
+ result = ''
221
+ result << '<html><head>'
222
+ result << "<meta content='text/html; charset=utf-8' http-equiv='Content-Type'/>"
223
+ result << '</head><body>'
224
+ result << "<h3>#{title}</h3>"
225
+ result << content
226
+ result << '</body></html>'
227
+ end
228
+
229
+ # get readable document by url, using ruby-readability here
230
+ def readable_article(url)
231
+ puts "begin fetch url : #{url}"
232
+ source = open(url).read
233
+ Readability::Document.new(source)
234
+ end
235
+
236
+ # the dir path to generated files
237
+ def tmp_dir
238
+ File.join @output_dir,"#{TMP_DIR}_#{@title.gsub(' ','_')}"
239
+ end
240
+
241
+ # create dirs of generated files
242
+ def make_generated_dirs
243
+ FileUtils.rm_rf tmp_dir if File.exist?(tmp_dir)
244
+ FileUtils.mkdir_p tmp_dir unless File.exist?(tmp_dir)
245
+ end
246
+
247
+ # exist to clear tmp files such as ncx,opf or html other than mobi file
248
+ # keep them right now
249
+ def clear_tmp_dirs
250
+
251
+ end
252
+
253
+ end
254
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ describe "Mobi html file generator" do
3
+
4
+ it "should generate html files by urls" do
5
+ title = "Test_book"
6
+ book = Kindler::Book.new ({:urls=>["http://blog.farmostwood.net/643.html",
7
+ "http://www.ifanr.com/69878","http://www.oneplus.info/archives/455"],
8
+ :title=>title,:author=>'mike'})
9
+ book.generate
10
+ File.exist?(mobi_book_path(title)).should == true
11
+ end
12
+
13
+
14
+ it "should generate hacker news book" do
15
+ title = 'haker_news'
16
+ urls = []
17
+ urls << "http://jseliger.com/2010/09/26/how-universities-work-or-what-i-wish-i%E2%80%99d-known-freshman-year-a-guide-to-american-university-life-for-the-uninitiated/"
18
+ urls << "http://randykepple.com/photoblog/2010/10/8-bad-habits-that-crush-your-creativity-and-stifle-your-success/"
19
+ urls << "http://nathanmarz.com/blog/how-to-get-a-job-at-a-kick-ass-startup-for-programmers.html"
20
+ urls << "http://tumblr.intranation.com/post/766290565/how-set-up-your-own-private-git-server-linux"
21
+ urls << "http://antirez.com/post/what-is-wrong-with-2006-programming.html"
22
+ urls << "http://fak3r.com/2009/09/14/howto-build-your-own-open-source-dropbox-clone/"
23
+ book = Kindler::Book.new :urls=>urls,:title=>title,:author=>'mike'
24
+ book.generate
25
+ File.exist?(mobi_book_path(title)).should == true
26
+ end
27
+
28
+ it "should generate book and infos on output_dir" do
29
+ title = 'my_dir_book'
30
+ urls = []
31
+ urls << "http://www.wowsai.com/home/space.php?uid=1&do=blog&id=4362&classid=2"
32
+ urls << "http://www.honeykennedy.com/2012/01/miss-moss-love-letters/"
33
+ urls << "http://www.mysenz.com/?p=3692"
34
+ book = Kindler::Book.new :urls=>urls,:title=>title,:author=>'mike',:output_dir=>'/Users/lidongbin/projects'
35
+ book.generate
36
+ File.exist?(mobi_book_path(title,'/Users/lidongbin/projects')).should == true
37
+ end
38
+
39
+ def mobi_book_path(title,output_dir='.')
40
+ File.join(output_dir,"kindler_generated_mobi_#{title}/#{title}.mobi")
41
+ end
42
+
43
+ end
@@ -0,0 +1,7 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'Although not required, bundler is recommended for running the tests.'
5
+ end
6
+
7
+ require 'kindler'
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kindler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - dongbin.li
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-30 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mini_magick
16
+ requirement: &2162549440 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2162549440
25
+ - !ruby/object:Gem::Dependency
26
+ name: ruby-readability
27
+ requirement: &2162549020 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2162549020
36
+ description: a simple gem to generate kindle mobi book
37
+ email:
38
+ - mike.d.1984@gmail.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .gitignore
44
+ - Gemfile
45
+ - Guardfile
46
+ - Rakefile
47
+ - Readme.md
48
+ - kindler.gemspec
49
+ - lib/kindler.rb
50
+ - lib/kindler/html_generator.rb
51
+ - lib/kindler/railtie.rb
52
+ - lib/kindler/toc_generator.rb
53
+ - lib/kindler/version.rb
54
+ - spec/cases/generator_spec.rb
55
+ - spec/spec_helper.rb
56
+ homepage: https://github.com/29decibel/kindler
57
+ licenses: []
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project: kindler
76
+ rubygems_version: 1.8.11
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: a simple gem to generate kindle mobi book
80
+ test_files:
81
+ - spec/cases/generator_spec.rb
82
+ - spec/spec_helper.rb
83
+ has_rdoc: