angular.rb 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. require 'yajl/json_gem'
  2. module Docs
  3. class Angular < UrlScraper
  4. self.type = 'angular'
  5. self.links = {
  6. home: 'https://angular.io/',
  7. code: 'https://github.com/angular/angular'
  8. }
  9. options[:max_image_size] = 256_000
  10. options[:attribution] = <<-HTML
  11. &copy; 2010&ndash;2022 Google, Inc.<br>
  12. Licensed under the Creative Commons Attribution License 4.0.
  13. HTML
  14. module Common
  15. private
  16. def initial_urls
  17. initial_urls = []
  18. Request.run "#{self.class.base_url}generated/navigation.json" do |response|
  19. data = JSON.parse(response.body)
  20. dig = ->(entry) do
  21. initial_urls << url_for("generated/docs/#{entry['url']}.json") if entry['url'] && entry['url'] != 'api'
  22. entry['children'].each(&dig) if entry['children']
  23. end
  24. data['SideNav'].each(&dig)
  25. end
  26. Request.run "#{self.class.base_url}generated/docs/api/api-list.json" do |response|
  27. data = JSON.parse(response.body)
  28. dig = ->(entry) do
  29. initial_urls << url_for("generated/docs/#{entry['path']}.json") if entry['path']
  30. initial_urls << url_for("generated/docs/api/#{entry['name']}.json") if entry['name'] && !entry['path']
  31. entry['items'].each(&dig) if entry['items']
  32. end
  33. data.each(&dig)
  34. end
  35. initial_urls
  36. end
  37. def handle_response(response)
  38. if response.mime_type.include?('json')
  39. begin
  40. json = JSON.parse(response.body)
  41. response.options[:response_body] = json['contents']
  42. response.url.path = response.url.path.gsub(/generated\/docs\/.*/, json['id'])
  43. response.effective_url.path = response.effective_url.path.gsub(/generated\/docs\/.*/, json['id'])
  44. rescue JSON::ParserError
  45. response.options[:response_body] = ''
  46. end
  47. response.headers['Content-Type'] = 'text/html'
  48. end
  49. super
  50. end
  51. end
  52. module Since12
  53. def url_for(path)
  54. # See encodeToLowercase im aio/tools/transforms/angular-base-package/processors/disambiguateDocPaths.js
  55. path = path.gsub(/[A-Z_]/) {|s| s.downcase + '_'}
  56. super
  57. end
  58. include Docs::Angular::Common
  59. end
  60. version do
  61. self.release = '13.1.3'
  62. self.base_url = 'https://angular.io/'
  63. self.root_path = 'docs'
  64. html_filters.push 'angular/clean_html', 'angular/entries'
  65. options[:follow_links] = false
  66. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  67. options[:fix_urls_before_parse] = ->(url) do
  68. url.sub! %r{\Aguide/}, '/guide/'
  69. url.sub! %r{\Atutorial/}, '/tutorial/'
  70. url.sub! %r{\Aapi/}, '/api/'
  71. url.sub! %r{\Agenerated/}, '/generated/'
  72. url
  73. end
  74. include Docs::Angular::Since12
  75. end
  76. version '12' do
  77. self.release = '12.2.13'
  78. self.base_url = 'https://v12.angular.io/'
  79. self.root_path = 'docs'
  80. html_filters.push 'angular/clean_html', 'angular/entries'
  81. options[:follow_links] = false
  82. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  83. options[:fix_urls_before_parse] = ->(url) do
  84. url.sub! %r{\Aguide/}, '/guide/'
  85. url.sub! %r{\Atutorial/}, '/tutorial/'
  86. url.sub! %r{\Aapi/}, '/api/'
  87. url.sub! %r{\Agenerated/}, '/generated/'
  88. url
  89. end
  90. include Docs::Angular::Since12
  91. end
  92. version '11' do
  93. self.release = '11.2.14'
  94. self.base_url = 'https://v11.angular.io/'
  95. self.root_path = 'docs'
  96. html_filters.push 'angular/clean_html', 'angular/entries'
  97. options[:follow_links] = false
  98. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  99. options[:fix_urls_before_parse] = ->(url) do
  100. url.sub! %r{\Aguide/}, '/guide/'
  101. url.sub! %r{\Atutorial/}, '/tutorial/'
  102. url.sub! %r{\Aapi/}, '/api/'
  103. url.sub! %r{\Agenerated/}, '/generated/'
  104. url
  105. end
  106. include Docs::Angular::Common
  107. end
  108. version '10' do
  109. self.release = '10.2.3'
  110. self.base_url = 'https://v10.angular.io/'
  111. self.root_path = 'docs'
  112. html_filters.push 'angular/clean_html', 'angular/entries'
  113. options[:follow_links] = false
  114. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  115. options[:fix_urls_before_parse] = ->(url) do
  116. url.sub! %r{\Aguide/}, '/guide/'
  117. url.sub! %r{\Atutorial/}, '/tutorial/'
  118. url.sub! %r{\Aapi/}, '/api/'
  119. url.sub! %r{\Agenerated/}, '/generated/'
  120. url
  121. end
  122. include Docs::Angular::Common
  123. end
  124. version '9' do
  125. self.release = '9.1.12'
  126. self.base_url = 'https://v9.angular.io/'
  127. self.root_path = 'docs'
  128. html_filters.push 'angular/clean_html', 'angular/entries'
  129. options[:follow_links] = false
  130. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  131. options[:fix_urls_before_parse] = ->(url) do
  132. url.sub! %r{\Aguide/}, '/guide/'
  133. url.sub! %r{\Atutorial/}, '/tutorial/'
  134. url.sub! %r{\Aapi/}, '/api/'
  135. url.sub! %r{\Agenerated/}, '/generated/'
  136. url
  137. end
  138. include Docs::Angular::Common
  139. end
  140. version '8' do
  141. self.release = '8.2.14'
  142. self.base_url = 'https://v8.angular.io/'
  143. self.root_path = 'docs'
  144. html_filters.push 'angular/clean_html', 'angular/entries'
  145. options[:follow_links] = false
  146. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  147. options[:fix_urls_before_parse] = ->(url) do
  148. url.sub! %r{\Aguide/}, '/guide/'
  149. url.sub! %r{\Atutorial/}, '/tutorial/'
  150. url.sub! %r{\Aapi/}, '/api/'
  151. url.sub! %r{\Agenerated/}, '/generated/'
  152. url
  153. end
  154. include Docs::Angular::Common
  155. end
  156. version '7' do
  157. self.release = '7.2.15'
  158. self.base_url = 'https://v7.angular.io/'
  159. self.root_path = 'docs'
  160. html_filters.push 'angular/clean_html', 'angular/entries'
  161. options[:follow_links] = false
  162. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  163. options[:fix_urls_before_parse] = ->(url) do
  164. url.sub! %r{\Aguide/}, '/guide/'
  165. url.sub! %r{\Atutorial/}, '/tutorial/'
  166. url.sub! %r{\Aapi/}, '/api/'
  167. url.sub! %r{\Agenerated/}, '/generated/'
  168. url
  169. end
  170. include Docs::Angular::Common
  171. end
  172. version '6' do
  173. self.release = '6.1.10'
  174. self.base_url = 'https://v6.angular.io/'
  175. self.root_path = 'docs'
  176. html_filters.push 'angular/clean_html', 'angular/entries'
  177. options[:follow_links] = false
  178. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  179. options[:fix_urls_before_parse] = ->(url) do
  180. url.sub! %r{\Aguide/}, '/guide/'
  181. url.sub! %r{\Atutorial/}, '/tutorial/'
  182. url.sub! %r{\Aapi/}, '/api/'
  183. url.sub! %r{\Agenerated/}, '/generated/'
  184. url
  185. end
  186. include Docs::Angular::Common
  187. end
  188. version '5' do
  189. self.release = '5.2.11'
  190. self.base_url = 'https://v5.angular.io/'
  191. self.root_path = 'docs'
  192. html_filters.push 'angular/clean_html', 'angular/entries'
  193. options[:follow_links] = false
  194. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  195. options[:fix_urls_before_parse] = ->(url) do
  196. url.sub! %r{\Aguide/}, '/guide/'
  197. url.sub! %r{\Atutorial/}, '/tutorial/'
  198. url.sub! %r{\Aapi/}, '/api/'
  199. url.sub! %r{\Agenerated/}, '/generated/'
  200. url
  201. end
  202. include Docs::Angular::Common
  203. end
  204. version '4' do
  205. self.release = '4.4.6'
  206. self.base_url = 'https://v4.angular.io/'
  207. self.root_path = 'docs'
  208. html_filters.push 'angular/clean_html', 'angular/entries'
  209. options[:follow_links] = false
  210. options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
  211. options[:fix_urls_before_parse] = ->(url) do
  212. url.sub! %r{\Aguide/}, '/guide/'
  213. url.sub! %r{\Atutorial/}, '/tutorial/'
  214. url.sub! %r{\Aapi/}, '/api/'
  215. url.sub! %r{\Agenerated/}, '/generated/'
  216. url
  217. end
  218. include Docs::Angular::Common
  219. end
  220. version '2' do
  221. self.release = '2.4.10'
  222. self.base_url = 'https://v2.angular.io/docs/ts/latest/'
  223. self.root_path = 'api/'
  224. html_filters.push 'angular/entries_v2', 'angular/clean_html_v2'
  225. stub 'api/' do
  226. base_url = URL.parse(self.base_url)
  227. capybara = load_capybara_selenium
  228. capybara.app_host = base_url.origin
  229. capybara.visit(base_url.path + 'api/')
  230. capybara.execute_script('return document.body.innerHTML')
  231. end
  232. options[:skip_patterns] = [/deprecated/, /VERSION-let/]
  233. options[:skip] = %w(
  234. index.html
  235. styleguide.html
  236. quickstart.html
  237. cheatsheet.html
  238. guide/cheatsheet.html
  239. guide/style-guide.html)
  240. options[:replace_paths] = {
  241. 'testing/index.html' => 'guide/testing.html',
  242. 'guide/glossary.html' => 'glossary.html',
  243. 'tutorial' => 'tutorial/',
  244. 'api' => 'api/'
  245. }
  246. options[:fix_urls] = -> (url) do
  247. url.sub! %r{\A(https://(?:v2\.)?angular\.io/docs/.+/)index\.html\z}, '\1'
  248. url
  249. end
  250. end
  251. def get_latest_version(opts)
  252. get_npm_version('@angular/core', opts)
  253. end
  254. private
  255. def parse(response)
  256. response.body.gsub! '<code-example', '<pre'
  257. response.body.gsub! '</code-example', '</pre'
  258. response.body.gsub! '<code-pane', '<pre'
  259. response.body.gsub! '</code-pane', '</pre'
  260. response.body.gsub! '<live-example></live-example>', 'live example'
  261. response.body.gsub! '<live-example', '<span'
  262. response.body.gsub! '</live-example', '</span'
  263. super
  264. end
  265. end
  266. end