memorack 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e66f5b1c38568ebc3011b2210c3b890fa0a8e36
4
- data.tar.gz: 006b12c2a64d34170e3a7f3b1543c1dd61120222
3
+ metadata.gz: 86c45efe555619b9ccb0baf170a9ec452f0fa52e
4
+ data.tar.gz: b012723ff47cef6d9887501fd28c88d3d6a5fcfc
5
5
  SHA512:
6
- metadata.gz: e6e4612436e39a618a59681f0db052f8069a05eb1d332ab754fddfc0cc4ba2371981ab77bf2e42f328d5f55e2025180ce73f0ad9d7370d4bb9bc28d65b3dfe81
7
- data.tar.gz: 44cfe752ef03701a381582aa26a1020320a161eb061b06b1d6c2a5864f901dca55c145056b3ad12b395e655e12247eb99995ac378b242e8cdf63065e5c9612e8
6
+ metadata.gz: 5ca5bf21735546d0371a71efebad1c902b869283495a26b4c276442e0cb949169ddafd894479590c3d77bebf5c82479a9548346607f1f9321301a9e6f6390c21
7
+ data.tar.gz: dbfa869e5a135c9d5244d7b92cb65aab7634786b8a0361c643e2b9039de285074ab65f88834f60a3396d8a58013da548bf82c00517bb07c0d3d5ac0fad560f5b
data/HISTORY.md CHANGED
@@ -1,5 +1,20 @@
1
1
  ## History
2
2
 
3
+ ### v0.2.0 / 2013-05-12
4
+
5
+ * plugin
6
+ * macro
7
+ * pages
8
+ * add `page.html` for content template
9
+ * support user domain themes/plugins folder (ex. `~/.etc/memorack/themes/`)
10
+ * yaml support for configuration (ex. `config.yml`)
11
+ * page title from content headline (markdown/org only)
12
+ * page title from locale (pages)
13
+ * page created/modified time
14
+ * to optional path of server subcommand (default: `content`)
15
+ * add option `--index` of build subcommand
16
+ * change default values
17
+
3
18
  ### v0.1.2 / 2013-05-06
4
19
 
5
20
  * build not remove .git/.hg/.svn/.cvs direcotry
data/README.md CHANGED
@@ -22,8 +22,8 @@ Or install it yourself as:
22
22
  $ memorack theme # Show theme list
23
23
  $ memorack theme THEME # Show theme info
24
24
  $ memorack theme -c THEME # Copy theme
25
- $ memorack server PATH # Instant Server
26
- $ memorack build [PATH] # Build static site
25
+ $ memorack server [PATH] # Instant Server
26
+ $ memorack build [PATH] # Build static site
27
27
 
28
28
  Standard startup
29
29
 
@@ -67,12 +67,16 @@ Template
67
67
  ├── .powenv -- for pow + rbenv
68
68
  ├── Gemfile -- `bundle install`
69
69
  ├── config.ru -- for rack application
70
- ├── content -- Content directory for memo
70
+ ├── content/ -- Content directory for memo
71
71
  │   └── README.md -- Sample file(remove it)
72
- └── themes
73
- └── custom -- Default theme
72
+ ├── plugins/ -- Plugins directory
73
+ └── themes/
74
+ └── custom/ -- Default theme
74
75
  ├── config.json -- Configuration
75
- └── index.md -- Description(Show by top page)
76
+ ├── index.md -- Description(Show by top page)
77
+ ├── locales/ -- Locales directory
78
+ ├── macro.yml -- Macro
79
+ └── pages/ -- Pages directory
76
80
 
77
81
  ## Customization
78
82
 
@@ -87,18 +91,18 @@ Template
87
91
 
88
92
  Directory
89
93
 
90
- └── themes
91
- └── custom
94
+ └── themes/
95
+ └── custom/
92
96
  ├── config.json
93
97
  ├── index.html <-- Edit layout
94
98
  └── index.md
95
99
 
96
100
  ### Logo
97
101
 
98
- └── themes
99
- └── custom
102
+ └── themes/
103
+ └── custom/
100
104
  ├── config.json <-- Add "logo": "/img/logo.png"
