rack-swagger 0.0.1 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +1 -1
  3. data/README.md +85 -1
  4. data/Rakefile +30 -0
  5. data/lib/rack/swagger.rb +35 -1
  6. data/lib/rack/swagger/asset_server.rb +22 -0
  7. data/lib/rack/swagger/index_page_server.rb +32 -0
  8. data/lib/rack/swagger/json_server.rb +30 -0
  9. data/lib/rack/swagger/rentpath/logo_small.png +0 -0
  10. data/lib/rack/swagger/rentpath/rentpath.diff +47 -0
  11. data/lib/rack/swagger/routes_to_models.rb +111 -0
  12. data/lib/rack/swagger/server_helpers.rb +55 -0
  13. data/lib/rack/swagger/sinatra_helpers.rb +78 -0
  14. data/lib/rack/swagger/version.rb +1 -1
  15. data/rack-swagger.gemspec +8 -2
  16. data/spec/lib/rack/swagger/asset_server_spec.rb +18 -0
  17. data/spec/lib/rack/swagger/index_page_server_spec.rb +21 -0
  18. data/spec/lib/rack/swagger/routes_to_models_spec.rb +81 -0
  19. data/spec/lib/rack/swagger/server_helpers_spec.rb +44 -0
  20. data/spec/lib/rack/swagger/sinatra_helpers_spec.rb +85 -0
  21. data/spec/spec_helper.rb +25 -0
  22. data/swagger-ui/dist/css/reset.css +125 -0
  23. data/swagger-ui/dist/css/screen.css +1224 -0
  24. data/swagger-ui/dist/css/screen.css.orig +1224 -0
  25. data/swagger-ui/dist/images/explorer_icons.png +0 -0
  26. data/swagger-ui/dist/images/logo_small.png +0 -0
  27. data/swagger-ui/dist/images/pet_store_api.png +0 -0
  28. data/swagger-ui/dist/images/throbber.gif +0 -0
  29. data/swagger-ui/dist/images/wordnik_api.png +0 -0
  30. data/swagger-ui/dist/index.html +105 -0
  31. data/swagger-ui/dist/index.html.orig +105 -0
  32. data/swagger-ui/dist/lib/backbone-min.js +38 -0
  33. data/swagger-ui/dist/lib/handlebars-1.0.0.js +2278 -0
  34. data/swagger-ui/dist/lib/highlight.7.3.pack.js +1 -0
  35. data/swagger-ui/dist/lib/jquery-1.8.0.min.js +2 -0
  36. data/swagger-ui/dist/lib/jquery.ba-bbq.min.js +18 -0
  37. data/swagger-ui/dist/lib/jquery.slideto.min.js +1 -0
  38. data/swagger-ui/dist/lib/jquery.wiggle.min.js +8 -0
  39. data/swagger-ui/dist/lib/shred.bundle.js +2765 -0
  40. data/swagger-ui/dist/lib/shred/content.js +193 -0
  41. data/swagger-ui/dist/lib/swagger-client.js +1477 -0
  42. data/swagger-ui/dist/lib/swagger-oauth.js +211 -0
  43. data/swagger-ui/dist/lib/swagger.js +1678 -0
  44. data/swagger-ui/dist/lib/underscore-min.js +32 -0
  45. data/swagger-ui/dist/o2c.html +15 -0
  46. data/swagger-ui/dist/swagger-ui.js +2477 -0
  47. data/swagger-ui/dist/swagger-ui.min.js +1 -0
  48. data/swagger-ui/master.tar.gz +0 -0
  49. data/swagger-ui/swagger-ui-v2.0.22.tar +0 -0
  50. data/swagger_ui_version.yml +4 -0
  51. data/templates/swagger_ui_version.yml +4 -0
  52. metadata +132 -12
