Unified · Split
| @@ -119,6 +119,8 @@ · 118 unmodified lines | ||
| 119 | 119 | for slug in @settings.getDocs() when not @docs.findBy('slug', slug) |
| 120 | 120 | needsSaving = true |
| 121 | 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 | 124 | doc ||= @disabledDocs.findBy('slug_without_version', slug) |
| 123 | 125 | if doc |
| 124 | 126 | @disabledDocs.remove(doc) |
| @@ -1,55 +1,22 @@ | ||
| 1 | 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 & { | |
| 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; } | |
| 19 | 7 | .banner { @extend %note-green; } |
| 8 | + code.stable { @extend %label-green; } | |
| 9 | + code.experimental { @extend %label-orange; } | |
| 10 | + code.deprecated { @extend %label-red; } | |
| 20 | 11 | .alert.is-important { @extend %note-red; } |
| 21 | 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 { | |
| 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; } | |
| 37 | 15 | |
| 38 | − &[align="right"] { | |
| 39 | − float: right; | |
| 40 | − margin: 0 0 0 1em; | |
| 41 | − } | |
| 42 | − } | |
| 16 | + img { margin: 1em 0; } | |
| 43 | 17 | |
| 44 | 18 | .location-badge { |
| 45 | − text-align: right; | |
| 46 | 19 | font-style: italic; |
| 47 | − } | |
| 48 | − | |
| 49 | − .filetree { | |
| 50 | − white-space: normal; | |
| 51 | − @extend %pre; | |
| 52 | − | |
| 53 | − .children { padding-left: 1em; } | |
| 20 | + text-align: right; | |
| 54 | 21 | } |
| 55 | 22 | } |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 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 | 16 | blockquote { @extend %note; } |
| 17 | 17 | blockquote > h4, blockquote > h5 { margin-top: .25rem; } |
| 18 | 18 | } |
| @@ -352,7 +352,9 @@ class App < Sinatra::Application · 351 unmodified lines | ||
| 352 | 352 | 'yii1' => 'yii~1.1', |
| 353 | 353 | 'python2' => 'python~2.7', |
| 354 | 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 | 358 | 'angular~1.5' => 'angularjs~1.5', |
| 357 | 359 | 'angular~1.4' => 'angularjs~1.4', |
| 358 | 360 | 'angular~1.3' => 'angularjs~1.3', |
| @@ -13,7 +13,7 @@ module Docs · 12 unmodified lines | ||
| 13 | 13 | end |
| 14 | 14 | |
| 15 | 15 | def mime_type |
| 16 | − @mime_type ||= headers['Content-Type'] || 'text/plain' | |
| 16 | + headers['Content-Type'] || 'text/plain' | |
| 17 | 17 | end |
| 18 | 18 | |
| 19 | 19 | def html? |
| @@ -2,103 +2,86 @@ module Docs · 1 unmodified line | ||
| 2 | 2 | class Angular |
| 3 | 3 | class CleanHtmlFilter < Filter |
| 4 | 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 | 5 | if root_page? |
| 6 | + css('.card-container').remove | |
| 17 | 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 | 8 | end |
| 25 | 9 | |
| 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 | |
| 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 | 13 | node.before(node.children).remove |
| 39 | 14 | end |
| 40 | 15 | |
| 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' | |
| 43 | 18 | end |
| 44 | 19 | |
| 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) | |
| 48 | 27 | end |
| 49 | 28 | |
| 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' | |
| 54 | 31 | end |
| 55 | 32 | |
| 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' | |
| 59 | 35 | end |
| 60 | 36 | |
| 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 | |
| 63 | 39 | end |
| 64 | 40 | |
| 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 | |
| 67 | 45 | end |
| 68 | 46 | |
| 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') | |
| 71 | 51 | end |
| 72 | 52 | |
| 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 | |
| 76 | 55 | |
| 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?('@') | |
| 81 | 61 | |
| 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'] | |
| 86 | 63 | |
| 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 | |
| 90 | 68 | |
| 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') | |
| 93 | 76 | end |
| 94 | 77 | |
| 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') | |
| 98 | 82 | |
| 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/') | |
| 102 | 85 | end |
| 103 | 86 | |
| 104 | 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 | 2 | class Angular |
| 3 | 3 | class EntriesFilter < Docs::EntriesFilter |
| 4 | 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) | |
| 5 | + name = at_css('h1').content | |
| 6 | + name.prepend "#{$1}. " if subpath =~ /\-pt(\d+)/ | |
| 26 | 7 | name |
| 27 | 8 | end |
| 28 | 9 | |
| 29 | 10 | 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') | |
| 35 | 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 | 19 | else |
| 37 | − type = at_css('.nav-title.is-selected').content.strip | |
| 38 | − type.remove! ' Reference' | |
| 39 | − type << ": #{mod}" if mod | |
| 40 | − type | |
| 20 | + 'Miscellaneous' | |
| 41 | 21 | end |
| 42 | 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 | 23 | end |
| 59 | 24 | end |
| 60 | 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 | 3 | module Docs |
| 2 | 4 | class Angular < UrlScraper |
| 3 | 5 | self.type = 'angular' |
| 4 | − self.root_path = 'api/' | |
| 5 | 6 | self.links = { |
| 6 | 7 | home: 'https://angular.io/', |
| 7 | 8 | code: 'https://github.com/angular/angular' |
| 8 | 9 | } |
| 9 | 10 | |
| 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 | |
| 32 | 12 | |
| 33 | 13 | options[:attribution] = <<-HTML |
| 34 | 14 | © 2010–2017 Google, Inc.<br> |
| 35 | 15 | Licensed under the Creative Commons Attribution License 4.0. |
| 36 | 16 | HTML |
| 37 | 17 | |
| 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 = [] | |
| 45 | 39 | |
| 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 | |
| 49 | 71 | end |
| 50 | 72 | |
| 51 | − version '2 TypeScript' do | |
| 73 | + version '2' do | |
| 52 | 74 | self.release = '2.4.10' |
| 53 | 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 | 108 | end |
| 55 | 109 | |
| 56 | 110 | private |