Unified · Split
| @@ -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 = true | 120 | 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 doc | 125 | if doc |
| 124 | @disabledDocs.remove(doc) | 126 | @disabledDocs.remove(doc) |
| @@ -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 | } |
| @@ -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 | } |
| @@ -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', |
| @@ -13,7 +13,7 @@ module Docs · 12 unmodified lines | |||
| 13 | end | 13 | end |
| 14 | 14 | ||
| 15 | def mime_type | 15 | def mime_type |
| 16 | @mime_type ||= headers['Content-Type'] || 'text/plain' | 16 | headers['Content-Type'] || 'text/plain' |
| 17 | end | 17 | end |
| 18 | 18 | ||
| 19 | def html? | 19 | def html? |
| @@ -2,103 +2,86 @@ module Docs · 1 unmodified line | |||
| 2 | class Angular | 2 | class Angular |
| 3 | class CleanHtmlFilter < Filter | 3 | class CleanHtmlFilter < Filter |
| 4 | def call | 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? | 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 | end | 8 | 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).remove | 13 | node.before(node.children).remove |
| 39 | end | 14 | 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 | end | 18 | 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').strip | 21 | 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 | end | 27 | 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.strip | 30 | node.name = 'h4' |
| 52 | node['data-language'] = 'dart' if node['class'].include?('dart') | ||
| 53 | node['data-language'] = 'html' if node.content.start_with?('<') | ||
| 54 | end | 31 | 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 | end | 35 | 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_element | 38 | node.content = node.content.strip |
| 63 | end | 39 | 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_element | 42 | node.css('.file').each do |n| |
| 43 | n.content = " #{n.content}" | ||
| 44 | end | ||
| 67 | end | 45 | 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 | end | 51 | 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 | end | 59 | 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 | end | 66 | 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.content | 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') | ||
| 93 | end | 76 | 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).remove | 79 | css('table[class]').remove_attr('class') |
| 97 | end | 80 | 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_badge | 84 | at_css('h1').content = subpath.remove('api/') |
| 101 | doc.last_element_child.after(location_badge) | ||
| 102 | end | 85 | end |
| 103 | 86 | ||
| 104 | doc | 87 | doc |
| @@ -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 | ||
| @@ -2,59 +2,24 @@ module Docs · 1 unmodified line | |||
| 2 | class Angular | 2 | class Angular |
| 3 | class EntriesFilter < Docs::EntriesFilter | 3 | class EntriesFilter < Docs::EntriesFilter |
| 4 | def get_name | 4 | 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.strip | 6 | 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 | name | 7 | name |
| 27 | end | 8 | end |
| 28 | 9 | ||
| 29 | def get_type | 10 | 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 | else | 19 | else |
| 37 | type = at_css('.nav-title.is-selected').content.strip | 20 | 'Miscellaneous' |
| 38 | type.remove! ' Reference' | ||
| 39 | type << ": #{mod}" if mod | ||
| 40 | type | ||
| 41 | end | 21 | end |
| 42 | end | 22 | 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 | 23 | end |
| 59 | end | 24 | end |
| 60 | end | 25 | end |
| @@ -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 | ||
| @@ -1,56 +1,110 @@ | |||
| 1 | require 'yajl/json_gem' | ||
| 2 | |||
| 1 | module Docs | 3 | module Docs |
| 2 | class Angular < UrlScraper | 4 | 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] = <<-HTML | 13 | options[:attribution] = <<-HTML |
| 34 | © 2010–2017 Google, Inc.<br> | 14 | © 2010–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 | HTML | 16 | HTML |
| 37 | 17 | ||
| 38 | stub 'api/' do | 18 | version do |
| 39 | base_url = URL.parse(self.base_url) | 19 | self.release = '4.3.2' |
| 40 | capybara = load_capybara_selenium | 20 | self.base_url = 'https://angular.io/' |
| 41 | capybara.app_host = base_url.origin | 21 | 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 | end | 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 = [] | ||
| 45 | 39 | ||
| 46 | version '4 TypeScript' do | 40 | 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 | end | 71 | end |
| 50 | 72 | ||
| 51 | version '2 TypeScript' do | 73 | 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 | end | 108 | end |
| 55 | 109 | ||
| 56 | private | 110 | private |