Only fork markdown tho, can't cache erb. Now also added a deploy script which runs erb
218 lines
4.7 KiB
Ruby
218 lines
4.7 KiB
Ruby
|
|
require 'roda'
|
|
require 'erb'
|
|
require 'nokogiri'
|
|
require 'redcarpet'
|
|
require 'tomlib'
|
|
|
|
$markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true)
|
|
|
|
$root = "/home/pranshu/Documents/proj/perc/test"
|
|
Dir.chdir $root;
|
|
|
|
class Config
|
|
attr_reader :approved_regex, :layout
|
|
def initialize
|
|
approved_files = [/\.md$/, /\.e?rb$/]
|
|
@approved_regex = Regexp.union(approved_files)
|
|
toml = Tomlib.load(File.read "config.toml")
|
|
|
|
@layout = toml["layout"] || "layout.erb"
|
|
# @layout = :layout
|
|
|
|
end
|
|
end
|
|
|
|
$config = Config.new();
|
|
|
|
class Sidebar
|
|
attr_reader :tree
|
|
FileNode = Struct.new(:type, :path, :name, :real)
|
|
DirNode = Struct.new(:type, :path, :name, :files, :index, :rb_file)
|
|
|
|
def initialize
|
|
@tree = process_dir "."
|
|
end
|
|
|
|
def show(n=@tree, indent="")
|
|
if n.type == :dir
|
|
print indent, n.path, "\n"
|
|
n.files.each do |r|
|
|
show r, " " + indent
|
|
end
|
|
else
|
|
print indent, n.path, "\n"
|
|
end
|
|
end
|
|
|
|
def html
|
|
return @html if defined?(@html)
|
|
builder = Nokogiri::HTML::Builder.new do |doc|
|
|
def deal_with_dir (doc, dir, path)
|
|
doc.li {
|
|
if dir.index
|
|
doc.a(:href => "/" + path + "/") {
|
|
doc.text dir.path
|
|
}
|
|
else
|
|
doc.text dir.path
|
|
end
|
|
doc.ul {
|
|
dir.files.each do |f|
|
|
fpath = File.join(path, f.path)
|
|
if f.type == :dir
|
|
deal_with_dir doc, f, fpath
|
|
else
|
|
doc.a(:href => "/#{fpath}") {
|
|
doc.li { doc.text f.name }
|
|
}
|
|
end
|
|
end
|
|
}
|
|
}
|
|
end
|
|
doc.div {
|
|
deal_with_dir doc, @tree, @tree.path
|
|
}
|
|
end
|
|
# colossus hack, but its fine for perf cause we cache
|
|
doc = Nokogiri::HTML(builder.to_html())
|
|
@html = doc.children[1].child.child.child.children[1].to_s
|
|
end
|
|
|
|
private
|
|
|
|
def getname(file)
|
|
File.basename(file, File.extname(file))
|
|
end
|
|
|
|
def dir_files()
|
|
# Remove "." and ".." from file list
|
|
Dir.entries(".").filter {|f| f !~ /^\./ }.filter do |f|
|
|
if File.file? f
|
|
f =~ $config.approved_regex
|
|
else
|
|
true
|
|
end
|
|
end
|
|
end
|
|
|
|
def process_dir(dir)
|
|
index = false
|
|
rb_file = false
|
|
dn = DirNode.new
|
|
dn.type = :dir
|
|
dn.files = []
|
|
temp = Dir.chdir(dir) do
|
|
ignored = false
|
|
if File.file? ".perc.toml"
|
|
toml = Tomlib.load(File.read ".perc.toml")
|
|
toml["routes"].each do |route|
|
|
name = route[0]
|
|
url = route[1]
|
|
dn.files.push(FileNode.new(:fil, url, name, false))
|
|
end
|
|
ignored = toml["ignore"] || false
|
|
ignored = Regexp.union(ignored)
|
|
end
|
|
dir_files.map do |f|
|
|
if File.file? f
|
|
if f =~ /index\.(erb|md)$/
|
|
index = f
|
|
next nil
|
|
elsif f =~ /\.rb$/
|
|
rb_file = f
|
|
next nil
|
|
else
|
|
if ignored and f =~ ignored
|
|
next nil
|
|
end
|
|
next FileNode.new(:file, f, getname(f), true)
|
|
end
|
|
else
|
|
next process_dir f
|
|
end
|
|
end
|
|
end
|
|
dn.files = temp.collect + dn.files
|
|
dn.files = dn.files.compact
|
|
dn.path = dir
|
|
dn.rb_file = rb_file
|
|
dn.name = dn.path
|
|
dn.index = index
|
|
# Read dir local config
|
|
dn
|
|
end
|
|
|
|
end
|
|
|
|
$sidebar = Sidebar.new
|
|
$files_cache = {}
|
|
def pview(file)
|
|
body = ""
|
|
cont = File.read(file) or return "Not found"
|
|
if (file =~ /\.erb$/)
|
|
# We can't cache erb
|
|
tp = ERB.new(cont)
|
|
body = tp.result(binding)
|
|
elsif (file =~ /\.md$/)
|
|
# But we can cache markdown
|
|
body = ($files_cache[file] ||= $markdown.render cont)
|
|
end
|
|
put_in_layout(body)
|
|
end
|
|
|
|
Dir["./**/*.rb"].each { |f| load(f) }
|
|
|
|
def put_in_layout (str)
|
|
body = str
|
|
tree = $sidebar.html
|
|
ERB.new(File.read($config.layout)).result(binding)
|
|
end
|
|
|
|
class App < Roda
|
|
|
|
route do |r|
|
|
r.root do
|
|
pview "main.erb"
|
|
end
|
|
|
|
process_dir r, $sidebar.tree, "."
|
|
|
|
end
|
|
|
|
# Now the saga begins,we transform file_tree into a routing tree
|
|
def process_dir (r, dir, cdir)
|
|
p = Proc.new do
|
|
dir.files.each do |f|
|
|
dd = File.join(cdir, f.path)
|
|
if f.type == :dir
|
|
# f is dir
|
|
process_dir r, f, dd
|
|
elsif f.real == true
|
|
# f is a file and is real
|
|
r.get f.path do
|
|
pview dd
|
|
end
|
|
end
|
|
end
|
|
if dir.index
|
|
r.is "" do
|
|
pview File.join(cdir, dir.index)
|
|
end
|
|
end
|
|
rf = dir.rb_file
|
|
if rf
|
|
eval "r.run #{File.basename(rf,File.extname(rf)).capitalize}"
|
|
end
|
|
end
|
|
if dir.path == "."
|
|
p.call
|
|
else
|
|
r.on dir.path do
|
|
p.call
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|