diff --git a/assets/images/docs.png b/assets/images/docs.png index f15d45ab..d1161c88 100644 Binary files a/assets/images/docs.png and b/assets/images/docs.png differ diff --git a/assets/images/docs@2x.png b/assets/images/docs@2x.png index 3ca913d2..6ccbcde5 100644 Binary files a/assets/images/docs@2x.png and b/assets/images/docs@2x.png differ diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json index 6b365355..5eb4e159 100644 --- a/assets/javascripts/news.json +++ b/assets/javascripts/news.json @@ -1,5 +1,8 @@ [ [ + "2016-07-31", + "New documentation: Bootstrap" + ], [ "2016-07-24", "New documentations: Julia, Crystal and Redux" ], [ diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index cbf8d811..9638ee52 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -105,6 +105,11 @@ credits = [ '2010-2016 Jeremy Ashkenas, DocumentCloud', 'MIT', 'https://raw.githubusercontent.com/jashkenas/backbone/master/LICENSE' + ], [ + 'Bootstrap', + '2011-2016 Twitter, Inc.', + 'CC BY', + 'https://creativecommons.org/licenses/by/3.0/' ], [ 'Bower', '2016 Bower contributors', diff --git a/assets/javascripts/views/pages/simple.coffee b/assets/javascripts/views/pages/simple.coffee index 84636982..6675e9b1 100644 --- a/assets/javascripts/views/pages/simple.coffee +++ b/assets/javascripts/views/pages/simple.coffee @@ -8,6 +8,7 @@ class app.views.SimplePage extends app.views.BasePage app.views.AngularPage = app.views.AngularjsPage = +app.views.Bsv3Page = app.views.CakephpPage = app.views.ChaiPage = app.views.CrystalPage = diff --git a/assets/stylesheets/application-dark.css.scss b/assets/stylesheets/application-dark.css.scss index cb86c364..ba6084a0 100644 --- a/assets/stylesheets/application-dark.css.scss +++ b/assets/stylesheets/application-dark.css.scss @@ -34,6 +34,7 @@ 'pages/angular', 'pages/angularjs', 'pages/apache', + 'pages/bootstrap', 'pages/bower', 'pages/c', 'pages/cakephp', diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index 1cc9d588..bce9f41d 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -34,6 +34,7 @@ 'pages/angular', 'pages/angularjs', 'pages/apache', + 'pages/bootstrap', 'pages/bower', 'pages/c', 'pages/cakephp', diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss index 2c04cd87..56a2b589 100644 --- a/assets/stylesheets/global/_icons.scss +++ b/assets/stylesheets/global/_icons.scss @@ -133,6 +133,7 @@ ._icon-crystal:before { background-position: -6rem -8rem; @extend %darkIconFix !optional; } ._icon-julia:before { background-position: -7rem -8rem; @extend %darkIconFix !optional; } ._icon-redux:before { background-position: -8rem -8rem; @extend %darkIconFix !optional; } +._icon-bootstrap:before { background-position: -9rem -8rem; } ._icon-react_native:before { background-position: 0 -9rem; } ._icon-phalcon:before { background-position: -1rem -9rem; } ._icon-matplotlib:before { background-position: -2rem -9rem; } diff --git a/assets/stylesheets/pages/_bootstrap.scss b/assets/stylesheets/pages/_bootstrap.scss new file mode 100644 index 00000000..8f89d167 --- /dev/null +++ b/assets/stylesheets/pages/_bootstrap.scss @@ -0,0 +1,62 @@ +._bsv3 { + @extend %simple; + + h4 > code, h5 > code { @extend %label; } + + h2 > small { + color: $textColorLight; + float: right; + } + + .bs-callout { @extend %note; } + .bs-callout-info { @extend %note-blue; } + .bs-callout-danger { @extend %note-red; } + .bs-callout > h4, .bs-callout > h5 { margin-top: .25rem; } + + .text-danger { @extend %label, %label-red; } + + .bs-example { + padding: .375rem .625rem; + line-height: 1.5; + @extend %heading-box; + } + + div.bs-example { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + + + pre { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-top: 0; + margin-top: 0; + } + } + + a.thumbnail { + display: block; + padding: .25em; + @extend %box; + + &:after { content: none; } + + h4 { margin: .75em 0 .5em; } + > img { display: block; } + } + + .col { margin-bottom: 1.5em; } + + @media (min-width: 800px) { + .row { + display: flex; + flex-wrap: wrap; + } + + .col { + flex: 0 1 auto; + padding: 0 1em; + width: 33.33%; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + } +} diff --git a/assets/stylesheets/pages/_simple.scss b/assets/stylesheets/pages/_simple.scss index cdb8298d..128f029e 100644 --- a/assets/stylesheets/pages/_simple.scss +++ b/assets/stylesheets/pages/_simple.scss @@ -12,7 +12,7 @@ h1, h2, h3 { margin-left: 0; } } - p > code, li > code { @extend %label; } + p > code, li > code, td > code { @extend %label; } blockquote { @extend %note; } blockquote > h4, blockquote > h5 { margin-top: .25rem; } } diff --git a/lib/docs/filters/bootstrap/clean_html_v3.rb b/lib/docs/filters/bootstrap/clean_html_v3.rb new file mode 100644 index 00000000..becd1e3d --- /dev/null +++ b/lib/docs/filters/bootstrap/clean_html_v3.rb @@ -0,0 +1,64 @@ +module Docs + class Bootstrap + class CleanHtmlV3Filter < Filter + def call + at_css('div[role=main]').child.before(at_css('#content .container').inner_html) + @doc = at_css('div[role=main]') + + css('h1, h2, h3, h4, h5').each do |node| + node.name = node.name.sub(/\d/) { |i| i.to_i + 1 } + end + at_css('h2').name = 'h1' + + css('hr', '.zero-clipboard', '.modal', '.panel-group').remove + + css('.bs-docs-section', '.table-responsive').each do |node| + node.before(node.children).remove + end + + css('> .show-grid', '.bs-example', '.bs-glyphicons', '.responsive-utilities-test').each do |node| + if node.previous_element['class'].try(:include?, 'bs-example') + node.remove + else + node.content = '' + node.name = 'p' + node['class'] = 'bs-example' + node.remove_attribute('data-example-id') + prev = node.previous_element + prev = prev.previous_element until prev['id'] + node.inner_html = %(Open example on getbootstrap.com) + end + end + + css('.bs-example + figure').each do |node| + node.previous_element.name = 'div' + end + + css('div[class*="col-"]').each do |node| + node['class'] = 'col' + end + + css('.__cf_email__').each do |node| + node.replace(decode_cloudflare_email(node['data-cfemail'])) + end + + css('figure.highlight').each do |node| + code = node.at_css('code') + node['data-language'] = code['data-lang'] + node.content = code.content + node.name = 'pre' + end + + css('table, tr, td, th, pre').each do |node| + node.remove_attribute('class') + end + + css('thead td:empty').each do |node| + node.name = 'th' + end + + doc + end + end + end +end diff --git a/lib/docs/filters/bootstrap/entries_v3.rb b/lib/docs/filters/bootstrap/entries_v3.rb new file mode 100644 index 00000000..85c439f8 --- /dev/null +++ b/lib/docs/filters/bootstrap/entries_v3.rb @@ -0,0 +1,65 @@ +module Docs + class Bootstrap + class EntriesV3Filter < Docs::EntriesFilter + def get_name + at_css('h1').content + end + + def get_type + name + end + + def additional_entries + return [] if root_page? + entries = [] + + css('.bs-docs-sidenav > li').each do |node| + link = node.at_css('a') + name = link.content + next if IGNORE_ENTRIES.include?(name) + + id = link['href'].remove('#') + entries << [name, id] + next if name =~ /Sass|Less|Glyphicons/ + + node.css('> ul > li > a').each do |link| + n = link.content + next if n.start_with?('Ex: ') || n.start_with?('Default ') || n =~ /example/i || IGNORE_ENTRIES.include?(n) + id = link['href'].remove('#') + n.downcase! + n.prepend "#{name}: " + entries << [n, id] + end + end + + %w(modals dropdowns scrollspy tabs tooltips popovers alerts buttons collapse carousel affix).each do |dom_id| + css("##{dom_id}-options + p + div tbody td:first-child").each do |node| + name = node.content.strip + id = node.parent['id'] = "#{dom_id}-#{name.parameterize}-option" + name.prepend "#{dom_id.singularize.titleize}: " + name << ' (option)' + entries << [name, id] + end + + css("##{dom_id}-methods ~ h4 code").each do |node| + next unless name = node.content[/\('(\w+)'\)/, 1] + id = node.parent['id'] = "#{dom_id}-#{name.parameterize}-method" + name.prepend "#{dom_id.singularize.titleize}: " + name << ' (method)' + entries << [name, id] + end + end + + entries + end + + IGNORE_ENTRIES = %w( + Overview + Introduction + Usage + Methods + Options + ) + end + end +end diff --git a/lib/docs/scrapers/bootstrap.rb b/lib/docs/scrapers/bootstrap.rb new file mode 100644 index 00000000..d0c10d66 --- /dev/null +++ b/lib/docs/scrapers/bootstrap.rb @@ -0,0 +1,33 @@ +module Docs + class Bootstrap < UrlScraper + options[:attribution] = <<-HTML + © 2011–2016 Twitter, Inc.
+ Code licensed under the MIT License.
+ Documentation licensed under the Creative Commons Attribution License v3.0. + HTML + + version '3' do + self.type = 'bsv3' + self.release = '3.3.7' + self.base_url = 'https://getbootstrap.com/' + self.root_path = 'getting-started' + self.links = { + home: 'https://getbootstrap.com/', + code: 'https://github.com/twbs/bootstrap' + } + + html_filters.push 'bootstrap/entries_v3', 'bootstrap/clean_html_v3' + + options[:trailing_slash] = false + options[:only] = %w(getting-started css components javascript) + end + + private + + def handle_response(response) + response.effective_url.scheme = 'https' + response.effective_url.path = response.effective_url.path.remove(/\/\z/) + super + end + end +end diff --git a/public/icons/docs/bootstrap/16.png b/public/icons/docs/bootstrap/16.png new file mode 100644 index 00000000..2ac6870c Binary files /dev/null and b/public/icons/docs/bootstrap/16.png differ diff --git a/public/icons/docs/bootstrap/16@2x.png b/public/icons/docs/bootstrap/16@2x.png new file mode 100644 index 00000000..86e0e66f Binary files /dev/null and b/public/icons/docs/bootstrap/16@2x.png differ diff --git a/public/icons/docs/bootstrap/SOURCE b/public/icons/docs/bootstrap/SOURCE new file mode 100644 index 00000000..936a54e3 --- /dev/null +++ b/public/icons/docs/bootstrap/SOURCE @@ -0,0 +1 @@ +https://raw.githubusercontent.com/twbs/bootstrap/master/docs/favicon.ico