appbox-octopress 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|