101
- ├── img
105
+ ├── img/
102
106
  │ └── logo.png <-- Add image file
103
107
  ├── index.html <-- Add <img id="logo" src="{{logo}}" />
104
108
  └── index.md
@@ -107,8 +111,8 @@ Directory
107
111
 
108
112
  Download [highlight.js](http://softwaremaniacs.org/soft/highlight/en/)
109
113
 
110
- └── themes
111
- └── custom
114
+ └── themes/
115
+ └── custom/
112
116
  ├── config.json
113
117
  ├── highlight.js <-- `unzip highlight.zip`
114
118
  ├── index.html <-- Add code
@@ -130,7 +134,6 @@ Edit `config.json`
130
134
 
131
135
  {
132
136
  "formats": ["markdown", "org"],
133
- "requires": ["org-ruby"],
134
137
  ...
135
138
  }
136
139
 
@@ -156,7 +159,6 @@ Special variables -- `{{{VAR}}}`
156
159
  * Template comments translate english
157
160
  * Add customizing tips
158
161
  * More test program
159
- * Plugin
160
162
  * Generate EPUB3
161
163
 
162
164
  ## Contributing
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -15,6 +15,7 @@ module MemoRack
15
15
  prefix: '/',
16
16
  suffix: '.html',
17
17
  uri_escape: true,
18
+ env: ENV,
18
19
  }
19
20
 
20
21
  DEFAULT_KEEPS = ['.git', '.hg', '.svn', '.csv']
@@ -25,12 +26,18 @@ module MemoRack
25
26
 
26
27
  url = @site[:url]
27
28
  options[:prefix] = File.join(url, options[:prefix]) unless url.empty?
29
+ @suffix = options[:suffix]
28
30
 
29
31
  output = File.expand_path(options[:output])
30
32
  dir_init(output, keeps)
31
33
 
32
34
  @contents = contents(options)
33
35
  @templates = Set.new @contents.files.collect { |file| file[:path] }
36
+ @directories = Set.new @templates.collect { |path| File.dirname(path) }
37
+ @directories.delete('.')
38
+
39
+ # ロケールの更新
40
+ update_locale(options[:env])
34
41
 
35
42
  # トップページを作成する
36
43
  content_write(:index, '.html', output) { |template|
@@ -40,12 +47,24 @@ module MemoRack
40
47
  suffix = options[:suffix]
41
48
  suffix = '/index.html' if ['', '/'].member?(suffix)
42
49
 
50
+ # サブディレクトリの index.html を出力する
51
+ build_index(@directories, output, &callback) if options[:index] || @options[:index]
52
+
53
+ # 固定ページのレンダリングを行う
54
+ pages.each { |path_info, path|
55
+ callback.call(path_info) if callback
56
+
57
+ content_write(path_info, suffix, output) { |template|
58
+ render_page template, {path_info: path_info}
59
+ }
60
+ }
61
+
43
62
  # コンテンツのレンダリングを行う
44
63
  @templates.each { |path|
45
64
  callback.call(path) if callback
46
65
 
47
66
  content_write(path, suffix, output) { |template|
48
- render_content(template)
67
+ render_content template, {path_info: path}, nil
49
68
  }
50
69
  }
51
70
 
@@ -157,6 +176,21 @@ module MemoRack
157
176
  }
158
177
  end
159
178
 
179
+ # サブディレクトリの index.html を出力する
180
+ def build_index(directories, output, &callback)
181
+ # . は取除く
182
+ directories.delete('.')
183
+
184
+ # index.html を出力する
185
+ directories.each { |path|
186
+ callback.call(path) if callback
187
+
188
+ content_write(path, '/index.html', output) { |template|
189
+ render_content template, {path_info: path}, nil
190
+ }
191
+ }
192
+ end
193
+
160
194
  #### テンプレート
161
195
 
162
196
  # インデックスを作成
@@ -170,7 +204,7 @@ module MemoRack
170
204
 
171
205
  # メニューを作成
172
206
  template :menu do
173
- @contents.generate(StringIO.new).string
207
+ @contents.generate(StringIO.new, &method(:content_name).to_proc).string
174
208
  end
175
209
 
176
210
  end
