class MemoRack::Core
Constants
- DEFAULT_APP_OPTIONS
- DEFAULT_LOCALS
テンプレートで使用するローカル変数の初期値
- DEFAULT_OPTIONS
- DEFAULT_TEMPLATE_OPTIONS
テンプレートエンジンのオプション
Attributes
options_chain[R]
root[R]
suffix[R]
themes[R]
Public Class Methods
app()
click to toggle source
# File lib/memorack/core.rb, line 45 def self.app @@app end
new(options={})
click to toggle source
# File lib/memorack/core.rb, line 49 def initialize(options={}) @@app = self options = DEFAULT_OPTIONS.merge(to_sym_keys(options)) @themes_folders = [options[:themes_folder], folder(:themes, :user), folder(:themes)] @themes_folders.delete nil @themes_folders.reject! { |folder| ! File.directory?(folder) } read_config(options[:theme], options) read_config(DEFAULT_APP_OPTIONS[:theme], options) if @themes.empty? @options = options # DEFAULT_APP_OPTIONS に含まれるキーをすべてインスタンス変数に登録する DEFAULT_APP_OPTIONS.each { |key, item| instance_variable_set("@#{key}".to_sym, options[key]) # @options からテンプレートで使わないものを削除 @options.delete(key) } # プラグインの読込み load_plugins # ロケールの読込み I18n.load_path = @locale_paths I18n.backend.load_translations I18n.enforce_available_locales = false @requires.each { |lib| require lib } @locals = default_locals(@options) use_engine(@markdown) end
template(name, &block)
click to toggle source
テンプレートを作成する
# File lib/memorack/core.rb, line 668 def self.template(name, &block) define_method(self.template_method(name), &block) end
template_method(name)
click to toggle source
テンプレート名
# File lib/memorack/core.rb, line 663 def self.template_method(name) name.kind_of?(Symbol) && "template_#{name}".to_sym end
Public Instance Methods
add_config_chain(dir, theme = nil)
click to toggle source
設定ファイルのデータをチェインに追加
# File lib/memorack/core.rb, line 183 def add_config_chain(dir, theme = nil) # テーマ・チェインに追加 @themes << File.join(dir, '') if theme # config の読込み config = read_data(File.join(dir, 'config')) if config @options_chain << config theme = config[:theme] end # macro の読込み macro = read_data(File.join(dir, 'macro')) @macro_chain << macro if macro && macro.kind_of?(Hash) # locale の読込み @locale_paths += Dir[File.expand_path('locales/*.yml', dir)] theme end
collect_formats()
click to toggle source
対応フォーマットを取得する
# File lib/memorack/core.rb, line 618 def collect_formats unless @collect_formats @collect_formats = {} @formats.each { |item| if item.kind_of?(Array) @collect_formats[item.first] = item elsif item.kind_of?(Hash) @collect_formats.merge!(item) else @collect_formats[item] = extnames(item) end } end @collect_formats end
content_name(path)
click to toggle source
パスからコンテント名を取得する
# File lib/memorack/core.rb, line 652 def content_name(path) plugin = PageInfo[path] if plugin plugin.new(File.expand_path(path, @root))[:title] else File.basename(path, '.*') end end
contents(options = {})
click to toggle source
コンテンツファイルの収集する
# File lib/memorack/core.rb, line 642 def contents(options = {}) default_options = {prefix: '/', suffix: @suffix, uri_escape: true, formats: collect_formats} options = default_options.merge(options) mdmenu = MdMenu.new(options) Dir.chdir(@root) { |path| mdmenu.collection('.') } mdmenu end
css_exts()
click to toggle source
css の拡張子リストを作成する
# File lib/memorack/core.rb, line 280 def css_exts @css_exts ||= Set.new ['css', *@css] end
default_locals(locals = {})
click to toggle source
デフォルトの locals を生成する
# File lib/memorack/core.rb, line 117 def default_locals(locals = {}) locals = BaseLocals.new(self, locals) locals[:site] ||= @site locals end
embed_macro(hash, macro, options = {}, locals = hash)
click to toggle source
マクロを組込む
# File lib/memorack/core.rb, line 471 def embed_macro(hash, macro, options = {}, locals = hash) macro.each { |key, value| case value when Hash if hash[key].kind_of?(Array) embed_macro_for_array(hash[key], value, options, locals) else hash[key] = value_to_locals(hash[key]) embed_macro(hash[key], value, options, locals) end when Array hash[key] = [] unless hash[key] a = hash[key] if a.kind_of?(Array) value.each_with_index { |item, index| if item.kind_of?(Hash) a[index] = value_to_locals(a[index]) embed_macro(a[index], item, options, locals) else a[index] = item end } end else hash.define_key(key) { |hash, key| if value #render :mustache, value, {}, locals engine = Tilt.new('.mustache', {}) { value } engine.render({}, locals).force_encoding('UTF-8') end } end } end
embed_macro_for_array(array, macro, options = {}, locals)
click to toggle source
マクロを配列に組込む
# File lib/memorack/core.rb, line 509 def embed_macro_for_array(array, macro, options = {}, locals) array.each_with_index { |item, index| if item.kind_of?(Array) embed_macro_for_array(item, macro, options, locals) else array[index] = value_to_locals(item) embed_macro(array[index], macro, options) end } end
enable_exts()
click to toggle source
対応している拡張子
# File lib/memorack/core.rb, line 637 def enable_exts @enable_exts ||= collect_formats.values.flatten end
extnames(extname)
click to toggle source
Tilt
に登録されている拡張子を集める
# File lib/memorack/core.rb, line 601 def extnames(extname) klass = Tilt[extname] r = [] if Tilt.respond_to?(:mappings) r |= Tilt.mappings.select { |key, value| value.member?(klass) }.collect { |key, value| key } end if Tilt.respond_to?(:default_mapping) r |= Tilt.default_mapping.template_map.select { |key, value| value == klass }.collect { |key, value| key } r |= Tilt.default_mapping.lazy_map.select { |key, value| value.assoc(klass.to_s) }.collect { |key, value| key } end r end
file_search(template, options = {}, exts = enable_exts)
click to toggle source
ファイルを探す
# File lib/memorack/core.rb, line 308 def file_search(template, options = {}, exts = enable_exts) options = {views: @root}.merge(options) if options[:views].kind_of?(Array) err = nil options[:views].each { |views| options[:views] = views begin path = file_search(template, options, exts) return path if path rescue Errno::ENOENT => e err = e end } raise err if err return nil end dir = options[:views] dir = File.join(dir, options[:folder]) if options[:folder] if exts exts.each { |ext| path = File.join(dir, "#{template}.#{ext}") return path if File.exists?(path) } else path = File.join(dir, template) return path if File.exists?(path) end return nil end
folder(name, domain = :app)
click to toggle source
フォルダ(ディレクトリ)を取得する
# File lib/memorack/core.rb, line 86 def folder(name, domain = :app) @folders ||= {} @folders[domain] ||= {} unless @folders[domain][name] case domain when :user dir = File.join(ENV['HOME'], '.etc/memorack') when :app dir = File.dirname(__FILE__) else return nil end end @folders[domain][name] ||= File.expand_path(name.to_s, dir) end
load_plugin(name, path)
click to toggle source
プラグインファイルを読込む
# File lib/memorack/core.rb, line 240 def load_plugin(name, path) loaded = false if File.directory?(path) path = File.join(path, File.basename(path) + '.rb') if File.exists?(path) require_relative(path) loaded = true end elsif path =~ /\.rb$/ require_relative(File.expand_path(path)) loaded = true end if loaded @plugins << name end end
load_plugins()
click to toggle source
プラグインを読込む
# File lib/memorack/core.rb, line 230 def load_plugins plugins_folders.reverse.each { |folder| Dir.glob(File.join(folder, '*')) { |path| name = path.gsub(%r[^#{folder}/], '') load_plugin(name, path) } } end
pages()
click to toggle source
テーマから固定ページのファイルを収集する
# File lib/memorack/core.rb, line 285 def pages unless @pages @pages = {} @themes.each { |theme| folder = File.join(theme, 'pages/') if Dir.exists?(folder) Dir.chdir(folder) { |dir| Dir.glob(File.join('**/*')) { |path| path_info, ext = split_extname(path) path_info = File.join('', path_info) @pages[path_info] ||= File.expand_path(path) } } end } end @pages end
plugins_folders()
click to toggle source
プラグイン・フォルダを取得する
# File lib/memorack/core.rb, line 214 def plugins_folders unless @plugins_folders @plugins_folders = ['plugins/', folder(:plugins, :user), folder(:plugins)] @plugins_folders.delete nil @plugins_folders.reject! { |folder| ! File.directory?(folder) } @themes.each { |theme| path = File.join(theme, 'plugins/') @plugins_folders.unshift path if File.directory?(path) } end @plugins_folders end
read_config(theme, options = {})
click to toggle source
設定ファイルを読込む
# File lib/memorack/core.rb, line 149 def read_config(theme, options = {}) @themes ||= [] @options_chain = [] @locale_paths = [] @macro_chain = [] @macro = {} @plugins = Set.new begin require 'json' while theme dir = theme_path(theme) break unless dir break if @themes.member?(dir) # 設定ファイルのデータをチェインに追加 theme = add_config_chain(dir, theme) end rescue end # デフォルトの設定をチェインに追加 add_config_chain(File.expand_path('../config', __FILE__)) # マクロをマージ @macro_chain.reverse.each { |macro| @macro.merge!(macro) } # オプションをマージ @options_chain.reverse.each { |opts| options.merge!(opts) } options end
read_data(name, exts = ['json', 'yml', 'yaml'])
click to toggle source
json/yaml のデータを読込む
# File lib/memorack/core.rb, line 124 def read_data(name, exts = ['json', 'yml', 'yaml']) begin exts.each { |ext| path = [name, ext].join('.') if File.readable?(path) data = File.read(path) case ext when 'json' hash = JSON.parse(data) when 'yml', 'yaml' hash = YAML.load(data) end data = to_sym_keys(hash) if hash return data end } rescue end nil end
render(engine, template, options = {}, locals = {})
click to toggle source
テンプレートエンジンで render する
# File lib/memorack/core.rb, line 346 def render(engine, template, options = {}, locals = {}) options = {views: @root}.merge(options) if template.kind_of?(Pathname) path = template elsif options[:views].kind_of?(Array) err = nil options[:views].each { |views| options[:views] = views begin return render(engine, template, options, locals) rescue Errno::ENOENT => e err = e end } raise err else fname = template.kind_of?(String) ? template : "#{template}.#{engine}" path = File.join(options[:views], fname) end engine = Tilt.new(File.join(File.dirname(path), ".#{engine}"), options) { method = MemoApp.template_method(template) if method && respond_to?(method) data = send(method) else data = File.binread(path) data.force_encoding('UTF-8') end data } engine.render(options, locals).force_encoding('UTF-8') end
render_content(path_info, locals = {}, exts = enable_exts)
click to toggle source
コンテンツをレンダリングする
# File lib/memorack/core.rb, line 537 def render_content(path_info, locals = {}, exts = enable_exts) path = File.join(@root, path_info) if File.directory?(path) return render_with_mustache Pathname.new(path), nil, {}, locals end path, ext = split_extname(path_info) fullpath = file_search(path_info, @options, exts) if fullpath path = path_info ext = split_extname(fullpath)[1] end return nil unless ext && Tilt.registered?(ext) template = fullpath ? Pathname.new(fullpath) : path.to_sym content = render_with_mustache template, ext, {}, locals end
render_css(path_info, locals = {})
click to toggle source
CSSをレンダリングする
# File lib/memorack/core.rb, line 560 def render_css(path_info, locals = {}) return unless @css path, = split_extname(path_info) options = {views: @themes} fullpath = file_search(path, options, css_exts) return nil unless fullpath ext = split_extname(fullpath)[1] case ext when 'css' return File.binread(fullpath) when 'scss', 'sass' options[:cache_location] = File.expand_path('sass-cache', @tmpdir) end render ext, Pathname.new(fullpath), options, locals end
render_page(path_info, locals = {})
click to toggle source
固定ページをレンダリングする
# File lib/memorack/core.rb, line 527 def render_page(path_info, locals = {}) path_info = path_info.gsub(%r[(/|.html)$], '') path = pages[path_info] return nil unless path ext = split_extname(path)[1] content = render_with_mustache Pathname.new(path), ext, {}, locals end
render_with_mustache(template, engine = :markdown, options = {}, locals = {})
click to toggle source
レイアウトに mustache を適用してテンプレートエンジンでレンダリングする
# File lib/memorack/core.rb, line 386 def render_with_mustache(template, engine = :markdown, options = {}, locals = {}) begin mustache_templ = [] mustache_templ << options[:mustache] if options[:mustache] options = @options.merge(options) locals = @locals.merge(locals) locals.define_key(:__content__) { |hash, key| if engine render engine, template, options elsif locals[:directory?] # ディレクトリ nil else template end } locals[:directory?] = true if template.kind_of?(Pathname) && template.directory? locals[:content?] = true unless template == :index || locals[:directory?] locals[:page] = page = Locals[locals[:page] || {}] if template.kind_of?(Pathname) path = template.to_s plugin = PageInfo[path] locals[:page] = page = plugin.new(path, page, locals) if plugin end page.define_key(:name) { |hash, key| if hash.kind_of?(PageInfo) hash.value(:title) elsif template != :index fname = locals[:path_info] fname ||= template.to_s.force_encoding('UTF-8') File.basename(fname) end } # マクロを組込む embed_macro(locals, @macro) # HTMLページをレンダリングする if engine && engine.to_sym == :html unless template.kind_of?(Pathname) path = file_search(template, @options, [engine]) return nil unless path template = Pathname.new(path) end locals.define_key(:__content__) { |hash, key| } return render :mustache, template, {views: @themes}, locals end mustache_templ << 'page.html' if locals[:content?] mustache_templ << 'index.html' mustache_templ.each { |templ| path = file_search(templ, {views: @themes}, nil) next unless path path = Pathname.new(path) return render :mustache, path, {views: @themes}, locals } raise "Not found template #{mustache_templ}" rescue => e e.to_s end end
require_plugin(plugin)
click to toggle source
プラグインを読込む(読込み済みのものは読込まない)
# File lib/memorack/core.rb, line 261 def require_plugin(plugin) return if @plugins.include?(plugin) plugins_folders.reverse.each { |folder| path = File.join(folder, plugin) load_plugin(folder, path) if File.exist?(path) load_plugin(folder, path + '.rb') if File.exist?(path + '.rb') } end
split_extname(path)
click to toggle source
拡張子を取出す
# File lib/memorack/core.rb, line 582 def split_extname(path) return [$1, $2] if /^(.+)\.([^.]+)/ =~ path [path] end
theme_path(theme)
click to toggle source
テーマのパスを取得する
# File lib/memorack/core.rb, line 105 def theme_path(theme) return nil unless theme @themes_folders.each { |folder| path = theme && File.join(folder, theme) return path if File.exists?(path) && File.directory?(path) } nil end
to_sym_keys(hash)
click to toggle source
キーをシンボルに変換する
# File lib/memorack/core.rb, line 589 def to_sym_keys(hash) hash.inject({}) { |memo, entry| key, value = entry value = to_sym_keys(value) if value.kind_of?(Hash) memo[key.to_sym] = value memo } end
update_locale(env = ENV)
click to toggle source
locale を env情報で更新する
# File lib/memorack/core.rb, line 206 def update_locale(env = ENV) locale ||= env['HTTP_ACCEPT_LANGUAGE'] locale ||= env['LANG'] if env['LANG'] locale = locale[0, 2].to_sym if locale I18n.locale = locale if I18n.available_locales.include?(locale) end
use_engine(engine)
click to toggle source
テンプレートエンジンを使用できるようにする
# File lib/memorack/core.rb, line 272 def use_engine(engine) require engine if engine # Tilt で Redcarpet 2.x を使うためのおまじない Object.send(:remove_const, :RedcarpetCompat) if defined?(RedcarpetCompat) == 'constant' end
value_to_locals(value)
click to toggle source
Localsクラス 変換する
# File lib/memorack/core.rb, line 458 def value_to_locals(value) case value when Locals when Hash value = Locals[value] else value = Locals[] end value end