maglove 0.5.4 → 0.5.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68e99357e1c9657d692067ffc9ccc18ec8abf2b3
4
- data.tar.gz: 3ff5da3c4f3b972aa400d3eb63cad8bfc59945f0
3
+ metadata.gz: de2a076857bf9fc5e27988f5c13650ecfc6a92a7
4
+ data.tar.gz: cab8e9e7dfc96f8ced3101d779544500630fc4cd
5
5
  SHA512:
6
- metadata.gz: 82928b5fe88f1a0c3480dea707b37c9686f6245032490a28c0de387b252f251719f539740eaa659321fb7dd9bd08da8bb7e36ad3c763239d3ddc352e31d8b9b7
7
- data.tar.gz: fb52aa0ae644a31f511542d71fdb2a46b63e3dfdb29cf9408f095ddaa7018f46298b46ad033266a3d2c7bac709457e9a4bc9482f556c62287c75a58497fc1920
6
+ metadata.gz: b8bca796f465d49329fd353433171e0c2c62c3ee6e1bc4ac9c2a2ae6d2f62af9d5d060b3ea149563efcca17c0f5d3e2deccbddd77a10d386e31ca9775ff5f12f
7
+ data.tar.gz: 83c0ceec58dab01e8386b215a9ca241426fd943121e0b9b4c529af50351c8250a8024438fa66325036aa125aecb8cd6894099ef74d429e936946b73d18eaa41d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- maglove (0.5.4)
4
+ maglove (0.5.5)
5
5
  activesupport (~> 4.2)
6
6
  bundler (~> 1.10)
7
7
  coffee-script (~> 2.4)
@@ -10,11 +10,6 @@ module MagLove
10
10
  MagLove::Server.new(options.theme).run!
11
11
  end
12
12
 
13
- task :hpub, port: "8080" do |args, options|
14
- info("▸ starting hpub server at http://127.0.0.1:#{options.port}/manifest.json")
15
- MagLove::Hpub::Server.new(options.port).run!
16
- end
17
-
18
13
  end
19
14
  end
20
15
  end
