module StaticCms require 'fileutils' require 'ruby_patch' require 'static_cms/version' require 'static_cms/patch' SITE_TEMPLATE_DIR = File.join(__DIR__, '../data/site_template') module Command def self.init(dir = '.') FileUtils.mkdir_p(dir) success = false FileUtils.cd(dir){|dir| success = system <<-EOS git init > #{File::NULL} git commit --allow-empty -m 'Empty commit.' > #{File::NULL} cp -r #{File.join(SITE_TEMPLATE_DIR, '*')} . > #{File::NULL} git add . > #{File::NULL} git commit -m 'Copied from site template.' > #{File::NULL} EOS } success end def self.update site_template_dir = File.join(__DIR__, '../data/site_template') FileUtils.cp_r(File.join(site_template_dir, 'templates'), '.') FileUtils.cp_r(File.join(site_template_dir, 'sources'), '.') FileUtils.cp_r(File.join(site_template_dir, 'statics'), '.') FileUtils.cp(File.join(site_template_dir, 'rakefile'), '.') end end class Site require 'yaml' CONFIG_DEFAULT = { 'lang' => 'en', 'www' => nil, 'dir' => File.join(__DIR__, 'root'), 'author' => '', 'robots' => 'noarchive', 'favicon' => 'images/favicon.png', 'charset' => 'utf-8', } attr_accessor :pages attr_accessor *(CONFIG_DEFAULT.keys) def initialize config = CONFIG_DEFAULT.merge(YAML.load_file('config.yaml')) @www = config.delete('www') @www += '/' unless @www[-1] == '/' config.each{|k, v| instance_variable_set("@#{k}", v)} @pages = YAML.load_file('pages.yaml')\ .to_a.map{|name, params| ::StaticCms::Page.new(self, name, params)} end end class Page require 'fileutils' require 'haml' PARAMS_DEFAULT ={ 'visible' => true, 'title' => '', 'template' => 'default', 'articles' => [], 'statics' => [], 'sources' => [], 'base' => nil, } attr_accessor :site, :name, :dir attr_accessor *(PARAMS_DEFAULT.keys) def initialize(site, name, params = {}) @site = site @name = name @dir = File.join("root", @name) params = PARAMS_DEFAULT.merge(params) @template = File.join('templates', params.delete('template')) + '.html.haml' @articles = params.delete('articles').map{|name| ::StaticCms::Article.use(self, name)} @statics = params.delete('statics').map{|file| File.join('statics', file)} @sources = params.delete('sources').map{|file| File.join('sources', file)} @base = params.delete('base') || @site.www params.each{|k, v| instance_variable_set("@#{k}", v) } end def generate FileUtils.mkdir_p(@dir) if @visible @statics.each{|file| cp_if_new(file)} @sources.each{|file| compile(file)} template = @template else @statics.each{|file| FileUtils.rm_rf(static_target(file))} @sources.each{|file| FileUtils.rm_rf(compile_target(file))} template = 'templates/moved.html.haml' end html = ::Haml::Engine.new(File.read(template)).render(self) target = File.join(@dir, 'index.html') open(target, 'w'){|io| io.write(html) io.flush io.fsync } end private def haml(text) ::Haml::Engine.new(text).render(self) end def link_to_article(name) article = ::StaticCms::Article.alist[name] page = article.pages.first url = File.join(@site.www, page.name, "index.html\##{name}") "#{article.title}" end def cp_if_new(source) target = static_target(source) if !File.file?(target) || File.mtime(source) > File.mtime(target) FileUtils.cp(source, target) FileUtils.chmod(0644, target) end end def compile(source) ext = File.extname(source) target = compile_target(source) case ext when /\A\.sass\z/ system "sass #{source} > #{target}" else raise NotImplementedError, file end end def static_target(source) File.join(@dir, File.basename(source)) end def compile_target(source) ext = File.extname(source) File.join(@dir, File.basename(source, ext)) end end module Helpers require 'haml' EXT_TO_LANG = Hash.new(:general)\ .merge({ '.f90' => :fortran, '.f95' => :fortran, '.f03' => :fortran, '.f08' => :fortran, '.f' => :fortran, '.f77' => :fortran, '.rb' => :ruby, }) module_function def to_plain(text) escaped_text = ::Haml::Helpers.html_escape(text) ::Haml::Helpers.preserve(escaped_text) end def to_code(text, lang = :general) pre_text = to_plain(text) "
#{pre_text}
" end end class Article @alist = Hash.new{|h, k| raise KeyError, k.to_s} def self.alist @alist end PARAMS_DEFAULT = { 'title' => '', } attr_accessor :pages, :name, :file, :data attr_accessor *(PARAMS_DEFAULT.keys) def initialize(name) @pages = [] @name = name @file = File.join('articles', name) + '.html.yhaml' yaml, @data = File.read(@file).split(/^\.\.\.$/, 2) params = PARAMS_DEFAULT.merge(YAML.load(yaml)) params.each{|k, v| instance_variable_set("@#{k}", v)} self.class.alist[@name] = self end def self.load `git ls-files articles`.split\ .select{|f| f =~ /\.html\.yhaml\z/}\ .map{|f| f.sub(/\Aarticles\//, '')}\ .map{|f| File.basename(f, '.html.yhaml')}\ .each{|name| self.new(name)} end def self.use(page, name) self.load unless self.alist.has_key?(name) raise ArgumentError, name unless self.alist.has_key?(name) article = self.alist[name] article.pages << page article end end require 'thor' class Runner < Thor desc "init [DIR]", "Initialize DIR directory for StaticCms [default: .]." def init(dir = '.') ::StaticCms::Command.init(dir) end end end