Add Angular 2 documentation

pull/421/merge
Thibaut Courouble 9 years ago
parent cd9f50c38b
commit b78244fb53

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 120 KiB

@ -116,6 +116,7 @@
needsSaving = true
doc = @disabledDocs.findBy('slug', 'node~4_lts') if slug == 'node~4.2_lts'
doc = @disabledDocs.findBy('slug', 'xslt_xpath') if slug == 'xpath'
doc = @disabledDocs.findBy('slug', "angularjs~#{match[1]}") if match = /^angular~(1\.\d)$/.exec(slug)
doc ||= @disabledDocs.findBy('slug_without_version', slug)
if doc
@disabledDocs.remove(doc)

@ -1,5 +1,8 @@
[
[
"2016-06-12",
"New documentation: <a href=\"/angular/\">Angular 2</a>"
], [
"2016-06-05",
"New documentation: <a href=\"/kotlin/\">Kotlin</a> and <a href=\"/padrino/\">Padrino</a>"
], [
@ -154,9 +157,6 @@
], [
"2014-02-12",
"The root/category pages are now included in the search index (e.g. <a href=\"/#q=CSS\">CSS</a>)"
], [
"2014-01-26",
"Updated <a href=\"/angular/\">Angular.js</a> documentation"
], [
"2014-01-19",
"New <a href=\"/d3/\">D3.js</a> and <a href=\"/knockout/\">Knockout.js</a> documentations"
@ -210,7 +210,7 @@
"URL search now automatically opens the first result."
], [
"2013-08-13",
"New <a href=\"/angular/\">Angular.js</a> documentation"
"New <a href=\"/angularjs/\">Angular.js</a> documentation"
], [
"2013-08-11",
"New <a href=\"/sass/\">Sass</a> and <a href=\"/less/\">Less</a> documentations"

@ -86,7 +86,7 @@ app.templates.aboutPage = -> """
"""
credits = [
[ 'Angular.js',
[ 'Angular<br>Angular.js',
'2010-2016 Google, Inc.',
'CC BY',
'https://creativecommons.org/licenses/by/4.0/'

@ -7,6 +7,7 @@ class app.views.SimplePage extends app.views.BasePage
return
app.views.AngularPage =
app.views.AngularjsPage =
app.views.CakephpPage =
app.views.ElixirPage =
app.views.EmberPage =

@ -30,6 +30,7 @@
@import 'pages/simple',
'pages/angular',
'pages/angularjs',
'pages/apache',
'pages/bower',
'pages/c',

@ -30,6 +30,7 @@
@import 'pages/simple',
'pages/angular',
'pages/angularjs',
'pages/apache',
'pages/bower',
'pages/c',

@ -38,7 +38,7 @@
._icon-node_lts:before { background-position: -6rem -1rem; }
._icon-sass:before { background-position: -7rem -1rem; }
._icon-less:before { background-position: -8rem -1rem; }
._icon-angular:before { background-position: -9rem -1rem; }
._icon-angularjs:before { background-position: -9rem -1rem; }
._icon-coffeescript:before { background-position: 0 -2rem; @extend %darkIconFix !optional; }
._icon-ember:before { background-position: -1rem -2rem; }
%icon-menu { background-position: -2rem -2rem; }
@ -141,3 +141,4 @@
._icon-numpy:before { background-position: -5rem -11rem; }
._icon-kotlin:before { background-position: -6rem -11rem; }
._icon-padrino:before { background-position: -7rem -11rem; }
._icon-angular:before { background-position: -8rem -11rem; }

@ -1,54 +1,53 @@
._angular {
h2 { @extend %block-heading; }
padding-left: 1rem;
//
// Index
//
h1, h2, > h3, .banner, .badges { margin-left: -1rem; }
.nav-index-section {
margin: 1.5em 0 1em -2em;
list-style: none;
font-weight: bold;
text-transform: capitalize;
}
._mobile & {
padding-left: 0;
//
// Other
//
h1, h2, > h3, .banner, .badges { margin-left: 0; }
}
h3, h4 { font-size: 1rem; }
h2 { @extend %block-heading; }
> h3 { @extend %block-label, %label-blue; }
.alert { @extend %note; }
.alert-success { @extend %note-green; }
.alert-error { @extend %note-red; }
p > code, .status-badge { @extend %label; }
p > code, li > code, td > code { @extend %label; }
.l-sub-section, .alert, .banner { @extend %note; }
.banner { @extend %note-green; }
.alert.is-important { @extend %note-red; }
.alert.is-helpful { @extend %note-blue; }
.view-source, .improve-docs {
position: relative;
float: right;
line-height: 1.7rem;
padding-left: 1em;
font-size: .875rem;
background: $contentBackground;
td > h3, .l-sub-section > h3, .l-sub-section > h4, .alert > h3, .alert > h4 {
margin-top: .25rem;
font-size: 1em;
}
.defs {
padding-left: 1rem;
list-style: none;
img {
display: block;
margin: 1em auto;
> li > h3:first-child {
margin: 0 0 1em -1rem;
@extend %block-label, %label-blue;
&[align="left"] {
float: left;
margin: 0 1em 0 0;
}
> li + li { margin-top: 2em; }
h4 {
margin: 1em 0 .5em;
font-size: 1em;
&[align="right"] {
float: right;
margin: 0 0 0 1em;
}
}
.location-badge {
text-align: right;
font-style: italic;
}
.filetree {
white-space: normal;
@extend %pre;
ul { list-style-type: disc; }
.children { padding-left: 1em; }
}
}

@ -0,0 +1,54 @@
._angularjs {
h2 { @extend %block-heading; }
//
// Index
//
.nav-index-section {
margin: 1.5em 0 1em -2em;
list-style: none;
font-weight: bold;
text-transform: capitalize;
}
//
// Other
//
h3, h4 { font-size: 1rem; }
.alert { @extend %note; }
.alert-success { @extend %note-green; }
.alert-error { @extend %note-red; }
p > code, li > code, td > code { @extend %label; }
.view-source, .improve-docs {
position: relative;
float: right;
line-height: 1.7rem;
padding-left: 1em;
font-size: .875rem;
background: $contentBackground;
}
.defs {
padding-left: 1rem;
list-style: none;
> li > h3:first-child {
margin: 0 0 1em -1rem;
@extend %block-label, %label-blue;
}
> li + li { margin-top: 2em; }
h4 {
margin: 1em 0 .5em;
font-size: 1em;
}
ul { list-style-type: disc; }
}
}

@ -280,12 +280,16 @@ class App < Sinatra::Application
'iojs' => 'node',
'yii1' => 'yii~1.1',
'python2' => 'python~2.7',
'xpath' => 'xslt_xpath'
'xpath' => 'xslt_xpath',
'angular~1.5' => 'angularjs~1.5',
'angular~1.4' => 'angularjs~1.4',
'angular~1.3' => 'angularjs~1.3',
'angular~1.2' => 'angularjs~1.2'
}
get %r{\A/([\w~\.]+)(\-[\w\-]+)?(/.*)?\z} do |doc, type, rest|
return redirect "/#{DOC_REDIRECTS[doc]}#{type}#{rest}" if DOC_REDIRECTS.key?(doc)
return redirect "/angular/api#{rest}", 301 if doc == 'angular' && rest.start_with?('/ng')
return redirect "/angularjs/api#{rest}", 301 if doc == 'angular' && rest.start_with?('/ng')
return 404 unless @doc = find_doc(doc)
if rest.nil?

@ -2,96 +2,85 @@ module Docs
class Angular
class CleanHtmlFilter < Filter
def call
root_page? ? root : other
container = at_css('article.docs-content')
container.child.before(at_css('header.hero h1')).before(css('header.hero .badges')).before(css('header.hero + .banner'))
@doc = container
# Remove ng-* attributes
css('*').each do |node|
node.attributes.each_key do |attribute|
node.remove_attribute(attribute) if attribute.start_with? 'ng-'
end
css('pre.no-bg-with-indent').each do |node|
node.content = ' ' + node.content.gsub("\n", "\n ")
end
doc
end
def root
css('.nav-index-group').each do |node|
if heading = node.at_css('.nav-index-group-heading')
heading.name = 'h2'
end
node.parent.before(node.children)
css('.openParens').each do |node|
node.parent.name = 'pre'
node.parent.content = node.parent.css('code, pre').map(&:content).join("\n")
end
css('.nav-index-section').each do |node|
node.content = node.content
css('button.verbose', 'button.verbose + .l-verbose-section', 'a[id=top]', 'a[href="#top"]').remove
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').each do |node|
node.before(node.children).remove
end
css('.toc-close', '.naked-list').remove
end
css('span.badges').each do |node|
node.name = 'div'
end
def other
css('#example', '.example', '#description_source', '#description_demo', '[id$="example"]', 'hr').remove
css('pre[language]').each do |node|
node['data-language'] = node['language'].sub(/\Ats/, 'typescript').strip
end
css('header').each do |node|
node.before(node.children).remove
css('pre.prettyprint').each do |node|
node.content = node.content.strip
end
if h1 = at_css('h1')
h1.prepend_child(css('.view-source', '.improve-docs'))
css('a[id]:empty').each do |node|
node.next_element['id'] = node['id'] if node.next_element
end
# Remove root-level <div>
while div = at_css('h1 + div')
div.before(div.children)
div.remove
css('a[name]:empty').each do |node|
node.next_element['id'] = node['name'] if node.next_element
end
css('.api-profile-header-structure > li').each do |node|
node.inner_html = node.inner_html.remove('- ')
css('tr[style]').each do |node|
node.remove_attribute 'style'
end
css('h1').each_with_index do |node, i|
next if i == 0
css('h1:not(:first-child)').each do |node|
node.name = 'h2'
end
end unless at_css('h2')
# Remove examples
css('.runnable-example').each do |node|
node.parent.remove
css('img[style]').each do |node|
node['align'] ||= node['style'][/float:\s*(left|right)/, 1]
node['style'] = node['style'].split(';').map(&:strip).select { |s| s =~ /\Awidth|height/ }.join(';')
end
# Remove dead links (e.g. ngRepeat)
css('a.type-hint').each do |node|
node.name = 'code'
node.remove_attribute 'href'
css('.example-title + pre').each do |node|
node['name'] = node.previous_element.content.strip
node.previous_element.remove
end
css('pre > code').each do |node|
node['class'] ||= ''
lang = if node['class'].include?('lang-html') || node.content =~ /\A</
'html'
elsif node['class'].include?('lang-css')
'css'
elsif node['class'].include?('lang-js') || node['class'].include?('lang-javascript')
'javascript'
css('pre[name]').each do |node|
case node['data-language']
when 'html' then node.content = "<!-- #{node['name']} -->\n\n" + node.content
when 'css' then node.content = "/* #{node['name']} */\n\n" + node.content
else node.content = "// #{node['name']}\n\n" + node.content
end
node.parent['data-language'] = lang if lang
end
node.before(node.children).remove
css('a.is-button > h3').each do |node|
node.parent.content = node.content
end
# Remove some <code> elements
css('h1 > code', 'h2 > code', 'h3 > code', 'h4 > code', 'h6 > code').each do |node|
node.before(node.content).remove
css('#angular-2-glossary ~ .l-sub-section').each do |node|
node.before(node.children).remove
end
css('ul.methods', 'ul.properties', 'ul.events').add_class('defs').each do |node|
node.css('> li > h3').each do |h3|
next if h3.content.present?
h3.content = h3.next_element.content
h3.next_element.remove
end
location_badge = at_css('.location-badge')
if location_badge && doc.last_element_child != location_badge
doc.last_element_child.after(location_badge)
end
doc
end
end
end

@ -2,51 +2,42 @@ module Docs
class Angular
class EntriesFilter < Docs::EntriesFilter
def get_name
if slug.start_with?('api')
name = URI.unescape(slug).split('/').last
name.remove! %r{\Ang\.}
name << " (#{subtype})" if subtype == 'directive' || subtype == 'filter'
name.prepend("#{type}.") unless type.starts_with?('ng ') || name == type
name
elsif slug.start_with?('guide')
name = URI.decode(at_css('.improve-docs')['href'][/message=docs\(guide%2F(.+?)\)/, 1])
name.prepend 'Guide: '
name
name = at_css('header.hero h1').content.strip
name = name.split(':').first
if mod
if name == 'Testing'
return "#{mod.capitalize} Testing"
elsif name == 'Index' || name == 'Angular'
return mod
end
end
name << '()' if at_css('.status-badge').try(:content) == 'Function'
name
end
def get_type
if slug.start_with?('api')
type = slug.split('/').drop(1).first
type << " #{subtype}s" if type == 'ng' && subtype
type
elsif slug.start_with?('guide')
if slug.start_with?('guide/')
'Guide'
else
type = at_css('.is-nav-title-selected').content.strip
type.remove! ' Reference'
type << ": #{mod}" if mod
type
end
end
def subtype
return @subtype if defined? @subtype
node = at_css '.api-profile-header-structure'
data = node.content.match %r{(\w+?) in module} if node
@subtype = data && data[1]
end
INDEX = Set.new
def additional_entries
return [] unless slug.start_with?('api')
entries = []
def include_default_entry?
INDEX.add?([name, type].join(';')) ? true : false # ¯\_(ツ)_/¯
end
css('ul.defs').each do |list|
list.css('> li[id]').each do |node|
next unless heading = node.at_css('h3')
name = heading.content.strip
name.sub! %r{\(.*\);}, '()'
name.prepend "#{self.name.split.first}."
entries << [name, node['id']]
end
end
private
entries
def mod
@mod ||= slug[/api\/([\w\-]+)\//, 1]
end
end
end

@ -0,0 +1,98 @@
module Docs
class Angularjs
class CleanHtmlFilter < Filter
def call
root_page? ? root : other
# Remove ng-* attributes
css('*').each do |node|
node.attributes.each_key do |attribute|
node.remove_attribute(attribute) if attribute.start_with? 'ng-'
end
end
doc
end
def root
css('.nav-index-group').each do |node|
if heading = node.at_css('.nav-index-group-heading')
heading.name = 'h2'
end
node.parent.before(node.children)
end
css('.nav-index-section').each do |node|
node.content = node.content
end
css('.toc-close', '.naked-list').remove
end
def other
css('#example', '.example', '#description_source', '#description_demo', '[id$="example"]', 'hr').remove
css('header').each do |node|
node.before(node.children).remove
end
if h1 = at_css('h1')
h1.prepend_child(css('.view-source', '.improve-docs'))
end
# Remove root-level <div>
while div = at_css('h1 + div')
div.before(div.children)
div.remove
end
css('.api-profile-header-structure > li').each do |node|
node.inner_html = node.inner_html.remove('- ')
end
css('h1').each_with_index do |node, i|
next if i == 0
node.name = 'h2'
end
# Remove examples
css('.runnable-example').each do |node|
node.parent.remove
end
# Remove dead links (e.g. ngRepeat)
css('a.type-hint').each do |node|
node.name = 'code'
node.remove_attribute 'href'
end
css('pre > code').each do |node|
node['class'] ||= ''
lang = if node['class'].include?('lang-html') || node.content =~ /\A</
'html'
elsif node['class'].include?('lang-css')
'css'
elsif node['class'].include?('lang-js') || node['class'].include?('lang-javascript')
'javascript'
end
node.parent['data-language'] = lang if lang
node.before(node.children).remove
end
# Remove some <code> elements
css('h1 > code', 'h2 > code', 'h3 > code', 'h4 > code', 'h6 > code').each do |node|
node.before(node.content).remove
end
css('ul.methods', 'ul.properties', 'ul.events').add_class('defs').each do |node|
node.css('> li > h3').each do |h3|
next if h3.content.present?
h3.content = h3.next_element.content
h3.next_element.remove
end
end
end
end
end
end

@ -1,5 +1,5 @@
module Docs
class Angular
class Angularjs
class CleanUrlsFilter < Filter
def call
html.gsub! %r{angularjs\.org/([\d\.]+)/docs/partials/(\w+)/}, 'angularjs.org/\1/docs/\2/'

@ -0,0 +1,53 @@
module Docs
class Angularjs
class EntriesFilter < Docs::EntriesFilter
def get_name
if slug.start_with?('api')
name = URI.unescape(slug).split('/').last
name.remove! %r{\Ang\.}
name << " (#{subtype})" if subtype == 'directive' || subtype == 'filter'
name.prepend("#{type}.") unless type.starts_with?('ng ') || name == type
name
elsif slug.start_with?('guide')
name = URI.decode(at_css('.improve-docs')['href'][/message=docs\(guide%2F(.+?)\)/, 1])
name.prepend 'Guide: '
name
end
end
def get_type
if slug.start_with?('api')
type = slug.split('/').drop(1).first
type << " #{subtype}s" if type == 'ng' && subtype
type
elsif slug.start_with?('guide')
'Guide'
end
end
def subtype
return @subtype if defined? @subtype
node = at_css '.api-profile-header-structure'
data = node.content.match %r{(\w+?) in module} if node
@subtype = data && data[1]
end
def additional_entries
return [] unless slug.start_with?('api')
entries = []
css('ul.defs').each do |list|
list.css('> li[id]').each do |node|
next unless heading = node.at_css('h3')
name = heading.content.strip
name.sub! %r{\(.*\);}, '()'
name.prepend "#{self.name.split.first}."
entries << [name, node['id']]
end
end
entries
end
end
end
end

@ -1,68 +1,59 @@
module Docs
class Angular < UrlScraper
self.name = 'Angular.js'
self.slug = 'angular'
self.type = 'angular'
self.root_path = 'api.html'
self.initial_paths = %w(guide.html)
html_filters.push 'angular/clean_html', 'angular/entries', 'title'
text_filters.push 'angular/clean_urls'
options[:title] = false
options[:root_title] = 'Angular.js'
options[:decode_and_clean_paths] = true
options[:fix_urls_before_parse] = ->(str) do
str.gsub!('[', '%5B')
str.gsub!(']', '%5D')
str
end
options[:fix_urls] = ->(url) do
%w(api guide).each do |str|
url.sub! "/partials/#{str}/#{str}/", "/partials/#{str}/"
url.sub! %r{/#{str}/img/}, "/img/"
url.sub! %r{/#{str}/(.+?)/#{str}/}, "/#{str}/"
url.sub! %r{/partials/#{str}/(.+?)(?<!\.html)(?:\z|(#.*))}, "/partials/#{str}/\\1.html\\2"
url.sub! %r{/partials/.+/#{str}/}, "/partials/#{str}/"
end
self.root_path = 'api/'
self.links = {
home: 'https://angular.io/',
code: 'https://github.com/angular/angular'
}
html_filters.push 'angular/entries', 'angular/clean_html'
options[:skip_patterns] = [/deprecated/]
options[:skip] = %w(
index.html
styleguide.html
quickstart.html
guide/cheatsheet.html
guide/style-guide.html)
options[:replace_paths] = {
'testing/index.html' => 'guide/testing.html',
'glossary.html' => 'guide/glossary.html',
'tutorial' => 'tutorial/'
}
options[:fix_urls] = -> (url) do
url.sub! %r{\A(https://angular\.io/docs/.+/)index\.html\z}, '\1'
url.sub! %r{\A(https://angular\.io/docs/.+/index)/\z}, '\1'
url
end
options[:only_patterns] = [%r{\Aapi/}, %r{\Aguide/}]
options[:skip] = %w(api/ng.html)
options[:attribution] = <<-HTML
&copy; 2010&ndash;2016 Google, Inc.<br>
Licensed under the Creative Commons Attribution License 4.0.
HTML
stub '' do
stub 'api/' do
capybara = load_capybara_selenium
capybara.app_host = 'https://code.angularjs.org'
capybara.visit("/#{self.class.release}/docs/api")
capybara.execute_script("return document.querySelector('.side-navigation').innerHTML")
end
version '1.5' do
self.release = '1.5.6'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
capybara.app_host = 'https://angular.io'
capybara.visit('/docs/ts/latest/api/')
capybara.execute_script('return document.body.innerHTML')
end
version '1.4' do
self.release = '1.4.11'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
version '2.0 TypeScript' do
self.release = '2.0.0rc1'
self.base_url = "https://angular.io/docs/ts/latest/"
end
version '1.3' do
self.release = '1.3.20'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
end
private
version '1.2' do
self.release = '1.2.29'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
def parse(string)
string.gsub! '<code-example', '<pre'
string.gsub! '</code-example', '</pre'
string.gsub! '<code-pane', '<pre'
string.gsub! '</code-pane', '</pre'
super string
end
end
end

@ -0,0 +1,68 @@
module Docs
class Angularjs < UrlScraper
self.name = 'Angular.js'
self.slug = 'angularjs'
self.type = 'angularjs'
self.root_path = 'api.html'
self.initial_paths = %w(guide.html)
html_filters.push 'angularjs/clean_html', 'angularjs/entries', 'title'
text_filters.push 'angularjs/clean_urls'
options[:title] = false
options[:root_title] = 'Angular.js'
options[:decode_and_clean_paths] = true
options[:fix_urls_before_parse] = ->(str) do
str.gsub!('[', '%5B')
str.gsub!(']', '%5D')
str
end
options[:fix_urls] = ->(url) do
%w(api guide).each do |str|
url.sub! "/partials/#{str}/#{str}/", "/partials/#{str}/"
url.sub! %r{/#{str}/img/}, "/img/"
url.sub! %r{/#{str}/(.+?)/#{str}/}, "/#{str}/"
url.sub! %r{/partials/#{str}/(.+?)(?<!\.html)(?:\z|(#.*))}, "/partials/#{str}/\\1.html\\2"
url.sub! %r{/partials/.+/#{str}/}, "/partials/#{str}/"
end
url
end
options[:only_patterns] = [%r{\Aapi/}, %r{\Aguide/}]
options[:skip] = %w(api/ng.html)
options[:attribution] = <<-HTML
&copy; 2010&ndash;2016 Google, Inc.<br>
Licensed under the Creative Commons Attribution License 4.0.
HTML
stub '' do
capybara = load_capybara_selenium
capybara.app_host = 'https://code.angularjs.org'
capybara.visit("/#{self.class.release}/docs/api")
capybara.execute_script("return document.querySelector('.side-navigation').innerHTML")
end
version '1.5' do
self.release = '1.5.6'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
end
version '1.4' do
self.release = '1.4.11'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
end
version '1.3' do
self.release = '1.3.20'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
end
version '1.2' do
self.release = '1.2.29'
self.base_url = "https://code.angularjs.org/#{release}/docs/partials/"
end
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -1 +1 @@
https://github.com/angular/angular.js/tree/master/images/logo/AngularJS-Shield.exports
https://angular.io/presskit.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1 @@
https://github.com/angular/angular.js/tree/master/images/logo/AngularJS-Shield.exports
Loading…
Cancel
Save