History

Update Angular documentation (4.3.2)

Thibaut Courouble committed 9 years ago

Commit 3f43c031 parent dd8c80010 files · +382 −192Browse files

Unified · Split

10 files
  1. assets/javascripts/app/app.coffee +2 −0
  2. assets/stylesheets/pages/_angular.scss +9 −42
  3. assets/stylesheets/pages/_simple.scss +1 −1
  4. lib/app.rb +3 −1
  5. lib/docs/core/response.rb +1 −1
  6. lib/docs/filters/angular/clean_html.rb +51 −68
  7. lib/docs/filters/angular/clean_html_v2.rb +157 −0
  8. lib/docs/filters/angular/entries.rb +10 −45
  9. lib/docs/filters/angular/entries_v2.rb +60 −0
  10. lib/docs/scrapers/angular.rb +88 −34
assets/javascripts/app/app.coffee+2−0
@@ -119,6 +119,8 @@ · 118 unmodified lines
119119 for slug in @settings.getDocs() when not @docs.findBy('slug', slug)
120120 needsSaving = true
121121 doc = @disabledDocs.findBy('slug', 'webpack') if slug == 'webpack~2'
122+ doc = @disabledDocs.findBy('slug', 'angular') if slug == 'angular~4_typescript'
123+ doc = @disabledDocs.findBy('slug', 'angular~2') if slug == 'angular~2_typescript'
122124 doc ||= @disabledDocs.findBy('slug_without_version', slug)
123125 if doc
124126 @disabledDocs.remove(doc)
assets/stylesheets/pages/_angular.scss+9−42
@@ -1,55 +1,22 @@
11 ._angular {
2− padding-left: 1rem;
2+ @extend %simple;
33
4− h1, h2, > h3, .banner, .badges, .breadcrumbs { margin-left: -1rem; }
4+ .pre-title { @extend %pre-heading; }
55
6− ._mobile & {
7− padding-left: 0;
8−
9− h1, h2, > h3, .banner, .badges, .breadcrumbs { margin-left: 0; }
10− }
11−
12− h2 { @extend %block-heading; }
13− > h3 { @extend %block-label, %label-blue; }
14− .code-example > h4, .pre-title { @extend %pre-heading; }
15−
16− p > code, dd > code, .status-badge { @extend %label; }
17−
18− .l-sub-section, .alert, .banner, .breadcrumbs { @extend %note; }
6+ .breadcrumbs { @extend %note; }
197 .banner { @extend %note-green; }
8+ code.stable { @extend %label-green; }
9+ code.experimental { @extend %label-orange; }
10+ code.deprecated { @extend %label-red; }
2011 .alert.is-important { @extend %note-red; }
2112 .alert.is-helpful, .breadcrumbs { @extend %note-blue; }
22− .breadcrumbs { padding-left: 2em; }
23−
24− td > h3, .l-sub-section > h3, .l-sub-section > h4, .alert > h3, .alert > h4, .row-margin > h3 {
25− margin-top: .25rem;
26− font-size: 1em;
27− }
2813
29− img {
30− display: block;
31− margin: 1em auto;
32−
33− &[align="left"] {
34− float: left;
35− margin: 0 1em 0 0;
36− }
14+ .breadcrumbs { padding-left: 2em; }
3715
38− &[align="right"] {
39− float: right;
40− margin: 0 0 0 1em;
41− }
42− }
16+ img { margin: 1em 0; }
4317
4418 .location-badge {
45− text-align: right;
4619 font-style: italic;
47− }
48−
49− .filetree {
50− white-space: normal;
51− @extend %pre;
52−
53− .children { padding-left: 1em; }
20+ text-align: right;
5421 }
5522 }
assets/stylesheets/pages/_simple.scss+1−1
@@ -12,7 +12,7 @@ · 11 unmodified lines
1212 h1, h2, h3 { margin-left: 0; }
1313 }
1414
15− p > code, li > code, td > code, blockquote > code { @extend %label; }
15+ p > code, li > code, td > code, blockquote > code, dd > code { @extend %label; }
1616 blockquote { @extend %note; }
1717 blockquote > h4, blockquote > h5 { margin-top: .25rem; }
1818 }
lib/app.rb+3−1
@@ -352,7 +352,9 @@ class App < Sinatra::Application · 351 unmodified lines
352352 'yii1' => 'yii~1.1',
353353 'python2' => 'python~2.7',
354354 'xpath' => 'xslt_xpath',
355− 'angular~2.0_typescript' => 'angular~2_typescript',
355+ 'angular~4_typescript' => 'angular',
356+ 'angular~2_typescript' => 'angular~2',
357+ 'angular~2.0_typescript' => 'angular~2',
356358 'angular~1.5' => 'angularjs~1.5',
357359 'angular~1.4' => 'angularjs~1.4',
358360 'angular~1.3' => 'angularjs~1.3',
lib/docs/core/response.rb+1−1
@@ -13,7 +13,7 @@ module Docs · 12 unmodified lines
1313 end
1414
1515 def mime_type
16− @mime_type ||= headers['Content-Type'] || 'text/plain'
16+ headers['Content-Type'] || 'text/plain'
1717 end
1818
1919 def html?
lib/docs/filters/angular/clean_html.rb+51−68
@@ -2,103 +2,86 @@ module Docs · 1 unmodified line
22 class Angular
33 class CleanHtmlFilter < Filter
44 def call
5− container = at_css('article.docs-content')
6− badges = css('header.hero .badge, header.hero .hero-subtitle').map do |node|
7− node.name = 'span'
8− node['class'] = 'status-badge'
9− node.to_html
10− end.join(' ')
11− badges = %(<div class="badges">#{badges}</div>)
12− container.child.before(at_css('header.hero h1')).before(badges).before(css('header.hero + .banner, header.hero .breadcrumbs'))
13− @doc = container
14−
15− title = at_css('h1').content.strip
165 if root_page?
6+ css('.card-container').remove
177 at_css('h1').content = 'Angular Documentation'
18− elsif title == 'Index'
19− at_css('h1').content = result[:entries].first.name
20− elsif title == 'Angular'
21− at_css('h1').content = slug.split('/').last.gsub('-', ' ')
22− elsif at_css('.breadcrumbs') && title != result[:entries].first.name
23− at_css('h1').content = result[:entries].first.name
248 end
259
26− css('pre.no-bg-with-indent').each do |node|
27− node.content = ' ' + node.content.gsub("\n", "\n ")
28− end
29−
30− css('.openParens').each do |node|
31− node.parent.name = 'pre'
32− node.parent.content = node.parent.css('code, pre').map(&:content).join("\n")
33− end
34−
35− css('button.verbose', 'button.verbose + .l-verbose-section', 'a[id=top]', 'a[href="#top"]', '.sidebar').remove
10+ css('br', 'hr', '.material-icons', '.header-link').remove
3611
37− css('.c10', '.showcase', '.showcase-content', '.l-main-section', 'div.div', 'div[flex]', 'code-tabs', 'md-card', 'md-card-content', 'div:not([class])', 'footer', '.card-row', '.card-row-container', 'figure', 'blockquote', 'exported', 'defined', 'div.ng-scope', '.code-example header', 'section.desc', '.row', '.dart-api-entry-main', '.main-content', 'section.summary', 'span.signature').each do |node|
12+ css('.content', 'article', '.api-header', 'section', '.instance-member').each do |node|
3813 node.before(node.children).remove
3914 end
4015
41− css('span.badges').each do |node|
42− node.name = 'div'
16+ css('label', 'h2 > em', 'h3 > em').each do |node|
17+ node.name = 'code'
4318 end
4419
45− css('pre[language]').each do |node|
46− node['data-language'] = node['language'].sub(/\Ats/, 'typescript').strip
47− node['data-language'] = 'html' if node.content.start_with?('<')
20+ css('h1 + code').each do |node|
21+ node.before('<p></p>')
22+ while node.next_element.name == 'code'
23+ node.previous_element << ' '
24+ node.previous_element << node.next_element
25+ end
26+ node.previous_element.prepend_child(node)
4827 end
4928
50− css('pre.prettyprint').each do |node|
51− node.content = node.content.strip
52− node['data-language'] = 'dart' if node['class'].include?('dart')
53− node['data-language'] = 'html' if node.content.start_with?('<')
29+ css('td h3', '.l-sub-section > h3', '.alert h3', '.row-margin > h3', '.api-heading ~ h3', '.api-heading + h2', '.metadata-member h3').each do |node|
30+ node.name = 'h4'
5431 end
5532
56− css('.multi-line-signature').each do |node|
57− node.name = 'pre'
58− node.content = node.content.strip
33+ css('.l-sub-section', '.alert', '.banner').each do |node|
34+ node.name = 'blockquote'
5935 end
6036
61− css('a[id]:empty').each do |node|
62− node.next_element['id'] = node['id'] if node.next_element
37+ css('.file').each do |node|
38+ node.content = node.content.strip
6339 end
6440
65− css('a[name]:empty').each do |node|
66− node.next_element['id'] = node['name'] if node.next_element
41+ css('.filetree .children').each do |node|
42+ node.css('.file').each do |n|
43+ n.content = " #{n.content}"
44+ end
6745 end
6846
69− css('tr[style]').each do |node|
70− node.remove_attribute 'style'
47+ css('.filetree').each do |node|
48+ node.content = node.css('.file').map(&:inner_html).join("\n")
49+ node.name = 'pre'
50+ node.remove_attribute('class')
7151 end
7252
73− css('h1:not(:first-child)').each do |node|
74− node.name = 'h2'
75− end unless at_css('h2')
53+ css('pre').each do |node|
54+ node.content = node.content.strip
7655
77− css('img[style]').each do |node|
78− node['align'] ||= node['style'][/float:\s*(left|right)/, 1]
79− node['style'] = node['style'].split(';').map(&:strip).select { |s| s =~ /\Awidth|height/ }.join(';')
80− end
56+ node['data-language'] = 'typescript' if node['path'].try(:ends_with?, '.ts')
57+ node['data-language'] = 'html' if node['path'].try(:ends_with?, '.html')
58+ node['data-language'] = 'css' if node['path'].try(:ends_with?, '.css')
59+ node['data-language'] = node['language'].sub(/\Ats/, 'typescript').strip if node['language']
60+ node['data-language'] ||= 'typescript' if node.content.start_with?('@')
8161
82− css('.example-title + pre').each do |node|
83− node['name'] = node.previous_element.content.strip
84− node.previous_element.remove
85− end
62+ node.before(%(<div class="pre-title">#{node['title']}</div>)) if node['title']
8663
87− css('pre[name]').each do |node|
88− node.before(%(<div class="pre-title">#{node['name']}</div>))
89− end
64+ if node['class'] && node['class'].include?('api-heading')
65+ node.name = 'h3'
66+ node.inner_html = "<code>#{node.inner_html}</code>"
67+ end
9068
91− css('a.is-button > h3').each do |node|
92− node.parent.content = node.content
69+ node.remove_attribute('path')
70+ node.remove_attribute('region')
71+ node.remove_attribute('linenums')
72+ node.remove_attribute('title')
73+ node.remove_attribute('language')
74+ node.remove_attribute('hidecopy')
75+ node.remove_attribute('class')
9376 end
9477
95− css('#angular-2-glossary ~ .l-sub-section').each do |node|
96− node.before(node.children).remove
97− end
78+ css('h1[class]').remove_attr('class')
79+ css('table[class]').remove_attr('class')
80+ css('table[width]').remove_attr('width')
81+ css('tr[style]').remove_attr('style')
9882
99− location_badge = at_css('.location-badge')
100− if location_badge && doc.last_element_child != location_badge
101− doc.last_element_child.after(location_badge)
83+ if at_css('.api-type-label.module')
84+ at_css('h1').content = subpath.remove('api/')
10285 end
10386
10487 doc
lib/docs/filters/angular/clean_html_v2.rb+157−0
@@ -0,0 +1,157 @@
1+module Docs
2+ class Angular
3+ class CleanHtmlV2Filter < Filter
4+ def call
5+ container = at_css('article.docs-content')
6+ badges = css('header.hero .badge, header.hero .hero-subtitle').map do |node|
7+ node.name = 'span'
8+ node['class'] = 'status-badge'
9+ node.to_html
10+ end.join(' ')
11+ badges = %(<div class="badges">#{badges}</div>)
12+ container.child.before(at_css('header.hero h1')).before(badges).before(css('header.hero + .banner, header.hero .breadcrumbs'))
13+ @doc = container
14+
15+ title = at_css('h1').content.strip
16+ if root_page?
17+ at_css('h1').content = 'Angular 2 Documentation'
18+ elsif title == 'Index'
19+ at_css('h1').content = result[:entries].first.name
20+ elsif title == 'Angular'
21+ at_css('h1').content = slug.split('/').last.gsub('-', ' ')
22+ elsif at_css('.breadcrumbs') && title != result[:entries].first.name
23+ at_css('h1').content = result[:entries].first.name
24+ end
25+
26+ css('pre.no-bg-with-indent').each do |node|
27+ node.content = ' ' + node.content.gsub("\n", "\n ")
28+ end
29+
30+ css('.openParens').each do |node|
31+ node.parent.name = 'pre'
32+ node.parent.content = node.parent.css('code, pre').map(&:content).join("\n")
33+ end
34+
35+ css('button.verbose', 'button.verbose + .l-verbose-section', 'a[id=top]', 'a[href="#top"]', '.sidebar', 'br').remove
36+
37+ css('.c10', '.showcase', '.showcase-content', '.l-main-section', 'div.div', 'div[flex]', 'code-tabs', 'md-card', 'md-card-content', 'div:not([class])', 'footer', '.card-row', '.card-row-container', 'figure', 'blockquote', 'exported', 'defined', 'div.ng-scope', '.code-example header', 'section.desc', '.row', '.dart-api-entry-main', '.main-content', 'section.summary', 'span.signature').each do |node|
38+ node.before(node.children).remove
39+ end
40+
41+ css('span.badges').each do |node|
42+ node.name = 'div'
43+ end
44+
45+ css('pre[language]').each do |node|
46+ node['data-language'] = node['language'].sub(/\Ats/, 'typescript').strip
47+ node['data-language'] = 'html' if node.content.start_with?('<')
48+ node.remove_attribute('language')
49+ node.remove_attribute('format')
50+ end
51+
52+ css('pre.prettyprint').each do |node|
53+ node.content = node.content.strip
54+ node['data-language'] = 'dart' if node['class'].include?('dart')
55+ node['data-language'] = 'html' if node.content.start_with?('<')
56+ node.remove_attribute('class')
57+ end
58+
59+ css('.multi-line-signature').each do |node|
60+ node.name = 'pre'
61+ node.content = node.content.strip
62+ end
63+
64+ css('a[id]:empty').each do |node|
65+ node.next_element['id'] = node['id'] if node.next_element
66+ end
67+
68+ css('a[name]:empty').each do |node|
69+ node.next_element['id'] = node['name'] if node.next_element
70+ end
71+
72+ css('tr[style]').each do |node|
73+ node.remove_attribute 'style'
74+ end
75+
76+ css('h1:not(:first-child)').each do |node|
77+ node.name = 'h2'
78+ end unless at_css('h2')
79+
80+ css('img[style]').each do |node|
81+ node['align'] ||= node['style'][/float:\s*(left|right)/, 1]
82+ node['style'] = node['style'].split(';').map(&:strip).select { |s| s =~ /\Awidth|height/ }.join(';')
83+ end
84+
85+ css('.example-title + pre').each do |node|
86+ node['name'] = node.previous_element.content.strip
87+ node.previous_element.remove
88+ end
89+
90+ css('pre[name]').each do |node|
91+ node.before(%(<div class="pre-title">#{node['name']}</div>))
92+ end
93+
94+ css('a.is-button > h3').each do |node|
95+ node.parent.content = node.content
96+ end
97+
98+ css('#angular-2-glossary ~ .l-sub-section').each do |node|
99+ node.before(node.children).remove
100+ end
101+
102+ location_badge = at_css('.location-badge')
103+ if location_badge && doc.last_element_child != location_badge
104+ doc.last_element_child.after(location_badge)
105+ end
106+
107+ css('.filetree .children').each do |node|
108+ node.css('.file').each do |n|
109+ n.content = " #{n.content}"
110+ end
111+ end
112+
113+ css('.filetree').each do |node|
114+ node.content = node.css('.file').map(&:inner_html).join("\n")
115+ node.name = 'pre'
116+ node.remove_attribute('class')
117+ end
118+
119+ css('.status-badge').each do |node|
120+ node.name = 'code'
121+ node.content = node.content.strip
122+ node.remove_attribute('class')
123+ end
124+
125+ css('div.badges').each do |node|
126+ node.name = 'p'
127+ end
128+
129+ css('td h3', '.l-sub-section > h3', '.alert h3', '.row-margin > h3').each do |node|
130+ node.name = 'h4'
131+ end
132+
133+ css('.l-sub-section', '.alert', '.banner').each do |node|
134+ node.name = 'blockquote'
135+ end
136+
137+ css('.code-example > h4').each do |node|
138+ node['class'] = 'pre-title'
139+ end
140+
141+ css('.row-margin', '.ng-cloak').each do |node|
142+ node.before(node.children).remove
143+ end
144+
145+ css('*[layout]').remove_attr('layout')
146+ css('*[layout-xs]').remove_attr('layout-xs')
147+ css('*[flex]').remove_attr('flex')
148+ css('*[flex-xs]').remove_attr('flex-xs')
149+ css('*[ng-class]').remove_attr('ng-class')
150+ css('*[align]').remove_attr('align')
151+ css('h1, h2, h3').remove_attr('class')
152+
153+ doc
154+ end
155+ end
156+ end
157+end
lib/docs/filters/angular/entries.rb+10−45
@@ -2,59 +2,24 @@ module Docs · 1 unmodified line
22 class Angular
33 class EntriesFilter < Docs::EntriesFilter
44 def get_name
5− if slug.start_with?('tutorial') || slug.start_with?('guide')
6− name = at_css('.nav-list-item.is-selected, header.hero h1').content.strip
7− else
8− name = at_css('header.hero h1').content.strip
9− end
10−
11− name = name.split(':').first
12−
13− if mod
14− if name == 'Index'
15− return slug.split('/')[1..-2].join('/')
16− elsif name == 'Angular'
17− return slug.split('/').last.split('-').first
18− end
19− end
20−
21− subtitle = at_css('.hero-subtitle').try(:content)
22− breadcrumbs = css('.breadcrumbs li').map(&:content)[2..-2]
23−
24− name.prepend "#{breadcrumbs.join('.')}#" if breadcrumbs.present? && breadcrumbs[0] != name
25− name << '()' if %w(Function Method Constructor).include?(subtitle)
5+ name = at_css('h1').content
6+ name.prepend "#{$1}. " if subpath =~ /\-pt(\d+)/
267 name
278 end
289
2910 def get_type
30− if slug.start_with?('guide/')
31− 'Guide'
32− elsif slug.start_with?('cookbook/')
33− 'Cookbook'
34− elsif slug == 'glossary'
11+ if slug.start_with?('guide')
3512 'Guide'
13+ elsif slug.start_with?('tutorial')
14+ 'Tutorial'
15+ elsif node = at_css('th:contains("npm Package")')
16+ node.next_element.content.remove('@angular/')
17+ elsif at_css('.api-type-label.module')
18+ name.split('/').first
3619 else
37− type = at_css('.nav-title.is-selected').content.strip
38− type.remove! ' Reference'
39− type << ": #{mod}" if mod
40− type
20+ 'Miscellaneous'
4121 end
4222 end
43−
44− INDEX = Set.new
45−
46− def include_default_entry?
47− INDEX.add?([name, type].join(';')) ? true : false # ¯\_(ツ)_/¯
48− end
49−
50− private
51−
52− def mod
53− return @mod if defined?(@mod)
54− @mod = slug[/api\/([\w\-\.]+)\//, 1]
55− @mod.remove! 'angular2.' if @mod
56− @mod
57− end
5823 end
5924 end
6025 end
lib/docs/filters/angular/entries_v2.rb+60−0
@@ -0,0 +1,60 @@
1+module Docs
2+ class Angular
3+ class EntriesV2Filter < Docs::EntriesFilter
4+ def get_name
5+ if slug.start_with?('tutorial') || slug.start_with?('guide')
6+ name = at_css('.nav-list-item.is-selected, header.hero h1').content.strip
7+ else
8+ name = at_css('header.hero h1').content.strip
9+ end
10+
11+ name = name.split(':').first
12+
13+ if mod
14+ if name == 'Index'
15+ return slug.split('/')[1..-2].join('/')
16+ elsif name == 'Angular'
17+ return slug.split('/').last.split('-').first
18+ end
19+ end
20+
21+ subtitle = at_css('.hero-subtitle').try(:content)
22+ breadcrumbs = css('.breadcrumbs li').map(&:content)[2..-2]
23+
24+ name.prepend "#{breadcrumbs.join('.')}#" if breadcrumbs.present? && breadcrumbs[0] != name
25+ name << '()' if %w(Function Method Constructor).include?(subtitle)
26+ name
27+ end
28+
29+ def get_type
30+ if slug.start_with?('guide/')
31+ 'Guide'
32+ elsif slug.start_with?('cookbook/')
33+ 'Cookbook'
34+ elsif slug == 'glossary'
35+ 'Guide'
36+ else
37+ type = at_css('.nav-title.is-selected').content.strip
38+ type.remove! ' Reference'
39+ type << ": #{mod}" if mod
40+ type
41+ end
42+ end
43+
44+ INDEX = Set.new
45+
46+ def include_default_entry?
47+ INDEX.add?([name, type].join(';')) ? true : false # ¯\_(ツ)_/¯
48+ end
49+
50+ private
51+
52+ def mod
53+ return @mod if defined?(@mod)
54+ @mod = slug[/api\/([\w\-\.]+)\//, 1]
55+ @mod.remove! 'angular2.' if @mod
56+ @mod
57+ end
58+ end
59+ end
60+end
lib/docs/scrapers/angular.rb+88−34
@@ -1,56 +1,110 @@
1+require 'yajl/json_gem'
2+
13 module Docs
24 class Angular < UrlScraper
35 self.type = 'angular'
4− self.root_path = 'api/'
56 self.links = {
67 home: 'https://angular.io/',
78 code: 'https://github.com/angular/angular'
89 }
910
10− html_filters.push 'angular/entries', 'angular/clean_html'
11−
12− options[:skip_patterns] = [/deprecated/, /VERSION-let/]
13− options[:skip] = %w(
14− index.html
15− styleguide.html
16− quickstart.html
17− cheatsheet.html
18− guide/cheatsheet.html
19− guide/style-guide.html)
20−
21− options[:replace_paths] = {
22− 'testing/index.html' => 'guide/testing.html',
23− 'guide/glossary.html' => 'glossary.html',
24− 'tutorial' => 'tutorial/',
25− 'api' => 'api/'
26− }
27−
28− options[:fix_urls] = -> (url) do
29− url.sub! %r{\A(https://(?:v2\.)?angular\.io/docs/.+/)index\.html\z}, '\1'
30− url
31− end
11+ options[:max_image_size] = 256_000
3212
3313 options[:attribution] = <<-HTML
3414 &copy; 2010&ndash;2017 Google, Inc.<br>
3515 Licensed under the Creative Commons Attribution License 4.0.
3616 HTML
3717
38− stub 'api/' do
39− base_url = URL.parse(self.base_url)
40− capybara = load_capybara_selenium
41− capybara.app_host = base_url.origin
42− capybara.visit(base_url.path + 'api/')
43− capybara.execute_script('return document.body.innerHTML')
44− end
18+ version do
19+ self.release = '4.3.2'
20+ self.base_url = 'https://angular.io/'
21+ self.root_path = 'docs'
22+
23+ html_filters.push 'angular/clean_html', 'angular/entries'
24+
25+ options[:follow_links] = false
26+ options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/]
27+ options[:fix_urls_before_parse] = ->(url) do
28+ url.sub! %r{\Aguide/}, '/guide/'
29+ url.sub! %r{\Atutorial/}, '/tutorial/'
30+ url.sub! %r{\Aapi/}, '/api/'
31+ url.sub! %r{\Agenerated/}, '/generated/'
32+ url
33+ end
34+
35+ private
36+
37+ def initial_urls
38+ initial_urls = []
4539
46− version '4 TypeScript' do
47− self.release = '4.0.3'
48− self.base_url = 'https://angular.io/docs/ts/latest/'
40+ Request.run 'https://angular.io/generated/navigation.json' do |response|
41+ data = JSON.parse(response.body)
42+ dig = ->(entry) do
43+ initial_urls << url_for("generated/docs/#{entry['url']}.json") if entry['url'] && entry['url'] != 'api'
44+ entry['children'].each(&dig) if entry['children']
45+ end
46+ data['SideNav'].each(&dig)
47+ end
48+
49+ Request.run 'https://angular.io/generated/docs/api/api-list.json' do |response|
50+ data = JSON.parse(response.body)
51+ dig = ->(entry) do
52+ initial_urls << url_for("generated/docs/#{entry['path']}.json") if entry['path']
53+ initial_urls << url_for("generated/docs/api/#{entry['name']}.json") if entry['name'] && !entry['path']
54+ entry['items'].each(&dig) if entry['items']
55+ end
56+ data.each(&dig)
57+ end
58+
59+ initial_urls
60+ end
61+
62+ def handle_response(response)
63+ if response.mime_type.include?('json')
64+ response.options[:response_body] = JSON.parse(response.body)['contents']
65+ response.headers['Content-Type'] = 'text/html'
66+ response.url.path = response.url.path.sub('/generated/docs/', '/').remove('.json')
67+ response.effective_url.path = response.effective_url.path.sub('/generated/docs/', '/').remove('.json')
68+ end
69+ super
70+ end
4971 end
5072
51− version '2 TypeScript' do
73+ version '2' do
5274 self.release = '2.4.10'
5375 self.base_url = 'https://v2.angular.io/docs/ts/latest/'
76+ self.root_path = 'api/'
77+
78+ html_filters.push 'angular/entries_v2', 'angular/clean_html_v2'
79+
80+ stub 'api/' do
81+ base_url = URL.parse(self.base_url)
82+ capybara = load_capybara_selenium
83+ capybara.app_host = base_url.origin
84+ capybara.visit(base_url.path + 'api/')
85+ capybara.execute_script('return document.body.innerHTML')
86+ end
87+
88+ options[:skip_patterns] = [/deprecated/, /VERSION-let/]
89+ options[:skip] = %w(
90+ index.html
91+ styleguide.html
92+ quickstart.html
93+ cheatsheet.html
94+ guide/cheatsheet.html
95+ guide/style-guide.html)
96+
97+ options[:replace_paths] = {
98+ 'testing/index.html' => 'guide/testing.html',
99+ 'guide/glossary.html' => 'glossary.html',
100+ 'tutorial' => 'tutorial/',
101+ 'api' => 'api/'
102+ }
103+
104+ options[:fix_urls] = -> (url) do
105+ url.sub! %r{\A(https://(?:v2\.)?angular\.io/docs/.+/)index\.html\z}, '\1'
106+ url
107+ end
54108 end
55109
56110 private