diff --git a/assets/images/icons.png b/assets/images/icons.png index 20187782..2b84306a 100644 Binary files a/assets/images/icons.png and b/assets/images/icons.png differ diff --git a/assets/images/icons@2x.png b/assets/images/icons@2x.png index 86f9eb42..555fb5b4 100644 Binary files a/assets/images/icons@2x.png and b/assets/images/icons@2x.png differ diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index df890842..33d1e1c4 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -143,6 +143,11 @@ credits = [ '1997-2013 The PHP Documentation Group', 'CC BY', 'http://creativecommons.org/licenses/by/3.0/' + ], [ + 'PostgreSQL', + '1996-2013 The PostgreSQL Global Development Group
© 1994 The Regents of the University of California', + 'PostgreSQL', + 'http://www.postgresql.org/about/licence/' ], [ 'Python', '1990-2013 Python Software Foundation
Python is a trademark of the Python Software Foundation.', diff --git a/assets/javascripts/templates/pages/news_tmpl.coffee b/assets/javascripts/templates/pages/news_tmpl.coffee index 90266907..5f6b2fb5 100644 --- a/assets/javascripts/templates/pages/news_tmpl.coffee +++ b/assets/javascripts/templates/pages/news_tmpl.coffee @@ -24,7 +24,10 @@ newsItem = (date, news) -> result app.news = [ - [ 1386892800000, # December 13, 2013 + [ 1386979200000, # December 14, 2013 + """ New PostgreSQL documentation """ + ], [ + 1386892800000, # December 13, 2013 """ New Git and Redis documentations """ ], [ 1385424000000, # November 26, 2013 diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index 4a9ed2ee..e88e3890 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -37,6 +37,7 @@ 'pages/mdn', 'pages/node', 'pages/php', + 'pages/postgres', 'pages/rdoc', 'pages/redis', 'pages/rfc', diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss index 3c8f7bb1..897d5224 100644 --- a/assets/stylesheets/global/_icons.scss +++ b/assets/stylesheets/global/_icons.scss @@ -44,3 +44,4 @@ ._icon-python:before { background-position: 0 -6rem; } ._icon-git:before { background-position: -1rem -6rem; } ._icon-redis:before { background-position: -2rem -6rem; } +._icon-postgresql:before { background-position: -3rem -6rem; } diff --git a/assets/stylesheets/pages/_postgres.scss b/assets/stylesheets/pages/_postgres.scss new file mode 100644 index 00000000..da8dc08a --- /dev/null +++ b/assets/stylesheets/pages/_postgres.scss @@ -0,0 +1,13 @@ +._postgres { + padding-left: 1rem; + + h1, h1 ~ p, h2 { margin-left: -1rem; } + h2 { @extend %block-heading; } + + .VARIABLELIST dt { @extend %block-label, %label-blue; } + + blockquote.NOTE, blockquote.IMPORTANT { @extend %note; } + blockquote.TIP { @extend %note, %note-green; } + + p > code { @extend %label; } +} diff --git a/lib/docs/filters/postgresql/clean_html.rb b/lib/docs/filters/postgresql/clean_html.rb new file mode 100644 index 00000000..8c9a9f45 --- /dev/null +++ b/lib/docs/filters/postgresql/clean_html.rb @@ -0,0 +1,44 @@ +module Docs + class Postgresql + class CleanHtmlFilter < Filter + def call + root_page? ? root : other + doc + end + + def root + doc.inner_html = ' ' + end + + def other + css('a[name]').each do |node| + node.parent['id'] = node['name'] + node.before(node.children).remove + end + + css('div.SECT1', 'pre > kbd', 'tt > code', 'h1 > tt').each do |node| + node.before(node.children).remove + end + + css('table').each do |node| + node.remove_attribute 'border' + node.remove_attribute 'width' + end + + css('td').each do |node| + node.remove_attribute 'align' + node.remove_attribute 'valign' + end + + css('tt').each do |node| + node.name = 'code' + end + + css('.REFSYNOPSISDIV > p').each do |node| + node.name = 'pre' + node.content = node.content + end + end + end + end +end diff --git a/lib/docs/filters/postgresql/clean_nav.rb b/lib/docs/filters/postgresql/clean_nav.rb new file mode 100644 index 00000000..0f6c7090 --- /dev/null +++ b/lib/docs/filters/postgresql/clean_nav.rb @@ -0,0 +1,25 @@ +module Docs + class Postgresql + class CleanNavFilter < Filter + def call + extract_up_path + extract_chapter + css('.NAVHEADER', '.NAVFOOTER').remove + doc + end + + def extract_up_path + if node = at_css('.NAVHEADER a[accesskey="U"]') + result[:pg_up_path] = node['href'] + end + end + + def extract_chapter + return unless text = at_css('.NAVHEADER td[align="center"]').content + return unless match = text.match(/\AChapter (\d+)\. (.+)\z/) + result[:pg_chapter] = match[1].to_i + result[:pg_chapter_name] = match[2] + end + end + end +end diff --git a/lib/docs/filters/postgresql/entries.rb b/lib/docs/filters/postgresql/entries.rb new file mode 100644 index 00000000..1436e5d4 --- /dev/null +++ b/lib/docs/filters/postgresql/entries.rb @@ -0,0 +1,153 @@ +module Docs + class Postgresql + class EntriesFilter < Docs::EntriesFilter + REPLACE_NAMES = { + 'Sorting Rows' => 'ORDER BY', + 'Select Lists' => 'SELECT Lists', + 'Data Type Formatting Functions' => 'Formatting Functions', + 'Enum Support Functions' => 'Enum Functions', + 'Row and Array Comparisons' => 'Array Comparisons', + 'Sequence Manipulation Functions' => 'Sequence Functions', + 'System Administration Functions' => 'Administration Functions', + 'System Information Functions' => 'Information Functions' } + + def get_name + name = at_css('h1').content + clean_heading_name(name) + + if %w(Overview Introduction).include?(name) + result[:pg_chapter_name] + else + name.sub! ' (Common Table Expressions)', '' + REPLACE_NAMES[name] || name + end + end + + def clean_heading_name(name) + name.sub! %r{\A[\d\.\s]+}, '' + name.sub! 'Using ', '' + name.sub! %r{\AThe }, '' + name + end + + def get_type + return if initial_page? + + if result[:pg_up_path] == 'sql-commands.html' + 'Commands' + elsif result[:pg_up_path].start_with? 'reference-' + 'Applications' + elsif type = result[:pg_chapter_name] + if type.start_with?('Func') && (match = name.match(/\A(?!Form|Seq|Set|Enum)(.+) Func/)) + "Functions: #{match[1]}" + else + type.sub 'SQL ', '' + end + end + end + + def additional_entries + return [] if skip_additional_entries? + return get_config_entries if config_page? + return get_heading_entries('h3[id]') if slug == 'functions-xml' + + if type == 'Data Types' + return get_custom_entries case slug + when 'rangetypes' then 'li > p > .TYPE:first-child' + when 'datatype-textsearch' then '.SECT2 > .TYPE' + else '.CALSTABLE td:first-child > .TYPE' end + end + + entries = get_heading_entries('h2[id]') + + if slug == 'queries-union' + entries.concat get_custom_entries('p > .LITERAL:first-child') + elsif slug == 'queries-table-expressions' + entries.concat get_heading_entries('h3[id]') + entries.concat get_custom_entries('dt > .LITERAL:first-child') + elsif slug == 'functions-logical' + entries.concat get_custom_entries('> table td:first-child > code') + elsif slug == 'functions-formatting' + entries.concat get_custom_entries('#FUNCTIONS-FORMATTING-TABLE td:first-child > code') + elsif slug == 'functions-admin' + entries.concat get_custom_entries('.TABLE td:first-child > code') + elsif slug == 'functions-string' + entries.concat get_custom_entries('> div[id^="FUNC"] td:first-child > code') + elsif type && type.start_with?('Functions') + entries.concat get_custom_entries('> .TABLE td:first-child > code:first-child') + entries.concat get_comparison_entries if slug == 'functions-comparison' + end + + entries + end + + def get_config_entries + css('.VARIABLELIST dt[id]').map do |node| + name = node.at_css('.VARNAME').content + ["Config: #{name}", node['id']] + end + end + + def get_heading_entries(selector) + css(selector).inject [] do |entries, node| + name = node.content + clean_heading_name(name) + + unless skip_heading?(name) + entries << ["#{additional_entry_prefix}: #{name}", node['id']] + end + + entries + end + end + + def get_custom_entries(selector) + css(selector).inject [] do |entries, node| + name = node.content + name.gsub! %r{\(.*?\)}m, '' + name.gsub! %r{\[.*?\]}m, '' + name.squeeze! ' ' + name.sub! %r{\([^\)]*\z}, '' # bug fix: json_populate_record + name = '||' if name.include? ' || ' + id = name.gsub(/[^a-z0-9\-_]/) { |char| char.ord } + id = id.parameterize + name.prepend "#{additional_entry_prefix}: " + + unless entries.any? { |entry| entry[0] == name } + node['id'] = id + entries << [name, id] + end + + entries + end + end + + def get_comparison_entries + %w(IS NULL BETWEEN DISTINCT\ FROM).map do |name| + ["#{self.name}: #{name}"] + end + end + + def additional_entry_prefix + type.dup.sub!('Functions: ', '') || self.name + end + + def skip_additional_entries? + slug == 'config-setting' || %w(Concurrency\ Control Localization).include?(type) + end + + def skip_heading?(name) + %w(Usage\ Patterns Portability Caveats Overview).include?(name) || + (type.start_with?('Functions') && slug != 'functions-xml' && name.split.first.upcase!) + end + + def include_default_entry? + !(initial_page? || at_css('.TOC') || config_page?) + end + + def config_page? + slug.start_with? 'runtime-config' + end + end + end +end diff --git a/lib/docs/scrapers/postgresql.rb b/lib/docs/scrapers/postgresql.rb new file mode 100644 index 00000000..909036fd --- /dev/null +++ b/lib/docs/scrapers/postgresql.rb @@ -0,0 +1,55 @@ +module Docs + class Postgresql < FileScraper + self.name = 'PostgreSQL' + self.type = 'postgres' + self.version = 'up to 9.3.2' + self.dir = '/Users/Thibaut/DevDocs/Docs/PostgreSQL' + self.base_url = 'http://www.postgresql.org/docs/9.3/static/' + self.root_path = 'reference.html' + self.initial_paths = %w(sql.html runtime-config.html charset.html) + + html_filters.insert_before 'normalize_urls', 'postgresql/clean_nav' + html_filters.push 'postgresql/clean_html', 'postgresql/entries', 'title' + + options[:title] = false + options[:root_title] = 'PostgreSQL' + options[:follow_links] = ->(filter) { filter.initial_page? } + + options[:only] = %w( + arrays.html + rowtypes.html + rangetypes.html + mvcc-intro.html + transaction-iso.html + explicit-locking.html + applevel-consistency.html + locking-indexes.html + config-setting.html + locale.html + collation.html + multibyte.html) + + options[:only_patterns] = [ + /\Asql\-/, + /\Aapp\-/, + /\Addl\-/, + /\Adml\-/, + /\Aqueries\-/, + /\Adatatype\-/, + /\Afunctions\-/, + /\Aindexes\-/, + /\Aruntime\-config\-/] + + options[:skip] = %w( + ddl-others.html + runtime-config-custom.html + runtime-config-short.html + functions-event-triggers.html + functions-trigger.html) + + options[:attribution] = <<-HTML + © 1996–2013 The PostgreSQL Global Development Group
+ Licensed under the PostgreSQL License. + HTML + end +end diff --git a/public/icons/docs/postgresql/16.png b/public/icons/docs/postgresql/16.png new file mode 100644 index 00000000..22f64d43 Binary files /dev/null and b/public/icons/docs/postgresql/16.png differ diff --git a/public/icons/docs/postgresql/16@2x.png b/public/icons/docs/postgresql/16@2x.png new file mode 100644 index 00000000..0496ae43 Binary files /dev/null and b/public/icons/docs/postgresql/16@2x.png differ diff --git a/public/icons/docs/postgresql/SOURCE b/public/icons/docs/postgresql/SOURCE new file mode 100644 index 00000000..84ce600b --- /dev/null +++ b/public/icons/docs/postgresql/SOURCE @@ -0,0 +1 @@ +http://www.postgresql.org/about/press/presskit93/#logos