Add GTK documentation
Unified · Split
| @@ -1,4 +1,8 @@ | |||
| 1 | [ | 1 | [ |
| 2 | [ | ||
| 3 | "2020-12-23", | ||
| 4 | "New documentation: <a href=\"/gtk/\">GTK</a>" | ||
| 5 | ], | ||
| 2 | [ | 6 | [ |
| 3 | "2020-12-07", | 7 | "2020-12-07", |
| 4 | "New documentations: <a href=\"/flask/\">Flask</a>, <a href=\"/groovy/\">Groovy</a>, <a href=\"/jinja/\">Jinja</a>, <a href=\"/werkzeug/\">Werkzeug</a>" | 8 | "New documentations: <a href=\"/flask/\">Flask</a>, <a href=\"/groovy/\">Groovy</a>, <a href=\"/jinja/\">Jinja</a>, <a href=\"/werkzeug/\">Werkzeug</a>" |
| @@ -356,6 +356,11 @@ credits = [ · 355 unmodified lines | |||
| 356 | 'GruntJS Team', | 356 | 'GruntJS Team', |
| 357 | 'MIT', | 357 | 'MIT', |
| 358 | 'https://github.com/gruntjs/grunt-docs/blob/master/package.json#L10' | 358 | 'https://github.com/gruntjs/grunt-docs/blob/master/package.json#L10' |
| 359 | ], [ | ||
| 360 | 'GTK', | ||
| 361 | 'The GNOME Project', | ||
| 362 | 'LGPLv2.1+', | ||
| 363 | 'https://gitlab.gnome.org/GNOME/gtk/-/blob/master/COPYING' | ||
| 359 | ], [ | 364 | ], [ |
| 360 | 'Handlebars', | 365 | 'Handlebars', |
| 361 | '2011-2017 Yehuda Katz', | 366 | '2011-2017 Yehuda Katz', |
| @@ -59,10 +59,11 @@ · 58 unmodified lines | |||
| 59 | 'pages/express', | 59 | 'pages/express', |
| 60 | 'pages/git', | 60 | 'pages/git', |
| 61 | 'pages/github', | 61 | 'pages/github', |
| 62 | 'pages/gnuplot', | ||
| 62 | 'pages/go', | 63 | 'pages/go', |
| 63 | 'pages/graphite', | 64 | 'pages/graphite', |
| 64 | 'pages/groovy', | 65 | 'pages/groovy', |
| 65 | 'pages/gnuplot', | 66 | 'pages/gtk', |
| 66 | 'pages/haproxy', | 67 | 'pages/haproxy', |
| 67 | 'pages/haskell', | 68 | 'pages/haskell', |
| 68 | 'pages/jekyll', | 69 | 'pages/jekyll', |
| @@ -0,0 +1,15 @@ | |||
| 1 | ._gtk { | ||
| 2 | padding-left: 1rem; | ||
| 3 | |||
| 4 | h1, h2, h3 { margin-left: -1rem; } | ||
| 5 | h2 { @extend %block-heading; } | ||
| 6 | h3 { @extend %block-label, %label-blue; } | ||
| 7 | |||
| 8 | div.toc { margin-top: 1.5em; } | ||
| 9 | .toc dl { margin-top: 0; margin-bottom: 0; } | ||
| 10 | |||
| 11 | .note { @extend %note, %note-green; } | ||
| 12 | .warning { @extend %note, %note-orange; } | ||
| 13 | |||
| 14 | .gallery-float { float:left; } | ||
| 15 | } | ||
| @@ -190,6 +190,8 @@ More information about how filters work is available on the [Filter Reference](. · 189 unmodified lines | |||
| 190 | In order to keep scrapers up-to-date the `get_latest_version(opts)` method should be overridden. If `self.release` is defined, this should return the latest version of the documentation. If `self.release` is not defined, it should return the Epoch time when the documentation was last modified. If the documentation will never change, simply return `1.0.0`. The result of this method is periodically reported in a "Documentation versions report" issue which helps maintainers keep track of outdated documentations. | 190 | In order to keep scrapers up-to-date the `get_latest_version(opts)` method should be overridden. If `self.release` is defined, this should return the latest version of the documentation. If `self.release` is not defined, it should return the Epoch time when the documentation was last modified. If the documentation will never change, simply return `1.0.0`. The result of this method is periodically reported in a "Documentation versions report" issue which helps maintainers keep track of outdated documentations. |
| 191 | 191 | ||
| 192 | To make life easier, there are a few utility methods that you can use in `get_latest_version`: | 192 | To make life easier, there are a few utility methods that you can use in `get_latest_version`: |
| 193 | |||
| 194 | ### General HTTP methods | ||
| 193 | * `fetch(url, opts)` | 195 | * `fetch(url, opts)` |
| 194 | 196 | ||
| 195 | Makes a GET request to the url and returns the response body. | 197 | Makes a GET request to the url and returns the response body. |
| @@ -205,11 +207,15 @@ To make life easier, there are a few utility methods that you can use in `get_la · 9 unmodified lines | |||
| 205 | Makes a GET request to the url and returns the JSON body converted to a dictionary. | 207 | Makes a GET request to the url and returns the JSON body converted to a dictionary. |
| 206 | 208 | ||
| 207 | Example: [lib/docs/scrapers/mdn/mdn.rb](../lib/docs/scrapers/mdn/mdn.rb) | 209 | Example: [lib/docs/scrapers/mdn/mdn.rb](../lib/docs/scrapers/mdn/mdn.rb) |
| 210 | |||
| 211 | ### Package repository methods | ||
| 208 | * `get_npm_version(package, opts)` | 212 | * `get_npm_version(package, opts)` |
| 209 | 213 | ||
| 210 | Returns the latest version of the given npm package. | 214 | Returns the latest version of the given npm package. |
| 211 | 215 | ||
| 212 | Example: [lib/docs/scrapers/bower.rb](../lib/docs/scrapers/bower.rb) | 216 | Example: [lib/docs/scrapers/bower.rb](../lib/docs/scrapers/bower.rb) |
| 217 | |||
| 218 | ### GitHub methods | ||
| 213 | * `get_latest_github_release(owner, repo, opts)` | 219 | * `get_latest_github_release(owner, repo, opts)` |
| 214 | 220 | ||
| 215 | Returns the tag name of the latest GitHub release of the given repository. If the tag name is preceded by a "v", the "v" will be removed. | 221 | Returns the tag name of the latest GitHub release of the given repository. If the tag name is preceded by a "v", the "v" will be removed. |
| @@ -225,3 +231,15 @@ To make life easier, there are a few utility methods that you can use in `get_la · 9 unmodified lines | |||
| 225 | Returns the contents of the requested file in the default branch of the given repository. | 231 | Returns the contents of the requested file in the default branch of the given repository. |
| 226 | 232 | ||
| 227 | Example: [lib/docs/scrapers/minitest.rb](../lib/docs/scrapers/minitest.rb) | 233 | Example: [lib/docs/scrapers/minitest.rb](../lib/docs/scrapers/minitest.rb) |
| 234 | * `get_latest_github_commit_date(owner, repo, opts)` | ||
| 235 | |||
| 236 | Returns the date of the most recent commit in the default branch of the given repository. | ||
| 237 | |||
| 238 | Example: [lib/docs/scrapers/reactivex.rb](../lib/docs/scrapers/reactivex.rb) | ||
| 239 | |||
| 240 | ### GitLab methods | ||
| 241 | * `get_gitlab_tags(hostname, group, project, opts)` | ||
| 242 | |||
| 243 | Returns the list of tags on the given repository ([format](https://docs.gitlab.com/ee/api/tags.html)). | ||
| 244 | |||
| 245 | Example: [lib/docs/scrapers/gtk.rb](../lib/docs/scrapers/gtk.rb) | ||
| @@ -270,5 +270,9 @@ module Docs · 269 unmodified lines | |||
| 270 | timestamp = commits[0]['commit']['author']['date'] | 270 | timestamp = commits[0]['commit']['author']['date'] |
| 271 | Date.iso8601(timestamp).to_time.to_i | 271 | Date.iso8601(timestamp).to_time.to_i |
| 272 | end | 272 | end |
| 273 | |||
| 274 | def get_gitlab_tags(hostname, group, project, opts) | ||
| 275 | fetch_json("https://#{hostname}/api/v4/projects/#{group}%2F#{project}/repository/tags", opts) | ||
| 276 | end | ||
| 273 | end | 277 | end |
| 274 | end | 278 | end |
| @@ -0,0 +1,69 @@ | |||
| 1 | module Docs | ||
| 2 | class Gtk | ||
| 3 | class CleanHtmlFilter < Filter | ||
| 4 | def call | ||
| 5 | |||
| 6 | css('table#top', 'table > colgroup', 'h2.title', '.footer', 'hr', 'br').remove | ||
| 7 | |||
| 8 | if root_page? | ||
| 9 | css('span > a').each do |node| | ||
| 10 | node.parent.before(node).remove | ||
| 11 | end | ||
| 12 | end | ||
| 13 | |||
| 14 | if top_table = at_css('.refnamediv > table') | ||
| 15 | top_table.css('td > p', 'td > img').each do |node| | ||
| 16 | top_table.before(node) | ||
| 17 | end | ||
| 18 | top_table.remove | ||
| 19 | end | ||
| 20 | |||
| 21 | css('table').each do |node| | ||
| 22 | node.remove_attribute 'border' | ||
| 23 | node.remove_attribute 'width' | ||
| 24 | end | ||
| 25 | |||
| 26 | # Move anchors to general headings | ||
| 27 | css('h2 > a[name]', 'h3 > a[name]').each do |node| | ||
| 28 | node.parent['id'] = node['name'] | ||
| 29 | end | ||
| 30 | |||
| 31 | # Move anchors to function/struct/enum/etc. | ||
| 32 | css('a[name] + h2', 'a[name] + h3').each do |node| | ||
| 33 | node['id'] = node.previous_element['name'] | ||
| 34 | end | ||
| 35 | |||
| 36 | # Move anchors to struct and enum members | ||
| 37 | css('td.struct_member_name', 'td.enum_member_name').each do |node| | ||
| 38 | node['id'] = node.at_css('a[name]')['name'] | ||
| 39 | end | ||
| 40 | |||
| 41 | # Remove surrounding table from code blocks | ||
| 42 | css('.listing_frame').each do |node| | ||
| 43 | node.before(at_css('.listing_code')).remove | ||
| 44 | end | ||
| 45 | |||
| 46 | css('.literallayout code').each do |node| | ||
| 47 | node.name = 'pre' | ||
| 48 | end | ||
| 49 | |||
| 50 | # Fix code highlighting | ||
| 51 | css('pre').each do |node| | ||
| 52 | # If a codeblock has URLs, don't touch it | ||
| 53 | next if node.at_css('a[href]') | ||
| 54 | |||
| 55 | node.content = node.content | ||
| 56 | |||
| 57 | # it's not perfect, but make a guess at language | ||
| 58 | if node.content =~ /\<\?xml/ | ||
| 59 | node['data-language'] = 'xml' | ||
| 60 | else | ||
| 61 | node['data-language'] = 'c' | ||
| 62 | end | ||
| 63 | end | ||
| 64 | |||
| 65 | doc | ||
| 66 | end | ||
| 67 | end | ||
| 68 | end | ||
| 69 | end | ||
| @@ -0,0 +1,154 @@ | |||
| 1 | module Docs | ||
| 2 | class Gtk | ||
| 3 | class EntriesFilter < Docs::EntriesFilter | ||
| 4 | # The GTK documentation paths are "flat" and while the contents of each | ||
| 5 | # page provides a way to determine the direct parent relationship, we | ||
| 6 | # really need a full hierarchy of pages *a priori* to be able to fully | ||
| 7 | # categorize all pages and entries. So we're going to recursivly generate | ||
| 8 | # a full map of page -> parent relationships from the table of contents... | ||
| 9 | PARENT_BY_PATH = {} | ||
| 10 | |||
| 11 | # And then use it to generate the list of 'breadcrumb' paths for each page | ||
| 12 | # ex: ['gtkwidgets', 'fancywidgets', 'gtkexamplewidget'] | ||
| 13 | attr_accessor :breadcrumbs | ||
| 14 | |||
| 15 | # Map of paths to Page Names/Titles | ||
| 16 | NAME_BY_PATH = {} | ||
| 17 | |||
| 18 | # GTK+ 3 and GTK 4 | ||
| 19 | REPLACE_NAMES = { | ||
| 20 | 'I. GTK+ Overview' => '1. Overview', | ||
| 21 | 'II. GTK+ Widgets and Objects' => '2. Widgets and Objects', | ||
| 22 | 'III. GTK+ Core Reference' => '3. Core Reference', | ||
| 23 | 'IV. Theming in GTK+' => '4. Theming', | ||
| 24 | 'VI. GTK+ Tools' => '6. Tools', | ||
| 25 | 'VII. GTK+ Platform Support' => '7. Platform Support', | ||
| 26 | |||
| 27 | 'I. Introduction' => '1. Introduction', | ||
| 28 | 'II. GTK Concepts' => '2. Concepts', | ||
| 29 | 'III. GTK Widgets and Objects' => '3. Widgets and Objects', | ||
| 30 | 'IV. GTK Core Reference' => '4. Core Reference', | ||
| 31 | 'V. Theming in GTK' => '5. Theming', | ||
| 32 | 'VII. GTK Tools' => '7. Tools', | ||
| 33 | 'VIII. GTK Platform Support' => '8. Platform Support' | ||
| 34 | } | ||
| 35 | |||
| 36 | def call | ||
| 37 | if root_page? | ||
| 38 | # Generate NAME_BY_PATH Hash | ||
| 39 | css('dl.toc a').each do |node| | ||
| 40 | name = node.content | ||
| 41 | path = node['href'].split('/').last.remove('.html') | ||
| 42 | NAME_BY_PATH[path] = REPLACE_NAMES[name] || name | ||
| 43 | end | ||
| 44 | # Generate PARENT_BY_PATH Hash | ||
| 45 | process_toc(at_css('dl.toc'), nil) | ||
| 46 | end | ||
| 47 | super | ||
| 48 | end | ||
| 49 | |||
| 50 | # Recursive depth-first search | ||
| 51 | # Treat solo 'dt' nodes as leaf nodes and | ||
| 52 | # sibling 'dt + dd' nodes as nodes with children | ||
| 53 | def process_toc(toc_dl_node, parent_path) | ||
| 54 | toc_dl_node.css('> dt').each do |node| | ||
| 55 | node_path = node.at_css('a')['href'].split('/').last.remove('.html') | ||
| 56 | PARENT_BY_PATH[node_path] = parent_path | ||
| 57 | |||
| 58 | if node.next_element && node.next_element.name == 'dd' | ||
| 59 | children = node.next_element.children.first | ||
| 60 | process_toc(children, node_path) | ||
| 61 | end | ||
| 62 | end | ||
| 63 | end | ||
| 64 | |||
| 65 | def breadcrumbs | ||
| 66 | @breadcrumbs ||= get_breadcrumbs | ||
| 67 | end | ||
| 68 | |||
| 69 | def get_breadcrumbs | ||
| 70 | return [] if root_page? | ||
| 71 | |||
| 72 | breadcrumbs = [] | ||
| 73 | path = slug.downcase | ||
| 74 | while path | ||
| 75 | breadcrumbs.prepend path | ||
| 76 | path = PARENT_BY_PATH[path] | ||
| 77 | end | ||
| 78 | |||
| 79 | breadcrumbs | ||
| 80 | end | ||
| 81 | |||
| 82 | def get_name | ||
| 83 | NAME_BY_PATH[self.breadcrumbs.last] | ||
| 84 | end | ||
| 85 | |||
| 86 | def get_type | ||
| 87 | NAME_BY_PATH[self.breadcrumbs.first] | ||
| 88 | end | ||
| 89 | |||
| 90 | def additional_entries | ||
| 91 | entries = [] | ||
| 92 | type = case self.breadcrumbs.first | ||
| 93 | when 'gtkobjects' | ||
| 94 | "Widgets / #{NAME_BY_PATH[self.breadcrumbs[1]]}" | ||
| 95 | when 'gtkbase' | ||
| 96 | "Base / #{self.name}" | ||
| 97 | when'theming' | ||
| 98 | "Theming / #{self.name}" | ||
| 99 | end | ||
| 100 | |||
| 101 | if funcs = at_css('h2:contains("Functions")') | ||
| 102 | funcs.next_element.css('td.function_name > a').each do |node| | ||
| 103 | name = "#{node.content}()" | ||
| 104 | id = node['href'] | ||
| 105 | entries << [name, id, type] | ||
| 106 | end | ||
| 107 | end | ||
| 108 | |||
| 109 | css('td.property_name > a').each do |node| | ||
| 110 | name = "#{node.content} (#{self.name} property)" | ||
| 111 | id = node['href'] | ||
| 112 | entries << [name, id, type] | ||
| 113 | end | ||
| 114 | |||
| 115 | css('td.signal_name > a').each do |node| | ||
| 116 | name = "#{node.content} (#{self.name} signal)" | ||
| 117 | id = node['href'] | ||
| 118 | entries << [name, id, type] | ||
| 119 | end | ||
| 120 | |||
| 121 | css('td.enum_member_name').each do |node| | ||
| 122 | name = node.content | ||
| 123 | id = node.at_css('a')['name'] | ||
| 124 | entries << [name, id, type] | ||
| 125 | end | ||
| 126 | |||
| 127 | if values_node = at_css('h2:contains("Types and Values") + .informaltable') | ||
| 128 | values_node.css('tr').each do |node| | ||
| 129 | data_type = node.css('td').first.content | ||
| 130 | name = node.at_css('td.function_name').content | ||
| 131 | if data_type == ' ' | ||
| 132 | name = "#{name} (type)" | ||
| 133 | elsif data_type == 'enum' || data_type == 'struct' | ||
| 134 | name = "#{name} (#{data_type})" | ||
| 135 | end | ||
| 136 | id = node.at_css('td.function_name a')['href'] | ||
| 137 | entries << [name, id, type] | ||
| 138 | end | ||
| 139 | end | ||
| 140 | |||
| 141 | if slug == 'gtk-running' | ||
| 142 | css('h3 > a[name]').each do |node| | ||
| 143 | name = node.parent.content | ||
| 144 | id = node['name'] | ||
| 145 | entries << [name, id, 'Platform / Environment Variables'] | ||
| 146 | end | ||
| 147 | end | ||
| 148 | |||
| 149 | entries | ||
| 150 | end | ||
| 151 | |||
| 152 | end | ||
| 153 | end | ||
| 154 | end | ||
| @@ -0,0 +1,116 @@ | |||
| 1 | module Docs | ||
| 2 | class Gtk < UrlScraper | ||
| 3 | self.name = 'GTK' | ||
| 4 | self.slug = 'gtk' | ||
| 5 | self.type = 'gtk' | ||
| 6 | self.root_path = 'index.html' | ||
| 7 | self.links = { | ||
| 8 | home: 'https://www.gtk.org/', | ||
| 9 | code: 'https://gitlab.gnome.org/GNOME/gtk/' | ||
| 10 | } | ||
| 11 | |||
| 12 | html_filters.push 'gtk/entries', 'gtk/clean_html', 'title' | ||
| 13 | |||
| 14 | options[:container] = '.content' | ||
| 15 | |||
| 16 | # These are all "index"-ish pages with no valuable content | ||
| 17 | GTK3_SKIP = %w( | ||
| 18 | gtk.html | ||
| 19 | gtk-resources.html gtk-question-index.html | ||
| 20 | gtkobjects.html | ||
| 21 | Application.html Builder.html WindowWidgets.html LayoutContainers.html | ||
| 22 | DisplayWidgets.html ButtonWidgets.html NumericEntry.html | ||
| 23 | TextWidgetObjects.html TreeWidgetObjects.html MenusAndCombos.html | ||
| 24 | SelectorWidgets.html Ornaments.html ScrollingWidgets.html Printing.html | ||
| 25 | ShortcutsOverview.html MiscObjects.html AbstractObjects.html | ||
| 26 | PlugSocket.html RecentDocuments.html ApplicationChoosing.html | ||
| 27 | Gestures.html DeprecatedObjects.html | ||
| 28 | gtkbase.html | ||
| 29 | theming.html | ||
| 30 | migrating.html | ||
| 31 | ch26s02.html ch28s02.html | ||
| 32 | pt06.html | ||
| 33 | platform-support.html | ||
| 34 | glossary.html | ||
| 35 | annotation-glossary.html | ||
| 36 | ) | ||
| 37 | |||
| 38 | GTK3_SKIP_PATTERNS = [ | ||
| 39 | /migrating/, /checklist/, /ch30/, /ch32/, /api-index-/ | ||
| 40 | ] | ||
| 41 | |||
| 42 | # These are all "index"-ish pages with no valuable content | ||
| 43 | GTK4_SKIP = %w( | ||
| 44 | gtk.html | ||
| 45 | gtk-resources.html gtk-question-index.html ch02s02.html | ||
| 46 | concepts.html | ||
| 47 | gtkobjects.html | ||
| 48 | Lists.html Trees.html Application.html Builder.html WindowWidgets.html | ||
| 49 | LayoutContainers.html LayoutManagers.html DisplayWidgets.html | ||
| 50 | MediaSupport.html ButtonWidgets.html NumericEntry.html | ||
| 51 | MenusAndCombos.html SelectorWidgets.html DrawingWidgets.html | ||
| 52 | Ornaments.html ScrollingWidgets.html Printing.html | ||
| 53 | ShortcutsOverview.html MiscObjects.html AbstractObjects.html | ||
| 54 | RecentDocuments.html ApplicationChoosing.html Gestures.html ch36.html | ||
| 55 | ch37.html | ||
| 56 | gtkbase.html | ||
| 57 | theming.html | ||
| 58 | migrating.html | ||
| 59 | ch41s02.html ch41s03.html | ||
| 60 | pt07.html | ||
| 61 | platform-support.html | ||
| 62 | api-index-full.html | ||
| 63 | annotation-glossary.html | ||
| 64 | ) | ||
| 65 | |||
| 66 | GTK4_SKIP_PATTERNS = [ | ||
| 67 | /migrating/, /ch03/, /ch09/, /ch10/ | ||
| 68 | ] | ||
| 69 | |||
| 70 | options[:attribution] = <<-HTML | ||
| 71 | © 2005–2020 The GNOME Project<br> | ||
| 72 | Licensed under the GNU Lesser General Public License version 2.1 or later. | ||
| 73 | HTML | ||
| 74 | |||
| 75 | version '4.0' do | ||
| 76 | self.release = '4.0.0' | ||
| 77 | self.base_url = "https://developer.gnome.org/gtk4/#{self.version}/" | ||
| 78 | |||
| 79 | options[:root_title] = 'GTK 4 Reference Manual' | ||
| 80 | options[:skip] = GTK4_SKIP | ||
| 81 | options[:skip_patterns] = GTK4_SKIP_PATTERNS | ||
| 82 | end | ||
| 83 | |||
| 84 | version '3.24' do | ||
| 85 | self.release = '3.24.24' | ||
| 86 | self.base_url = "https://developer.gnome.org/gtk3/#{self.version}/" | ||
| 87 | |||
| 88 | options[:root_title] = 'GTK+ 3 Reference Manual' | ||
| 89 | options[:skip] = GTK3_SKIP | ||
| 90 | options[:skip_patterns] = GTK3_SKIP_PATTERNS | ||
| 91 | end | ||
| 92 | |||
| 93 | version '3.22' do | ||
| 94 | self.release = '3.22.3' | ||
| 95 | self.base_url = "https://developer.gnome.org/gtk3/#{self.version}/" | ||
| 96 | |||
| 97 | options[:root_title] = 'GTK+ 3 Reference Manual' | ||
| 98 | options[:skip] = GTK3_SKIP | ||
| 99 | options[:skip_patterns] = GTK3_SKIP_PATTERNS | ||
| 100 | end | ||
| 101 | |||
| 102 | version '3.20' do | ||
| 103 | self.release = '3.20.4' | ||
| 104 | self.base_url = "https://developer.gnome.org/gtk3/#{self.version}/" | ||
| 105 | |||
| 106 | options[:root_title] = 'GTK+ 3 Reference Manual' | ||
| 107 | options[:skip] = GTK3_SKIP | ||
| 108 | options[:skip_patterns] = GTK3_SKIP_PATTERNS | ||
| 109 | end | ||
| 110 | |||
| 111 | def get_latest_version(opts) | ||
| 112 | tags = get_gitlab_tags('gitlab.gnome.org', 'GNOME', 'gtk', opts) | ||
| 113 | tags[0]['name'] | ||
| 114 | end | ||
| 115 | end | ||
| 116 | end | ||
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1 @@ | |||
| 1 | https://www.gtk.org/assets/img/logo-gtk-sm.png | ||