maglove 0.5.2 → 0.5.4

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: 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