Sinatra で Code Viewer を作る(Ruby)

code_viewer.rb

require 'sinatra'
require 'sinatra/reloader'
require 'rouge'

set :bind, '192.168.11.150'
set :port, 16524

suffixes = {"rb" => "Ruby", "html" => "HTML", "css" => "CSS", "erb" => "ERB", "c" => "C",
  "cpp" => "Cpp", "py" => "Python", "go" => "Go"}
types = %W(Base16 Colorful Github Gruvbox IgorPro Molokai Monokai MonokaiSublime Pastie ThankfulEyes Tulip)
type_num = 3

formatter = Rouge::Formatters::HTML.new

handle_dir = ->(dname) {
  dirs = []
  files = []
  Dir.chdir(dname)
  Dir.glob("*").sort.each do |fname|
    if File.directory?(fname)
      dirs << [fname, handle_dir.(fname)]
    else
      m = /\.(.*)/.match(fname)
      m = m ? m[1] : ""
      sf = suffixes[m] || "PlainText"
      lexer= eval("Rouge::Lexers::" + sf).new
      html = formatter.format(lexer.lex(File.read(fname))) rescue next
      files << [fname, html]
    end
  end
  Dir.chdir("..")
  {:dirs => dirs, :files => files}
}
sources = handle_dir.("user_codes")

get '/' do
  @sources = sources
  @css_types = types
  @type_num = type_num
  erb :index
end

post '/' do
  type_num = params[:css_style].to_i
  redirect '/'
end

make_page = ->(h, path) {
  h[:dirs].each {|d| make_page.(d[1], path + d[0] + '/')}
  h[:files].each do |f|
    get path + f[0] do
      @html = f[1]
      @css_name = types[type_num].downcase
      erb :render
    end
  end
}
make_page.(sources, "/")

 

ディレクトリ views 内

index.erb

<!DOCTYPE html>
<html lang="ja">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Code Viewer</title>
<head>
</head>
<body>

<h1>Code Viewer</h1>

<form method="post">
<p>CSS Style
 <select name="css_style">
<% @css_types.each_with_index do |ty, i| %>
<option value="<%= i %>"><%= ty %></option>
<% end %>
</select> <input type="submit" value="選択">
 <span style="color: blue;"><%= @css_types[@type_num] %></span></p>
</form>

<% def handle(h, path) %>
<ul>
  <% h[:dirs].each do |d| %>
<li><%= d[0] %></li>
    <% handle(d[1], path + '/' + d[0]) %>
  <% end %>
  <% h[:files].each do |f| %>
<li><a href="<%= path + '/' + f[0] %>" style="color: green;"><%= f[0] %></a></li>
  <% end %>
</ul>
<% end %>

<% handle(@sources, "") %>

</body>
</html>

render.erb

<!DOCTYPE html>
<html lang="ja">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Code Viewer</title>
<head>
<link rel="stylesheet" type="text/css" href="/css/<%= @css_name %>.css">
<style type="text/css">
pre.highlight {
  font-family: Courier New, Consolas, monospace;
  font-size: 100%;
  padding: 10px;
  line-height: 1.1em;
  white-space: pre-wrap;
}
</style>
</head>
<body>

<pre class="highlight">
<%= @html %>
</pre>

</body>
</html>