maglove 0.5.2 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20485f270588ad311854a3af53e8b0a7a4bd8b2c
4
- data.tar.gz: edfd342cc45467d5686043e5f6862814efc4cd71
3
+ metadata.gz: 68e99357e1c9657d692067ffc9ccc18ec8abf2b3
4
+ data.tar.gz: 3ff5da3c4f3b972aa400d3eb63cad8bfc59945f0
5
5
  SHA512:
6
- metadata.gz: 08b42d4c6f5e509445b835f1f7015e8574bdfe77218f7d67a714389d5291f87439445842deac4f9100bd459916b949bc959ee529fc1916abadbca1e6fbcf85dc
7
- data.tar.gz: 7da51b86c57e1f40cfe44b9f47d1981fe8d9bc4e0d0ac8c87145e063ed2e42762a81b4be3b4b4314ab333fc0064f29b06e483f78c2409805a418751ed7e3245f
6
+ metadata.gz: 82928b5fe88f1a0c3480dea707b37c9686f6245032490a28c0de387b252f251719f539740eaa659321fb7dd9bd08da8bb7e36ad3c763239d3ddc352e31d8b9b7
7
+ data.tar.gz: fb52aa0ae644a31f511542d71fdb2a46b63e3dfdb29cf9408f095ddaa7018f46298b46ad033266a3d2c7bac709457e9a4bc9482f556c62287c75a58497fc1920
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- maglove (0.5.2)
4
+ maglove (0.5.4)
5
5
  activesupport (~> 4.2)
6
6
  bundler (~> 1.10)
7
7
  coffee-script (~> 2.4)
@@ -44,7 +44,7 @@ GEM
44
44
  dotenv (2.0.2)
45
45
  execjs (2.6.0)
46
46
  exifr (1.2.3.1)
47
- filewatcher (0.5.2)
47
+ filewatcher (0.5.3)
48
48
  trollop (~> 2.0)
49
49
  fspath (2.1.1)
50
50
  haml (4.0.7)
@@ -55,7 +55,7 @@ GEM
55
55
  nokogiri (~> 1.6)
56
56
  highline (1.7.8)
57
57
  i18n (0.7.0)
58
- image_optim (0.21.0)
58
+ image_optim (0.22.0)
59
59
  exifr (~> 1.2, >= 1.2.2)
60
60
  fspath (~> 2.1)
61
61
  image_size (~> 1.3)
@@ -75,17 +75,17 @@ GEM
75
75
  little-plugger (~> 1.1)
76
76
  multi_json (~> 1.10)
77
77
  method_source (0.8.2)
78
- mini_portile (0.6.2)
78
+ mini_portile2 (2.0.0)
79
79
  minitar (0.5.4)
80
80
  minitest (5.8.3)
81
81
  multi_json (1.11.2)
82
- nokogiri (1.6.6.4)
83
- mini_portile (~> 0.6.0)
82
+ nokogiri (1.6.7)
83
+ mini_portile2 (~> 2.0.0.rc2)
84
84
  parser (2.2.2.6)
85
85
  ast (>= 1.1, < 3.0)
86
86
  powerpack (0.1.1)
87
87
  progress (3.1.0)
88
- pry (0.10.1)
88
+ pry (0.10.3)
89
89
  coderay (~> 1.1.0)
90
90
  method_source (~> 0.8.1)
91
91
  slop (~> 3.4)
