require 'pp'
require 'htemplate'
require 'pathname'
require 'bluecloth'
require 'digest/md5'
module Enid
VERSION = "0.3.1"
Entry = Struct.new(:entry, :children, :order)
Title = Struct.new(:text, :ref)
Text = Struct.new(:text)
Link = Struct.new(:href, :text)
ReverseLink = Struct.new(:href, :text)
Attachment = Struct.new(:file, :text)
class Top
def text; ""; end
def id; nil; end
def href; "/"; end
def pretty; "top"; end
def match?(term); false; end
def to_html; ""; end
end
class Entry
TEMPLATE = HTemplate.new(<<'EOF')
$ unless @skip_root
$:entry.to_html
$ if !children.empty? && @too_deep && id
...
$ end
$ end
$ if !children.empty? && !@too_deep
$ children.each { |child|
-
$:{child.to_html(@depth+1)}
$ }
$ end
EOF
def to_html(depth=0, maxdepth=3, skip_root=false)
@depth = depth
@too_deep = depth >= maxdepth
@skip_root = skip_root && depth == 0
TEMPLATE.expand(self)
end
def id
entry.id
end
def href
entry.href
end
def resolve(world)
if Link === entry
if world.include?(entry.href)
target = world[entry.href]
original_title = entry.text
self.entry = target.entry.dup
self.entry.text ||= original_title
self.children = target.children + children
else
self.entry = Title.new(entry.text, entry.href)
end
resolve world
end
children.each { |child|
child.resolve world
}
world
end
def reverse_index(index=nil)
index ||= Hash.new { |h, k| h[k] = [] }
children.each { |child|
index[child.id] << id if child.id && id && !index[child.id].include?(id)
child.reverse_index index
}
index
end
def add_to_world(world={})
world[id] = self if id
children.each { |child|
child.add_to_world world
}
world
end
def resolve_reverse_links(world)
children.each { |child|
if ReverseLink === child.entry
p [:rlink, child.entry.href, entry.href]
if world[child.entry.href]
world[child.entry.href].children << Entry.new(Link.new(entry.href, entry.pretty), [])
end
else
child.resolve_reverse_links world
end
}
world
end
def sort!
case order
when :ascending
children.sort! { |a, b| smartsort(a) <=> smartsort(b) }
when :descending
children.sort! { |a, b| smartsort(b) <=> smartsort(a) }
end
children.each { |child|
child.sort!
}
self
end
def search(term, &block)
if entry.match?(term)
block.call self
end
children.each { |child|
child.search(term, &block)
}
end
protected
def smartsort(item)
nitem = item.to_s.downcase
if nitem =~ /\A\d*\z/
[[0, ""], [item.to_i, item]]
else
nitem.scan(/\d+|\D+/).map { |part|
[part.to_i, part]
}
end
end
end
class Title
def to_html
%Q{