@@ -0,0 +1,55 @@
1
+ module Rack
2
+ module Swagger
3
+ module ServerHelpers
4
+ def swagger_dist_path
5
+ ::File.expand_path("../../../../swagger-ui/dist", __FILE__)
6
+ end
7
+
8
+ def swagger_index_html_path
9
+ ::File.join(swagger_dist_path, "index.html")
10
+ end
11
+
12
+ def display_file_or_404(type, file, root_or_resource=nil)
13
+ if ::File.exists?(file)
14
+ [
15
+ 200,
16
+ {
17
+ 'Content-Type' => type == :json ? 'application/json' : 'text/html',
18
+ 'Cache-Control' => 'public, max-age=86400'
19
+ },
20
+ ::StringIO.new(display_file(type, file, root_or_resource))
21
+ ]
22
+ else
23
+ [404, {}, ["Not found"]]
24
+ end
25
+ end
26
+
27
+ def display_file(type, file, root_or_resource=nil)
28
+ @files ||= {}
29
+ @files[file] ||= begin
30
+ contents = ::File.read(file)
31
+ contents = overwrite_base_path(contents, base_path_value(root_or_resource)) if type == :json
32
+ contents
33
+ end
34
+ end
35
+
36
+ def base_path_value(root_or_resource=nil)
37
+ if root_or_resource == :root
38
+ @opts[:overwrite_base_path] + "/docs/api-docs"
39
+ else
40
+ @opts[:overwrite_base_path]
41
+ end
42
+ end
43
+
44
+ def overwrite_base_path(contents, value)
45
+ if value
46
+ contents = JSON.parse(contents)
47
+ contents["basePath"] = value
48
+ contents.to_json
49
+ else
50
+ contents
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,78 @@
1
+ module Rack
2
+ module Swagger
3
+ module SinatraHelpers
4
+ def self.get_all_routes(*apps)
5
+ routes = {}
6
+ apps.each do |app|
7
+ routes_by_verb = get_routes app
8
+
9
+ HTTP_VERBS.each do |verb|
10
+ unless routes_by_verb[ verb ].nil?
11
+ routes[ verb ] ||= []
12
+ routes[ verb ] += routes_by_verb[ verb ]
13
+ end
14
+ end
15
+ end
16
+ routes
17
+ end
18
+
19
+ private
20
+
21
+ HTTP_VERBS = %w( GET
22
+ HEAD
23
+ POST
24
+ PUT
25
+ DELETE
26
+ TRACE
27
+ OPTIONS
28
+ CONNECT
29
+ PATCH )
30
+
31
+ def self.expand_routes(routes)
32
+ all_routes = routes.map do |r|
33
+ path = r[0].to_s
34
+
35
+ # this is to undo sinatra/base.rb#compile()
36
+ path = path.gsub(/^\(\?-mix:\\A\\/, "").
37
+ gsub(/\\z\)$/, "").
38
+ gsub(/\\\/\?$/,"").
39
+ gsub("([^#]+)?", "").
40
+ gsub("(?:\\.|%2[Ee])",".").
41
+ gsub("\\/","/")
42
+
43
+ # this is to replace the regexes with param names from the array
44
+ r[1].each do |param|
45
+ path = path.sub("([^/?#]+)", "{#{param}}")
46
+ end
47
+
48
+ # this is to split paths with optional pieces into more than one path
49
+ alternate_paths = []
50
+ path.split("/?").each do |segment|
51
+ if alternate_paths.last
52
+ alternate_paths << alternate_paths.last + "/" + segment.sub(/\?$/, "")
53
+ else
54
+ alternate_paths << segment.sub(/\?$/, "")
55
+ end
56
+ end
57
+
58
+ if alternate_paths.empty?
59
+ path
60
+ else
61
+ alternate_paths
62
+ end
63
+ end
64
+
65
+ all_routes.flatten
66
+ end
67
+
68
+ def self.get_routes(app)
69
+ routes_by_verb = {}
70
+ HTTP_VERBS.each do |verb|
71
+ routes = app.routes[verb]
72
+ routes_by_verb[ verb ] = routes.nil? ? nil : expand_routes( routes )
73
+ end
74
+ routes_by_verb
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Swagger
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.6"
4
4
  end
5
5
  end
@@ -18,6 +18,12 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.7"
22
- spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "rspec"
22
+ spec.add_development_dependency "rack-test"
23
+
24
+ spec.add_dependency "bundler", "~> 1.7"
25
+ spec.add_dependency "rake", "~> 10.0"
26
+ spec.add_dependency "rack", "~> 1.4"
27
+ spec.add_dependency "httpclient", "~> 2"
28
+ spec.add_dependency "activesupport"
23
29
  end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Swagger::AssetServer do
