diff options
Diffstat (limited to 'lib')
28 files changed, 937 insertions, 0 deletions
diff --git a/lib/olddoc.rb b/lib/olddoc.rb new file mode 100644 index 0000000..f230cbf --- /dev/null +++ b/lib/olddoc.rb @@ -0,0 +1,21 @@ +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +module Olddoc + VERSION = '1.0.0' + + autoload :Changelog, 'olddoc/changelog' + autoload :Gemspec, 'olddoc/gemspec' + autoload :History, 'olddoc/history' + autoload :Merge, 'olddoc/merge' + autoload :NewsAtom, 'olddoc/news_atom' + autoload :NewsRdoc, 'olddoc/news_rdoc' + autoload :Prepare, 'olddoc/prepare' + autoload :Readme, 'olddoc/readme' + + def self.config(path = ".olddoc.yml") + File.readable?(path) and return YAML.load(File.read(path)) + warn "#{path} not found in current directory" + {} + end +end +require_relative 'oldweb' diff --git a/lib/olddoc/changelog.rb b/lib/olddoc/changelog.rb new file mode 100644 index 0000000..7a7fe96 --- /dev/null +++ b/lib/olddoc/changelog.rb @@ -0,0 +1,28 @@ +# helper method for generating the ChangeLog in RDoc format atomically +require 'tempfile' + +module Olddoc::Changelog + include Olddoc::History + + def changelog + fp = Tempfile.new('ChangeLog', '.') + fp.write "ChangeLog from #@cgit_uri" + cmd = %w(git log) + if @changelog_start && tags[0] + range = "#@changelog_start..#{tags[0][:tag]}" + fp.write(" (#{range})") + cmd << range + end + fp.write("\n\n") + prefix = " " + IO.popen(cmd.join(' ')) do |io| + io.each { |line| + fp.write prefix + fp.write line + } + end + fp.chmod(0666 & ~File.umask) + File.rename(fp.path, 'ChangeLog') + fp.close! + end +end diff --git a/lib/olddoc/gemspec.rb b/lib/olddoc/gemspec.rb new file mode 100644 index 0000000..73382ab --- /dev/null +++ b/lib/olddoc/gemspec.rb @@ -0,0 +1,17 @@ +# helper methods for gemspecs +module Olddoc::Gemspec + include Olddoc::Readme + + def extra_rdoc_files(manifest) + File.readlines('.document').map! do |x| + x.chomp! + if File.directory?(x) + manifest.grep(%r{\A#{x}/}) + elsif File.file?(x) + x + else + nil + end + end.flatten.compact + end +end diff --git a/lib/olddoc/history.rb b/lib/olddoc/history.rb new file mode 100644 index 0000000..b817d2d --- /dev/null +++ b/lib/olddoc/history.rb @@ -0,0 +1,57 @@ +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +require 'uri' + +module Olddoc::History + def initialize_history + @tags = @old_summaries = nil + end + + # returns a cgit URI for a given +tag_name+ + def tag_uri(tag_name) + uri = @cgit_uri.dup + uri.path += "/tag/" + uri.query = "id=#{tag_name}" + uri + end + + def tags + timefmt = '%Y-%m-%dT%H:%M:%SZ' + @tags ||= `git tag -l`.split(/\n/).map do |tag| + next if tag == "v0.0.0" + if %r{\Av[\d\.]+} =~ tag + type = `git cat-file -t #{tag}`.chomp + user_type = { "tag" => "tagger", "commit" => "committer" }[type] + user_type or abort "unable to determine what to do with #{type}=#{tag}" + header, subject, body = `git cat-file #{type} #{tag}`.split(/\n\n/, 3) + body ||= "initial" unless old_summaries.include?(tag) + header = header.split(/\n/) + + tagger = header.grep(/\A#{user_type} /).first + time = Time.at(tagger.split(/ /)[-2].to_i).utc + { + :time => time.strftime(timefmt), + :ruby_time => time, + :tagger_name => %r{^#{user_type} ([^<]+)}.match(tagger)[1].strip, + :tagger_email => %r{<([^>]+)>}.match(tagger)[1].strip, + :id => `git rev-parse refs/tags/#{tag}`.chomp!, + :tag => tag, + :subject => subject.strip, + :body => (old = old_summaries[tag]) ? "#{old}\n#{body}" : body, + } + end + end.compact.sort { |a,b| b[:time] <=> a[:time] } + end + + def old_summaries + @old_summaries ||= if File.exist?(".CHANGELOG.old") + File.readlines(".CHANGELOG.old").inject({}) do |hash, line| + version, summary = line.split(/ - /, 2) + hash[version] = summary + hash + end + else + {} + end + end +end diff --git a/lib/olddoc/merge.rb b/lib/olddoc/merge.rb new file mode 100644 index 0000000..da5bd07 --- /dev/null +++ b/lib/olddoc/merge.rb @@ -0,0 +1,26 @@ +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) + +class Olddoc::Merge + def initialize(opts) + @merge_html = opts["merge_html"] || {} + end + + # FIXME: generate manpages directly from rdoc instead of relying on + # pandoc to do it via markdown. + def run + @merge_html.each do |file, source| + rdoc_html = "doc/#{file}.html" + fragment = File.read(source) + File.open(rdoc_html, "a+") { |fp| + html = fp.read + if html.sub!(%r{\s*<p>\s*olddoc_placeholder\s*</p>\s*}sm, fragment) + fp.truncate(0) + fp.write(html) + else + warn "olddoc_placeholder not found in #{rdoc_html}" + end + } + end + end +end diff --git a/lib/olddoc/news_atom.rb b/lib/olddoc/news_atom.rb new file mode 100644 index 0000000..6a92b3e --- /dev/null +++ b/lib/olddoc/news_atom.rb @@ -0,0 +1,51 @@ +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +require 'builder' + +module Olddoc::NewsAtom + include Olddoc::History + include Olddoc::Readme + + # generates an Atom feed based on git tags in the document directory + def news_atom_xml + project_name, short_desc, _ = readme_metadata + new_tags = tags[0,10] + atom_uri = @rdoc_uri.dup + atom_uri.path += "NEWS.atom.xml" + news_uri = @rdoc_uri.dup + news_uri.path += "NEWS.html" + x = Builder::XmlMarkup.new + x.feed(xmlns: "http://www.w3.org/2005/Atom") do + x.id(atom_uri.to_s) + x.title("#{project_name} news") + x.subtitle(short_desc) + x.link(rel: 'alternate', type: 'text/html', href: news_uri.to_s) + x.updated(new_tags.empty? ? '1970-01-01:00:00:00Z' : new_tags[0][:time]) + new_tags.each do |tag| + x.entry do + x.title(tag[:subject]) + x.updated(tag[:time]) + x.published(tag[:time]) + x.author do + x.name(tag[:tagger_name]) + x.email(tag[:tagger_email]) + end + uri = tag_uri(tag[:tag]).to_s + x.link(rel: "alternate", type: 'text/html', href: uri) + x.id(uri) + x.content(type: :xhtml) { x.pre(tag[:body]) } + end # entry + end # new_tags + end # feed + [ x.target!, new_tags ] + end + + def news_atom(dest = "NEWS.atom.xml") + xml, new_tags = news_atom_xml + File.open(dest, "w") { |fp| fp.write(xml) } + unless new_tags.empty? + time = new_tags[0][:ruby_time] + File.utime(time, time, dest) + end + end +end diff --git a/lib/olddoc/news_rdoc.rb b/lib/olddoc/news_rdoc.rb new file mode 100644 index 0000000..cc51bec --- /dev/null +++ b/lib/olddoc/news_rdoc.rb @@ -0,0 +1,36 @@ +# -*- encoding: utf-8 -*- +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) + +require 'tempfile' + +module Olddoc::NewsRdoc + include Olddoc::History + + def puts_tag(fp, tag) + time = tag[:time].tr('T', ' ').gsub!(/:\d\dZ/, ' UTC') + fp.puts "=== #{tag[:subject]} / #{time}" + fp.puts "" + + body = tag[:body] + fp.puts tag[:body].gsub(/^/smu, " ").gsub(/[ \t]+$/smu, "") + fp.puts "" + end + + # generates a NEWS file in the top-level directory based on git tags + def news_rdoc + news = Tempfile.new('NEWS', '.') + tags.each { |tag| puts_tag(news, tag) } + File.open("LATEST", "wb") { |latest| + if tags.empty? + latest.puts "Currently unreleased" + news.puts "No news yet." + else + puts_tag(latest, tags[0]) + end + } + news.chmod(0666 & ~File.umask) + File.rename(news.path, 'NEWS') + news.close! + end +end diff --git a/lib/olddoc/prepare.rb b/lib/olddoc/prepare.rb new file mode 100644 index 0000000..f760bd3 --- /dev/null +++ b/lib/olddoc/prepare.rb @@ -0,0 +1,27 @@ +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) + +require 'uri' +class Olddoc::Prepare + include Olddoc::NewsRdoc + include Olddoc::NewsAtom + include Olddoc::Changelog + include Olddoc::Readme + + def initialize(opts) + rdoc_url = opts['rdoc_url'] + cgit_url = opts['cgit_url'] + rdoc_url && cgit_url or + abort "rdoc_url and cgit_url required in .olddoc.yml for `prepare'" + @rdoc_uri = URI.parse(rdoc_url) + @cgit_uri = URI.parse(cgit_url) + @changelog_start = opts['changelog_start'] + @name, @short_desc = readme_metadata + end + + def run + news_rdoc + changelog + news_atom + end +end diff --git a/lib/olddoc/readme.rb b/lib/olddoc/readme.rb new file mode 100644 index 0000000..18f0205 --- /dev/null +++ b/lib/olddoc/readme.rb @@ -0,0 +1,27 @@ +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) + +# helpers for parsing the top-level README file +module Olddoc::Readme + + def readme_path + 'README' + end + + # returns a one-paragraph summary from the README + def readme_description + File.read(readme_path).split(/\n\n/)[1] + end + + # parses the README file in the top-level directory for project metadata + def readme_metadata + l = File.readlines(readme_path)[0].strip! + l.gsub!(/^=\s+/, '') or abort "#{l.inspect} doesn't start with '='" + title = l.dup + if l.gsub!(/^(\w+\!)\s+/, '') # Rainbows! + return $1, l, title + else + return (l.split(/\s*[:-]\s*/, 2)).push(title) + end + end +end diff --git a/lib/oldweb.rb b/lib/oldweb.rb new file mode 100644 index 0000000..d045693 --- /dev/null +++ b/lib/oldweb.rb @@ -0,0 +1,303 @@ +# Copyright (C) 2015, all contributors <olddoc-public@80x24.org> +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +# Loosely derived from Darkfish in the main rdoc distribution +require 'rdoc' +require 'erb' +require 'pathname' +require 'yaml' +require 'cgi' +require 'uri' + +class Oldweb + RDoc::RDoc.add_generator(self) + include ERB::Util + attr_reader :class_dir + attr_reader :file_dir + + # description of the generator + DESCRIPTION = 'minimal HTML generator' + + # version of this generator + VERSION = '1' + + def initialize(store, options) + # just because we're capable of generating UTF-8 to get human names + # right does not mean we should overuse it for quotation marks and such, + # our clients may not have the necessary fonts. + RDoc::Text::TO_HTML_CHARACTERS[Encoding::UTF_8] = + RDoc::Text::TO_HTML_CHARACTERS[Encoding::ASCII] + + @store = store + @options = options + @base_dir = Pathname.pwd.expand_path + @dry_run = options.dry_run + @file_output = true + @template_dir = Pathname.new(File.join(File.dirname(__FILE__), 'oldweb')) + @template_cache = {} + @classes = nil + @context = nil + @files = nil + @methods = nil + @modsort = nil + @class_dir = nil + @file_dir = nil + @outputdir = nil + @old_vcs_url = nil + @git_tag = nil + + # olddoc-specific stuff + # infer title from README + if options.title == 'RDoc Documentation' && File.readable?('README') + line = File.open('README') { |fp| fp.gets.strip } + line.sub!(/\A=+\s*/, '') + options.title = line + end + + # load olddoc config + cfg = '.olddoc.yml' + if File.readable?(cfg) + @old_cfg = YAML.load(File.read(cfg)) + else + @old_cfg = {} + warn "#{cfg} not readable" + end + %w(toc_max).each { |k| v = @old_cfg[k] and @old_cfg[k] = v.to_i } + @old_cfg['toc_max'] ||= 6 + + ni = {} + noindex = @old_cfg['noindex'] and noindex.each { |k| ni[k] = true } + @old_cfg['noindex'] = ni + + if cgit_url = @old_cfg['cgit_url'] + cgit_url += '/tree/%s' # path name + tag = @git_tag and cgit_url << "id=#{URI.escape(tag)}" + cgit_url << '#n%d' # lineno + @old_vcs_url = cgit_url + end + end + + def generate + setup + generate_class_files + generate_file_files + generate_table_of_contents + src = Dir["#@outputdir/README*.html"].first + begin + dst = "#@outputdir/index.html" + File.link(src, dst) + rescue SystemCallError + IO.copy_stream(src, dst) + end if src + end + + def rel_path(out_file) + rel_prefix = @outputdir.relative_path_from(out_file.dirname) + rel_prefix == '.' ? '' : "#{rel_prefix}/" + end + + # called standalone by servelet + def generate_class(klass, template_file = nil) + setup + current = klass + template_file ||= @template_dir + 'class.rhtml' + out_file = @outputdir + klass.path + rel_prefix = rel_path(out_file) + @title = "#{klass.type} #{klass.full_name}" + @suppress_warning = [ rel_prefix, current ] + render_template(template_file, out_file) { |io| binding } + end + + # Generate a documentation file for each class and module + def generate_class_files + setup + template_file = @template_dir + 'class.rhtml' + current = nil + + @classes.each do |klass| + current = klass + generate_class(klass, template_file) + end + rescue => e + e!(e, "error generating #{current.path}: #{e.message} (#{e.class})") + end + + # Generate a documentation file for each file + def generate_file_files + setup + @files.each do |file| + generate_page(file) if file.text? + end + end + + # Generate a page file for +file+ + def generate_page(file, out_file = @outputdir + file.path) + setup + template_file = @template_dir + 'page.rhtml' + rel_prefix = rel_path(out_file) + current = file + + @title = "#{file.page_name} - #{@options.title}" + + # use the first header as title instead of page_name if there is one + File.open("#{@options.root}/#{file.absolute_name}") do |f| + line = f.gets.strip + line.sub!(/^=+\s*/, '') and @title = line + end + + @suppress_warning = [ current, rel_prefix ] + + render_template(template_file, out_file) { |io| binding } + rescue => e + e!(e, "error generating #{out_file}: #{e.message} (#{e.class})") + end + + # Generates the 404 page for the RDoc servlet + def generate_servlet_not_found(message) + setup + template_file = @template_dir + 'servlet_not_found.rhtml' + rel_prefix = '' + @suppress_warning = rel_prefix + @title = 'Not Found' + render_template(template_file) { |io| binding } + rescue => e + e!(e, "error generating servlet_not_found: #{e.message} (#{e.class})") + end + + # Generates the servlet root page for the RDoc servlet + def generate_servlet_root(installed) + setup + + template_file = @template_dir + 'servlet_root.rhtml' + + rel_prefix = '' + @suppress_warning = rel_prefix + + @title = 'Local RDoc Documentation' + render_template(template_file) { |io| binding } + rescue => e + e!(e, "error generating servlet_root: #{e.message} (#{e.class})") + end + + def generate_table_of_contents + setup + template_file = @template_dir + 'table_of_contents.rhtml' + out_file = @outputdir + 'table_of_contents.html' + rel_prefix = rel_path(out_file) + @suppress_warning = rel_prefix + @title = "Table of Contents - #{@options.title}" + render_template(template_file, out_file) { |io| binding } + rescue => e + e!(e, "error generating table_of_contents.html: #{e.message} (#{e.class})") + end + + def setup + return if @outputdir + @outputdir = Pathname.new(@options.op_dir).expand_path(@base_dir) + return unless @store + @classes = @store.all_classes_and_modules.sort + @files = @store.all_files.sort + @methods = @classes.map(&:method_list).flatten.sort + @modsort = @classes.select(&:display?).sort + end + + # Creates a template from its components and the +body_file+. + def assemble_template(body_file) + body = body_file.read + head = @template_dir + '_head.rhtml' + tail = @template_dir + '_tail.rhtml' + "<html><head>#{head.read.strip}</head><body\n" \ + "id=\"top\">#{body.strip}#{tail.read.strip}</body></html>" + end + + # Renders the ERb contained in +file_name+ relative to the template + # directory and returns the result based on the current context. + def render(file_name) + template_file = @template_dir + file_name + template = template_for(template_file, false, RDoc::ERBPartial) + template.filename = template_file.to_s + template.result(@context) + end + + # Load and render the erb template in the given +template_file+ and write + # it out to +out_file+. + # Both +template_file+ and +out_file+ should be Pathname-like objects. + # An io will be yielded which must be captured by binding in the caller. + def render_template(template_file, out_file = nil) # :yield: io + io_output = out_file && !@dry_run && @file_output + erb_klass = io_output ? RDoc::ERBIO : ERB + template = template_for(template_file, true, erb_klass) + + if io_output + out_file.dirname.mkpath + out_file.open('w', 0644) do |io| + io.set_encoding(@options.encoding) + @context = yield io + template_result(template, @context, template_file) + end + else + @context = yield nil + template_result(template, @context, template_file) + end + end + + # Creates the result for +template+ with +context+. If an error is raised a + # Pathname +template_file+ will indicate the file where the error occurred. + def template_result(template, context, template_file) + template.filename = template_file.to_s + template.result(context) + rescue NoMethodError => e + e!(e, "Error while evaluating #{template_file.expand_path}: #{e.message}") + end + + def template_for(file, page = true, klass = ERB) + template = @template_cache[file] + + return template if template + + if page + template = assemble_template(file) + erbout = 'io' + else + template = file.read + template = template.encode(@options.encoding) + file_var = File.basename(file).sub(/\..*/, '') + erbout = "_erbout_#{file_var}" + end + + template = klass.new(template, nil, '<>', erbout) + @template_cache[file] = template + end + + def e!(e, msg) + raise RDoc::Error, msg, e.backtrace + end + + def method_srclink(m) + url = @old_vcs_url or return "" + line = m.line or return "" + path = URI.escape(m.file_name) + %Q(<a href="#{url % [ path, line ]}">source</a>) + end + + # reach into RDoc internals to generate less HTML + module LessHtml + def accept_verbatim(verbatim) + @res << "\n<pre>#{CGI.escapeHTML(verbatim.text.rstrip)}</pre>\n" + end + + def accept_heading(heading) + level = [6, heading.level].min + label = heading.label(@code_object) + @res << "<h#{level}" + @res << (@options.output_decoration ? "\nid=\"#{label}\">" : ">") + @res << to_html(heading.text) + @res << "</h#{level}>" + end + end +end + +class RDoc::Markup::ToHtml # :nodoc: + remove_method :accept_heading + remove_method :accept_verbatim + include Oldweb::LessHtml +end diff --git a/lib/oldweb/_head.rhtml b/lib/oldweb/_head.rhtml new file mode 100644 index 0000000..9a9242c --- /dev/null +++ b/lib/oldweb/_head.rhtml @@ -0,0 +1,7 @@ +<meta charset="<%= @options.charset %>"><title><%= h @title %></title><% +if rdoc_url = @old_cfg['rdoc_url'] %><link +rel="alternate" +title="Atom feed" +href="<%= rdoc_url %>NEWS.atom.xml" +type="application/atom+xml" /><% +end %> diff --git a/lib/oldweb/_sidebar_classes.rhtml b/lib/oldweb/_sidebar_classes.rhtml new file mode 100644 index 0000000..66f7fbf --- /dev/null +++ b/lib/oldweb/_sidebar_classes.rhtml @@ -0,0 +1,27 @@ +<% +@modsort.delete_if do |c| + c.full_name == "unknown" || @old_cfg["noindex"].include?(c.full_name) +end +unless @modsort.empty? + # To save space and reduce visual noise, we want to display: + # Top Sub1 Sub2 Sub3 + # Instead of + # Top Top::Sub1 Top::Sub2 Top::Sub3 + top_mod = nil + @modsort.each do |mod| %><% + parts = mod.full_name.split('::') + if parts[0] != top_mod && parts.size == 1 + top_mod = parts[0] + %><%= '<br />' if mod != @modsort[0] %><% + elsif parts[0] != top_mod + top_mod = nil + %><%= '<br />' if mod != @modsort[0] %><%= parts[0] %> <% + else + parts.shift + end +%><a +href="<%= rel_prefix %><%= mod.path %>"><%= parts.join('::') %></a> +<% + end +end +%><br /> diff --git a/lib/oldweb/_sidebar_extends.rhtml b/lib/oldweb/_sidebar_extends.rhtml new file mode 100644 index 0000000..8dab782 --- /dev/null +++ b/lib/oldweb/_sidebar_extends.rhtml @@ -0,0 +1,13 @@ +<% +unless klass.extends.empty? +%><p><b>Extended with:</b> <% + klass.each_extend do |ext| + unless String === ext.module +%><a +href="<%= klass.aref_to ext.module.path %>"><%= ext.module.full_name %></a><% + else +%><%= ext.name %><% + end + end +end +%> diff --git a/lib/oldweb/_sidebar_includes.rhtml b/lib/oldweb/_sidebar_includes.rhtml new file mode 100644 index 0000000..46a1d1d --- /dev/null +++ b/lib/oldweb/_sidebar_includes.rhtml @@ -0,0 +1,12 @@ +<% +unless klass.includes.empty? +%><p><b>Included modules:</b> <% + klass.each_include do |inc| + unless String === inc.module %><a +href="<%= klass.aref_to inc.module.path %>"><%= inc.module.full_name %></a><% + else %><%= + inc.name %><% + end + end +end +%> diff --git a/lib/oldweb/_sidebar_installed.rhtml b/lib/oldweb/_sidebar_installed.rhtml new file mode 100644 index 0000000..74d3bab --- /dev/null +++ b/lib/oldweb/_sidebar_installed.rhtml @@ -0,0 +1,10 @@ +<h3>Documentation</h3><ul><% +installed.each do |name, href, exists, type, _| + next if type == :extra %><li><% + if exists + %><a +href="<%= href %>"><%= h name %></a><% + else + %><%= h name %><% + end +end %></ul> diff --git a/lib/oldweb/_sidebar_methods.rhtml b/lib/oldweb/_sidebar_methods.rhtml new file mode 100644 index 0000000..f84fe9c --- /dev/null +++ b/lib/oldweb/_sidebar_methods.rhtml @@ -0,0 +1,6 @@ +<% unless klass.method_list.empty? %> +<h3 id="method-list-section">Methods</h3><% +klass.each_method do |meth| %> +<a href="#<%= meth.aref %>"><%= +meth.singleton ? '::' : '#' %><%= h meth.name %></a><% +end %><% end %> diff --git a/lib/oldweb/_sidebar_navigation.rhtml b/lib/oldweb/_sidebar_navigation.rhtml new file mode 100644 index 0000000..a7ea935 --- /dev/null +++ b/lib/oldweb/_sidebar_navigation.rhtml @@ -0,0 +1,6 @@ +<br /><a +href="<%= rel_prefix %>table_of_contents.html#pages">Pages</a> +<a +href="<%= rel_prefix %>table_of_contents.html#classes">Classes</a> +<a +href="<%= rel_prefix %>table_of_contents.html#methods">Methods</a> diff --git a/lib/oldweb/_sidebar_pages.rhtml b/lib/oldweb/_sidebar_pages.rhtml new file mode 100644 index 0000000..cdc23f4 --- /dev/null +++ b/lib/oldweb/_sidebar_pages.rhtml @@ -0,0 +1,17 @@ +<% +simple_files = @files.select(&:text?) +unless simple_files.empty? + current_name = nil + if defined?(current) && current.respond_to?(:page_name) + current_name = current.page_name + end + simple_files.each do |f| + next if @old_cfg["noindex"].include?(f.page_name) + b = (current_name == f.page_name) +%><a +href="<%= rel_prefix %><%= f.path %>"><%= +b ? '<b>' : '' %><%= h f.page_name %><%= b ? '</b>' : ''%></a> +<% + end +end +%><br /> diff --git a/lib/oldweb/_sidebar_parent.rhtml b/lib/oldweb/_sidebar_parent.rhtml new file mode 100644 index 0000000..9323101 --- /dev/null +++ b/lib/oldweb/_sidebar_parent.rhtml @@ -0,0 +1,13 @@ +<% +# having Object as parent is boring +if klass.type == 'class' && klass.superclass != 'Object' +%><p><b>Parent:</b> <% + if klass.superclass and not String === klass.superclass +%><a +href="<%= klass.aref_to klass.superclass.path %>"><%= + klass.superclass.full_name %></a><% + else +%><%= klass.superclass %><% + end +end +%> diff --git a/lib/oldweb/_sidebar_sections.rhtml b/lib/oldweb/_sidebar_sections.rhtml new file mode 100644 index 0000000..b6e9458 --- /dev/null +++ b/lib/oldweb/_sidebar_sections.rhtml @@ -0,0 +1,8 @@ +<% +unless klass.sections.length == 1 +%><p><b>Sections:</b> <% + klass.sort_sections.each do |section| %><a +href="#<%= section.aref %>"><%= h section.title %></a><% + end +end +%> diff --git a/lib/oldweb/_sidebar_table_of_contents.rhtml b/lib/oldweb/_sidebar_table_of_contents.rhtml new file mode 100644 index 0000000..890b0cc --- /dev/null +++ b/lib/oldweb/_sidebar_table_of_contents.rhtml @@ -0,0 +1,15 @@ +<% +comment = current.respond_to?(:comment_location) ? current.comment_location : + current.comment +table = current.parse(comment).table_of_contents +if table.length > 1 +%><% + table.each_with_index do |heading, i| + next if heading.level > @old_cfg['toc_max'] +%><a +href="#<%= heading.label(current) %>"><%= + i == 0 ? "top" : heading.plain_html %></a> +<% + end %><br /><% +end +%> diff --git a/lib/oldweb/_tail.rhtml b/lib/oldweb/_tail.rhtml new file mode 100644 index 0000000..d1fc7e5 --- /dev/null +++ b/lib/oldweb/_tail.rhtml @@ -0,0 +1,25 @@ +<% +public_email = @old_cfg['public_email'] +private_email = @old_cfg['private_email'] +ml_url = @old_cfg['ml_url'] +git_doc = 'https://kernel.org/pub/software/scm/git/docs/' +se_url = "#{git_doc}git-send-email.html" +rp_url = "#{git_doc}git-request-pull.html" + +if public_email && private_email && ml_url %><hr /><p> +We love to hear from you!<br /> +Email patches (using <a +href="<%= se_url %>">git send-email</a>), +pull requests (formatted using <a +href="<%= rp_url %>">git request-pull</a>), questions, bug reports, +suggestions, etc. to us publically at:<br /><a +href="mailto:<%= public_email %>"><%= public_email %></a><br /> +Mail archives are available at: <a +href="<%= ml_url %>"><%= ml_url %></a><br /> +Please send plain-text email only and do not waste bandwidth on HTML mail, +HTML mail will not be read.<br /> +Quote as little as reasonable and do not <a +href="http://catb.org/jargon/html/T/top-post.html">top post</a>.<br /> +For sensitive topics, email us privately at: +<a +href="mailto:<%= private_email %>"><%= private_email %></a><% end %> diff --git a/lib/oldweb/class.rhtml b/lib/oldweb/class.rhtml new file mode 100644 index 0000000..107ce41 --- /dev/null +++ b/lib/oldweb/class.rhtml @@ -0,0 +1,79 @@ +<%= +render('_sidebar_pages.rhtml') << +render('_sidebar_classes.rhtml') << +render('_sidebar_methods.rhtml') +%><h1 +id="<%= h klass.aref %>"><%= klass.type %> <%= klass.full_name %></h1><%= +klass.description.strip +%><% +nd = '(Not documented)' +klass.each_section do |section, constants, attributes| + constants = constants.select(&:display?) + attributes = attributes.select(&:display?) + if section.title +%><h2 +id="<%= section.aref %>"><%= section.title %></h2><% + end + if section.comment %><p><%= section.description.strip %></p><% + end + unless constants.empty? %><h3>Constants</h3><% + constants.each { |const| + %><h4 +id="<%= const.name %>"><%= const.name %></h4><%= + const.comment ? const.description.strip : nd %><% + } %><% + end + unless attributes.empty? %><h3>Attributes</h3><% + attributes.each do |attrib| +%><h4 +id="<%= attrib.aref %>"><%= + h(attrib.name) %> [<%= attrib.rw %>]</h4><%= + attrib.comment ? attrib.description.strip : nd %><% + end + end + klass.methods_by_type(section).each do |type, visibilities| + next if visibilities.empty? + visibilities.each do |visibility, methods| + next if methods.empty? %><h3 +id="<%= visibility %>-<%= type %>-<%= section.aref %>-method-details"> +<%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3><% + methods.each do |method| + %><pre id="<%= method.aref %>"><b><% + if method.call_seq %><%= h method.call_seq %><% + else + %><%= h method.name %> <%= h method.param_seq %><% + end %></b><%= method_srclink(method) %></pre><%= + method.comment ? method.description.strip : nd %><% + if method.calls_super %>Calls superclass method<%= + method.superclass_method ? + method.formatter.link(method.superclass_method.full_name, + method.superclass_method.full_name) : nil + %><% + end + unless method.aliases.empty? + %> Also aliased as: <%= + method.aliases.map do |aka| + if aka.parent # HACK lib/rexml/encodings + %{<a href="#{klass.aref_to(aka.path)}">#{h aka.name}</a>} + else + h aka.name + end + end.join ", " %><% + end + if method.is_alias_for + %><br />Alias for: +<a +href="<%= klass.aref_to method.is_alias_for.path %>"><%= + h method.is_alias_for.name %></a><% + end + end + end + end +end +%><%= +render('_sidebar_sections.rhtml').strip << +render('_sidebar_parent.rhtml').strip << +render('_sidebar_includes.rhtml').strip << +render('_sidebar_extends.rhtml').strip << +render('_sidebar_navigation.rhtml').strip +%> diff --git a/lib/oldweb/page.rhtml b/lib/oldweb/page.rhtml new file mode 100644 index 0000000..9049ee5 --- /dev/null +++ b/lib/oldweb/page.rhtml @@ -0,0 +1,5 @@ +<%= +render('_sidebar_pages.rhtml') << +render('_sidebar_classes.rhtml') << +file.description.strip +%> diff --git a/lib/oldweb/servlet_not_found.rhtml b/lib/oldweb/servlet_not_found.rhtml new file mode 100644 index 0000000..3264d9e --- /dev/null +++ b/lib/oldweb/servlet_not_found.rhtml @@ -0,0 +1,5 @@ +<%= + render('_sidebar_navigation.rhtml') << + render('_sidebar_pages.rhtml') << + render('_sidebar_classes.rhtml') +%><h1>Not Found</h1><%= message %> diff --git a/lib/oldweb/servlet_root.rhtml b/lib/oldweb/servlet_root.rhtml new file mode 100644 index 0000000..839198f --- /dev/null +++ b/lib/oldweb/servlet_root.rhtml @@ -0,0 +1,39 @@ +<h2><a href="<%= rel_prefix %>">Home</a></h2><%= +render '_sidebar_installed.rhtml' +%><h1>Local RDoc Documentation</h1> +<p>Here you can browse local documentation from the ruby standard library and + your installed gems. +<% extra_dirs = installed.select { |_, _, _, type,| type == :extra } %> +<% unless extra_dirs.empty? %> +<h2>Extra Documentation Directories</h2> + <p>The following additional documentation directories are available:</p> + <ol> + <% extra_dirs.each do |name, href, exists, _, path| %> + <li> + <% if exists %> + <a href="<%= href %>"><%= h name %></a> (<%= h path %>) + <% else %> + <%= h name %> (<%= h path %>; not available) + <% end %> + <% end %> + </ol> +<% end %> +<% +gems = installed.select { |_, _, _, type,| type == :gem } +missing = gems.reject { |_, _, exists,| exists } +unless missing.empty? %> +<h2>Missing Gem Documentation</h2> +<p>You are missing documentation for some of your installed gems. +You can install missing documentation for gems by running +<kbd>gem rdoc --all</kbd>. After installing the missing documentation you +only need to reload this page. The newly created documentation will +automatically appear. +<p>You can also install documentation for a specific gem by running one of +the following commands. +<ul> +<% names = missing.map { |name,| name.sub(/-([^-]*)$/, '') }.uniq %> +<% names.each do |name| %> + <li><kbd>gem rdoc <%=h name %></kbd> +<% end %> +</ul> +<% end %> diff --git a/lib/oldweb/table_of_contents.rhtml b/lib/oldweb/table_of_contents.rhtml new file mode 100644 index 0000000..ed455a8 --- /dev/null +++ b/lib/oldweb/table_of_contents.rhtml @@ -0,0 +1,52 @@ +<h1><%= h @title %></h1><% +simple_files = @files.select(&:text?) +unless simple_files.empty? +%><h2 id="pages">Pages</h2> +<ul><% + simple_files.sort.each do |file| %><li><a +href="<%= file.path %>"><%= h file.page_name %></a> +<% + # HACK table_of_contents should not exist on Document + table = file.parse(file.comment).table_of_contents + unless table.empty? +%><ul><% + table.each do |heading| + %><li><a +href="<%= file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a> +<% end +%></ul><% + end +%><% + end +%></ul><% +end +%><h2 +id="classes">Classes and Modules</h2><ul><% +@modsort.each do |klass| %><li +class="<%= klass.type %>"><a +href="<%= klass.path %>"><%= klass.full_name %></a> +<% + table = [] + table.concat klass.parse(klass.comment_location).table_of_contents + table.concat klass.section_contents + + unless table.empty? + %><ul><% + table.each do |item| + %><li><a +href="<%= klass.path %>#<%= item.aref %>"><%= item.plain_html %></a> +<% + end %></ul><% + end +%><% +end +%></ul><h2 +id="methods">Methods</h2><ul><% + @store.all_classes_and_modules.map do |mod| + mod.method_list + end.flatten.sort.each do |method| +%><li><a +href="<%= method.path %>"><%= h method.pretty_name %></a> +- <%= method.parent.full_name %><% +end +%></ul> diff --git a/lib/rdoc/discover.rb b/lib/rdoc/discover.rb new file mode 100644 index 0000000..e497514 --- /dev/null +++ b/lib/rdoc/discover.rb @@ -0,0 +1,5 @@ +begin + gem 'rdoc', '~> 4.1' + require_relative '../olddoc' +rescue Gem::LoadError +end unless defined?(Olddoc) |