#!/usr/bin/ruby
#Given partial HTML files in the pages directory, generate full XHTML files in the htdocs directory.
#Each page is given a title corresponding to its directory (in reverse, since browsers often truncate later bits).
#A menu parallels the directory structure. Optionally, a file linktitle may be placed in a directory to change the link text in the menu.
#htdocs/site.css is set to the stylesheet.
#Finally, these pages are surrounded by the usual XHTML incantations.
#Where are the input and output files given the web path?
class Setup
def initialize(in_root, out_root)
@in_root = with_slash(in_root)
@out_root = with_slash(out_root)
end
def in_fs(web_path)
@in_root + web_path
end
def out_fs(web_path)
@out_root + web_path
end
private
def with_slash(str)
str[-1] == "/" ? str : (str + "/")
end
end
#One node in the directory tree.
class Directory
#Web path
attr_reader :path
#Basename of path
attr_reader :base
#Text of link to use. Equal to base unless overridden by a linktitle file.
attr_reader :linktitle
#Subdirectories, also Directory objects.
attr_reader :dirs
#HTML documents in this directory, as defined by ending with .html
attr_reader :pages
def initialize(setup, parent, path)
@setup = setup
@parent = parent
@path = path
@nesting = path.count('/')
in_fs = @setup.in_fs(path)
@base = File.basename(path)
@linktitle = @base
@pages=[]
@dirs=[]
Dir.foreach(in_fs) do |entry|
if entry == "." or entry == ".."
next
elsif entry[-5..-1] == ".html"
@pages << entry
elsif File::Stat.new(in_fs + entry).directory?
@dirs << Directory.new(@setup, self, @path + entry + '/')
elsif entry == "linktitle"
@linktitle = File.new(in_fs + entry).read.chomp
else
$stderr.puts "Extra file #{path + entry}"
end
end
@dirs.sort! { |a,b| a.linktitle <=> b.linktitle }
@pages.sort!
$stderr.puts "Missing index.html in #{path}" unless @pages.include?("index.html")
#Memoisation table for menu function
@menu_cache = {}
end
MENU_BREAK="
\n"
def menu(depth, child)
cache_key = [depth, child]
ret = @menu_cache[cache_key]
return ret if ret
@menu_cache[cache_key] = if @parent
@parent.menu(depth + 1, self)
else
menu_link(depth, true, self) + MENU_BREAK
end +
@dirs.map do |d|
menu_link(depth, d == child, d)
end.join(" | ") + (@dirs.empty? ? "" : MENU_BREAK)
end
PAGETITLE_BREAK=" . "
def pagetitle
@linktitle + if @parent
PAGETITLE_BREAK + @parent.pagetitle
else
""
end
end
def generate_all
@pages.each { |p| generate_page(p) }
@dirs.each { |d| d.generate_all }
end
private
def menu_link(depth, selected, dir)
"" + dir.linktitle + ""
end
def generate_page(page)
Dir.mkdir(@setup.out_fs(path), 0755) unless File.exists?(@setup.out_fs(path))
$stderr.puts "Writing #{@setup.out_fs(@path) + page}"
root_path = "../" * @nesting
File.new(@setup.out_fs(@path) + page, "w").write(
"\n" +
"\n" +
"\n" +
"