support_tables.rb 6.2 KB

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