@@ -27,7 +27,7 @@ module MemoRack
27
27
  opts.banner = <<-BANNER.gsub(/^\t+/,'')
28
28
  Usage: #{opts.program_name} create [options] PATH
29
29
  #{opts.program_name} theme [options] [THEME]
30
- #{opts.program_name} server [options] PATH
30
+ #{opts.program_name} server [options] [PATH]
31
31
  #{opts.program_name} build [options] [PATH]
32
32
  BANNER
33
33
 
@@ -150,9 +150,9 @@ module MemoRack
150
150
  }
151
151
 
152
152
  # サーバーの実行
153
- define_options(:server, '[options] PATH') { |opts, argv, options|
153
+ define_options(:server, '[options] [PATH]') { |opts, argv, options|
154
154
  default_options = {
155
- theme: 'oreilly',
155
+ theme: 'custom',
156
156
 
157
157
  server: {
158
158
  environment: ENV['RACK_ENV'] || 'development',
@@ -172,7 +172,6 @@ module MemoRack
172
172
  opts.on("-h", "--help", t(:help)) { abort opts.help }
173
173
 
174
174
  opts.parse!(argv)
175
- abort opts.help if argv.empty?
176
175
  }
177
176
 
178
177
  # 静的サイトのビルド
@@ -184,6 +183,7 @@ module MemoRack
184
183
 
185
184
  local: false,
186
185
  prettify: false,
186
+ index: false,
187
187
  }
188
188
 
189
189
  options.merge!(default_options)
@@ -199,6 +199,8 @@ module MemoRack
199
199
  t(:local)) { options[:local] = true }
200
200
  opts.on("--prettify",
201
201
  t(:prettify)) { options[:prettify] = true }
202
+ opts.on("--index",
203
+ t(:index)) { options[:index] = true }
202
204
  opts.on("-h", "--help", t(:help)) { abort opts.help }
203
205
 
204
206
  opts.parse!(argv)
@@ -271,7 +273,8 @@ module MemoRack
271
273
 
272
274
  # サーバーの実行
273
275
  def memorack_server(options, *argv)
274
- path = argv.shift
276
+ path ||= argv.shift
277
+ path ||= 'content'
275
278
  abort "Directory not exists '#{path}'" unless File.exists?(path)
276
279
  abort "Not directory '#{path}'" unless File.directory?(path)
277
280
 
@@ -0,0 +1,2 @@
1
+ page:
2
+ title: '{{#content?}}{{page.name}} | {{/content?}}{{title}}'
@@ -1,21 +1,25 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
+ require 'yaml'
3
4
  require 'pathname'
4
5
  require 'rubygems'
6
+ require 'i18n'
5
7
 
6
8
  require 'memorack/tilt-mustache'
7
- require 'memorack/locals'
8
9
  require 'memorack/mdmenu'
10
+ require 'memorack/locals'
11
+ require 'memorack/locals/base'
12
+
9
13
 
10
14
  module MemoRack
11
15
  class Core
12
- attr_reader :themes, :options_chain
16
+ attr_reader :themes, :options_chain, :suffix, :root
13
17
 
14
18
  DEFAULT_APP_OPTIONS = {
15
19
  root: 'content/',
16
20
  themes_folder: 'themes/',
17
21
  tmpdir: 'tmp/',
18
- theme: 'basic',
22
+ theme: 'oreilly',
19
23
  markdown: 'redcarpet',
20
24
  formats: ['markdown'],
21
25
  css: nil,
@@ -38,10 +42,19 @@ module MemoRack
38
42
 
39
43
  DEFAULT_OPTIONS = DEFAULT_APP_OPTIONS.merge(DEFAULT_TEMPLATE_OPTIONS).merge(DEFAULT_LOCALS)
40
44
 
45
+ def self.app
46
+ @@app
47
+ end
48
+
41
49
  def initialize(options={})
50
+ @@app = self
51
+
42
52
  options = DEFAULT_OPTIONS.merge(to_sym_keys(options))
43
53
 
44
- @themes_folders = [options[:themes_folder], File.expand_path('../themes/', __FILE__)]
54
+ @themes_folders = [options[:themes_folder], folder(:themes, :user), folder(:themes)]
55
+ @themes_folders.delete nil
56
+ @themes_folders.reject! { |folder| ! File.directory?(folder) }
57
+
45
58
  read_config(options[:theme], options)
46
59
  read_config(DEFAULT_APP_OPTIONS[:theme], options) if @themes.empty?
47
60
 
@@ -55,12 +68,38 @@ module MemoRack
55
68
  @options.delete(key)
56
69
  }
57
70
 
71
+ # プラグインの読込み
72
+ load_plugins
73
+
74
+ # ロケールの読込み
75
+ I18n.load_path = @locale_paths
76
+ I18n.backend.load_translations
77
+
58
78
  @requires.each { |lib| require lib }
59
79
  @locals = default_locals(@options)
60
80
 
61
81
  use_engine(@markdown)
62
82
  end
63
83
 
84
+ # フォルダ(ディレクトリ)を取得する
85
+ def folder(name, domain = :app)
86
+ @folders ||= {}
87
+ @folders[domain] ||= {}
88
+
89
+ unless @folders[domain][name]
90
+ case domain
91
+ when :user
92
+ dir = File.join(ENV['HOME'], '.etc/memorack')
93
+ when :app
94
+ dir = File.dirname(__FILE__)
95
+ else
96
+ return nil
97
+ end
98
+ end
99
+
100
+ @folders[domain][name] ||= File.expand_path(name.to_s, dir)
101
+ end
102
+
64
103
  # テーマのパスを取得する
65
104
  def theme_path(theme)
66
105
  return nil unless theme
@@ -75,28 +114,44 @@ module MemoRack
75
114
 
76
115
  # デフォルトの locals を生成する
77
116
  def default_locals(locals = {})
78
- locals = Locals[locals]
79
-
80
- locals[:site] ||= @site
81
-
82
- locals[:app] ||= Locals[]
83
- locals[:app][:name] ||= MemoRack::name
84
- locals[:app][:version] ||= MemoRack::VERSION
85
- locals[:app][:url] ||= MemoRack::HOMEPAGE
117
+ locals = BaseLocals.new(self, locals)
118
+ locals[:site] ||= @site
119
+ locals
120
+ end
86
121
 
87
- locals.define_key(:__menu__) { |hash, key|
88
- @menu = nil unless @directory_watcher # ファイル監視していない場合はメニューを初期化
89
- @menu ||= render :markdown, :menu, @options
90
- }
122
+ # json/yaml のデータを読込む
123
+ def read_data(name, exts = ['json', 'yml', 'yaml'])
124
+ begin
125
+ exts.each { |ext|
126
+ path = [name, ext].join('.')
127
+ if File.readable?(path)
128
+ data = File.read(path)
129
+
130
+ case ext
131
+ when 'json'
132
+ hash = JSON.parse(data)
133
+ when 'yml', 'yaml'
134
+ hash = YAML.load(data)
135
+ end
136
+
137
+ data = to_sym_keys(hash) if hash
138
+ return data
139
+ end
140
+ }
141
+ rescue
142
+ end
91
143
 
92
- locals
144
+ nil
93
145
  end
94
146
 
95
147
  # 設定ファイルを読込む
96
148
  def read_config(theme, options = {})
97
149
  @themes ||= []
98
150
  @options_chain = []
99
- @theme_chain = []
151
+ @locale_paths = []
152
+ @macro_chain = []
153
+ @macro = {}
154
+ @plugins = Set.new
100
155
 
101
156
  begin
102
157
  require 'json'
@@ -106,26 +161,112 @@ module MemoRack
106
161
  break unless dir
107
162
  break if @themes.member?(dir)
108
163
 
109
- # テーマ・チェインに追加
110
- @themes << File.join(dir, '')
111
-
112
- # config の読込み
113
- path = File.join(dir, 'config.json')
114
- break unless File.readable?(path)
115
-
116
- data = File.read(path)
117
- @options_chain << to_sym_keys(JSON.parse(data))
118
-
119
- theme = @options_chain.last[:theme]
164
+ # 設定ファイルのデータをチェインに追加
165
+ theme = add_config_chain(dir, theme)
120
166
  end
121
167
  rescue
122
168
  end
123
169
 
170
+ # デフォルトの設定をチェインに追加
171
+ add_config_chain(File.expand_path('../config', __FILE__))
172
+
173
+ # マクロをマージ
174
+ @macro_chain.reverse.each { |macro| @macro.merge!(macro) }
175
+
124
176
  # オプションをマージ
125
177
  @options_chain.reverse.each { |opts| options.merge!(opts) }
126
178
  options
127
179
  end
128
180
 
181
+ # 設定ファイルのデータをチェインに追加
182
+ def add_config_chain(dir, theme = nil)
183
+ # テーマ・チェインに追加
184
+ @themes << File.join(dir, '') if theme
185
+
186
+ # config の読込み
187
+ config = read_data(File.join(dir, 'config'))
188
+
189
+ if config
190
+ @options_chain << config
191
+ theme = config[:theme]
192
+ end
193
+
194
+ # macro の読込み
195
+ macro = read_data(File.join(dir, 'macro'))
196
+ @macro_chain << macro if macro && macro.kind_of?(Hash)
197
+
198
+ # locale の読込み
199
+ @locale_paths += Dir[File.expand_path('locales/*.yml', dir)]
200
+
201
+ theme
202
+ end
203
+
204
+ # locale を env情報で更新する
205
+ def update_locale(env = ENV)
206
+ locale ||= env['HTTP_ACCEPT_LANGUAGE']
207
+ locale ||= env['LANG'] if env['LANG']
208
+ locale = locale[0, 2].to_sym if locale
209
+ I18n.locale = locale if I18n.available_locales.include?(locale)
210
+ end
211
+
212
+ # プラグイン・フォルダを取得する
213
+ def plugins_folders
214
+ unless @plugins_folders
215
+ @plugins_folders = ['plugins/', folder(:plugins, :user), folder(:plugins)]
216
+ @plugins_folders.delete nil
217
+ @plugins_folders.reject! { |folder| ! File.directory?(folder) }
218
+
219
+ @themes.each { |theme|
220
+ path = File.join(theme, 'plugins/')
221
+ @plugins_folders.unshift path if File.directory?(path)
222
+ }
223
+ end
224
+
225
+ @plugins_folders
226
+ end
227
+
228
+ # プラグインを読込む
229
+ def load_plugins
230
+ plugins_folders.reverse.each { |folder|
231
+ Dir.glob(File.join(folder, '*')) { |path|
232
+ name = path.gsub(%r[^#{folder}/], '')
233
+ load_plugin(name, path)
234
+ }
235
+ }
236
+ end
237
+
238
+ # プラグインファイルを読込む
239
+ def load_plugin(name, path)
240
+ loaded = false
241
+
242
+ if File.directory?(path)
243
+ path = File.join(path, File.basename(path) + '.rb')
244
+
245
+ if File.exists?(path)
246
+ require_relative(path)
247
+ loaded = true
248
+ end
249
+ elsif path =~ /\.rb$/
250
+ require_relative(File.expand_path(path))
251
+ loaded = true
252
+ end
253
+
254
+ if loaded
255
+ @plugins << name
256
+ end
257
+ end
258
+
259
+ # プラグインを読込む(読込み済みのものは読込まない)
260
+ def require_plugin(plugin)
261
+ return if @plugins.include?(plugin)
262
+
263
+ plugins_folders.reverse.each { |folder|
264
+ path = File.join(folder, plugin)
265
+ load_plugin(folder, path) if File.exist?(path)
266
+ load_plugin(folder, path + '.rb') if File.exist?(path + '.rb')
267
+ }
268
+ end
269
+
129
270
  # テンプレートエンジンを使用できるようにする
130
271
  def use_engine(engine)
131
272
  require engine if engine
@@ -139,6 +280,29 @@ module MemoRack
139
280
  @css_exts ||= Set.new ['css', *@css]
140
281
  end
141
282
 
283
+ # テーマから固定ページのファイルを収集する
284
+ def pages
285
+ unless @pages
286
+ @pages = {}
287
+
288
+ @themes.each { |theme|
289
+ folder = File.join(theme, 'pages/')
290
+
291
+ if Dir.exists?(folder)
292
+ Dir.chdir(folder) { |dir|
293
+ Dir.glob(File.join('**/*')) { |path|
294
+ path_info, ext = split_extname(path)
295
+ path_info = File.join('', path_info)
296
+ @pages[path_info] ||= File.expand_path(path)
297
+ }
298
+ }
299
+ end
300
+ }
301
+ end
302
+
303
+ @pages
304
+ end
305
+
142
306
  # ファイルを探す
143
307
  def file_search(template, options = {}, exts = enable_exts)
144
308
  options = {views: @root}.merge(options)
@@ -161,13 +325,16 @@ module MemoRack
161
325
  return nil
162
326
  end
163
327
 
328
+ dir = options[:views]
329
+ dir = File.join(dir, options[:folder]) if options[:folder]
330
+
164
331
  if exts
165
332
  exts.each { |ext|
166
- path = File.join(options[:views], "#{template}.#{ext}")
333
+ path = File.join(dir, "#{template}.#{ext}")
167
334
  return path if File.exists?(path)
168
335
  }
169
336
  else
170
- path = File.join(options[:views], template)
337
+ path = File.join(dir, template)
171
338
  return path if File.exists?(path)
172
339
  end
173
340
 
@@ -217,7 +384,8 @@ module MemoRack
217
384
  # レイアウトに mustache を適用してテンプレートエンジンでレンダリングする
218
385
  def render_with_mustache(template, engine = :markdown, options = {}, locals = {})
219
386
  begin
220
- mustache_templ = options[:mustache] || 'index.html'
387
+ mustache_templ = []
388
+ mustache_templ << options[:mustache] if options[:mustache]
221
389
 
222
390
  options = @options.merge(options)
223
391
  locals = @locals.merge(locals)
@@ -225,47 +393,160 @@ module MemoRack
225
393
  locals.define_key(:__content__) { |hash, key|
226
394
  if engine
227
395
  render engine, template, options
396
+ elsif locals[:directory?]
397
+ # ディレクトリ
398
+ nil
228
399
  else
229
400
  template
230
401
  end
231
402
  }
232
403
 
233
- locals[:content] = true unless template == :index
404
+ locals[:directory?] = true if template.kind_of?(Pathname) && template.directory?
405
+ locals[:content?] = true unless template == :index || locals[:directory?]
234
406
  locals[:page] = page = Locals[locals[:page] || {}]
235
407
 
408
+ if template.kind_of?(Pathname)
409
+ path = template.to_s
410
+ plugin = PageInfo[path]
411
+ locals[:page] = page = plugin.new(path, page, locals) if plugin
412
+ end
413
+
236
414
  page.define_key(:name) { |hash, key|
237
- unless template == :index
415
+ if hash.kind_of?(PageInfo)
416
+ hash.value(:title)
417
+ elsif template != :index
238
418
  fname = locals[:path_info]
239
419
  fname ||= template.to_s.force_encoding('UTF-8')
240
420
  File.basename(fname)
241
421
  end
242
422
  }
243
423
 
244
- page.define_key(:title) { |hash, key|
245
- page_title = home_title = locals[:title]
246
- page_name = hash[:name]
247
- page_title = "#{page_name} | #{home_title}" if page_name
424
+ # マクロを組込む
425
+ embed_macro(locals, @macro)
426
+
427
+ # HTMLページをレンダリングする
428
+ if engine && engine.to_sym == :html
429
+ unless template.kind_of?(Pathname)
430
+ path = file_search(template, @options, [engine])
431
+ return nil unless path
432
+ template = Pathname.new(path)
433
+ end
434
+
435
+ locals.define_key(:__content__) { |hash, key| }
436
+ return render :mustache, template, {views: @themes}, locals
437
+ end
438
+
439
+ mustache_templ << 'page.html' if locals[:content?]
440
+ mustache_templ << 'index.html'
248
441
 
249
- page_title
442
+ mustache_templ.each { |templ|
443
+ path = file_search(templ, {views: @themes}, nil)
444
+ next unless path
445
+
446
+ path = Pathname.new(path)
447
+ return render :mustache, path, {views: @themes}, locals
250
448
  }
251
449
 
252
- render :mustache, mustache_templ, {views: @themes}, locals
450
+ raise "Not found template #{mustache_templ}"
253
451
  rescue => e
254
452
  e.to_s
255
453
  end
256
454
  end
257
455
 
456
+ # Localsクラス 変換する
457
+ def value_to_locals(value)
458
+ case value
459
+ when Locals
460
+ when Hash
461
+ value = Locals[value]
462
+ else
463
+ value = Locals[]
464
+ end
465
+
466
+ value
467
+ end
468
+
469
+ # マクロを組込む
470
+ def embed_macro(hash, macro, options = {}, locals = hash)
471
+ macro.each { |key, value|
472
+ case value
473
+ when Hash
474
+ if hash[key].kind_of?(Array)
475
+ embed_macro_for_array(hash[key], value, options, locals)
476
+ else
477
+ hash[key] = value_to_locals(hash[key])
478
+ embed_macro(hash[key], value, options, locals)
479
+ end
480
+ when Array
481
+ hash[key] = [] unless hash[key]
482
+ a = hash[key]
483
+
484
+ if a.kind_of?(Array)
485
+ value.each_with_index { |item, index|
486
+ if item.kind_of?(Hash)
487
+ a[index] = value_to_locals(a[index])
488
+ embed_macro(a[index], item, options, locals)
489
+ else
490
+ a[index] = item
491
+ end
492
+ }
493
+ end
494
+ else
495
+ hash.define_key(key) { |hash, key|
496
+ if value
497
+ #render :mustache, value, {}, locals
498
+
499
+ engine = Tilt.new('.mustache', {}) { value }
500
+ engine.render({}, locals).force_encoding('UTF-8')
501
+ end
502
+ }
503
+ end
504
+ }
505
+ end
506
+
507
+ # マクロを配列に組込む
508
+ def embed_macro_for_array(array, macro, options = {}, locals)
509
+ array.each_with_index { |item, index|
510
+ if item.kind_of?(Array)
511
+ embed_macro_for_array(item, macro, options, locals)
512
+ else
513
+ array[index] = value_to_locals(item)
514
+ embed_macro(array[index], macro, options)
515
+ end
516
+ }
517
+ end
518
+
519
+ # メニューをレンダリングする
520
+ def render_menu
521
+ @menu = nil unless @directory_watcher # ファイル監視していない場合はメニューを初期化
522
+ @menu ||= render :markdown, :menu, @options
523
+ end
524
+
525
+ # 固定ページをレンダリングする
526
+ def render_page(path_info, locals = {})
527
+ path_info = path_info.gsub(%r[(/|.html)$], '')
528
+ path = pages[path_info]
529
+ return nil unless path
530
+
531
+ ext = split_extname(path)[1]
532
+ content = render_with_mustache Pathname.new(path), ext, {}, locals
533
+ end
534
+
258
535
  # コンテンツをレンダリングする
259
- def render_content(path_info, locals = {})
536
+ def render_content(path_info, locals = {}, exts = enable_exts)
537
+ path = File.join(@root, path_info)
538
+
539
+ if File.directory?(path)
540
+ return render_with_mustache Pathname.new(path), nil, {}, locals
541
+ end
542
+
260
543
  path, ext = split_extname(path_info)
261
544
 
262
- if @suffix == ''
263
- fullpath = file_search(path_info, @options)
545
+ fullpath = file_search(path_info, @options, exts)
264
546
 
265
- if fullpath
266
- path = path_info
267
- ext = split_extname(fullpath)[1]
268
- end
547
+ if fullpath
548
+ path = path_info
549
+ ext = split_extname(fullpath)[1]
269
550
  end
270
551
 
271
552
  return nil unless ext && Tilt.registered?(ext)
@@ -355,6 +636,17 @@ module MemoRack
355
636
  mdmenu
356
637
  end
357
638
 
639
+ # パスからコンテント名を取得する
640
+ def content_name(path)
641
+ plugin = PageInfo[path]
642
+
643
+ if plugin
644
+ plugin.new(File.expand_path(path, @root))[:title]
645
+ else
646
+ File.basename(path, '.*')
647
+ end
648
+ end
649
+
358
650
  # テンプレート名
359
651
  def self.template_method(name)
360
652
  name.kind_of?(Symbol) && "template_#{name}".to_sym