@@ -0,0 +1,150 @@
1
+ /*
2
+ * Baker Ebook Framework - Basic Book
3
+ * last update: 2011-10-10
4
+ *
5
+ * Copyright (C) 2011 by Davide S. Casali <folletto AT gmail DOT com>
6
+ *
7
+ */
8
+
9
+
10
+
11
+ /****************************************************************************************************
12
+ * General
13
+ */
14
+ body {
15
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
16
+ font-size: 16px;
17
+ margin: 0;
18
+ background: #CCCCCC;
19
+ }
20
+
21
+ a {
22
+ color: #171717;
23
+ text-shadow: 0px 1px 0px #FFFFFF;
24
+ }
25
+
26
+
27
+ /****************************************************************************************************
28
+ * Typography
29
+ */
30
+ p, ul, ol {
31
+ font-size: 18px;
32
+ line-height: 40px;
33
+ }
34
+
35
+ h1, h2, h3, h4, h5, h6 {
36
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
37
+ font-weight: normal;
38
+ text-align: center;
39
+
40
+ border: 0;
41
+ margin: 0;
42
+ padding: 0;
43
+ }
44
+
45
+ /****************************************************************************************************
46
+ * Index
47
+ */
48
+ #index {
49
+ background: #CCC;
50
+ padding: 16px 0px 16px 16px;
51
+ }
52
+ #index .navigation h6,
53
+ #index .navigation ol li a small {
54
+ display: none;
55
+ }
56
+
57
+ #index .navigation ol {
58
+ display: inline;
59
+ padding: 0;
60
+ margin-right: 0px;
61
+ }
62
+
63
+ #index .navigation ol:after {
64
+ display: block;
65
+ clear: both;
66
+ content: '';
67
+ }
68
+
69
+ #index .navigation h5 {
70
+ background: #cf0000;
71
+ color: #ffffff;
72
+ display: inline-block;
73
+ font-size: 20px;
74
+
75
+ padding: 5px;
76
+ width: 55px;
77
+ height: 140px;
78
+ }
79
+
80
+ #index .navigation li {
81
+ background-position: top center;
82
+ background-size: 100%;
83
+ background-color: #FFF;
84
+ display: inline-block;
85
+ margin-right: 16px;
86
+ overflow: hidden;
87
+ position: relative;
88
+ padding: 0;
89
+ width: 150px;
90
+ vertical-align: top;
91
+ border: 4px solid #FFF;
92
+ float: left;
93
+ }
94
+
95
+ #index .navigation li.active, #index .navigation li:hover {
96
+ border-color: #FC4482;
97
+ }
98
+
99
+ #index .navigation li a {
100
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
101
+ font-weight: normal;
102
+ text-align: center;
103
+ text-decoration: none;
104
+ display: block;
105
+ width: 150px;
106
+ min-height: 108px;
107
+ max-height: 200px;
108
+ position: relative;
109
+ overflow: hidden;
110
+ }
111
+
112
+ #index .navigation li a img {
113
+ width: 100%;
114
+ display: inline-block;
115
+ float: left;
116
+ transition: transform 0.3s ease-in-out;
117
+ transition: -webkit-transform 0.3s ease-in-out;
118
+ -webkit-tap-highlight-color: transparent;
119
+ }
120
+
121
+
122
+ /* #index .navigation li a:focus img, #index .navigation li a:hover img, #index .navigation li a img:active { */
123
+ #index .navigation li.active a img {
124
+ -webkit-transform: scale(1.5, 1.5) rotate(15deg);
125
+ transform: scale(1.5, 1.5) rotate(15deg);
126
+ }
127
+
128
+ #index .navigation li a h7 {
129
+ display:none; /* temporarily hidden */
130
+ background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.36) 80%);
131
+ font-size: 12px;
132
+ padding: 42px 8px 8px;
133
+ position: absolute;
134
+ z-index: 2;
135
+ left: 0px;
136
+ right: 0px;
137
+ bottom: 0;
138
+ line-height: 20px;
139
+ color: #FFF;
140
+ text-shadow: 0px 1px 0px #000;
141
+ font-weight: bold;
142
+ text-transform: uppercase;
143
+ letter-spacing: 1px;
144
+ }
145
+
146
+ #index .navigation li a:after {
147
+ clear: both;
148
+ content: '';
149
+ display: block;
150
+ }
@@ -0,0 +1,31 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= "#{name} - Index"
5
+ %meta{'charset' => 'utf-8'}/
6
+ %meta{'name' => 'viewport', 'content' => 'width=device-width, height=208, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'}/
7
+ %link{'rel' => 'stylesheet', 'href' => 'stylesheets/index.css'}/
8
+ %body{'style' => "width: #{(174*templates.count)+16}px;"}
9
+ #index
10
+ .navigation
11
+ %ol
12
+ - templates.each_with_index do |template, index|
13
+ %li
14
+ %a{'href' => "#{template}.html"}
15
+ %img{'src' => "thumbs/#{template}.png"}
16
+ %h7= template
17
+ %small= "Page #{index+1}"
18
+ :javascript
19
+ var activateItem = function(event) {
20
+ if(event.target.nodeName === "IMG") {
21
+ var listItems = document.body.querySelectorAll(".navigation li");
22
+ for(var i=0; i<listItems.length; i++) {
23
+ listItems[i].classList.toggle("active", false);
24
+ }
25
+ event.target.parentNode.parentNode.classList.toggle("active", true);
26
+ }
27
+ };
28
+ var initialListItems = document.body.querySelectorAll(".navigation li");
29
+ for(var i=0; i<initialListItems.length; i++) {
30
+ initialListItems[i].addEventListener("click", activateItem, false);
31
+ }
@@ -0,0 +1,12 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= template
5
+ %meta{'charset' => 'utf-8'}/
6
+ %meta{'name' => 'viewport', 'content' => 'width=device-width, initial-scale=1.0'}/
7
+ %meta{'pageid' => template}/
8
+ %link{'rel' => 'stylesheet', 'href' => "./themes/#{theme}/theme.css"}/
9
+ %link{'rel' => 'stylesheet', 'href' => "./fonts/fonts.css"}/
10
+ %script{'type' => 'text/javascript', 'src' => "./themes/#{theme}/theme.js"}
11
+ %body
12
+ = contents
@@ -45,23 +45,27 @@ module MagLove
45
45
  end