4
+ include Rack::Test::Methods
5
+ include Rack::Swagger::ServerHelpers
6
+
7
+ def app
8
+ Rack::Swagger::AssetServer.new
9
+ end
10
+
11
+ it "serves files from swagger-ui" do
12
+ first_file = Dir.glob(swagger_dist_path + "/css/*").first
13
+ first_file.gsub!(swagger_dist_path, "")
14
+
15
+ get "/docs" + first_file
16
+ expect(last_response.body).to eq(File.read(swagger_dist_path + first_file))
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Swagger::IndexPageServer do
4
+ include Rack::Test::Methods
5
+ include Rack::Swagger::ServerHelpers
6
+
7
+ def app
8
+ Rack::Swagger::IndexPageServer.new
9
+ end
10
+
11
+ it "serves index.html at docs/" do
12
+ get "/docs/", url: "api-docs"
13
+ expect(last_response.body).to eq(File.read(swagger_dist_path + "/index.html"))
14
+ end
15
+
16
+ it "redirects docs => docs/?url=api-docs" do
17
+ get "/docs"
18
+ expect(last_response.status).to eq(302)
19
+ expect(last_response.location).to eq("docs/?url=api-docs")
20
+ end
21
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::Swagger::RoutesToModels do
4
+ include Rack::Swagger::RoutesToModels
5
+
6
+ let(:expected_result) {{
7
+ "Listing" =>
8
+ {id:"Listing", properties:
9
+ {id:{type:"string"}, lat:{type:"number", format:"float"},
10
+ lng:{type:"number", format:"float"}, free:{type:"boolean",
11
+ format:"boolean"}
12
+ }
13
+ },
14
+ "Pins" =>
15
+ {id:"Pins", properties:
16
+ {total:
17
+ {type:"integer", format:"int64"},
18
+ listings:{type:"array", items:{"$ref"=>"Listing"}}
19
+ }
20
+ }
21
+ }}
22
+
23
+ let(:sample_response) {{
24
+ total:6,
25
+ listings:[
26
+ {id:"2395", lat:33.9482, lng:-84.261, free:false},
27
+ {id:"111", lat:33.9465, lng:-84.2262, free:false},
28
+ {id:"11413", lat:33.9444, lng:-84.2455, free:false},
29
+ {id:"83798", lat:33.9512, lng:-84.2451, free:false},
30
+ {id:"16993", lat:33.9696, lng:-84.2046, free:false},
31
+ {id:"16020", lat:33.9072, lng:-84.196, free:false}
32
+ ]
33
+ }}
34
+
35
+ let(:expected_result_2) {{
36
+ "AdMobBannerIds"=>
37
+ {:id=>"AdMobBannerIds",
38
+ :properties=>
39
+ {"AGBannerResultsListTelCoAdUnitId"=>{:type=>"string"},
40
+ "AGBannerResultsListAdUnitId"=>{:type=>"string"},
41
+ "AGBannerDetailsAdUnitId"=>{:type=>"string"},
42
+ "AGBannerDetailsTelCoAdUnitId_1"=>{:type=>"string"},
43
+ "AGBannerDetailsTelCoAdUnitId_2"=>{:type=>"string"},
44
+ "AGBannerThankYouAdUnitId"=>{:type=>"string"},
45
+ "AGBannerThankYouTelCoAdUnitId"=>{:type=>"string"}}},
46
+ "Config"=>
47
+ {:id=>"Config",
48
+ :properties=>
49
+ {"copyright"=>{:type=>"string"},
50
+ "offsiteAnalyticsFlag"=>{:type=>"string"},
51
+ "offsiteAnalyticsQueueLimit"=>{:type=>"string"},
52
+ "adMobBannerIds"=>{"$ref"=>"AdMobBannerIds"}
53
+ }
54
+ }
55
+ }}
56
+
57
+ let(:sample_response_2) {{
58
+ "copyright"=>
59
+ "Copyright 2014 RentPath, Inc. All rights reserved. All photos, videos, text and other content are the property of RentPath, Inc. APARTMENT GUIDE and the APARTMENT GUIDE Trade Dress are registered trademarks of RentPath, Inc. or its affiliates.",
60
+ "offsiteAnalyticsFlag"=>"true",
61
+ "offsiteAnalyticsQueueLimit"=>"50",
62
+ "adMobBannerIds"=>
63
+ {"AGBannerResultsListTelCoAdUnitId"=>
64
+ "/7449/mob.aptguide.com.%@/Search/tlp_p",
65
+ "AGBannerResultsListAdUnitId"=>"/7449/mob.aptguide.com.%@/Search/b_lb_p1",
66
+ "AGBannerDetailsAdUnitId"=>"/7449/mob.aptguide.com.%@/Detail/b_lb_p1",
67
+ "AGBannerDetailsTelCoAdUnitId_1"=>"/7449/mob.aptguide.com.%@/Detail/tdp_p1",
68
+ "AGBannerDetailsTelCoAdUnitId_2"=>"/7449/mob.aptguide.com.%@/Detail/tdp_p2",
69
+ "AGBannerThankYouAdUnitId"=>"/7449/mob.aptguide.com.%@/ThankYou/b_lb_p1",
70
+ "AGBannerThankYouTelCoAdUnitId"=>"/7449/mob.aptguide.com.%@/ThankYou/tdp_p1"
71
+ }
72
+ }}
73
+
74
+ it "turns a response into a model declaration" do
75
+ expect(generate_models(sample_response, "Pins")).to eq expected_result
76
+ end
77
+
78
+ it "turns another response into a model declaration" do
79
+ expect(generate_models(sample_response_2, "Config")).to eq expected_result_2
80
+ end
81
+ end
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ describe Rack::Swagger::ServerHelpers do
4
+ include Rack::Swagger::ServerHelpers
5
+
6
+ before do
7
+ @opts = {}
8
+ end
9
+
10
+ describe "display_file_or_404" do
11
+ it "404 if file does not exist" do
12
+ result = display_file_or_404(:json, "blah.json")
13
+ expect(result[0]).to eq(404)
14
+ end
15
+
16
+ it "404 if file does not exist" do
17
+ result = display_file_or_404(:html, "blah.html")
18
+ expect(result[0]).to eq(404)
19
+ end
20
+
21
+ it "serves file if file does exist" do
22
+ result = display_file_or_404(:html, __FILE__)
23
+ expect(result[0]).to eq(200)
24
+ expect(result[2].read).to eq(File.read(__FILE__))
25
+ end
26
+
27
+ it "serves proper json content type for :json" do
28
+ result = display_file_or_404(:json, __FILE__)
29
+ expect(result[1]["Content-Type"]).to eq("application/json")
30
+ end
31
+ end
32
+
33
+ describe "overwrite_base_path" do
34
+ it "adds basePath" do
35
+ result = overwrite_base_path("{\"foo\":\"bar\"}", "baz")
36
+ expect(result).to eq("{\"foo\":\"bar\",\"basePath\":\"baz\"}")
37
+ end
38
+ it "overwrites basePath" do
39
+ @opts = {overwrite_base_path: "baz"}
40
+ result = overwrite_base_path("{\"basePath\":\"bar\"}", "baz")
41
+ expect(result).to eq("{\"basePath\":\"baz\"}")
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ class MockSinatraApp
4
+ attr_accessor :routes
5
+ end
6
+
7
+ describe Rack::Swagger::SinatraHelpers do
8
+ before do
9
+ # removed the Procs from the Sinatra::Base.routes output because
10
+ # we don't need it (replaced with nil)
11
+ app1routes = {
12
+ "GET"=>[[/\A\/config\z/, [], [], nil],
13
+ [/\A\/listings\/?\z/, [], [], nil],
14
+ [/\A\/show\/?([^\/?#]+)?\/?\z/, ["id"], [], nil],
15
+ [/\A\/diamondmax\/?\z/, [], [], nil],
16
+ [/\A\/map\/pins(?:\.|%2[Ee])json\z/, [], [], nil],
17
+ [/\A\/map\/pin\/([^\/?#]+)\/?\z/, ["id"], [], nil],
18
+ [/\A\/refinementlist\/?\z/, [], [], nil],
19
+ [/\A\/reviews\/([^\/?#]+)\/?\z/, ["id"], [], nil],
20
+ [/\A\/listings\/search\/?\z/, [], [], nil],
21
+ [/\A\/search\/?\z/, [], [], nil],
22
+ [/\A\/telcos\z/, [], [], nil],
23
+ [/\A\/([^\/?#]+)\/states\/?\z/, ["channel"], [], nil],
24
+ [/\A\/([^\/?#]+)\/([^\/?#]+)\/cities\/?\z/, ["channel", "state"], [], nil],
25
+ [/\A\/mgtco\/([^\/?#]+)\/([^\/?#]+)\/([^\/?#]+)\/?\z/, ["state", "city", "mgtcoid"], [], nil],
26
+ [/\A\/listings\/([^\/?#]+)\/recommendations\/?\z/, ["id"], [], nil],
27
+ [/\A\/protobuf_test\z/, [], [], nil],
28
+ [/\A\/rent\/listings\/?\z/, [], [], nil]
29
+
30
+ ], "HEAD"=>[[/\A\/config\z/, [], [], nil],
31
+ [/\A\/listings\/?\z/, [], [], nil],
32
+ [/\A\/show\/?([^\/?#]+)?\/?\z/, ["id"], [], nil],
33
+ [/\A\/diamondmax\/?\z/, [], [], nil],
34
+ [/\A\/map\/pins(?:\.|%2[Ee])json\z/, [], [], nil],
35
+ [/\A\/map\/pin\/([^\/?#]+)\/?\z/, ["id"], [], nil],
36
+ [/\A\/refinementlist\/?\z/, [], [], nil],
37
+ [/\A\/reviews\/([^\/?#]+)\/?\z/, ["id"], [], nil],
38
+ [/\A\/listings\/search\/?\z/, [], [], nil],
39
+ [/\A\/search\/?\z/, [], [], nil],
40
+ [/\A\/telcos\z/, [], [], nil],
41
+ [/\A\/([^\/?#]+)\/states\/?\z/, ["channel"], [], nil],
42
+ [/\A\/([^\/?#]+)\/([^\/?#]+)\/cities\/?\z/, ["channel", "state"], [], nil],
43
+ [/\A\/mgtco\/([^\/?#]+)\/([^\/?#]+)\/([^\/?#]+)\/?\z/, ["state", "city", "mgtcoid"], [], nil],
44
+ [/\A\/listings\/([^\/?#]+)\/recommendations\/?\z/, ["id"], [], nil],
45
+ [/\A\/protobuf_test\z/, [], [], nil],
46
+ [/\A\/rent\/listings\/?\z/, [], [], nil]
47
+ ]}
48
+
49
+ app2routes = {
50
+ "GET"=>[[/\A\/reviews\/([^\/?#]+)\/?\z/, ["id"], [], nil],
51
+ [/\A\/reviews\/partial\/([^\/?#]+)\z/, ["id"], [], nil]],
52
+
53
+ "HEAD"=>[[/\A\/reviews\/([^\/?#]+)\/?\z/, ["id"], [], nil],
54
+ [/\A\/reviews\/partial\/([^\/?#]+)\z/, ["id"], [], nil]],
55
+
56
+ "POST"=>[[/\A\/reviews\/flag\/([^\/?#]+)\/([^\/?#]+)\/([^\/?#]+)\z/, ["id", "type", "review_id"], [], nil]]
57
+ }
58
+
59
+ @app1 = MockSinatraApp.new
60
+ @app1.routes = app1routes
61
+ @app2 = MockSinatraApp.new
62
+ @app2.routes = app2routes
63
+ end
64
+
65
+ it "extracts the API routes from the Sinatra::Base.routes" do
66
+
67
+ expected_result = {"GET"=>["/config", "/listings", "/show", "/show/{id}", "/diamondmax",
68
+ "/map/pins.json", "/map/pin/{id}", "/refinementlist", "/reviews/{id}",
69
+ "/listings/search", "/search", "/telcos", "/{channel}/states",
70
+ "/{channel}/{state}/cities", "/mgtco/{state}/{city}/{mgtcoid}",
71
+ "/listings/{id}/recommendations", "/protobuf_test", "/rent/listings",
72
+ "/reviews/{id}", "/reviews/partial/{id}"],
73
+
74
+ "HEAD"=>["/config", "/listings", "/show", "/show/{id}", "/diamondmax",
75
+ "/map/pins.json", "/map/pin/{id}", "/refinementlist", "/reviews/{id}",
76
+ "/listings/search", "/search", "/telcos", "/{channel}/states",
77
+ "/{channel}/{state}/cities", "/mgtco/{state}/{city}/{mgtcoid}",
78
+ "/listings/{id}/recommendations", "/protobuf_test", "/rent/listings",
79
+ "/reviews/{id}", "/reviews/partial/{id}"],
80
+
81
+ "POST"=>["/reviews/flag/{id}/{type}/{review_id}"]}
82
+
83
+ expect(Rack::Swagger::SinatraHelpers.get_all_routes(@app1, @app2)).to eq(expected_result)
84
+ end
85
+ end
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "rack/swagger"
7
+ require "rack/swagger/routes_to_models"
8
+ require "rack/test"
9
+ require "rspec"
10
+ require 'rspec/autorun'
11
+
12
+ # Requires supporting ruby files with custom matchers and macros, etc,
13
+ # in spec/support/ and its subdirectories.
14
+ # Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
15
+
16
+ RSpec.configure do |config|
17
+ # == Mock Framework
18
+ #
19
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
20
+ #
21
+ # config.mock_with :mocha
22
+ # config.mock_with :flexmock
23
+ # config.mock_with :rr
24
+ config.mock_with :rspec
25
+ end
@@ -0,0 +1,125 @@
1
+ /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */
2
+ html,
3
+ body,
4
+ div,
5
+ span,
6
+ applet,
7
+ object,
8
+ iframe,
9
+ h1,
10
+ h2,
11
+ h3,
12
+ h4,
13
+ h5,
14
+ h6,
15
+ p,
16
+ blockquote,
17
+ pre,
18
+ a,
19
+ abbr,
20
+ acronym,
21
+ address,
22
+ big,
23
+ cite,
24
+ code,
25
+ del,
26
+ dfn,
27
+ em,
28
+ img,
29
+ ins,
30
+ kbd,
31
+ q,
32
+ s,
33
+ samp,
34
+ small,
35
+ strike,
36
+ strong,
37
+ sub,
38
+ sup,
39
+ tt,
40
+ var,
41
+ b,
42
+ u,
43
+ i,
44
+ center,
45
+ dl,
46
+ dt,
47
+ dd,
48
+ ol,
49
+ ul,
50
+ li,
51
+ fieldset,
52
+ form,
53
+ label,
54
+ legend,
55
+ table,
56
+ caption,
57
+ tbody,
58
+ tfoot,
59
+ thead,
60
+ tr,
61
+ th,
62
+ td,
63
+ article,
64
+ aside,
65
+ canvas,
66
+ details,
67
+ embed,
68
+ figure,
69
+ figcaption,
70
+ footer,
71
+ header,
72
+ hgroup,
73
+ menu,
74
+ nav,
75
+ output,
76
+ ruby,
77
+ section,
78
+ summary,
79
+ time,
80
+ mark,
81
+ audio,
82
+ video {
83
+ margin: 0;
84
+ padding: 0;
85
+ border: 0;
86
+ font-size: 100%;
87
+ font: inherit;
88
+ vertical-align: baseline;
89
+ }
90
+ /* HTML5 display-role reset for older browsers */
91
+ article,
92
+ aside,
93
+ details,
94
+ figcaption,
95
+ figure,
96
+ footer,
97
+ header,
98
+ hgroup,
99
+ menu,
100
+ nav,
101
+ section {
102
+ display: block;
103
+ }
104
+ body {
105
+ line-height: 1;
106
+ }
107
+ ol,
108
+ ul {
109
+ list-style: none;
110
+ }
111
+ blockquote,
112
+ q {
113
+ quotes: none;
114
+ }
115
+ blockquote:before,
116
+ blockquote:after,
117
+ q:before,
118
+ q:after {
119
+ content: '';
120
+ content: none;
121
+ }
122
+ table {
123
+ border-collapse: collapse;
124
+ border-spacing: 0;
125
+ }