appbox-octopress 0.0.1
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 +7 -0
- data/bin/appbox-octopress +2 -0
- data/lib/appbox_octopress.rb +12 -0
- data/lib/appbox_octopress/utilities.rb +39 -0
- data/templates/css/appbox.css +140 -0
- data/templates/plugins/appbox.rb +182 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f56277fa6cf5fef3f50dc3c6dc555ac65184d5cc
|
4
|
+
data.tar.gz: c3d11e6776716699fb6d032d02f38dda5742b6dd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4f479dc3b47a10d1487c0c37a67b6134f5ac1a0bda3c02413827bea8dd9df948a604f44bd7db7c73ae1f88ca1b3f5600440eb1a8772d285ee4e52339a7d2854a
|
7
|
+
data.tar.gz: 30cc3628dff45045a5181c5d85e7eafcb90cf74cd1e34f9cacd446f049cc7d21abce97d867a5150c81d194d5ed42f48ef551054674d7a4c987c92076e56de189
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require File.join(File.dirname(__FILE__) + '/appbox_octopress/utilities')
|
3
|
+
|
4
|
+
if ARGV.length == 1 && ARGV[0] == 'install'
|
5
|
+
AppboxOctopress::Utilities.install
|
6
|
+
puts "Appbox Octopress installed"
|
7
|
+
elsif ARGV.length == 1 && ARGV[0] == 'remove'
|
8
|
+
AppboxOctopress::Utilities.remove
|
9
|
+
puts "Appbox Octopress removed"
|
10
|
+
else
|
11
|
+
puts "Usage: appbox-octopress [install|remove]"
|
12
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module AppboxOctopress
|
2
|
+
module Utilities
|
3
|
+
PLUGINS_DIR = File.expand_path(File.dirname(__FILE__) + '/../../templates/plugins')
|
4
|
+
CSS_DIR = File.expand_path(File.dirname(__FILE__) + '/../../templates/css')
|
5
|
+
|
6
|
+
def self.install
|
7
|
+
FileUtils.copy_file plugin_path, plugin_destination
|
8
|
+
FileUtils.copy_file css_path, css_destination
|
9
|
+
add_stylesheet
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.remove
|
13
|
+
FileUtils.rm plugin_destination
|
14
|
+
FileUtils.rm css_destination
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def self.plugin_path
|
20
|
+
File.join(PLUGINS_DIR, 'appbox.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.plugin_destination
|
24
|
+
File.join(Dir.pwd, 'plugins', 'appbox.rb')
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.css_path
|
28
|
+
File.join(CSS_DIR, 'appbox.css')
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.css_destination
|
32
|
+
File.join(Dir.pwd, 'source', 'stylesheets', 'appbox.css')
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.add_stylesheet
|
36
|
+
File.open('source/_includes/custom/head.html', 'a') { |file| file << "<link href=\"{{ root_url }}/stylesheets/appbox.css\" media=\"screen, projection\" rel=\"stylesheet\" type=\"text/css\">\n"}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
.star {
|
2
|
+
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAQAAADI+WwIAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAJiS0dEAP+Hj8y/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAACXZwQWcAAAALAAAACgCF+qVAAAAAhUlEQVQI103NMQqCABgF4C+Fxg7QHDQ0JkFnaKqlKJBu4Np9hEDoBq2doCYP0B4UBKLYUKZvex+P/+9N/dJ3FXl9S9CopbF9U1pOkAgb3irVanOMlGqldeBoo9CmspMFOFmp/hzLmtuXzvrWvpwJFVJvLLqci8Qmzl8OhzBwcMdD6ilXfwAd9B9f78yTCQAAAABJRU5ErkJggg==) no-repeat;
|
3
|
+
background-size: 11px 10px;
|
4
|
+
}
|
5
|
+
|
6
|
+
.unstar {
|
7
|
+
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAQAAADI+WwIAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAJiS0dEAP+Hj8y/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAACXZwQWcAAAALAAAACgCF+qVAAAAAo0lEQVQI1z2NMQrCQBRE32YxGFDwBGJnYZkll0ilpDISLO28k4lFwN7CTsTKSisbK8ELCJFI/BZJdn41j/kzSqiVuZ3r1yzeAAanoajpcOwsW2dxf+0yWGe6CaVzNmgY4VHyQKAiVsIlUlvc9otK4lXugNnJjKqlkpi86X6exIZfNztZBGhKUgr4hBZ3A3UX4ye/CYdeWHch7MOzJ9R3jFLt8we7izGyoi32iQAAAABJRU5ErkJggg==) no-repeat;
|
8
|
+
background-size: 11px 10px;
|
9
|
+
}
|
10
|
+
.half-star {
|
11
|
+
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAQAAADI+WwIAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAJdnBBZwAAAAsAAAAKAIX6pUAAAACTSURBVAjXTY0xCsJAEEVfdiEgpPAWFpYTvMRWSioDwdIuh7GydbEIeAM7sU1lo42tR1CEdSzMJk4178H/H7qTVK4+A0URTNTMmZhVhEHXMK69/UEiS3Z0sOGOQqBMQAr2pABbgKDlujHQHlgQYpdWeRO7z/0Cj8swOcPyxvOEl/vXN/K2+kw5Zq4PipNR/E+Ft8IX7yMjsFUGo0cAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzVxteM2AAAAAElFTkSuQmCC) no-repeat;
|
12
|
+
background-size: 11px 10px;
|
13
|
+
}
|
14
|
+
.rating {
|
15
|
+
width: 11px;
|
16
|
+
height: 10px;
|
17
|
+
display: inline-block;
|
18
|
+
background-size: 11px 10px
|
19
|
+
}
|
20
|
+
|
21
|
+
.appicon {
|
22
|
+
width: 64px;
|
23
|
+
height: 64px;
|
24
|
+
float: left;
|
25
|
+
margin: 10px !important;
|
26
|
+
border-radius: 5px;
|
27
|
+
-moz-border-radius: 5px;
|
28
|
+
-webkit-border-radius: 5px
|
29
|
+
}
|
30
|
+
|
31
|
+
.appbox {
|
32
|
+
clear: both;
|
33
|
+
font-family: Arial;
|
34
|
+
border: 1px solid #E5E5E5;
|
35
|
+
background-color: #F9F9F9;
|
36
|
+
width: auto;
|
37
|
+
line-height: 1;
|
38
|
+
color: #545450;
|
39
|
+
margin: 16px 0;
|
40
|
+
font-size: 1em/16px;
|
41
|
+
}
|
42
|
+
|
43
|
+
.appdetails {
|
44
|
+
font-size: .95em;
|
45
|
+
margin: 10px;
|
46
|
+
height: 64px;
|
47
|
+
}
|
48
|
+
|
49
|
+
.apptitle {
|
50
|
+
font-size: 1.15em;
|
51
|
+
font-weight: bold;
|
52
|
+
height: 22px;
|
53
|
+
padding: 0;
|
54
|
+
margin: 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
.apptitle a {
|
58
|
+
color: #000 !important;
|
59
|
+
}
|
60
|
+
|
61
|
+
.apptitle a:hover {
|
62
|
+
text-decoration: none !important;
|
63
|
+
color: #B4B4B4 !important;
|
64
|
+
}
|
65
|
+
|
66
|
+
.developer {
|
67
|
+
height: 21px;
|
68
|
+
line-height: 21px;
|
69
|
+
vertical-align: middle;
|
70
|
+
padding: 0;
|
71
|
+
margin: 0;
|
72
|
+
}
|
73
|
+
|
74
|
+
.price {
|
75
|
+
height: 20px;
|
76
|
+
display: table-cell;
|
77
|
+
vertical-align: bottom;
|
78
|
+
padding: 0;
|
79
|
+
margin: 0;
|
80
|
+
}
|
81
|
+
|
82
|
+
.screenshots {
|
83
|
+
width: auto;
|
84
|
+
margin: 0 auto;
|
85
|
+
padding: 10px;
|
86
|
+
}
|
87
|
+
|
88
|
+
.screenshots .slider {
|
89
|
+
overflow-x: scroll;
|
90
|
+
overflow-y: hidden;
|
91
|
+
height: 300px;
|
92
|
+
margin-top: 0;
|
93
|
+
}
|
94
|
+
|
95
|
+
.screenshots .slider ul {
|
96
|
+
padding: 0 !important;
|
97
|
+
margin: 0 !important;
|
98
|
+
list-style-image: none;
|
99
|
+
white-space: nowrap;
|
100
|
+
}
|
101
|
+
|
102
|
+
.screenshots .slider ul li {
|
103
|
+
padding: 0;
|
104
|
+
margin: 0;
|
105
|
+
margin-right: 6px;
|
106
|
+
list-style-type: none;
|
107
|
+
display: inline;
|
108
|
+
}
|
109
|
+
|
110
|
+
.screenshots .slider ul li:last-child {
|
111
|
+
margin-right: 0;
|
112
|
+
}
|
113
|
+
|
114
|
+
.screenshots .slider ul li img {
|
115
|
+
height: 300px !important;
|
116
|
+
display: inline;
|
117
|
+
}
|
118
|
+
|
119
|
+
.appbutton {
|
120
|
+
height: 44px;
|
121
|
+
float: right;
|
122
|
+
margin: 10px;
|
123
|
+
display: inline-block;
|
124
|
+
background-color: #E5E5E5;
|
125
|
+
border: 1px solid #E5E5E5;
|
126
|
+
padding: 10px 15px;
|
127
|
+
font-weight: bold;
|
128
|
+
font-size: .95em;
|
129
|
+
line-height: 1.6em;
|
130
|
+
text-align: center;
|
131
|
+
border-radius: 5px;
|
132
|
+
-moz-border-radius: 5px;
|
133
|
+
-webkit-border-radius: 5px;
|
134
|
+
}
|
135
|
+
|
136
|
+
.appbutton:hover {
|
137
|
+
background-color: #C1C1C1;
|
138
|
+
color: #FFF;
|
139
|
+
text-decoration: none !important;
|
140
|
+
}
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'digest/md5'
|
7
|
+
|
8
|
+
module Jekyll
|
9
|
+
class AppBox < Liquid::Tag
|
10
|
+
|
11
|
+
@id = ''
|
12
|
+
@store = ''
|
13
|
+
@style = ''
|
14
|
+
|
15
|
+
def initialize(tag_name, markup, tokens)
|
16
|
+
super
|
17
|
+
@result = Hash.new
|
18
|
+
|
19
|
+
@resultarray = ['icon', 'screenshots', 'name', 'url', 'version', 'price', 'developer', 'developerurl','rating']
|
20
|
+
|
21
|
+
@cachefolder = File.expand_path "../.appboxcache", File.dirname(__FILE__)
|
22
|
+
FileUtils.mkdir_p @cachefolder
|
23
|
+
|
24
|
+
if markup =~ /([A-Za-z]+)(\s[A-Za-z]+\s|\s)([A-Za-z._0-9]+)/i
|
25
|
+
@id = $3.strip
|
26
|
+
@style = $2.strip
|
27
|
+
@store = $1.strip
|
28
|
+
else
|
29
|
+
puts "Error with Markup. Your Values -- Id: #{@id} -- Style: #{@style} -- Store: #{@store}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def render(context)
|
34
|
+
# Get ID of post to generate identifying MD5 hash
|
35
|
+
@post_id = context["page"]["id"]
|
36
|
+
# make sure to pass only posts with id
|
37
|
+
unless @post_id.nil?
|
38
|
+
if File.exist? get_cached_file(@store, @id, @post_id)
|
39
|
+
get_cached_data(@id)
|
40
|
+
else
|
41
|
+
if @store == 'appstore'
|
42
|
+
apple_fetch_data(@id)
|
43
|
+
elsif @store == 'googleplay'
|
44
|
+
googleplay_fetch_data(@id)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
out = ''
|
49
|
+
out += get_small_style
|
50
|
+
|
51
|
+
if @style == 'screenshots'
|
52
|
+
out += get_screenshot_style
|
53
|
+
end
|
54
|
+
out += get_footer
|
55
|
+
|
56
|
+
%(#{out})
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def get_small_style
|
62
|
+
|
63
|
+
small = ''
|
64
|
+
small += "<p><div class=\"appbox\"><a class=\"appbutton\" href=\"#{@result["url"]}\">"
|
65
|
+
if @store == 'appstore'
|
66
|
+
small += "Go to <br />AppStore"
|
67
|
+
elsif @store == 'googleplay'
|
68
|
+
small += "Go to <br /> PlayStore"
|
69
|
+
end
|
70
|
+
small += "</a>"
|
71
|
+
small += "<div><a href=\"#{@result["url"]}\">"
|
72
|
+
small += "<img class=\"appicon\" src=\"#{@result["icon"]}\" /></a></div>"
|
73
|
+
small += "<div class=\"appdetails\"><div class=\"apptitle\"><a href=\"#{@result["url"]}\">#{@result["name"]}</a></div>"
|
74
|
+
small += "<div class=\"developer\"><a href=\"#{@result["developerurl"]}\">#{@result["developer"]}</a></div>"
|
75
|
+
small += "<div class=\"price\">#{@result["price"]} #{get_rating_stars(@result["rating"])}</div>"
|
76
|
+
small += "</div>"
|
77
|
+
small
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_footer
|
81
|
+
footer = ''
|
82
|
+
footer += "</div></p>"
|
83
|
+
footer
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_screenshot_style
|
87
|
+
screenshots = ''
|
88
|
+
|
89
|
+
screenshots += "<div class=\"screenshots\"><div class=\"slider\"><ul>"
|
90
|
+
unless @result["screenshots"].empty?
|
91
|
+
@result["screenshots"].each do |screenshot|
|
92
|
+
screenshots += "<li><img src=\"#{screenshot}\" /></li>"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
screenshots += "</ul></div></div>"
|
96
|
+
screenshots
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_rating_stars(value)
|
100
|
+
stars = ''
|
101
|
+
value.to_i.times do |star|
|
102
|
+
stars += "<span class=\"rating star\"></span>"
|
103
|
+
end
|
104
|
+
unless value.modulo(1) < 0.5
|
105
|
+
stars += "<span class=\"rating half-star\"></span>"
|
106
|
+
end
|
107
|
+
halfstar = 0
|
108
|
+
halfstar = 1 if value.modulo(1) >= 0.5
|
109
|
+
(5 - value.to_i - halfstar).times do |emptystar|
|
110
|
+
stars += "<span class=\"rating unstar\"></span>"
|
111
|
+
end
|
112
|
+
stars
|
113
|
+
end
|
114
|
+
|
115
|
+
def apple_fetch_data(app_id)
|
116
|
+
requestarray = ['artworkUrl512','screenshotUrls','trackName','trackViewUrl','version','formattedPrice','artistName','artistViewUrl', 'averageUserRatingForCurrentVersion']
|
117
|
+
|
118
|
+
url = "http://itunes.apple.com/lookup?id=#{app_id}"
|
119
|
+
resp = Net::HTTP.get_response(URI.parse(url))
|
120
|
+
app_data = JSON.parse resp.body
|
121
|
+
|
122
|
+
@resultarray.zip(requestarray).each do |result,request|
|
123
|
+
@result[result] = app_data["results"][0][request]
|
124
|
+
end
|
125
|
+
|
126
|
+
save_cached_data(get_cached_file(@store, app_id, @post_id))
|
127
|
+
end
|
128
|
+
|
129
|
+
def googleplay_fetch_data(app_id)
|
130
|
+
base_url = 'https://play.google.com'
|
131
|
+
|
132
|
+
doc = Nokogiri::HTML(open("#{base_url}/store/apps/details?id=#{app_id}"), nil, 'utf-8')
|
133
|
+
|
134
|
+
# requestarray hints:
|
135
|
+
# 1) App Icon e.g. big icon in Chrome Webstore
|
136
|
+
# 2) Array of screenshots
|
137
|
+
# 3) Name of the app
|
138
|
+
# 4) URL to the app
|
139
|
+
# 5) Versionnumber of the app
|
140
|
+
# 6) Price of the app
|
141
|
+
# 7) Developername
|
142
|
+
# 8) Developer URL
|
143
|
+
# 9) Rating value
|
144
|
+
|
145
|
+
requestarray = [ doc.css("div.cover-container img").first['src'],
|
146
|
+
doc.css("div.thumbnails img.screenshot").collect {|thumb| thumb['src']},
|
147
|
+
doc.css("div.info-container div.document-title div").first.content,
|
148
|
+
base_url + "/store/apps/details?id=#{app_id}",
|
149
|
+
doc.css("div[itemprop=softwareVersion]").first.content.strip,
|
150
|
+
doc.css("meta[itemprop=price]").first['content'],
|
151
|
+
doc.css("div.info-container div a.document-subtitle").first.content,
|
152
|
+
base_url + doc.css("div.info-container div a.document-subtitle").first['href'],
|
153
|
+
doc.css("div.tiny-star div.current-rating").first['style'][/\d+\.\d+/].to_f.round(1) / 100 * 5
|
154
|
+
]
|
155
|
+
@resultarray.zip(requestarray).each do |result, request|
|
156
|
+
@result[result] = request
|
157
|
+
end
|
158
|
+
|
159
|
+
save_cached_data(get_cached_file(@store, app_id, @post_id))
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_cached_data(app_id)
|
163
|
+
cached_file = get_cached_file(@store, app_id, @post_id)
|
164
|
+
@result = JSON.parse File.read cached_file if File.exist? cached_file
|
165
|
+
return nil if @result.nil?
|
166
|
+
end
|
167
|
+
|
168
|
+
def save_cached_data(cached_file)
|
169
|
+
File.open(cached_file, "w") do |file|
|
170
|
+
file.write @result.to_json
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def get_cached_file(store, app_id, post_id)
|
175
|
+
File.join @cachefolder, "#{store}_#{app_id}-#{Digest::MD5.hexdigest(post_id)}.cache"
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
Liquid::Template.register_tag('appbox', Jekyll::AppBox)
|
182
|
+
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: appbox-octopress
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Philipp Jaeckel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Parse and visualize data from AppStore and GooglePlay Store to display
|
14
|
+
it in Octopress or Jekyll posts
|
15
|
+
email: mail@sots.name
|
16
|
+
executables:
|
17
|
+
- appbox-octopress
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/appbox_octopress/utilities.rb
|
22
|
+
- lib/appbox_octopress.rb
|
23
|
+
- bin/appbox-octopress
|
24
|
+
- templates/css/appbox.css
|
25
|
+
- templates/plugins/appbox.rb
|
26
|
+
homepage: http://rubygems.org/gems/appbox-octopress
|
27
|
+
licenses:
|
28
|
+
- MIT
|
29
|
+
metadata: {}
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 2.1.10
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: AppBox Octopress
|
50
|
+
test_files: []
|