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 00000000..d3a7e72a Binary files /dev/null and b/public/icons/docs/gtk/16.png differ diff --git a/public/icons/docs/gtk/16@2x.png b/public/icons/docs/gtk/16@2x.png new file mode 100644 index 00000000..dd3482d6 Binary files /dev/null and b/public/icons/docs/gtk/16@2x.png differ diff --git a/public/icons/docs/gtk/SOURCE b/public/icons/docs/gtk/SOURCE new file mode 100644 index 00000000..a18c5432 --- /dev/null +++ b/public/icons/docs/gtk/SOURCE @@ -0,0 +1 @@ +https://www.gtk.org/assets/img/logo-gtk-sm.png