support_tables.rb 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. require 'yajl/json_gem'
  2. module Docs
  3. class SupportTables < Doc
  4. include Instrumentable
  5. self.name = 'Support Tables'
  6. self.slug = 'browser_support_tables'
  7. self.type = 'support_tables'
  8. def build_pages
  9. url = 'https://github.com/Fyrd/caniuse/raw/master/data.json'
  10. instrument 'running.scraper', urls: [url]
  11. response = Request.run(url)
  12. instrument 'process_response.scraper', response: response
  13. data = JSON.parse(response.body)
  14. instrument 'queued.scraper', urls: data['data'].keys
  15. data['agents']['and_chr']['browser'] = 'Android Chrome'
  16. data['agents']['and_ff']['browser'] = 'Android Firefox'
  17. data['agents']['and_uc']['browser'] = 'Android UC Browser'
  18. data['desktop_agents'] = data['agents'].select { |_, agent| agent['type'] == 'desktop' }
  19. data['mobile_agents'] = data['agents'].select { |–, agent| agent['type'] == 'mobile' }
  20. data['total_versions'] = data['agents']['firefox']['versions'].length
  21. index_page = {
  22. path: 'index',
  23. store_path: 'index.html',
  24. output: ERB.new(INDEX_PAGE_ERB).result(binding),
  25. entries: [Entry.new(nil, 'index', nil)]
  26. }
  27. yield index_page
  28. data['data'].each do |feature_id, feature|
  29. url = "https://github.com/Fyrd/caniuse/raw/master/features-json/#{feature_id}.json"
  30. response = Request.run(url)
  31. instrument 'process_response.scraper', response: response
  32. feature = JSON.parse(response.body)
  33. name = feature['title']
  34. type = feature['categories'].find { |category| name.include?(category) } || feature['categories'].first
  35. page = {
  36. path: feature_id,
  37. store_path: "#{feature_id}.html",
  38. output: ERB.new(PAGE_ERB).result(binding),
  39. entries: [Entry.new(name, feature_id, type)]
  40. }
  41. yield page
  42. end
  43. end
  44. def md_to_html(str)
  45. str = CGI::escape_html(str.strip)
  46. str.gsub! %r{`(.*?)`}, '<code>\1</code>'
  47. str.gsub! %r{\n\s*\n}, '</p><p>'
  48. str.gsub! "\n", '<br>'
  49. str.gsub! %r{\[(.+?)\]\((.+?)\)}, '<a href="\2">\1</a>'
  50. str
  51. end
  52. def support_to_css_class(support)
  53. support.select { |s| s.length == 1 }.join(' ')
  54. end
  55. def support_to_note_indicators(support)
  56. notes = support.select { |s| s.start_with?('#') }.map { |s| s[1..-1] }
  57. notes << '*' if support.include?('x')
  58. "<sup>(#{notes.join(',')})</sup>" if notes.present?
  59. end
  60. INDEX_PAGE_ERB = <<-HTML.strip_heredoc
  61. <h1>Browser support tables</h1>
  62. HTML
  63. PAGE_ERB = <<-HTML.strip_heredoc
  64. <h1><%= feature['title'] %></h1>
  65. <p><%= md_to_html feature['description'] %></p>
  66. <table>
  67. <% if feature['spec'].present? %>
  68. <tr>
  69. <th>Spec</th>
  70. <td><a href="<%= feature['spec'] %>"><%= feature['spec'] %></a></td>
  71. </tr>
  72. <% end %>
  73. <% if feature['status'].present? %>
  74. <tr>
  75. <th>Status</th>
  76. <td><%= data['statuses'][feature['status']] %></td>
  77. </tr>
  78. <% end %>
  79. </table>
  80. <% ['desktop', 'mobile'].each do |type| %>
  81. <table class="stats">
  82. <tr>
  83. <% data["\#{type}_agents"].each do |agent_id, agent| %>
  84. <th><%= agent['browser'] %></th>
  85. <% end %>
  86. </tr>
  87. <% (0...(data['total_versions'])).reverse_each do |i| %>
  88. <% next if data["\#{type}_agents"].none? { |_, agent| agent['versions'][i] } %>
  89. <% if i == (data['total_versions'] - 8) %>
  90. <tr class="show-all">
  91. <th class="show-all" colspan="<%= data["\#{type}_agents"].length %>">
  92. <a href="#" class="show-all">Show all</a>
  93. </th>
  94. </tr>
  95. <% end %>
  96. <tr<%= ' class="current"' if i == (data['total_versions'] - 4) %>>
  97. <% data["\#{type}_agents"].each do |agent_id, agent| %>
  98. <% version = agent['versions'][i] %>
  99. <% if version %>
  100. <% support = feature['stats'][agent_id][version].split(' ') %>
  101. <% feature['prefix'] = true if support.include?('x') %>
  102. <td class="<%= support_to_css_class(support) %>"><%= version %> <%= support_to_note_indicators(support) %></td>
  103. <% else %>
  104. <td>&nbsp;</td>
  105. <% end %>
  106. <% end %>
  107. </tr>
  108. <% end %>
  109. </table>
  110. <% end %>
  111. <h2>Notes</h2>
  112. <% if feature['notes'].present? %>
  113. <p><%= md_to_html feature['notes'] %></p>
  114. <% end %>
  115. <% if feature['notes_by_num'].present? %>
  116. <ol>
  117. <% feature['notes_by_num'].each do |num, note| %>
  118. <li><p><%= md_to_html note %></p></li>
  119. <% end %>
  120. </ol>
  121. <% end %>
  122. <% if feature['prefix'] %>
  123. <dl>
  124. <dd><sup>*</sup> Partial support with prefix.</dd>
  125. </dl>
  126. <% end %>
  127. <% if feature['bugs'].present? %>
  128. <h2>Bugs</h2>
  129. <ul>
  130. <% feature['bugs'].each do |bug| %>
  131. <li><p><%= md_to_html bug['description'] %></p></li>
  132. <% end %>
  133. </ul>
  134. <% end %>
  135. <% if feature['links'].present? %>
  136. <h2>Resources</h2>
  137. <ul>
  138. <% feature['links'].each do |link| %>
  139. <li><a href="<%= link['url'] %>"><%= link['title'] %></a></li>
  140. <% end %>
  141. </ul>
  142. <% end %>
  143. <div class="_attribution">
  144. <p class="_attribution-p">
  145. Data by caniuse.com<br>
  146. Licensed under the Creative Commons Attribution License v4.0.<br>
  147. <a href="http://caniuse.com/#feat=<%= feature_id %>" class="_attribution-link">http://caniuse.com/#feat=<%= feature_id %></a>
  148. </p>
  149. </div>
  150. HTML
  151. def get_latest_version(opts)
  152. body = fetch('https://feeds.feedburner.com/WhenCanIUse?format=xml', opts)
  153. timestamp = body.scan(/<updated>([^<]+)<\/updated>/)[0][0]
  154. DateTime.parse(timestamp).to_time.to_i
  155. end
  156. end
  157. end