Unified · Split
Binary file not shown.
Binary file not shown.
| @@ -143,6 +143,11 @@ credits = [ · 142 unmodified lines | ||
| 143 | 143 | '1997-2013 The PHP Documentation Group', |
| 144 | 144 | 'CC BY', |
| 145 | 145 | 'http://creativecommons.org/licenses/by/3.0/' |
| 146 | + ], [ | |
| 147 | + 'PostgreSQL', | |
| 148 | + '1996-2013 The PostgreSQL Global Development Group<br>© 1994 The Regents of the University of California', | |
| 149 | + 'PostgreSQL', | |
| 150 | + 'http://www.postgresql.org/about/licence/' | |
| 146 | 151 | ], [ |
| 147 | 152 | 'Python', |
| 148 | 153 | '1990-2013 Python Software Foundation<br>Python is a trademark of the Python Software Foundation.', |
| @@ -24,7 +24,10 @@ newsItem = (date, news) -> · 23 unmodified lines | ||
| 24 | 24 | result |
| 25 | 25 | |
| 26 | 26 | app.news = [ |
| 27 | − [ 1386892800000, # December 13, 2013 | |
| 27 | + [ 1386979200000, # December 14, 2013 | |
| 28 | + """ New <a href="/postgresql/">PostgreSQL</a> documentation """ | |
| 29 | + ], [ | |
| 30 | + 1386892800000, # December 13, 2013 | |
| 28 | 31 | """ New <a href="/git/">Git</a> and <a href="/redis/">Redis</a> documentations """ |
| 29 | 32 | ], [ |
| 30 | 33 | 1385424000000, # November 26, 2013 |
| @@ -37,6 +37,7 @@ · 36 unmodified lines | ||
| 37 | 37 | 'pages/mdn', |
| 38 | 38 | 'pages/node', |
| 39 | 39 | 'pages/php', |
| 40 | + 'pages/postgres', | |
| 40 | 41 | 'pages/rdoc', |
| 41 | 42 | 'pages/redis', |
| 42 | 43 | 'pages/rfc', |
| @@ -44,3 +44,4 @@ · 43 unmodified lines | ||
| 44 | 44 | ._icon-python:before { background-position: 0 -6rem; } |
| 45 | 45 | ._icon-git:before { background-position: -1rem -6rem; } |
| 46 | 46 | ._icon-redis:before { background-position: -2rem -6rem; } |
| 47 | +._icon-postgresql:before { background-position: -3rem -6rem; } | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +._postgres { | |
| 2 | + padding-left: 1rem; | |
| 3 | + | |
| 4 | + h1, h1 ~ p, h2 { margin-left: -1rem; } | |
| 5 | + h2 { @extend %block-heading; } | |
| 6 | + | |
| 7 | + .VARIABLELIST dt { @extend %block-label, %label-blue; } | |
| 8 | + | |
| 9 | + blockquote.NOTE, blockquote.IMPORTANT { @extend %note; } | |
| 10 | + blockquote.TIP { @extend %note, %note-green; } | |
| 11 | + | |
| 12 | + p > code { @extend %label; } | |
| 13 | +} | |
| @@ -0,0 +1,44 @@ | ||
| 1 | +module Docs | |
| 2 | + class Postgresql | |
| 3 | + class CleanHtmlFilter < Filter | |
| 4 | + def call | |
| 5 | + root_page? ? root : other | |
| 6 | + doc | |
| 7 | + end | |
| 8 | + | |
| 9 | + def root | |
| 10 | + doc.inner_html = ' ' | |
| 11 | + end | |
| 12 | + | |
| 13 | + def other | |
| 14 | + css('a[name]').each do |node| | |
| 15 | + node.parent['id'] = node['name'] | |
| 16 | + node.before(node.children).remove | |
| 17 | + end | |
| 18 | + | |
| 19 | + css('div.SECT1', 'pre > kbd', 'tt > code', 'h1 > tt').each do |node| | |
| 20 | + node.before(node.children).remove | |
| 21 | + end | |
| 22 | + | |
| 23 | + css('table').each do |node| | |
| 24 | + node.remove_attribute 'border' | |
| 25 | + node.remove_attribute 'width' | |
| 26 | + end | |
| 27 | + | |
| 28 | + css('td').each do |node| | |
| 29 | + node.remove_attribute 'align' | |
| 30 | + node.remove_attribute 'valign' | |
| 31 | + end | |
| 32 | + | |
| 33 | + css('tt').each do |node| | |
| 34 | + node.name = 'code' | |
| 35 | + end | |
| 36 | + | |
| 37 | + css('.REFSYNOPSISDIV > p').each do |node| | |
| 38 | + node.name = 'pre' | |
| 39 | + node.content = node.content | |
| 40 | + end | |
| 41 | + end | |
| 42 | + end | |
| 43 | + end | |
| 44 | +end | |
| @@ -0,0 +1,25 @@ | ||
| 1 | +module Docs | |
| 2 | + class Postgresql | |
| 3 | + class CleanNavFilter < Filter | |
| 4 | + def call | |
| 5 | + extract_up_path | |
| 6 | + extract_chapter | |
| 7 | + css('.NAVHEADER', '.NAVFOOTER').remove | |
| 8 | + doc | |
| 9 | + end | |
| 10 | + | |
| 11 | + def extract_up_path | |
| 12 | + if node = at_css('.NAVHEADER a[accesskey="U"]') | |
| 13 | + result[:pg_up_path] = node['href'] | |
| 14 | + end | |
| 15 | + end | |
| 16 | + | |
| 17 | + def extract_chapter | |
| 18 | + return unless text = at_css('.NAVHEADER td[align="center"]').content | |
| 19 | + return unless match = text.match(/\AChapter (\d+)\. (.+)\z/) | |
| 20 | + result[:pg_chapter] = match[1].to_i | |
| 21 | + result[:pg_chapter_name] = match[2] | |
| 22 | + end | |
| 23 | + end | |
| 24 | + end | |
| 25 | +end | |
| @@ -0,0 +1,153 @@ | ||
| 1 | +module Docs | |
| 2 | + class Postgresql | |
| 3 | + class EntriesFilter < Docs::EntriesFilter | |
| 4 | + REPLACE_NAMES = { | |
| 5 | + 'Sorting Rows' => 'ORDER BY', | |
| 6 | + 'Select Lists' => 'SELECT Lists', | |
| 7 | + 'Data Type Formatting Functions' => 'Formatting Functions', | |
| 8 | + 'Enum Support Functions' => 'Enum Functions', | |
| 9 | + 'Row and Array Comparisons' => 'Array Comparisons', | |
| 10 | + 'Sequence Manipulation Functions' => 'Sequence Functions', | |
| 11 | + 'System Administration Functions' => 'Administration Functions', | |
| 12 | + 'System Information Functions' => 'Information Functions' } | |
| 13 | + | |
| 14 | + def get_name | |
| 15 | + name = at_css('h1').content | |
| 16 | + clean_heading_name(name) | |
| 17 | + | |
| 18 | + if %w(Overview Introduction).include?(name) | |
| 19 | + result[:pg_chapter_name] | |
| 20 | + else | |
| 21 | + name.sub! ' (Common Table Expressions)', '' | |
| 22 | + REPLACE_NAMES[name] || name | |
| 23 | + end | |
| 24 | + end | |
| 25 | + | |
| 26 | + def clean_heading_name(name) | |
| 27 | + name.sub! %r{\A[\d\.\s]+}, '' | |
| 28 | + name.sub! 'Using ', '' | |
| 29 | + name.sub! %r{\AThe }, '' | |
| 30 | + name | |
| 31 | + end | |
| 32 | + | |
| 33 | + def get_type | |
| 34 | + return if initial_page? | |
| 35 | + | |
| 36 | + if result[:pg_up_path] == 'sql-commands.html' | |
| 37 | + 'Commands' | |
| 38 | + elsif result[:pg_up_path].start_with? 'reference-' | |
| 39 | + 'Applications' | |
| 40 | + elsif type = result[:pg_chapter_name] | |
| 41 | + if type.start_with?('Func') && (match = name.match(/\A(?!Form|Seq|Set|Enum)(.+) Func/)) | |
| 42 | + "Functions: #{match[1]}" | |
| 43 | + else | |
| 44 | + type.sub 'SQL ', '' | |
| 45 | + end | |
| 46 | + end | |
| 47 | + end | |
| 48 | + | |
| 49 | + def additional_entries | |
| 50 | + return [] if skip_additional_entries? | |
| 51 | + return get_config_entries if config_page? | |
| 52 | + return get_heading_entries('h3[id]') if slug == 'functions-xml' | |
| 53 | + | |
| 54 | + if type == 'Data Types' | |
| 55 | + return get_custom_entries case slug | |
| 56 | + when 'rangetypes' then 'li > p > .TYPE:first-child' | |
| 57 | + when 'datatype-textsearch' then '.SECT2 > .TYPE' | |
| 58 | + else '.CALSTABLE td:first-child > .TYPE' end | |
| 59 | + end | |
| 60 | + | |
| 61 | + entries = get_heading_entries('h2[id]') | |
| 62 | + | |
| 63 | + if slug == 'queries-union' | |
| 64 | + entries.concat get_custom_entries('p > .LITERAL:first-child') | |
| 65 | + elsif slug == 'queries-table-expressions' | |
| 66 | + entries.concat get_heading_entries('h3[id]') | |
| 67 | + entries.concat get_custom_entries('dt > .LITERAL:first-child') | |
| 68 | + elsif slug == 'functions-logical' | |
| 69 | + entries.concat get_custom_entries('> table td:first-child > code') | |
| 70 | + elsif slug == 'functions-formatting' | |
| 71 | + entries.concat get_custom_entries('#FUNCTIONS-FORMATTING-TABLE td:first-child > code') | |
| 72 | + elsif slug == 'functions-admin' | |
| 73 | + entries.concat get_custom_entries('.TABLE td:first-child > code') | |
| 74 | + elsif slug == 'functions-string' | |
| 75 | + entries.concat get_custom_entries('> div[id^="FUNC"] td:first-child > code') | |
| 76 | + elsif type && type.start_with?('Functions') | |
| 77 | + entries.concat get_custom_entries('> .TABLE td:first-child > code:first-child') | |
| 78 | + entries.concat get_comparison_entries if slug == 'functions-comparison' | |
| 79 | + end | |
| 80 | + | |
| 81 | + entries | |
| 82 | + end | |
| 83 | + | |
| 84 | + def get_config_entries | |
| 85 | + css('.VARIABLELIST dt[id]').map do |node| | |
| 86 | + name = node.at_css('.VARNAME').content | |
| 87 | + ["Config: #{name}", node['id']] | |
| 88 | + end | |
| 89 | + end | |
| 90 | + | |
| 91 | + def get_heading_entries(selector) | |
| 92 | + css(selector).inject [] do |entries, node| | |
| 93 | + name = node.content | |
| 94 | + clean_heading_name(name) | |
| 95 | + | |
| 96 | + unless skip_heading?(name) | |
| 97 | + entries << ["#{additional_entry_prefix}: #{name}", node['id']] | |
| 98 | + end | |
| 99 | + | |
| 100 | + entries | |
| 101 | + end | |
| 102 | + end | |
| 103 | + | |
| 104 | + def get_custom_entries(selector) | |
| 105 | + css(selector).inject [] do |entries, node| | |
| 106 | + name = node.content | |
| 107 | + name.gsub! %r{\(.*?\)}m, '' | |
| 108 | + name.gsub! %r{\[.*?\]}m, '' | |
| 109 | + name.squeeze! ' ' | |
| 110 | + name.sub! %r{\([^\)]*\z}, '' # bug fix: json_populate_record | |
| 111 | + name = '||' if name.include? ' || ' | |
| 112 | + id = name.gsub(/[^a-z0-9\-_]/) { |char| char.ord } | |
| 113 | + id = id.parameterize | |
| 114 | + name.prepend "#{additional_entry_prefix}: " | |
| 115 | + | |
| 116 | + unless entries.any? { |entry| entry[0] == name } | |
| 117 | + node['id'] = id | |
| 118 | + entries << [name, id] | |
| 119 | + end | |
| 120 | + | |
| 121 | + entries | |
| 122 | + end | |
| 123 | + end | |
| 124 | + | |
| 125 | + def get_comparison_entries | |
| 126 | + %w(IS NULL BETWEEN DISTINCT\ FROM).map do |name| | |
| 127 | + ["#{self.name}: #{name}"] | |
| 128 | + end | |
| 129 | + end | |
| 130 | + | |
| 131 | + def additional_entry_prefix | |
| 132 | + type.dup.sub!('Functions: ', '') || self.name | |
| 133 | + end | |
| 134 | + | |
| 135 | + def skip_additional_entries? | |
| 136 | + slug == 'config-setting' || %w(Concurrency\ Control Localization).include?(type) | |
| 137 | + end | |
| 138 | + | |
| 139 | + def skip_heading?(name) | |
| 140 | + %w(Usage\ Patterns Portability Caveats Overview).include?(name) || | |
| 141 | + (type.start_with?('Functions') && slug != 'functions-xml' && name.split.first.upcase!) | |
| 142 | + end | |
| 143 | + | |
| 144 | + def include_default_entry? | |
| 145 | + !(initial_page? || at_css('.TOC') || config_page?) | |
| 146 | + end | |
| 147 | + | |
| 148 | + def config_page? | |
| 149 | + slug.start_with? 'runtime-config' | |
| 150 | + end | |
| 151 | + end | |
| 152 | + end | |
| 153 | +end | |
| @@ -0,0 +1,55 @@ | ||
| 1 | +module Docs | |
| 2 | + class Postgresql < FileScraper | |
| 3 | + self.name = 'PostgreSQL' | |
| 4 | + self.type = 'postgres' | |
| 5 | + self.version = 'up to 9.3.2' | |
| 6 | + self.dir = '/Users/Thibaut/DevDocs/Docs/PostgreSQL' | |
| 7 | + self.base_url = 'http://www.postgresql.org/docs/9.3/static/' | |
| 8 | + self.root_path = 'reference.html' | |
| 9 | + self.initial_paths = %w(sql.html runtime-config.html charset.html) | |
| 10 | + | |
| 11 | + html_filters.insert_before 'normalize_urls', 'postgresql/clean_nav' | |
| 12 | + html_filters.push 'postgresql/clean_html', 'postgresql/entries', 'title' | |
| 13 | + | |
| 14 | + options[:title] = false | |
| 15 | + options[:root_title] = 'PostgreSQL' | |
| 16 | + options[:follow_links] = ->(filter) { filter.initial_page? } | |
| 17 | + | |
| 18 | + options[:only] = %w( | |
| 19 | + arrays.html | |
| 20 | + rowtypes.html | |
| 21 | + rangetypes.html | |
| 22 | + mvcc-intro.html | |
| 23 | + transaction-iso.html | |
| 24 | + explicit-locking.html | |
| 25 | + applevel-consistency.html | |
| 26 | + locking-indexes.html | |
| 27 | + config-setting.html | |
| 28 | + locale.html | |
| 29 | + collation.html | |
| 30 | + multibyte.html) | |
| 31 | + | |
| 32 | + options[:only_patterns] = [ | |
| 33 | + /\Asql\-/, | |
| 34 | + /\Aapp\-/, | |
| 35 | + /\Addl\-/, | |
| 36 | + /\Adml\-/, | |
| 37 | + /\Aqueries\-/, | |
| 38 | + /\Adatatype\-/, | |
| 39 | + /\Afunctions\-/, | |
| 40 | + /\Aindexes\-/, | |
| 41 | + /\Aruntime\-config\-/] | |
| 42 | + | |
| 43 | + options[:skip] = %w( | |
| 44 | + ddl-others.html | |
| 45 | + runtime-config-custom.html | |
| 46 | + runtime-config-short.html | |
| 47 | + functions-event-triggers.html | |
| 48 | + functions-trigger.html) | |
| 49 | + | |
| 50 | + options[:attribution] = <<-HTML | |
| 51 | + © 1996–2013 The PostgreSQL Global Development Group<br> | |
| 52 | + Licensed under the PostgreSQL License. | |
| 53 | + HTML | |
| 54 | + end | |
| 55 | +end | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1 @@ | ||
| 1 | +http://www.postgresql.org/about/press/presskit93/#logos | |