Class: MemoRack::Core
- Inherits:
-
Object
- Object
- MemoRack::Core
- Defined in:
- lib/memorack/core.rb
Constant Summary collapse
- DEFAULT_APP_OPTIONS =
{ root: 'content/', themes_folder: 'themes/', tmpdir: 'tmp/', theme: 'oreilly', markdown: 'redcarpet', formats: ['markdown'], css: nil, suffix: '', public: [], site: {}, requires: [], directory_watcher: false }
- DEFAULT_TEMPLATE_OPTIONS =
テンプレートエンジンのオプション
{ tables: true }
- DEFAULT_LOCALS =
テンプレートで使用するローカル変数の初期値
{ title: 'memo' }
- DEFAULT_OPTIONS =
DEFAULT_APP_OPTIONS.merge(DEFAULT_TEMPLATE_OPTIONS).merge(DEFAULT_LOCALS)
Instance Attribute Summary collapse
-
#options_chain ⇒ Object
readonly
Returns the value of attribute options_chain.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#suffix ⇒ Object
readonly
Returns the value of attribute suffix.
-
#themes ⇒ Object
readonly
Returns the value of attribute themes.
Class Method Summary collapse
- .app ⇒ Object
-
.template(name, &block) ⇒ Object
テンプレートを作成する.
-
.template_method(name) ⇒ Object
テンプレート名.
Instance Method Summary collapse
-
#add_config_chain(dir, theme = nil) ⇒ Object
設定ファイルのデータをチェインに追加.
-
#collect_formats ⇒ Object
対応フォーマットを取得する.
-
#content_name(path) ⇒ Object
パスからコンテント名を取得する.
-
#contents(options = {}) ⇒ Object
コンテンツファイルの収集する.
-
#css_exts ⇒ Object
css の拡張子リストを作成する.
-
#default_locals(locals = {}) ⇒ Object
デフォルトの locals を生成する.
-
#embed_macro(hash, macro, options = {}, locals = hash) ⇒ Object
マクロを組込む.
-
#embed_macro_for_array(array, macro, options = {}, locals) ⇒ Object
マクロを配列に組込む.
-
#enable_exts ⇒ Object
対応している拡張子.
-
#extnames(extname) ⇒ Object
Tilt に登録されている拡張子を集める.
-
#file_search(template, options = {}, exts = enable_exts) ⇒ Object
ファイルを探す.
-
#folder(name, domain = :app) ⇒ Object
フォルダ(ディレクトリ)を取得する.
-
#initialize(options = {}) ⇒ Core
constructor
A new instance of Core.
-
#load_plugin(name, path) ⇒ Object
プラグインファイルを読込む.
-
#load_plugins ⇒ Object
プラグインを読込む.
-
#pages ⇒ Object
テーマから固定ページのファイルを収集する.
-
#plugins_folders ⇒ Object
プラグイン・フォルダを取得する.
-
#read_config(theme, options = {}) ⇒ Object
設定ファイルを読込む.
-
#read_data(name, exts = ['json', 'yml', 'yaml']) ⇒ Object
json/yaml のデータを読込む.
-
#render(engine, template, options = {}, locals = {}) ⇒ Object
テンプレートエンジンで render する.
-
#render_content(path_info, locals = {}, exts = enable_exts) ⇒ Object
コンテンツをレンダリングする.
-
#render_css(path_info, locals = {}) ⇒ Object
CSSをレンダリングする.
-
#render_menu ⇒ Object
メニューをレンダリングする.
-
#render_page(path_info, locals = {}) ⇒ Object
固定ページをレンダリングする.
-
#render_with_mustache(template, engine = :markdown, options = {}, locals = {}) ⇒ Object
レイアウトに mustache を適用してテンプレートエンジンでレンダリングする.
-
#require_plugin(plugin) ⇒ Object
プラグインを読込む(読込み済みのものは読込まない).
-
#split_extname(path) ⇒ Object
拡張子を取出す.
-
#theme_path(theme) ⇒ Object
テーマのパスを取得する.
-
#to_sym_keys(hash) ⇒ Object
キーをシンボルに変換する.
-
#update_locale(env = ENV) ⇒ Object
locale を env情報で更新する.
-
#use_engine(engine) ⇒ Object
テンプレートエンジンを使用できるようにする.
-
#value_to_locals(value) ⇒ Object
Localsクラス 変換する.
Constructor Details
#initialize(options = {}) ⇒ Core
Returns a new instance of Core.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/memorack/core.rb', line 50 def initialize(={}) @@app = self = DEFAULT_OPTIONS.merge(to_sym_keys()) @themes_folders = [[:themes_folder], folder(:themes, :user), folder(:themes)] @themes_folders.delete nil @themes_folders.reject! { |folder| ! File.directory?(folder) } read_config([:theme], ) read_config(DEFAULT_APP_OPTIONS[:theme], ) if @themes.empty? @options = # DEFAULT_APP_OPTIONS に含まれるキーをすべてインスタンス変数に登録する DEFAULT_APP_OPTIONS.each { |key, item| instance_variable_set("@#{key}".to_sym, [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 |
Instance Attribute Details
#options_chain ⇒ Object (readonly)
Returns the value of attribute options_chain.
17 18 19 |
# File 'lib/memorack/core.rb', line 17 def @options_chain end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
17 18 19 |
# File 'lib/memorack/core.rb', line 17 def root @root end |
#suffix ⇒ Object (readonly)
Returns the value of attribute suffix.
17 18 19 |
# File 'lib/memorack/core.rb', line 17 def suffix @suffix end |
#themes ⇒ Object (readonly)
Returns the value of attribute themes.
17 18 19 |
# File 'lib/memorack/core.rb', line 17 def themes @themes end |
Class Method Details
.app ⇒ Object
46 47 48 |
# File 'lib/memorack/core.rb', line 46 def self.app @@app end |
.template(name, &block) ⇒ Object
テンプレートを作成する
669 670 671 |
# File 'lib/memorack/core.rb', line 669 def self.template(name, &block) define_method(self.template_method(name), &block) end |
.template_method(name) ⇒ Object
テンプレート名
664 665 666 |
# File 'lib/memorack/core.rb', line 664 def self.template_method(name) name.kind_of?(Symbol) && "template_#{name}".to_sym end |
Instance Method Details
#add_config_chain(dir, theme = nil) ⇒ Object
設定ファイルのデータをチェインに追加
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/memorack/core.rb', line 184 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.('locales/*.yml', dir)] theme end |
#collect_formats ⇒ Object
対応フォーマットを取得する
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
# File 'lib/memorack/core.rb', line 619 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) ⇒ Object
パスからコンテント名を取得する
653 654 655 656 657 658 659 660 661 |
# File 'lib/memorack/core.rb', line 653 def content_name(path) plugin = PageInfo[path] if plugin plugin.new(File.(path, @root))[:title] else File.basename(path, '.*') end end |
#contents(options = {}) ⇒ Object
コンテンツファイルの収集する
643 644 645 646 647 648 649 650 |
# File 'lib/memorack/core.rb', line 643 def contents( = {}) = {prefix: '/', suffix: @suffix, uri_escape: true, formats: collect_formats} = .merge() = MdMenu.new() Dir.chdir(@root) { |path| .collection('.') } end |
#css_exts ⇒ Object
css の拡張子リストを作成する
281 282 283 |
# File 'lib/memorack/core.rb', line 281 def css_exts @css_exts ||= Set.new ['css', *@css] end |
#default_locals(locals = {}) ⇒ Object
デフォルトの locals を生成する
118 119 120 121 122 |
# File 'lib/memorack/core.rb', line 118 def default_locals(locals = {}) locals = BaseLocals.new(self, locals) locals[:site] ||= @site locals end |
#embed_macro(hash, macro, options = {}, locals = hash) ⇒ Object
マクロを組込む
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 |
# File 'lib/memorack/core.rb', line 472 def (hash, macro, = {}, locals = hash) macro.each { |key, value| case value when Hash if hash[key].kind_of?(Array) (hash[key], value, , locals) else hash[key] = value_to_locals(hash[key]) (hash[key], value, , 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]) (a[index], item, , 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) ⇒ Object
マクロを配列に組込む
510 511 512 513 514 515 516 517 518 519 |
# File 'lib/memorack/core.rb', line 510 def (array, macro, = {}, locals) array.each_with_index { |item, index| if item.kind_of?(Array) (item, macro, , locals) else array[index] = value_to_locals(item) (array[index], macro, ) end } end |
#enable_exts ⇒ Object
対応している拡張子
638 639 640 |
# File 'lib/memorack/core.rb', line 638 def enable_exts @enable_exts ||= collect_formats.values.flatten end |
#extnames(extname) ⇒ Object
Tilt に登録されている拡張子を集める
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
# File 'lib/memorack/core.rb', line 602 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) ⇒ Object
ファイルを探す
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/memorack/core.rb', line 309 def file_search(template, = {}, exts = enable_exts) = {views: @root}.merge() if [:views].kind_of?(Array) err = nil [:views].each { |views| [:views] = views begin path = file_search(template, , exts) return path if path rescue Errno::ENOENT => e err = e end } raise err if err return nil end dir = [:views] dir = File.join(dir, [:folder]) if [: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) ⇒ Object
フォルダ(ディレクトリ)を取得する
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/memorack/core.rb', line 87 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.(name.to_s, dir) end |
#load_plugin(name, path) ⇒ Object
プラグインファイルを読込む
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/memorack/core.rb', line 241 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.(path)) loaded = true end if loaded @plugins << name end end |
#load_plugins ⇒ Object
プラグインを読込む
231 232 233 234 235 236 237 238 |
# File 'lib/memorack/core.rb', line 231 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 ⇒ Object
テーマから固定ページのファイルを収集する
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/memorack/core.rb', line 286 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.(path) } } end } end @pages end |
#plugins_folders ⇒ Object
プラグイン・フォルダを取得する
215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/memorack/core.rb', line 215 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 = {}) ⇒ Object
設定ファイルを読込む
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/memorack/core.rb', line 150 def read_config(theme, = {}) @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.('../config', __FILE__)) # マクロをマージ @macro_chain.reverse.each { |macro| @macro.merge!(macro) } # オプションをマージ @options_chain.reverse.each { |opts| .merge!(opts) } end |
#read_data(name, exts = ['json', 'yml', 'yaml']) ⇒ Object
json/yaml のデータを読込む
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/memorack/core.rb', line 125 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 = {}) ⇒ Object
テンプレートエンジンで render する
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/memorack/core.rb', line 347 def render(engine, template, = {}, locals = {}) = {views: @root}.merge() if template.kind_of?(Pathname) path = template elsif [:views].kind_of?(Array) err = nil [:views].each { |views| [:views] = views begin return render(engine, template, , locals) rescue Errno::ENOENT => e err = e end } raise err else fname = template.kind_of?(String) ? template : "#{template}.#{engine}" path = File.join([:views], fname) end engine = Tilt.new(File.join(File.dirname(path), ".#{engine}"), ) { 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(, locals).force_encoding('UTF-8') end |
#render_content(path_info, locals = {}, exts = enable_exts) ⇒ Object
コンテンツをレンダリングする
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
# File 'lib/memorack/core.rb', line 538 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 = {}) ⇒ Object
CSSをレンダリングする
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
# File 'lib/memorack/core.rb', line 561 def render_css(path_info, locals = {}) return unless @css path, = split_extname(path_info) = {views: @themes} fullpath = file_search(path, , css_exts) return nil unless fullpath ext = split_extname(fullpath)[1] case ext when 'css' return File.binread(fullpath) when 'scss', 'sass' [:cache_location] = File.('sass-cache', @tmpdir) end render ext, Pathname.new(fullpath), , locals end |
#render_menu ⇒ Object
メニューをレンダリングする
522 523 524 525 |
# File 'lib/memorack/core.rb', line 522 def @menu = nil unless @directory_watcher # ファイル監視していない場合はメニューを初期化 @menu ||= render :markdown, :menu, @options end |
#render_page(path_info, locals = {}) ⇒ Object
固定ページをレンダリングする
528 529 530 531 532 533 534 535 |
# File 'lib/memorack/core.rb', line 528 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 = {}) ⇒ Object
レイアウトに mustache を適用してテンプレートエンジンでレンダリングする
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 |
# File 'lib/memorack/core.rb', line 387 def render_with_mustache(template, engine = :markdown, = {}, locals = {}) begin mustache_templ = [] mustache_templ << [:mustache] if [:mustache] = @options.merge() locals = @locals.merge(locals) locals.define_key(:__content__) { |hash, key| if engine render engine, template, 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 } # マクロを組込む (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) ⇒ Object
プラグインを読込む(読込み済みのものは読込まない)
262 263 264 265 266 267 268 269 270 |
# File 'lib/memorack/core.rb', line 262 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) ⇒ Object
拡張子を取出す
583 584 585 586 587 |
# File 'lib/memorack/core.rb', line 583 def split_extname(path) return [$1, $2] if /^(.+)\.([^.]+)/ =~ path [path] end |
#theme_path(theme) ⇒ Object
テーマのパスを取得する
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/memorack/core.rb', line 106 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) ⇒ Object
キーをシンボルに変換する
590 591 592 593 594 595 596 597 598 599 |
# File 'lib/memorack/core.rb', line 590 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) ⇒ Object
locale を env情報で更新する
207 208 209 210 211 212 |
# File 'lib/memorack/core.rb', line 207 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) ⇒ Object
テンプレートエンジンを使用できるようにする
273 274 275 276 277 278 |
# File 'lib/memorack/core.rb', line 273 def use_engine(engine) require engine if engine # Tilt で Redcarpet 2.x を使うためのおまじない Object.send(:remove_const, :RedcarpetCompat) if defined?(RedcarpetCompat) == 'constant' end |