46
46
 
47
47
  def write!
48
+ write_to!(output_path)
49
+ end
50
+
51
+ def write_to!(path)
48
52
  return false if not valid?
49
- FileUtils.mkdir_p(File.dirname(output_path))
53
+ FileUtils.mkdir_p(File.dirname(path))
50
54
 
51
- File.open("#{output_path}+", 'wb') do |f|
55
+ File.open("#{path}+", 'wb') do |f|
52
56
  f.write @contents
53
57
  end
54
58
 
55
59
  # Atomic write
56
- FileUtils.mv("#{output_path}+", output_path)
60
+ FileUtils.mv("#{path}+", path)
57
61
 
58
62
  # Set mtime correctly
59
- File.utime(mtime, mtime, output_path)
63
+ File.utime(mtime, mtime, path)
60
64
 
61
65
  true
62
66
  ensure
63
67
  # Ensure tmp file gets cleaned up
64
- FileUtils.rm("#{output_path}+") if File.exist?("#{output_path}+")
68
+ FileUtils.rm("#{path}+") if File.exist?("#{path}+")
65
69
  end
66
70
 
67
71
  def absolute_path
@@ -10,6 +10,11 @@ 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
+
13
18
  end
14
19
  end
15
20
  end
@@ -0,0 +1,214 @@
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
@@ -1,3 +1,3 @@
1
1
  module MagLove
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.4"
3
3
  end
data/lib/maglove.rb CHANGED
@@ -14,6 +14,7 @@ require "less"
14
14
  require "commander"
15
15
  require "image_optim"
16
16
  require "zlib"
17
+ require 'zip'
17
18
  require "archive/tar/minitar"
18
19
 
19
20
  require "maglove/version"
@@ -43,4 +44,5 @@ require "maglove/application"
43
44
  require "maglove/asset/theme"
44
45
  require "maglove/asset/base_theme"
45
46
  require "maglove/server"
47
+ require "maglove/hpub/server"
46
48
  require "maglove/template/tumblr"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maglove
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Strebitzer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-03 00:00:00.000000000 Z
11
+ date: 2015-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -304,6 +304,9 @@ files:
304
304
  - README.md
305
305
  - bin/maglove
306
306
  - data/maglove/dump.haml
307
+ - data/maglove/hpub/index.css
308
+ - data/maglove/hpub/index.haml
309
+ - data/maglove/hpub/page.haml
307
310
  - data/maglove/scaffold/base/base.coffee
308
311
  - data/maglove/scaffold/base/base.less
309
312
  - data/maglove/scaffold/base/images/base/loading-bars.svg
@@ -389,6 +392,7 @@ files:
389
392
  - lib/maglove/helper/command_helper.rb
390
393
  - lib/maglove/helper/log_helper.rb
391
394
  - lib/maglove/helper/theme_helper.rb
395
+ - lib/maglove/hpub/server.rb
392
396
  - lib/maglove/phantom_script.rb
393
397
  - lib/maglove/server.rb
394
398
  - lib/maglove/template/tumblr.rb