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
119 for slug in @settings.getDocs() when not @docs.findBy('slug', slug)119 for slug in @settings.getDocs() when not @docs.findBy('slug', slug)
120 needsSaving = true120 needsSaving = true
121 doc = @disabledDocs.findBy('slug', 'webpack') if slug == 'webpack~2'121 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'
122 doc ||= @disabledDocs.findBy('slug_without_version', slug)124 doc ||= @disabledDocs.findBy('slug_without_version', slug)
123 if doc125 if doc
124 @disabledDocs.remove(doc)126 @disabledDocs.remove(doc)
assets/stylesheets/pages/_angular.scss+9−42
@@ -1,55 +1,22 @@
1._angular {1._angular {
2 padding-left: 1rem;2 @extend %simple;
3 3
4 h1, h2, > h3, .banner, .badges, .breadcrumbs { margin-left: -1rem; }4 .pre-title { @extend %pre-heading; }
5 5
6 ._mobile & {6 .breadcrumbs { @extend %note; }
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; }
19 .banner { @extend %note-green; }7 .banner { @extend %note-green; }
8 code.stable { @extend %label-green; }
9 code.experimental { @extend %label-orange; }
10 code.deprecated { @extend %label-red; }
20 .alert.is-important { @extend %note-red; }11 .alert.is-important { @extend %note-red; }
21 .alert.is-helpful, .breadcrumbs { @extend %note-blue; }12 .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 }
28 13
29 img {14 .breadcrumbs { padding-left: 2em; }
30 display: block;
31 margin: 1em auto;
32
33 &[align="left"] {
34 float: left;
35 margin: 0 1em 0 0;
36 }
37 15
38 &[align="right"] {16 img { margin: 1em 0; }
39 float: right;
40 margin: 0 0 0 1em;
41 }
42 }
43 17
44 .location-badge {18 .location-badge {
45 text-align: right;
46 font-style: italic;19 font-style: italic;
47 }20 text-align: right;
48
49 .filetree {
50 white-space: normal;
51 @extend %pre;
52
53 .children { padding-left: 1em; }
54 }21 }
55}22}
assets/stylesheets/pages/_simple.scss+1−1
@@ -12,7 +12,7 @@ · 11 unmodified lines
12 h1, h2, h3 { margin-left: 0; }12 h1, h2, h3 { margin-left: 0; }
13 }13 }
14 14
15 p > code, li > code, td > code, blockquote > code { @extend %label; }15 p > code, li > code, td > code, blockquote > code, dd > code { @extend %label; }
16 blockquote { @extend %note; }16 blockquote { @extend %note; }
17 blockquote > h4, blockquote > h5 { margin-top: .25rem; }17 blockquote > h4, blockquote > h5 { margin-top: .25rem; }
18}18}
lib/app.rb+3−1
@@ -352,7 +352,9 @@ class App < Sinatra::Application · 351 unmodified lines
352 'yii1' => 'yii~1.1',352 'yii1' => 'yii~1.1',
353 'python2' => 'python~2.7',353 'python2' => 'python~2.7',
354 'xpath' => 'xslt_xpath',354 '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',
356 'angular~1.5' => 'angularjs~1.5',358 'angular~1.5' => 'angularjs~1.5',
357 'angular~1.4' => 'angularjs~1.4',359 'angular~1.4' => 'angularjs~1.4',
358 'angular~1.3' => 'angularjs~1.3',360 'angular~1.3' => 'angularjs~1.3',
lib/docs/core/response.rb+1−1
@@ -13,7 +13,7 @@ module Docs · 12 unmodified lines
13 end13 end
14 14
15 def mime_type15 def mime_type
16 @mime_type ||= headers['Content-Type'] || 'text/plain'16 headers['Content-Type'] || 'text/plain'
17 end17 end
18 18
19 def html?19 def html?
lib/docs/filters/angular/clean_html.rb+51−68
@@ -2,103 +2,86 @@ module Docs · 1 unmodified line
2 class Angular2 class Angular
3 class CleanHtmlFilter < Filter3 class CleanHtmlFilter < Filter
4 def call4 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?5 if root_page?
6 css('.card-container').remove
17 at_css('h1').content = 'Angular Documentation'7 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
24 end8 end
25 9
26 css('pre.no-bg-with-indent').each do |node|10 css('br', 'hr', '.material-icons', '.header-link').remove
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
36 11
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|
38 node.before(node.children).remove13 node.before(node.children).remove
39 end14 end
40 15
41 css('span.badges').each do |node|16 css('label', 'h2 > em', 'h3 > em').each do |node|
42 node.name = 'div'17 node.name = 'code'
43 end18 end
44 19
45 css('pre[language]').each do |node|20 css('h1 + code').each do |node|
46 node['data-language'] = node['language'].sub(/\Ats/, 'typescript').strip21 node.before('<p></p>')
47 node['data-language'] = 'html' if node.content.start_with?('<')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)
48 end27 end
49 28
50 css('pre.prettyprint').each do |node|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|
51 node.content = node.content.strip30 node.name = 'h4'
52 node['data-language'] = 'dart' if node['class'].include?('dart')
53 node['data-language'] = 'html' if node.content.start_with?('<')
54 end31 end
55 32
56 css('.multi-line-signature').each do |node|33 css('.l-sub-section', '.alert', '.banner').each do |node|
57 node.name = 'pre'34 node.name = 'blockquote'
58 node.content = node.content.strip
59 end35 end
60 36
61 css('a[id]:empty').each do |node|37 css('.file').each do |node|
62 node.next_element['id'] = node['id'] if node.next_element38 node.content = node.content.strip
63 end39 end
64 40
65 css('a[name]:empty').each do |node|41 css('.filetree .children').each do |node|
66 node.next_element['id'] = node['name'] if node.next_element42 node.css('.file').each do |n|
43 n.content = " #{n.content}"
44 end
67 end45 end
68 46
69 css('tr[style]').each do |node|47 css('.filetree').each do |node|
70 node.remove_attribute 'style'48 node.content = node.css('.file').map(&:inner_html).join("\n")
49 node.name = 'pre'
50 node.remove_attribute('class')
71 end51 end
72 52
73 css('h1:not(:first-child)').each do |node|53 css('pre').each do |node|
74 node.name = 'h2'54 node.content = node.content.strip
75 end unless at_css('h2')
76 55
77 css('img[style]').each do |node|56 node['data-language'] = 'typescript' if node['path'].try(:ends_with?, '.ts')
78 node['align'] ||= node['style'][/float:\s*(left|right)/, 1]57 node['data-language'] = 'html' if node['path'].try(:ends_with?, '.html')
79 node['style'] = node['style'].split(';').map(&:strip).select { |s| s =~ /\Awidth|height/ }.join(';')58 node['data-language'] = 'css' if node['path'].try(:ends_with?, '.css')
80 end59 node['data-language'] = node['language'].sub(/\Ats/, 'typescript').strip if node['language']
60 node['data-language'] ||= 'typescript' if node.content.start_with?('@')
81 61
82 css('.example-title + pre').each do |node|62 node.before(%(<div class="pre-title">#{node['title']}</div>)) if node['title']
83 node['name'] = node.previous_element.content.strip
84 node.previous_element.remove
85 end
86 63
87 css('pre[name]').each do |node|64 if node['class'] && node['class'].include?('api-heading')
88 node.before(%(<div class="pre-title">#{node['name']}</div>))65 node.name = 'h3'
89 end66 node.inner_html = "<code>#{node.inner_html}</code>"
67 end
90 68
91 css('a.is-button > h3').each do |node|69 node.remove_attribute('path')
92 node.parent.content = node.content70 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')
93 end76 end
94 77
95 css('#angular-2-glossary ~ .l-sub-section').each do |node|78 css('h1[class]').remove_attr('class')
96 node.before(node.children).remove79 css('table[class]').remove_attr('class')
97 end80 css('table[width]').remove_attr('width')
81 css('tr[style]').remove_attr('style')
98 82
99 location_badge = at_css('.location-badge')83 if at_css('.api-type-label.module')
100 if location_badge && doc.last_element_child != location_badge84 at_css('h1').content = subpath.remove('api/')
101 doc.last_element_child.after(location_badge)
102 end85 end
103 86
104 doc87 doc
lib/docs/filters/angular/clean_html_v2.rb+157−0
@@ -0,0 +1,157 @@
1module 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
157end
lib/docs/filters/angular/entries.rb+10−45
@@ -2,59 +2,24 @@ module Docs · 1 unmodified line
2 class Angular2 class Angular
3 class EntriesFilter < Docs::EntriesFilter3 class EntriesFilter < Docs::EntriesFilter
4 def get_name4 def get_name
5 if slug.start_with?('tutorial') || slug.start_with?('guide')5 name = at_css('h1').content
6 name = at_css('.nav-list-item.is-selected, header.hero h1').content.strip6 name.prepend "#{$1}. " if subpath =~ /\-pt(\d+)/
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 name7 name
27 end8 end
28 9
29 def get_type10 def get_type
30 if slug.start_with?('guide/')11 if slug.start_with?('guide')
31 'Guide'
32 elsif slug.start_with?('cookbook/')
33 'Cookbook'
34 elsif slug == 'glossary'
35 'Guide'12 '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
36 else19 else
37 type = at_css('.nav-title.is-selected').content.strip20 'Miscellaneous'
38 type.remove! ' Reference'
39 type << ": #{mod}" if mod
40 type
41 end21 end
42 end22 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 end23 end
59 end24 end
60end25end
lib/docs/filters/angular/entries_v2.rb+60−0
@@ -0,0 +1,60 @@
1module 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
60end
lib/docs/scrapers/angular.rb+88−34
@@ -1,56 +1,110 @@
1require 'yajl/json_gem'
2
1module Docs3module Docs
2 class Angular < UrlScraper4 class Angular < UrlScraper
3 self.type = 'angular'5 self.type = 'angular'
4 self.root_path = 'api/'
5 self.links = {6 self.links = {
6 home: 'https://angular.io/',7 home: 'https://angular.io/',
7 code: 'https://github.com/angular/angular'8 code: 'https://github.com/angular/angular'
8 }9 }
9 10
10 html_filters.push 'angular/entries', 'angular/clean_html'11 options[:max_image_size] = 256_000
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
32 12
33 options[:attribution] = <<-HTML13 options[:attribution] = <<-HTML
34 &copy; 2010&ndash;2017 Google, Inc.<br>14 &copy; 2010&ndash;2017 Google, Inc.<br>
35 Licensed under the Creative Commons Attribution License 4.0.15 Licensed under the Creative Commons Attribution License 4.0.
36 HTML16 HTML
37 17
38 stub 'api/' do18 version do
39 base_url = URL.parse(self.base_url)19 self.release = '4.3.2'
40 capybara = load_capybara_selenium20 self.base_url = 'https://angular.io/'
41 capybara.app_host = base_url.origin21 self.root_path = 'docs'
42 capybara.visit(base_url.path + 'api/')22
43 capybara.execute_script('return document.body.innerHTML')23 html_filters.push 'angular/clean_html', 'angular/entries'
44 end24
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 = []
45 39
46 version '4 TypeScript' do40 Request.run 'https://angular.io/generated/navigation.json' do |response|
47 self.release = '4.0.3'41 data = JSON.parse(response.body)
48 self.base_url = 'https://angular.io/docs/ts/latest/'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
49 end71 end
50 72
51 version '2 TypeScript' do73 version '2' do
52 self.release = '2.4.10'74 self.release = '2.4.10'
53 self.base_url = 'https://v2.angular.io/docs/ts/latest/'75 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
54 end108 end
55 109
56 private110 private