@@ -0,0 +1,185 @@
1
+ module MagLove
2
+ class Server
3
+ module Hpub
4
+
5
+ class IssueServlet < WEBrick::HTTPServlet::AbstractServlet
6
+ include Commander::Methods
7
+
8
+ def do_GET(req, res)
9
+ theme = File.basename(req.path, ".*")
10
+ config = theme_config(nil, theme)
11
+ working_dir = Dir.mktmpdir
12
+ data_dir = Gem.datadir("maglove")
13
+
14
+ # Create book.json
15
+ book_json = {
16
+ "hpub" => 1,
17
+ "title" => config["name"],
18
+ "author" => ["MagLove"],
19
+ "creator" => ["MagLove"],
20
+ "date" => Time.now.strftime("%Y-%m-%d %H:%M:%S UTC"),
21
+ "url" => "book://www.magloft.com",
22
+ "orientation" => "both",
23
+ "-baker-background" => "#FFFFFF",
24
+ "-baker-index-height" => 240,
25
+ "-baker-media-autoplay" => false,
26
+ "-baker-rendering" => "three-cards",
27
+ "-baker-page-numbers-color" => "#333",
28
+ "-baker-vertical-bounce" => true,
29
+ "-baker-page-turn-tap" => true,
30
+ "-baker-start-at-page" => 1,
31
+ "-baker-max-zoom-level" => 2.0,
32
+ "zoomable" => true,
33
+ "contents" => config["templates"].map{|t| "#{t}.html"}
34
+ }
35
+ File.open("#{working_dir}/book.json", "w"){|f| f.write(book_json.to_json) }
36
+
37
+ # Copy assets
38
+ FileUtils.cp_r("dist/fonts", "#{working_dir}/fonts")
39
+ FileUtils.cp_r("dist/themes/#{theme}/thumbs", "#{working_dir}/thumbs")
40
+ FileUtils.cp("dist/themes/#{theme}/thumbs/#{config["templates"][0]}.png", "#{working_dir}/cover.png")
41
+ FileUtils.mkdir_p("#{working_dir}/stylesheets")
42
+ FileUtils.cp("#{data_dir}/hpub/index.css", "#{working_dir}/stylesheets/index.css")
43
+ FileUtils.mkdir_p("#{working_dir}/themes")
44
+ FileUtils.cp_r("dist/themes/#{theme}", "#{working_dir}/themes/#{theme}")
45
+
46
+ # Create index html
47
+ index_contents = File.read("#{data_dir}/hpub/index.haml")
48
+ engine = Haml::Engine.new(index_contents)
49
+ index_html = engine.render(Object.new, config)
50
+ File.open("#{working_dir}/index.html", "w"){|f| f.write(index_html) }
51
+
52
+ # Compile themes
53
+ Hamloft::Options.defaults[:asset_uri] = "."
54
+ theme_glob("templates/*.{html,haml,twig}", theme).each do |file|
55
+ # compile template
56
+ template = File.basename(file, ".*")
57
+ locals = {}
58
+ locals_contents = theme_contents(file.sub(/\.[^.]+\z/, ".yml"), theme)
59
+ if locals_contents
60
+ locals = YAML.load(locals_contents).with_indifferent_access
61
+ end
62
+ asset = theme_asset(file, theme, locals)
63
+
64
+ # wrap in page
65
+ page_contents = File.read("#{data_dir}/hpub/page.haml")
66
+ engine = Haml::Engine.new(page_contents)
67
+ page_html = engine.render(Object.new, {template: template, theme: theme, contents: compile_html(asset.contents)})
68
+
69
+ # Write to file
70
+ File.open("#{working_dir}/#{template}.html", "w"){|f| f.write(page_html) }
71
+ end
72
+
73
+ # Delete zip file
74
+ zip_path = "#{working_dir}/themes/#{theme}/#{theme}.tar.gz"
75
+ FileUtils.rm_f(zip_path) if File.exists?(zip_path)
76
+
77
+ # Create zip archive
78
+ FileUtils.rm_f("dist/#{theme}.hpub") if File.exists?("dist/#{theme}.hpub")
79
+ Zip::File.open("dist/#{theme}.hpub", Zip::File::CREATE) do |zipfile|
80
+ Dir[File.join(working_dir, '**', '**')].each do |file|
81
+ zipfile.add(file.sub("#{working_dir}/", ''), file)
82
+ end
83
+ end
84
+
85
+ # respond
86
+ res.status = 200
87
+ res['Content-Type'] = "application/zip"
88
+ res.body = File.read("dist/#{theme}.hpub")
89
+ end
90
+
91
+ private
92
+
93
+ def compile_html(contents)
94
+ doc = Nokogiri::HTML.fragment(contents.force_encoding("UTF-8"))
95
+
96
+ # unwrap widgets
97
+ doc.css("._typeloft_widget").each do |node|
98
+
99
+ # remove unneeded attributes
100
+ node.attributes.each do |key, attribute|
101
+ node.attributes[key].remove if key != "style" and key != "class"
102
+ end
103
+
104
+ # clean up classes
105
+ if not node.attributes["class"].nil?
106
+ classList = node.attributes["class"].value.split(" ")
107
+ classList.reject!{|cls| ["_typeloft_widget", "ui-resizable", "_typeloft_widget_selected", "_typeloft_widget_hover"].include?(cls)}
108
+ node.attributes["class"].value = classList.join(" ")
109
+ end
110
+ end
111
+
112
+ # remove scripts
113
+ doc.css('script').remove()
114
+
115
+ # unwrap drop containers
116
+ doc.css("._typeloft_widget_drop_container").each do |node|
117
+ node.children.each do |child|
118
+ node.parent << child
119
+ end
120
+ node.remove
121
+ end
122
+
123
+ # remove data-typeloft-slug attributes
124
+ doc.xpath( './/*[@data-typeloft-slug]|*[@data-typeloft-slug]' ).each do |node|
125
+ node.attributes["data-typeloft-slug"].remove
126
+ end
127
+
128
+ # remove contenteditable attributes
129
+ doc.xpath( './/*[@contenteditable]|*[@contenteditable]' ).each do |node|
130
+ node.attributes["contenteditable"].remove
131
+ end
132
+
133
+ # remove widget containers
134
+ doc.css("._typeloft_widget_container").remove()
135
+
136
+ # remove typeloft classes
137
+ doc.xpath(".//*[@*[contains(., '_typeloft_')]]").each do |node|
138
+ classes = node[:class].split(' ').select{|cls| !cls.include?('_typeloft_')}
139
+ node[:class] = classes.join(' ')
140
+ end
141
+
142
+ # convert iframe https links to http
143
+ doc.search('iframe[src*="https://"]').each do |node|
144
+ src = node[:src].sub('https://', 'http://')
145
+ node[:src] = src
146
+ end
147
+
148
+ # fetch html
149
+ clean_html_chars(doc.to_s)
150
+ end
151
+
152
+ def clean_html_chars(characters)
153
+ ["\u1680", "\u180E", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200A", "\u200B", "\u202F", "\u205F", "\u3000", "\uFEFF"].each do |char|
154
+ characters = characters.force_encoding("UTF-8").gsub(char, "&nbsp&nbsp")
155
+ end
156
+ characters.force_encoding("BINARY").gsub(0xC2.chr+0xA0.chr+" ","&nbsp;&nbsp;").gsub(0xC2.chr+0xA0.chr,"&nbsp;")
157
+ end
158
+ end
159
+
160
+ class ManifestServlet < WEBrick::HTTPServlet::AbstractServlet
161
+ include Commander::Methods
162
+
163
+ def do_GET(req, res)
164
+ res.content_type = "application/json"
165
+ manifest = []
166
+ Dir.glob("dist/themes/*") do |dir|
167
+ theme = File.basename(dir)
168
+ config = theme_config(nil, theme)
169
+ manifest.push({
170
+ name: theme,
171
+ title: config["name"],
172
+ product_id: nil,
173
+ info: config["description"],
174
+ date: Time.now.strftime("%Y-%m-%d %H:%M:%S"),
175
+ url: "http://#{req.host}:#{req.port}/issue/#{theme}.hpub",
176
+ cover: "http://#{req.host}:#{req.port}/themes/#{theme}/thumbs/#{config["templates"][0]}.png"
177
+ })
178
+ end
179
+ res.body = manifest.to_json
180
+ end
181
+ end
182
+
183
+ end
184
+ end
185
+ end
@@ -56,6 +56,9 @@ module MagLove
56
56
  res.content_type = "text/css"
57
57
  res.body = parser.parse(less_contents).to_css
58
58
  end
59
+
60
+ self.webrick.mount "/issue", Hpub::IssueServlet
61
+ self.webrick.mount "/manifest.json", Hpub::ManifestServlet
59
62
  end
60
63
 
61
64
  def mount_template(path, view, options={})
@@ -1,3 +1,3 @@
1
1
  module MagLove
2
- VERSION = "0.5.4"
2
+ VERSION = "0.5.5"
3
3
  end
data/lib/maglove.rb CHANGED
@@ -43,6 +43,6 @@ require "maglove/phantom_script"
43
43
  require "maglove/application"
44
44
  require "maglove/asset/theme"
45
45
  require "maglove/asset/base_theme"
46
+ require "maglove/server/hpub"
46
47
  require "maglove/server"
47
- require "maglove/hpub/server"
48
48
  require "maglove/template/tumblr"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maglove
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Strebitzer
@@ -392,9 +392,9 @@ files:
392
392
  - lib/maglove/helper/command_helper.rb
393
393
  - lib/maglove/helper/log_helper.rb
394
394
  - lib/maglove/helper/theme_helper.rb
395
- - lib/maglove/hpub/server.rb
396
395
  - lib/maglove/phantom_script.rb
397
396
  - lib/maglove/server.rb
397
+ - lib/maglove/server/hpub.rb
398
398
  - lib/maglove/template/tumblr.rb
399
399
  - lib/maglove/tilt/coffee_template.rb
400
400
  - lib/maglove/tilt/haml_template.rb
@@ -1,214 +0,0 @@
1
- module MagLove
2
- module Hpub
3
-
4
- class IssueServlet < WEBrick::HTTPServlet::AbstractServlet
5
- include Commander::Methods
6
-
7
- def do_GET(req, res)
8
- theme = File.basename(req.path, ".*")
9
- config = theme_config(nil, theme)
10
- working_dir = Dir.mktmpdir
11
- data_dir = Gem.datadir("maglove")
12
-
13
- # Create book.json
14
- book_json = {
15
- "hpub" => 1,
16
- "title" => config["name"],
17
- "author" => ["MagLove"],
18
- "creator" => ["MagLove"],
19
- "date" => Time.now.strftime("%Y-%m-%d %H:%M:%S UTC"),
20
- "url" => "book://www.magloft.com",
21
- "orientation" => "both",
22
- "-baker-background" => "#FFFFFF",
23
- "-baker-index-height" => 240,
24
- "-baker-media-autoplay" => false,
25
- "-baker-rendering" => "three-cards",
26
- "-baker-page-numbers-color" => "#333",
27
- "-baker-vertical-bounce" => true,
28
- "-baker-page-turn-tap" => true,
29
- "-baker-start-at-page" => 1,
30
- "-baker-max-zoom-level" => 2.0,
31
- "zoomable" => true,
32
- "contents" => config["templates"].map{|t| "#{t}.html"}
33
- }
34
- File.open("#{working_dir}/book.json", "w"){|f| f.write(book_json.to_json) }
35
-
36
- # Copy assets
37
- FileUtils.cp_r("dist/fonts", "#{working_dir}/fonts")
38
- FileUtils.cp_r("dist/themes/#{theme}/thumbs", "#{working_dir}/thumbs")
39
- FileUtils.cp("dist/themes/#{theme}/thumbs/#{config["templates"][0]}.png", "#{working_dir}/cover.png")
40
- FileUtils.mkdir_p("#{working_dir}/stylesheets")
41
- FileUtils.cp("#{data_dir}/hpub/index.css", "#{working_dir}/stylesheets/index.css")
42
- FileUtils.mkdir_p("#{working_dir}/themes")
43
- FileUtils.cp_r("dist/themes/#{theme}", "#{working_dir}/themes/#{theme}")
44
-
45
- # Create index html
46
- index_contents = File.read("#{data_dir}/hpub/index.haml")
47
- engine = Haml::Engine.new(index_contents)
48
- index_html = engine.render(Object.new, config)
49
- File.open("#{working_dir}/index.html", "w"){|f| f.write(index_html) }
50
-
51
- # Compile themes
52
- Hamloft::Options.defaults[:asset_uri] = "."
53
- theme_glob("templates/*.{html,haml,twig}", theme).each do |file|
54
- # compile template
55
- template = File.basename(file, ".*")
56
- locals = {}
57
- locals_contents = theme_contents(file.sub(/\.[^.]+\z/, ".yml"), theme)
58
- if locals_contents
59
- locals = YAML.load(locals_contents).with_indifferent_access
60
- end
61
- asset = theme_asset(file, theme, locals)
62
-
63
- # wrap in page
64
- page_contents = File.read("#{data_dir}/hpub/page.haml")
65
- engine = Haml::Engine.new(page_contents)
66
- page_html = engine.render(Object.new, {template: template, theme: theme, contents: compile_html(asset.contents)})
67
-
68
- # Write to file
69
- File.open("#{working_dir}/#{template}.html", "w"){|f| f.write(page_html) }
70
- end
71
-
72
- # Delete zip file
73
- zip_path = "#{working_dir}/themes/#{theme}/#{theme}.tar.gz"
74
- FileUtils.rm_f(zip_path) if File.exists?(zip_path)
75
-
76
- # Create zip archive
77
- FileUtils.rm_f("dist/#{theme}.hpub") if File.exists?("dist/#{theme}.hpub")
78
- Zip::File.open("dist/#{theme}.hpub", Zip::File::CREATE) do |zipfile|
79
- Dir[File.join(working_dir, '**', '**')].each do |file|
80
- zipfile.add(file.sub("#{working_dir}/", ''), file)
81
- end
82
- end
83
-
84
- # respond
85
- res.status = 200
86
- res['Content-Type'] = "application/zip"
87
- res.body = File.read("dist/#{theme}.hpub")
88
- end
89
-
90
- private
91
-
92
- def compile_html(contents)
93
- doc = Nokogiri::HTML.fragment(contents.force_encoding("UTF-8"))
94
-
95
- # unwrap widgets
96
- doc.css("._typeloft_widget").each do |node|
97
-
98
- # remove unneeded attributes
99
- node.attributes.each do |key, attribute|
100
- node.attributes[key].remove if key != "style" and key != "class"
101
- end
102
-
103
- # clean up classes
104
- if not node.attributes["class"].nil?
105
- classList = node.attributes["class"].value.split(" ")
106
- classList.reject!{|cls| ["_typeloft_widget", "ui-resizable", "_typeloft_widget_selected", "_typeloft_widget_hover"].include?(cls)}
107
- node.attributes["class"].value = classList.join(" ")
108
- end
109
- end
110
-
111
- # remove scripts
112
- doc.css('script').remove()
113
-
114
- # unwrap drop containers
115
- doc.css("._typeloft_widget_drop_container").each do |node|
116
- node.children.each do |child|
117
- node.parent << child
118
- end
119
- node.remove
120
- end
121
-
122
- # remove data-typeloft-slug attributes
123
- doc.xpath( './/*[@data-typeloft-slug]|*[@data-typeloft-slug]' ).each do |node|
124
- node.attributes["data-typeloft-slug"].remove
125
- end
126
-
127
- # remove contenteditable attributes
128
- doc.xpath( './/*[@contenteditable]|*[@contenteditable]' ).each do |node|
129
- node.attributes["contenteditable"].remove
130
- end
131
-
132
- # remove widget containers
133
- doc.css("._typeloft_widget_container").remove()
134
-
135
- # remove typeloft classes
136
- doc.xpath(".//*[@*[contains(., '_typeloft_')]]").each do |node|
137
- classes = node[:class].split(' ').select{|cls| !cls.include?('_typeloft_')}
138
- node[:class] = classes.join(' ')
139
- end
140
-
141
- # convert iframe https links to http
142
- doc.search('iframe[src*="https://"]').each do |node|
143
- src = node[:src].sub('https://', 'http://')
144
- node[:src] = src
145
- end
146
-
147
- # fetch html
148
- clean_html_chars(doc.to_s)
149
- end
150
-
151
- def clean_html_chars(characters)
152
- ["\u1680", "\u180E", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200A", "\u200B", "\u202F", "\u205F", "\u3000", "\uFEFF"].each do |char|
153
- characters = characters.force_encoding("UTF-8").gsub(char, "&nbsp&nbsp")
154
- end
155
- characters.force_encoding("BINARY").gsub(0xC2.chr+0xA0.chr+" ","&nbsp;&nbsp;").gsub(0xC2.chr+0xA0.chr,"&nbsp;")
156
- end
157
- end
158
-
159
- class Server
160
- include Commander::Methods
161
- attr_accessor :port, :webrick
162
-
163
- def initialize(port=8080)
164
- self.port = port
165
-
166
- # create server
167
- self.webrick = WEBrick::HTTPServer.new(
168
- Port: self.port,
169
- DocumentRoot: "dist/",
170
- Logger: WEBrick::Log.new("/dev/null"),
171
- AccessLog: []
172
- )
173
-
174
- # Manifest JSON
175
- mount("/manifest.json") do |req, res|
176
- res.content_type = "application/json"
177
- res.body = build_manifest_json
178
- end
179
-
180
- self.webrick.mount "/issue", IssueServlet
181
- end
182
-
183
- def build_manifest_json
184
- manifest = []
185
- Dir.glob("dist/themes/*") do |dir|
186
- theme = File.basename(dir)
187
- config = theme_config(nil, theme)
188
- manifest.push({
189
- name: theme,
190
- title: config["name"],
191
- product_id: nil,
192
- info: config["description"],
193
- date: Time.now.strftime("%Y-%m-%d %H:%M:%S"),
194
- url: "http://127.0.0.1:#{self.port}/issue/#{theme}.hpub",
195
- cover: "http://127.0.0.1:#{self.port}/themes/#{theme}/thumbs/#{config["templates"][0]}.png"
196
- })
197
- end
198
- manifest.to_json
199
- end
200
-
201
- def mount(path, &block)
202
- self.webrick.mount_proc(path, &block)
203
- end
204
-
205
- def run!
206
- trap 'INT' do
207
- self.webrick.shutdown
208
- end
209
- self.webrick.start
210
- end
211
-
212
- end
213
- end
214
- end