diff --git a/assets/stylesheets/pages/_haskell.scss b/assets/stylesheets/pages/_haskell.scss new file mode 100644 index 00000000..15b026b6 --- /dev/null +++ b/assets/stylesheets/pages/_haskell.scss @@ -0,0 +1,121 @@ +._icon-haskell:before { + background-image: image-url('/icons/docs/haskell/16.png'); + background-size: cover; + background-repeat: no-repeat; +} + +.empty-table .empty { + display: none; +} + +.arguments td.src { + background: #faf9e2; + width: 30%; +} + +th.src, +td.src { + font-family: $monoFont; + font-weight: normal; + font-style: normal; + background: #f8f8f8; +} + +caption { + font-weight: bold; + text-align: left; + font-style: italic; + font-size: 1.1em; +} + +// remove margin in descript listing +dd > pre { + @extend %pre; + margin: 0; + background: #faf9e2; + border-color: #dddaaa #dddaaa #d7d7a9; +} + +// warnings are red +.warning { + @extend %note; + @extend %note-red; +} + + +// complexity classes are blue boxes +.with-complexity { + display: flex; + display: -webkit-flex; + + justify-content: space-between; + -webkit-justify-content: space-between; + + align-items: flex-start; + -webkit-align-items: flex-start; + + align-content: stretch; + -webkit-align-content: stretch; +} + +.complexity { + @extend %note; + @extend %note-blue; + margin: 0; + margin-left: 1em; + margin-bottom: 0.75em; + font-style: italic; + white-space: nowrap; + + flex-shrink: 0; + -webkit-flex-shrink: 0; + + order: 2; + -webkit-order: 2; +} + +.complexity + span { + order: 1; + -webkit-order: 1; +} + +// add box type to "since: ..." +.added { + @extend %note; + @extend %note-gold; +} + +.added-cell { + @extend %note-gold; +} + +.fields h3 { + display: none; +} + +// separate types more +.src { + margin-top: 2.5em; +} + +h1 + .top .src, +h2 + .top .src, +h3 + .top .src, +.caption + .top .src { + margin-top: 0; +} + +// but not for first type +h1 + .top, +h2 + .top, +h3 + .top, +h4 + .top { + margin-top: 0; +} + +// change color of example code +.example { + border: 1px solid; + background: #faf9e2; + border-color: #dddaaa #dddaaa #d7d7a9; +} diff --git a/lib/docs/filters/haskell/clean_html.rb b/lib/docs/filters/haskell/clean_html.rb new file mode 100644 index 00000000..5f6105a7 --- /dev/null +++ b/lib/docs/filters/haskell/clean_html.rb @@ -0,0 +1,159 @@ +module Docs + class Haskell + class CleanHtmlFilter < Filter + def call + + # remove unwanted elements + css('#footer', '#package-header', '#module-header', '#synopsis', '.link', '#table-of-contents', '.package').remove + + # cpations in tables are h3 + css('table .caption').each do |node| + node.name = 'h3' + end + + # turn captions into real headers + css('.caption').each do |node| + node.name = 'h1' + end + + # section + css('.top > .caption').each do |node| + node.name = 'h2' + end + + # subsections + css('.top > .subs > .caption', '.fields > .caption').each do |node| + node.name = 'h3' + end + + # subsubsections + css('.top > .subs > .subs > .caption').each do |node| + node.name = 'h4' + end + + # ... + css('.top > .subs > .subs > .subs > .caption').each do |node| + node.name = 'h5' + end + + # ...... + css('.top > .subs > .subs > .subs > .subs > .caption').each do |node| + node.name = 'h6' + end + + # all pre's are examples + css('pre').each do |node| + node.add_css_class('example') + end + + # turn source listing in to pre + css('.src').each do |node| + if node.name != "td" + node.name = 'pre' + end + end + + # check if second column of table is totally empty. + # and remove it if it is + css('table').each do |table| + empty = true + table.css('td + td').each do |snd| + empty = empty && snd['class'] =~ /empty/ + end + if empty + # remove empty column + table.css('td + td').remove + end + end + + # move table captions into the tables + css(".caption + table").each do |table| + caption = table.previous + caption.name = "caption" + caption.parent = table + end + + css(".caption + .show table").each do |table| + caption = table.parent.parent.css('.caption')[0] + caption.name = 'caption' + caption.parent = table + end + + # better arguments display: + css('.src + .arguments table').each do |table| + src = table.parent.previous # the function name + row = doc.document.create_element('tr') + table.css('tr')[0].before(row) + src.parent = row + src.name = "th" + src['colspan'] = 2 + end + + # remove root page title + if root_page? + at_css('h1').remove + end + + # add id to links (based on name) + css('a').each do |node| + if node['name'] + node['id'] = node['name'] + end + end + + # make code in description into proper pre + css('dd > code').each do |node| + node.name = 'pre' + end + + # add some informational boxes + css('em').each do |node| + if node.content == 'Deprecated.' + # Make deprecated messages red. + node.parent.add_css_class('warning') + elsif node.content =~ /O\(.*\)/ + # this is big_O notation, but only apply the class if this is not + # inside running text (it must be at the start of a paragraph) + # from: + #

O(n). Koel ok

+ # to: + #

+ # O(n) + # Koel ok + #

+ if node.previous == nil + node.add_css_class('complexity') # add css class + node.name="span" # just make it div + node.next.content = node.next.content.gsub(/^. /, "") # remove . if directly after em + node.content = node.content.gsub(/\.$/, "") # remove trailing . if it's inside em + + # reparent the nodes + cont = doc.document.create_element "p", :class => "with-complexity" + node.parent.previous = cont + par = node.parent + node.parent = cont + par.parent = cont + par.name = "span" + end + elsif node.content =~ /Since: .*/ + # add box to 'Since:' annotations + if node.parent.parent.name == "td" + node.parent.parent.add_css_class('added-cell') + else + node.add_css_class('added') + end + end + end + + doc + end + end + end +end + +class Nokogiri::XML::Node + def add_css_class( *classes ) + existing = (self['class'] || "").split(/\s+/) + self['class'] = existing.concat(classes).uniq.join(" ") + end +end diff --git a/lib/docs/filters/haskell/entries.rb b/lib/docs/filters/haskell/entries.rb new file mode 100644 index 00000000..c0fbcbb6 --- /dev/null +++ b/lib/docs/filters/haskell/entries.rb @@ -0,0 +1,56 @@ +module Docs + class Haskell + class EntriesFilter < Docs::EntriesFilter + + # gets name and type in one fell swoop + # + # eg. + # Control.Monad > [Monad, Control] + # Control.Concurrent.Mvar > [Concurrent.MVar, Control] + # Array > [Array, nil] + def get_name_and_type + if at_css('h1') && at_css('h1').content == 'Haskell Hierarchical Libraries' + puts 'ok' + name = 'Haskell' + type = nil + else + # find full module identifier + caption = at_css('#module-header .caption') + + if caption + # split the module path + parts = caption.content.split('.') + + if parts.length > 1 + # if more than one part then the + # first is the type and the rest is the name + type = parts[0] + name = parts.drop(1).join('.') + else + # if only one part, this is the name + name = parts[0] + type = nil + end + else + # no caption found -> no type / no name + name = 'no-name' + type = 'no-type' + end + end + [name, type] + end + + # get the name + def get_name + n, t = get_name_and_type() + n + end + + # get the type + def get_type + n, t = get_name_and_type() + t + end + end + end +end diff --git a/lib/docs/scrapers/haskell.rb b/lib/docs/scrapers/haskell.rb new file mode 100755 index 00000000..9fbb7af0 --- /dev/null +++ b/lib/docs/scrapers/haskell.rb @@ -0,0 +1,24 @@ +module Docs + class Haskell < UrlScraper + self.name = 'Haskell' + self.slug = 'haskell' + self.type = 'haskell' + self.version = '7.8.2' + self.base_url = 'http://www.haskell.org/ghc/docs/7.8.2/html/libraries/' + self.initial_paths = ['/index.html'] + + html_filters.push 'haskell/entries' + html_filters.push 'haskell/clean_html' + html_filters.push 'title' + + + options[:container] = '#content' + options[:skip_patterns] = [/src/, /index/, /haskell2010/, /ghc-/, /Cabal-/] # skip source listings and index files + + options[:attribution] = <<-HTML + © The University Court of the University of Glasgow.
+ All rights reserved. See here for more info + HTML + + end +end diff --git a/public/icons/docs/haskell/16.png b/public/icons/docs/haskell/16.png new file mode 100644 index 00000000..97f90732 Binary files /dev/null and b/public/icons/docs/haskell/16.png differ diff --git a/public/icons/docs/haskell/16@2x.png b/public/icons/docs/haskell/16@2x.png new file mode 100644 index 00000000..7072220e Binary files /dev/null and b/public/icons/docs/haskell/16@2x.png differ