Class: Rack::Html5

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/html5.rb

Overview

Rack::Html5 sets custom headers for each HTML5 feature the browser supports. It does this by parsing the user agent and matching the features to the browser version based on information provided on: caniuse.com/#eras=farpast,past,now&cats=HTML5&statuses=rec,pr,cr,wd,ietf&nodetails=1

The headers that are being set:

  • HTTP_X_DETECTED_BROWSER: Browser that has been DETECTED, eg.: Firefox

  • HTTP_X_DETECTED_VERSION: Version of the browser that has been DETECTED, eg.: 3.6.6

  • HTTP_X_SUPPORTS_HTML5_WYSIWYG: WYSIWYG editable elements

  • HTTP_X_SUPPORTS_HTML5_CLASSNAME: getElementsByClassName

  • HTTP_X_SUPPORTS_HTML5_ELEMENTS: Stylable HTML5 elements

  • HTTP_X_SUPPORTS_HTML5_CANVAS: Canvas (basic support)

  • HTTP_X_SUPPORTS_HTML5_MESSAGING: Cross-document messaging

  • HTTP_X_SUPPORTS_HTML5_AUDIO: Audio element

  • HTTP_X_SUPPORTS_HTML5_VIDEO: Video element

  • HTTP_X_SUPPORTS_HTML5_TEXTAPI: Text API for canvas

  • HTTP_X_SUPPORTS_HTML5_DRAGANDDROP: Drag and drop

  • HTTP_X_SUPPORTS_HTML5_OFFLINE: Offline web applications

  • HTTP_X_SUPPORTS_HTML5_SVG: Inline SVG

  • HTTP_X_SUPPORTS_HTML5_FORMS: Form features (Web Forms 2.0)

Please note:

  • If the feature is not supported, the header will not be set.

  • If a browser implements a feature only partially, the corresponding header will not be set.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Html5

Returns a new instance of Html5.



28
29
30
31
# File 'lib/rack/html5.rb', line 28

def initialize(app)
  @app = app
  @features = []      
end

Instance Attribute Details

#browserObject

Returns the value of attribute browser.



26
27
28
# File 'lib/rack/html5.rb', line 26

def browser
  @browser
end

#envObject

Returns the value of attribute env.



26
27
28
# File 'lib/rack/html5.rb', line 26

def env
  @env
end

#featuresObject

Returns the value of attribute features.



26
27
28
# File 'lib/rack/html5.rb', line 26

def features
  @features
end

#user_agentObject

Returns the value of attribute user_agent.



26
27
28
# File 'lib/rack/html5.rb', line 26

def user_agent
  @user_agent
end

#versionObject

Returns the value of attribute version.



26
27
28
# File 'lib/rack/html5.rb', line 26

def version
  @version
end

Instance Method Details

#call(env) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/rack/html5.rb', line 41

def call(env)
  @env = env      
  @user_agent = @env['HTTP_USER_AGENT']
  
  detect_browser
  detect_features
  generate_headers
  
  @app.call(@env)
end

#comparable_version(v) ⇒ Object

New features are only being shipped with major version updated. So we’ll be on the safe side using the first two parts of the version number for comparisation. eg. version 10.5.6a will be cut down to 10.5, dots will be stripped, return value would be 105



81
82
83
# File 'lib/rack/html5.rb', line 81

def comparable_version(v)
  v.split(".")[0..1].join
end

#detect_browserObject

Detects the browser and version based on the user agent



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rack/html5.rb', line 53

def detect_browser     
  user_agent_matcher.each do |browser, regexp|        
    match = @user_agent.match(regexp)
    version = match.captures.first if match
    if version
      @browser = browser
      @version = version
      break
    end
  end
end

#detect_featuresObject

Detects the HTML5 features the browser supports



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/rack/html5.rb', line 66

def detect_features
  return unless @browser && @version
  feature_mapping[browser].each do |feature, version|
     if version           
       raise "Versions are not comparable: #{version}, #{@version}" if comparable_version(version).length != comparable_version(@version).length
       if comparable_version(@version) >= comparable_version(version)
         @features << feature
       end
     end
   end
end

#feature_mappingObject

Feature to browser version mapping according to the information provided on: caniuse.com/#eras=farpast,past,now&cats=HTML5&statuses=rec,pr,cr,wd,ietf&nodetails=1



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/rack/html5.rb', line 86

def feature_mapping
  {
    :firefox => {          
      :wysiwyg => "3.5",
      :classname => "3.0",
      :elements => "3.0",
      :canvas => "3.0",
      :messaging => "3.0",
      :audio => "3.5",
      :video => "3.5", 
      :textapi => "3.5",
      :draganddrop => "3.5", 
      :offline => "3.5", 
      :forms => nil,
      :svg => nil
    },
    :ie => {          
      :wysiwyg => "6.0",
      :classname => nil,
      :elements => nil,
      :canvas => nil,
      :messaging => "8.0",
      :audio => nil,
      :video => nil,
      :textapi => nil,
      :draganddrop => nil,
      :offline => nil,
      :forms => nil,
      :svg => nil
    }, 
    :opera => {
      :wysiwyg => "10.1",
      :classname => "10.1",
      :elements => "10.1",
      :canvas => "10.1",
      :messaging => "10.1",
      :audio => "10.5",
      :video => "10.5",
      :textapi => "10.5",
      :draganddrop => nil,
      :offline => "10.6",
      :forms => "10.1",
      :svg => nil          
    },         
    :chrome => {
      :wysiwyg => "3.0",
      :classname => "3.0",
      :elements => "3.0",
      :canvas => "3.0",
      :messaging => "3.0",
      :audio => "3.0",
      :video => "3.0",
      :textapi => "3.0",
      :draganddrop => "3.0",
      :offline => "4.0",
      :forms => nil,
      :svg => nil          
    }, 
    :safari => {
      :wysiwyg => "3.2",
      :classname => "3.2",
      :elements => "3.2",
      :canvas => "3.2",
      :messaging => "4.0",
      :audio => "3.2",
      :video => "3.2",
      :textapi => "4.2",
      :draganddrop => "4.0",
      :offline => "4.0",
      :forms => nil,
      :svg => nil          
    }
  }
end

#generate_headersObject



33
34
35
36
37
38
39
# File 'lib/rack/html5.rb', line 33

def generate_headers
  @env['HTTP_X_DETECTED_VERSION'] = version
  @env['HTTP_X_DETECTED_BROWSER'] = browser.to_s
  @features.each do |feature|
    @env["HTTP_X_SUPPORTS_HTML5_#{feature.to_s.upcase}"] = "true"
  end
end

#user_agent_matcherObject

Browser to user agent matching



162
163
164
165
166
167
168
169
170
171
# File 'lib/rack/html5.rb', line 162

def user_agent_matcher
  regexp_version = /((\d+\.?)+)/
  { 
    :firefox => /Firefox\/#{regexp_version}/, # eg. Firefox/1.5.0.12
    :ie => /MSIE #{regexp_version}/, # eg. compatible; MSIE 7.0;
    :chrome => /Chrome\/#{regexp_version}/, # eg. Chrome/5.0.307.11 Safari/532.9
    :safari => /AppleWebKit\/.*Version\/#{regexp_version}/, # eg. AppleWebKit/531.21.8 Version/4.0.4 Safari/531.21.10              
    :opera => /Opera\/#{regexp_version}/, # eg. Opera/9.80
  }
end