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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/maglove/command/server.rb +0 -5
- data/lib/maglove/server/hpub.rb +185 -0
- data/lib/maglove/server.rb +3 -0
- data/lib/maglove/version.rb +1 -1
- data/lib/maglove.rb +1 -1
- metadata +2 -2
- data/lib/maglove/hpub/server.rb +0 -214
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de2a076857bf9fc5e27988f5c13650ecfc6a92a7
|
4
|
+
data.tar.gz: cab8e9e7dfc96f8ced3101d779544500630fc4cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8bca796f465d49329fd353433171e0c2c62c3ee6e1bc4ac9c2a2ae6d2f62af9d5d060b3ea149563efcca17c0f5d3e2deccbddd77a10d386e31ca9775ff5f12f
|
7
|
+
data.tar.gz: 83c0ceec58dab01e8386b215a9ca241426fd943121e0b9b4c529af50351c8250a8024438fa66325036aa125aecb8cd6894099ef74d429e936946b73d18eaa41d
|
data/Gemfile.lock
CHANGED
@@ -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, "  ")
|
155
|
+
end
|
156
|
+
characters.force_encoding("BINARY").gsub(0xC2.chr+0xA0.chr+" "," ").gsub(0xC2.chr+0xA0.chr," ")
|
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
|
data/lib/maglove/server.rb
CHANGED
@@ -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={})
|
data/lib/maglove/version.rb
CHANGED
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
|
+
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
|
data/lib/maglove/hpub/server.rb
DELETED
@@ -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, "  ")
|
154
|
-
end
|
155
|
-
characters.force_encoding("BINARY").gsub(0xC2.chr+0xA0.chr+" "," ").gsub(0xC2.chr+0xA0.chr," ")
|
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
|