rack-smart-app-banner 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile.lock +13 -10
- data/{LICENSE → LICENSE.md} +1 -1
- data/README.md +42 -37
- data/Rakefile +7 -5
- data/lib/rack/smart-app-banner.rb +20 -16
- data/rack-smart-app-banner-0.1.0.gem +0 -0
- data/rack-smart-app-banner.gemspec +18 -16
- data/spec/fixtures/test.html +10 -0
- data/spec/rack_smart_app_banner_spec.rb +44 -0
- metadata +60 -47
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9958b9b0c48725ab6afeb9ce635d8373529632e8
|
4
|
+
data.tar.gz: d8990dc9b3b9dd69c91a0b6185362762ac5ed759
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dcbc39ffffc341e745d258e0a427aefdfc8cf38af3d0a4f090768ee866cd30db9200a7b8216dc9bc6b9993235a66c544592f05067ebd27e51afc411ad2601cdb
|
7
|
+
data.tar.gz: 1cef9f16c82f8c7bd021ebf9e7401ca6cc0e6089e5992b9e695063b634f0667622d1bc1688777d6576e50ef0e42c61a901d03991ac97c241bf34b6b41947d07f
|
data/Gemfile.lock
CHANGED
@@ -1,23 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rack-smart-app-banner (0.0
|
5
|
-
rack (>= 1.2.0,
|
4
|
+
rack-smart-app-banner (0.1.0)
|
5
|
+
rack (>= 1.2.0, < 2.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
minitest (2.
|
11
|
-
rack (1.
|
12
|
-
rack-test (0.
|
13
|
-
rack (>= 1.0)
|
14
|
-
rake (
|
10
|
+
minitest (2.12.1)
|
11
|
+
rack (1.6.11)
|
12
|
+
rack-test (0.8.3)
|
13
|
+
rack (>= 1.0, < 3)
|
14
|
+
rake (12.3.2)
|
15
15
|
|
16
16
|
PLATFORMS
|
17
17
|
ruby
|
18
18
|
|
19
19
|
DEPENDENCIES
|
20
|
-
minitest (~> 2.11
|
20
|
+
minitest (~> 2.11)
|
21
21
|
rack-smart-app-banner!
|
22
|
-
rack-test (~> 0.6
|
23
|
-
rake
|
22
|
+
rack-test (~> 0.6)
|
23
|
+
rake
|
24
|
+
|
25
|
+
BUNDLED WITH
|
26
|
+
2.0.1
|
data/{LICENSE → LICENSE.md}
RENAMED
data/README.md
CHANGED
@@ -1,65 +1,70 @@
|
|
1
|
-
rack-smart-app-banner
|
2
|
-
=====================
|
1
|
+
# rack-smart-app-banner
|
3
2
|
|
4
|
-
**Rack middleware to automatically include code for Smart App
|
5
|
-
|
6
|
-
![Smart App Banner Example](http://cl.ly/image/1K0W2F050a0h/smartappbanner.png)
|
3
|
+
**Rack middleware to automatically include code for Smart App Banners on iOS**
|
7
4
|
|
5
|
+
> Make it easy for users to discover and download your app from a website on iOS.
|
6
|
+
> With Safari’s Smart App Banner
|
7
|
+
> you can display a banner that provides a direct link to your app on the App Store,
|
8
|
+
> or opens the app if the user already has it installed.
|
9
|
+
> Smart App Banners integrate seamlessly,
|
10
|
+
> have the same look and feel users know from the App Store,
|
11
|
+
> and are easy to implement.
|
12
|
+
> <cite><a href="https://developer.apple.com/safari/resources/">Resources - Safari - Apple Developer</a></cite>
|
8
13
|
|
14
|
+
## Requirements
|
9
15
|
|
10
|
-
|
16
|
+
- Ruby 1.9 or higher
|
11
17
|
|
12
|
-
|
13
|
-
>
|
14
|
-
> If the app is already installed on a user's device, the banner intelligently changes its action, and tapping the banner will simply open the app. If the user doesn’t have your app on his device, tapping on the banner will take him to the app’s entry in the App Store.
|
18
|
+
## Installation
|
15
19
|
|
20
|
+
### Gemfile
|
16
21
|
|
22
|
+
```ruby
|
23
|
+
gem 'rack-smart-app-banner', require: 'rack/smart-app-banner'
|
24
|
+
```
|
17
25
|
|
18
26
|
## Usage
|
19
27
|
|
20
28
|
```ruby
|
21
|
-
require "rack/smart-app-banner"
|
22
|
-
|
23
29
|
use Rack::SmartAppBanner, app_id: "123456789",
|
24
30
|
affiliate_partner_id: 42,
|
25
31
|
affiliate_site_id: "abcdef123456",
|
26
|
-
app_argument: lambda {|request| request.path}
|
32
|
+
app_argument: lambda { |request| request.path }
|
27
33
|
```
|
28
34
|
|
29
|
-
|
35
|
+
Include this in the `config.ru` file of your Rack application,
|
36
|
+
to inject a corresponding `<meta>` tag into the `<head>` of each HTML document.
|
30
37
|
|
31
38
|
```html
|
32
|
-
<meta
|
39
|
+
<meta
|
40
|
+
name="apple-itunes-app"
|
41
|
+
content="app-id=123456789, affiliate-data=partnerId=42&siteID=abcdef123456 app-argument=http://listings/123"
|
42
|
+
/>
|
33
43
|
```
|
34
44
|
|
35
45
|
### Parameters
|
36
46
|
|
37
|
-
- `app_id`: _Required_.
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
- Ruby 1.9
|
47
|
+
- `app_id`: _Required_.
|
48
|
+
Your app's unique identifier.
|
49
|
+
To find your app ID from the [iTunes Link Maker](http://itunes.apple.com/linkmaker/),
|
50
|
+
type the name of your app in the Search field,
|
51
|
+
and select the appropriate country and media type.
|
52
|
+
In the results, find your app and select iPhone App Link in the column on the right.
|
53
|
+
Your app ID is the nine-digit number in between `id` and `?mt`.
|
54
|
+
- `affiliate_partner_id` & `affiliate_site_id`: _Optional_.
|
55
|
+
Your iTunes affiliate details, if you are an iTunes affiliate.
|
56
|
+
If you aren't, you can find out more about becoming an iTunes affiliate at
|
57
|
+
http://www.apple.com/itunes/affiliates/.
|
58
|
+
- `app_argument`: _Optional_.
|
59
|
+
A block that generates a URL that provides context to your native app.
|
60
|
+
If you include this and the user has your app installed,
|
61
|
+
they can jump from your website to the corresponding position in your iOS app.
|
54
62
|
|
55
63
|
## Contact
|
56
64
|
|
57
|
-
Mattt
|
58
|
-
|
59
|
-
- http://github.com/mattt
|
60
|
-
- http://twitter.com/mattt
|
61
|
-
- m@mattt.me
|
65
|
+
[Mattt](https://twitter.com/mattt)
|
62
66
|
|
63
67
|
## License
|
64
68
|
|
65
|
-
rack-smart-app-banner is available under the MIT license.
|
69
|
+
rack-smart-app-banner is available under the MIT license.
|
70
|
+
See the LICENSE file for more info.
|
data/Rakefile
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
2
4
|
Bundler.setup
|
3
5
|
|
4
|
-
gemspec = eval(File.read(
|
6
|
+
gemspec = eval(File.read('rack-smart-app-banner.gemspec'))
|
5
7
|
|
6
|
-
task :
|
8
|
+
task build: "#{gemspec.full_name}.gem"
|
7
9
|
|
8
|
-
file "#{gemspec.full_name}.gem" => gemspec.files + [
|
9
|
-
system
|
10
|
+
file "#{gemspec.full_name}.gem" => gemspec.files + ['rack-smart-app-banner.gemspec'] do
|
11
|
+
system 'gem build rack-smart-app-banner.gemspec'
|
10
12
|
system "gem install rack-smart-app-banner-#{Rack::SmartAppBanner::VERSION}.gem"
|
11
13
|
end
|
@@ -1,27 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
|
3
5
|
module Rack #:nodoc:
|
4
6
|
class SmartAppBanner
|
5
|
-
|
6
|
-
VERSION = "0.0.1"
|
7
|
+
VERSION = '0.1.0'
|
7
8
|
|
8
9
|
def initialize(app, options = {})
|
9
|
-
raise ArgumentError,
|
10
|
-
|
11
|
-
raise ArgumentError,
|
12
|
-
raise ArgumentError,
|
10
|
+
raise ArgumentError, 'App ID Required' unless options[:app_id] &&
|
11
|
+
!options[:app_id].empty?
|
12
|
+
raise ArgumentError, 'Incomplete Affiliate Information' if (options[:affiliate_partner_id] || options[:affiliate_site_id]) && !(options[:affiliate_partner_id] && options[:affiliate_site_id])
|
13
|
+
raise ArgumentError, 'App Argument Must Be Lambda' if options[:app_argument] && !options[:app_argument].lambda?
|
13
14
|
|
14
|
-
@app
|
15
|
+
@app = app
|
16
|
+
@options = options
|
15
17
|
end
|
16
18
|
|
17
19
|
def call(env)
|
18
20
|
@status, @headers, @response = @app.call(env)
|
19
21
|
return [@status, @headers, @response] unless html?
|
20
|
-
|
22
|
+
|
21
23
|
request = Rack::Request.new(env)
|
22
24
|
response = Rack::Response.new([], @status, @headers)
|
23
25
|
if @response.respond_to?(:to_ary)
|
24
|
-
@response.each do |fragment|
|
26
|
+
@response.each do |fragment|
|
25
27
|
response.write inject_smart_app_banner(request, fragment)
|
26
28
|
end
|
27
29
|
end
|
@@ -31,24 +33,26 @@ module Rack #:nodoc:
|
|
31
33
|
|
32
34
|
private
|
33
35
|
|
34
|
-
def html
|
36
|
+
def html?
|
37
|
+
@headers['Content-Type'] =~ /html/
|
38
|
+
end
|
35
39
|
|
36
40
|
def inject_smart_app_banner(request, response)
|
37
|
-
parameters = {'app-id' => @options[:app_id]}
|
38
|
-
parameters['affiliate-data'] = "partnerId=#{@options[:affiliate_partner_id]}&siteID=#{@options[:affiliate_site_id]}" if @options[:affiliate_partner_id]
|
41
|
+
parameters = { 'app-id' => @options[:app_id] }
|
42
|
+
parameters['affiliate-data'] = "partnerId=#{@options[:affiliate_partner_id]}&siteID=#{@options[:affiliate_site_id]}" if @options[:affiliate_partner_id] && @options[:affiliate_site_id]
|
39
43
|
parameters['app-argument'] = @options[:app_argument].call(request) if @options[:app_argument]
|
40
44
|
|
41
45
|
if argument = parameters['app-argument']
|
42
46
|
parameters['app-argument'] = "http://#{argument}" unless URI(argument).scheme
|
43
47
|
end
|
44
48
|
|
45
|
-
content = parameters.collect{|k, v| "#{k}=#{v}"}.join(
|
49
|
+
content = parameters.collect { |k, v| "#{k}=#{v}" }.join(', ')
|
46
50
|
|
47
|
-
meta =
|
48
|
-
<meta name="apple-itunes-app" content="#{content}" />
|
51
|
+
meta = <<~EOF
|
52
|
+
<meta name="apple-itunes-app" content="#{content}" />
|
49
53
|
EOF
|
50
54
|
|
51
|
-
response.gsub(%r{</head>}, meta +
|
55
|
+
response.gsub(%r{</head>}, meta + '</head>')
|
52
56
|
end
|
53
57
|
end
|
54
58
|
end
|
Binary file
|
@@ -1,25 +1,27 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
|
+
require 'rack/smart-app-banner'
|
4
5
|
|
5
6
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
7
|
-
s.authors = [
|
8
|
-
s.email =
|
9
|
-
s.
|
7
|
+
s.name = 'rack-smart-app-banner'
|
8
|
+
s.authors = ['Mattt']
|
9
|
+
s.email = 'mattt@me.com'
|
10
|
+
s.license = 'MIT'
|
11
|
+
s.homepage = 'https://github.com/mattt/rack-smart-app-banner'
|
10
12
|
s.version = Rack::SmartAppBanner::VERSION
|
11
13
|
s.platform = Gem::Platform::RUBY
|
12
|
-
s.summary =
|
13
|
-
s.description =
|
14
|
+
s.summary = 'rack-smart-app-banner'
|
15
|
+
s.description = 'Rack middleware to automatically include code for Smart App Banner, introduced in iOS 6.'
|
14
16
|
|
15
|
-
s.add_runtime_dependency
|
17
|
+
s.add_runtime_dependency 'rack', '>= 1.2.0', '< 2.0.0'
|
16
18
|
|
17
|
-
s.add_development_dependency
|
18
|
-
s.add_development_dependency
|
19
|
-
s.add_development_dependency
|
19
|
+
s.add_development_dependency 'minitest', '~> 2.11'
|
20
|
+
s.add_development_dependency 'rack-test', '~> 0.6'
|
21
|
+
s.add_development_dependency 'rake'
|
20
22
|
|
21
|
-
s.files = Dir[
|
23
|
+
s.files = Dir['./**/*'].reject { |file| file =~ %r{\./(bin|log|pkg|script|spec|test|vendor)} }
|
22
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
-
s.require_paths = [
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
26
|
+
s.require_paths = ['lib']
|
25
27
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'minitest/pride'
|
5
|
+
require 'rack'
|
6
|
+
require 'rack/lint'
|
7
|
+
require 'rack/mock'
|
8
|
+
require 'rack/smart-app-banner'
|
9
|
+
|
10
|
+
describe Rack::SmartAppBanner do
|
11
|
+
let(:html_file) do
|
12
|
+
File.read(File.expand_path('fixtures/test.html', __dir__))
|
13
|
+
end
|
14
|
+
let(:html_app) { proc { [200, { 'Content-Type' => 'text/html' }, [html_file]] } }
|
15
|
+
let(:text_app) { proc { [200, { 'Content-Type' => 'text/plain' }, ['TEXT']] } }
|
16
|
+
let(:typekit_html) { Rack::SmartAppBanner.new(html_app, app_id: '123456789') }
|
17
|
+
let(:typekit_text) { Rack::SmartAppBanner.new(text_app, app_id: '123456789') }
|
18
|
+
|
19
|
+
it { proc { Rack::SmartAppBanner.new(nil) }.must_raise(ArgumentError) }
|
20
|
+
|
21
|
+
it { typekit_html.must_be_kind_of(Rack::SmartAppBanner) }
|
22
|
+
it { typekit_text.must_be_kind_of(Rack::SmartAppBanner) }
|
23
|
+
|
24
|
+
describe 'script injection' do
|
25
|
+
describe 'html' do
|
26
|
+
let(:request) { Rack::MockRequest.new(Rack::Lint.new(typekit_html)) }
|
27
|
+
let(:response) { request.get('/') }
|
28
|
+
|
29
|
+
it { response.status.must_equal 200 }
|
30
|
+
it { response.body.must_match %(<meta name="apple-itunes-app" content="app-id=123456789" />) }
|
31
|
+
it { response.body.must_match '<title>Rack::SmartAppBanner Test</title>' }
|
32
|
+
it { response.body.must_match '<p>HTML</p>' }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'text' do
|
36
|
+
let(:request) { Rack::MockRequest.new(Rack::Lint.new(typekit_text)) }
|
37
|
+
let(:response) { request.get('/') }
|
38
|
+
|
39
|
+
it { response.status.must_equal 200 }
|
40
|
+
it { response.body.wont_match %(<meta name="apple-itunes-app" content="app-id=123456789" />) }
|
41
|
+
it { response.body.must_match 'TEXT' }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,105 +1,118 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-smart-app-banner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
- Mattt
|
7
|
+
- Mattt
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2019-07-08 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rack
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 1.2.0
|
22
|
-
- -
|
20
|
+
- - "<"
|
23
21
|
- !ruby/object:Gem::Version
|
24
22
|
version: 2.0.0
|
25
23
|
type: :runtime
|
26
24
|
prerelease: false
|
27
|
-
version_requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0
|
28
33
|
- !ruby/object:Gem::Dependency
|
29
34
|
name: minitest
|
30
|
-
requirement:
|
31
|
-
none: false
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
32
36
|
requirements:
|
33
|
-
- - ~>
|
37
|
+
- - "~>"
|
34
38
|
- !ruby/object:Gem::Version
|
35
|
-
version: 2.11
|
39
|
+
version: '2.11'
|
36
40
|
type: :development
|
37
41
|
prerelease: false
|
38
|
-
version_requirements:
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.11'
|
39
47
|
- !ruby/object:Gem::Dependency
|
40
48
|
name: rack-test
|
41
|
-
requirement:
|
42
|
-
none: false
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
43
50
|
requirements:
|
44
|
-
- - ~>
|
51
|
+
- - "~>"
|
45
52
|
- !ruby/object:Gem::Version
|
46
|
-
version: 0.6
|
53
|
+
version: '0.6'
|
47
54
|
type: :development
|
48
55
|
prerelease: false
|
49
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0.6'
|
50
61
|
- !ruby/object:Gem::Dependency
|
51
62
|
name: rake
|
52
|
-
requirement:
|
53
|
-
none: false
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
54
64
|
requirements:
|
55
|
-
- -
|
65
|
+
- - ">="
|
56
66
|
- !ruby/object:Gem::Version
|
57
|
-
version: 0
|
67
|
+
version: '0'
|
58
68
|
type: :development
|
59
69
|
prerelease: false
|
60
|
-
version_requirements:
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
61
75
|
description: Rack middleware to automatically include code for Smart App Banner, introduced
|
62
76
|
in iOS 6.
|
63
|
-
email:
|
77
|
+
email: mattt@me.com
|
64
78
|
executables: []
|
65
79
|
extensions: []
|
66
80
|
extra_rdoc_files: []
|
67
81
|
files:
|
68
|
-
- ./Gemfile
|
69
|
-
- ./Gemfile.lock
|
70
|
-
- ./
|
71
|
-
- ./
|
72
|
-
- ./
|
73
|
-
- ./
|
74
|
-
- ./
|
75
|
-
|
76
|
-
|
82
|
+
- "./Gemfile"
|
83
|
+
- "./Gemfile.lock"
|
84
|
+
- "./LICENSE.md"
|
85
|
+
- "./README.md"
|
86
|
+
- "./Rakefile"
|
87
|
+
- "./lib/rack/smart-app-banner.rb"
|
88
|
+
- "./rack-smart-app-banner-0.1.0.gem"
|
89
|
+
- "./rack-smart-app-banner.gemspec"
|
90
|
+
- spec/fixtures/test.html
|
91
|
+
- spec/rack_smart_app_banner_spec.rb
|
92
|
+
homepage: https://github.com/mattt/rack-smart-app-banner
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
77
96
|
post_install_message:
|
78
97
|
rdoc_options: []
|
79
98
|
require_paths:
|
80
99
|
- lib
|
81
100
|
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
101
|
requirements:
|
84
|
-
- -
|
102
|
+
- - ">="
|
85
103
|
- !ruby/object:Gem::Version
|
86
104
|
version: '0'
|
87
|
-
segments:
|
88
|
-
- 0
|
89
|
-
hash: 2669496524341184505
|
90
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
-
none: false
|
92
106
|
requirements:
|
93
|
-
- -
|
107
|
+
- - ">="
|
94
108
|
- !ruby/object:Gem::Version
|
95
109
|
version: '0'
|
96
|
-
segments:
|
97
|
-
- 0
|
98
|
-
hash: 2669496524341184505
|
99
110
|
requirements: []
|
100
111
|
rubyforge_project:
|
101
|
-
rubygems_version:
|
112
|
+
rubygems_version: 2.6.14
|
102
113
|
signing_key:
|
103
|
-
specification_version:
|
114
|
+
specification_version: 4
|
104
115
|
summary: rack-smart-app-banner
|
105
|
-
test_files:
|
116
|
+
test_files:
|
117
|
+
- spec/fixtures/test.html
|
118
|
+
- spec/rack_smart_app_banner_spec.rb
|