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 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,2 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/appbox_octopress')
@@ -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: []