From 2d1d5645826b59019ba1911b69143f0baa374114 Mon Sep 17 00:00:00 2001 From: Phil Scherer Date: Tue, 22 Dec 2020 19:11:20 -0500 Subject: [PATCH] Add GTK Documentation --- .../templates/pages/about_tmpl.coffee | 5 + assets/stylesheets/application.css.scss | 3 +- assets/stylesheets/pages/_gtk.scss | 15 ++ lib/docs/filters/gtk/clean_html.rb | 69 ++++++++ lib/docs/filters/gtk/entries.rb | 154 ++++++++++++++++++ lib/docs/scrapers/gtk.rb | 116 +++++++++++++ public/icons/docs/gtk/16.png | Bin 0 -> 1199 bytes public/icons/docs/gtk/16@2x.png | Bin 0 -> 2100 bytes public/icons/docs/gtk/SOURCE | 1 + 9 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 assets/stylesheets/pages/_gtk.scss create mode 100644 lib/docs/filters/gtk/clean_html.rb create mode 100644 lib/docs/filters/gtk/entries.rb create mode 100644 lib/docs/scrapers/gtk.rb create mode 100644 public/icons/docs/gtk/16.png create mode 100644 public/icons/docs/gtk/16@2x.png create mode 100644 public/icons/docs/gtk/SOURCE diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 4405aa26..217bb32b 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -356,6 +356,11 @@ credits = [ 'GruntJS Team', 'MIT', 'https://github.com/gruntjs/grunt-docs/blob/master/package.json#L10' + ], [ + 'GTK', + 'The GNOME Project', + 'LGPLv2.1+', + 'https://gitlab.gnome.org/GNOME/gtk/-/blob/master/COPYING' ], [ 'Handlebars', '2011-2017 Yehuda Katz', diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index 97347da6..fed660dc 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -59,10 +59,11 @@ 'pages/express', 'pages/git', 'pages/github', + 'pages/gnuplot', 'pages/go', 'pages/graphite', 'pages/groovy', - 'pages/gnuplot', + 'pages/gtk', 'pages/haproxy', 'pages/haskell', 'pages/jekyll', diff --git a/assets/stylesheets/pages/_gtk.scss b/assets/stylesheets/pages/_gtk.scss new file mode 100644 index 00000000..9df0cd3e --- /dev/null +++ b/assets/stylesheets/pages/_gtk.scss @@ -0,0 +1,15 @@ +._gtk { + padding-left: 1rem; + + h1, h2, h3 { margin-left: -1rem; } + h2 { @extend %block-heading; } + h3 { @extend %block-label, %label-blue; } + + div.toc { margin-top: 1.5em; } + .toc dl { margin-top: 0; margin-bottom: 0; } + + .note { @extend %note, %note-green; } + .warning { @extend %note, %note-orange; } + + .gallery-float { float:left; } +} diff --git a/lib/docs/filters/gtk/clean_html.rb b/lib/docs/filters/gtk/clean_html.rb new file mode 100644 index 00000000..d093ef47 --- /dev/null +++ b/lib/docs/filters/gtk/clean_html.rb @@ -0,0 +1,69 @@ +module Docs + class Gtk + class CleanHtmlFilter < Filter + def call + + css('table#top', 'table > colgroup', 'h2.title', '.footer', 'hr', 'br').remove + + if root_page? + css('span > a').each do |node| + node.parent.before(node).remove + end + end + + if top_table = at_css('.refnamediv > table') + top_table.css('td > p', 'td > img').each do |node| + top_table.before(node) + end + top_table.remove + end + + css('table').each do |node| + node.remove_attribute 'border' + node.remove_attribute 'width' + end + + # Move anchors to general headings + css('h2 > a[name]', 'h3 > a[name]').each do |node| + node.parent['id'] = node['name'] + end + + # Move anchors to function/struct/enum/etc. + css('a[name] + h2', 'a[name] + h3').each do |node| + node['id'] = node.previous_element['name'] + end + + # Move anchors to struct and enum members + css('td.struct_member_name', 'td.enum_member_name').each do |node| + node['id'] = node.at_css('a[name]')['name'] + end + + # Remove surrounding table from code blocks + css('.listing_frame').each do |node| + node.before(at_css('.listing_code')).remove + end + + css('.literallayout code').each do |node| + node.name = 'pre' + end + + # Fix code highlighting + css('pre').each do |node| + # If a codeblock has URLs, don't touch it + next if node.at_css('a[href]') + + node.content = node.content + + # it's not perfect, but make a guess at language + if node.content =~ /\<\?xml/ + node['data-language'] = 'xml' + else + node['data-language'] = 'c' + end + end + + doc + end + end + end +end diff --git a/lib/docs/filters/gtk/entries.rb b/lib/docs/filters/gtk/entries.rb new file mode 100644 index 00000000..5cb3d27a --- /dev/null +++ b/lib/docs/filters/gtk/entries.rb @@ -0,0 +1,154 @@ +module Docs + class Gtk + class EntriesFilter < Docs::EntriesFilter + # The GTK documentation paths are "flat" and while the contents of each + # page provides a way to determine the direct parent relationship, we + # really need a full hierarchy of pages *a priori* to be able to fully + # categorize all pages and entries. So we're going to recursivly generate + # a full map of page -> parent relationships from the table of contents... + PARENT_BY_PATH = {} + + # And then use it to generate the list of 'breadcrumb' paths for each page + # ex: ['gtkwidgets', 'fancywidgets', 'gtkexamplewidget'] + attr_accessor :breadcrumbs + + # Map of paths to Page Names/Titles + NAME_BY_PATH = {} + + # GTK+ 3 and GTK 4 + REPLACE_NAMES = { + 'I. GTK+ Overview' => '1. Overview', + 'II. GTK+ Widgets and Objects' => '2. Widgets and Objects', + 'III. GTK+ Core Reference' => '3. Core Reference', + 'IV. Theming in GTK+' => '4. Theming', + 'VI. GTK+ Tools' => '6. Tools', + 'VII. GTK+ Platform Support' => '7. Platform Support', + + 'I. Introduction' => '1. Introduction', + 'II. GTK Concepts' => '2. Concepts', + 'III. GTK Widgets and Objects' => '3. Widgets and Objects', + 'IV. GTK Core Reference' => '4. Core Reference', + 'V. Theming in GTK' => '5. Theming', + 'VII. GTK Tools' => '7. Tools', + 'VIII. GTK Platform Support' => '8. Platform Support' + } + + def call + if root_page? + # Generate NAME_BY_PATH Hash + css('dl.toc a').each do |node| + name = node.content + path = node['href'].split('/').last.remove('.html') + NAME_BY_PATH[path] = REPLACE_NAMES[name] || name + end + # Generate PARENT_BY_PATH Hash + process_toc(at_css('dl.toc'), nil) + end + super + end + + # Recursive depth-first search + # Treat solo 'dt' nodes as leaf nodes and + # sibling 'dt + dd' nodes as nodes with children + def process_toc(toc_dl_node, parent_path) + toc_dl_node.css('> dt').each do |node| + node_path = node.at_css('a')['href'].split('/').last.remove('.html') + PARENT_BY_PATH[node_path] = parent_path + + if node.next_element && node.next_element.name == 'dd' + children = node.next_element.children.first + process_toc(children, node_path) + end + end + end + + def breadcrumbs + @breadcrumbs ||= get_breadcrumbs + end + + def get_breadcrumbs + return [] if root_page? + + breadcrumbs = [] + path = slug.downcase + while path + breadcrumbs.prepend path + path = PARENT_BY_PATH[path] + end + + breadcrumbs + end + + def get_name + NAME_BY_PATH[self.breadcrumbs.last] + end + + def get_type + NAME_BY_PATH[self.breadcrumbs.first] + end + + def additional_entries + entries = [] + type = case self.breadcrumbs.first + when 'gtkobjects' + "Widgets / #{NAME_BY_PATH[self.breadcrumbs[1]]}" + when 'gtkbase' + "Base / #{self.name}" + when'theming' + "Theming / #{self.name}" + end + + if funcs = at_css('h2:contains("Functions")') + funcs.next_element.css('td.function_name > a').each do |node| + name = "#{node.content}()" + id = node['href'] + entries << [name, id, type] + end + end + + css('td.property_name > a').each do |node| + name = "#{node.content} (#{self.name} property)" + id = node['href'] + entries << [name, id, type] + end + + css('td.signal_name > a').each do |node| + name = "#{node.content} (#{self.name} signal)" + id = node['href'] + entries << [name, id, type] + end + + css('td.enum_member_name').each do |node| + name = node.content + id = node.at_css('a')['name'] + entries << [name, id, type] + end + + if values_node = at_css('h2:contains("Types and Values") + .informaltable') + values_node.css('tr').each do |node| + data_type = node.css('td').first.content + name = node.at_css('td.function_name').content + if data_type == ' ' + name = "#{name} (type)" + elsif data_type == 'enum' || data_type == 'struct' + name = "#{name} (#{data_type})" + end + id = node.at_css('td.function_name a')['href'] + entries << [name, id, type] + end + end + + if slug == 'gtk-running' + css('h3 > a[name]').each do |node| + name = node.parent.content + id = node['name'] + entries << [name, id, 'Platform / Environment Variables'] + end + end + + entries + end + + end + end +end diff --git a/lib/docs/scrapers/gtk.rb b/lib/docs/scrapers/gtk.rb new file mode 100644 index 00000000..cfa85956 --- /dev/null +++ b/lib/docs/scrapers/gtk.rb @@ -0,0 +1,116 @@ +module Docs + class Gtk < UrlScraper + self.name = 'GTK' + self.slug = 'gtk' + self.type = 'gtk' + self.root_path = 'index.html' + self.links = { + home: 'https://www.gtk.org/', + code: 'https://gitlab.gnome.org/GNOME/gtk/' + } + + html_filters.push 'gtk/entries', 'gtk/clean_html', 'title' + + options[:container] = '.content' + + # These are all "index"-ish pages with no valuable content + GTK3_SKIP = %w( + gtk.html + gtk-resources.html gtk-question-index.html + gtkobjects.html + Application.html Builder.html WindowWidgets.html LayoutContainers.html + DisplayWidgets.html ButtonWidgets.html NumericEntry.html + TextWidgetObjects.html TreeWidgetObjects.html MenusAndCombos.html + SelectorWidgets.html Ornaments.html ScrollingWidgets.html Printing.html + ShortcutsOverview.html MiscObjects.html AbstractObjects.html + PlugSocket.html RecentDocuments.html ApplicationChoosing.html + Gestures.html DeprecatedObjects.html + gtkbase.html + theming.html + migrating.html + ch26s02.html ch28s02.html + pt06.html + platform-support.html + glossary.html + annotation-glossary.html + ) + + GTK3_SKIP_PATTERNS = [ + /migrating/, /checklist/, /ch30/, /ch32/, /api-index-/ + ] + + # These are all "index"-ish pages with no valuable content + GTK4_SKIP = %w( + gtk.html + gtk-resources.html gtk-question-index.html ch02s02.html + concepts.html + gtkobjects.html + Lists.html Trees.html Application.html Builder.html WindowWidgets.html + LayoutContainers.html LayoutManagers.html DisplayWidgets.html + MediaSupport.html ButtonWidgets.html NumericEntry.html + MenusAndCombos.html SelectorWidgets.html DrawingWidgets.html + Ornaments.html ScrollingWidgets.html Printing.html + ShortcutsOverview.html MiscObjects.html AbstractObjects.html + RecentDocuments.html ApplicationChoosing.html Gestures.html ch36.html + ch37.html + gtkbase.html + theming.html + migrating.html + ch41s02.html ch41s03.html + pt07.html + platform-support.html + api-index-full.html + annotation-glossary.html + ) + + GTK4_SKIP_PATTERNS = [ + /migrating/, /ch03/, /ch09/, /ch10/ + ] + + options[:attribution] = <<-HTML + © 2005–2020 The GNOME Project
+ Licensed under the GNU Lesser General Public License version 2.1 or later. + HTML + + version '4.0' do + self.release = '4.0.0' + self.base_url = "https://developer.gnome.org/gtk4/#{self.version}/" + + options[:root_title] = 'GTK 4 Reference Manual' + options[:skip] = GTK4_SKIP + options[:skip_patterns] = GTK4_SKIP_PATTERNS + end + + version '3.24' do + self.release = '3.24.24' + self.base_url = "https://developer.gnome.org/gtk3/#{self.version}/" + + options[:root_title] = 'GTK+ 3 Reference Manual' + options[:skip] = GTK3_SKIP + options[:skip_patterns] = GTK3_SKIP_PATTERNS + end + + version '3.22' do + self.release = '3.22.3' + self.base_url = "https://developer.gnome.org/gtk3/#{self.version}/" + + options[:root_title] = 'GTK+ 3 Reference Manual' + options[:skip] = GTK3_SKIP + options[:skip_patterns] = GTK3_SKIP_PATTERNS + end + + version '3.20' do + self.release = '3.20.4' + self.base_url = "https://developer.gnome.org/gtk3/#{self.version}/" + + options[:root_title] = 'GTK+ 3 Reference Manual' + options[:skip] = GTK3_SKIP + options[:skip_patterns] = GTK3_SKIP_PATTERNS + end + + def get_latest_version(opts) + tags = get_gitlab_tags('gitlab.gnome.org', 'GNOME', 'gtk', opts) + tags[0]['name'] + end + end +end diff --git a/public/icons/docs/gtk/16.png b/public/icons/docs/gtk/16.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a7e72aa6595be62ba72b9f17e49818b6a6c344 GIT binary patch literal 1199 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 eF)%taF)c7PIxsM;@Bozn0000