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 +4 -4
- data/HISTORY.md +15 -0
- data/README.md +17 -15
- data/VERSION +1 -1
- data/lib/memorack/builder.rb +36 -2
- data/lib/memorack/cli.rb +8 -5
- data/lib/memorack/config/macro.yml +2 -0
- data/lib/memorack/core.rb +339 -47
- data/lib/memorack/locales/en.yml +1 -0
- data/lib/memorack/locales/ja.yml +1 -0
- data/lib/memorack/locals.rb +31 -1
- data/lib/memorack/locals/app.rb +16 -0
- data/lib/memorack/locals/base.rb +84 -0
- data/lib/memorack/mdmenu.rb +3 -2
- data/lib/memorack/memoapp.rb +7 -2
- data/lib/memorack/pageinfo.rb +151 -0
- data/lib/memorack/plugin.rb +54 -0
- data/lib/memorack/plugins/formats/formats.rb +12 -0
- data/lib/memorack/plugins/formats/markdown.rb +32 -0
- data/lib/memorack/plugins/formats/org.rb +54 -0
- data/lib/memorack/template/.gitignore +1 -0
- data/lib/memorack/template/plugins/.gitkeep +0 -0
- data/lib/memorack/template/themes/custom/locales/.gitkeep +0 -0
- data/lib/memorack/template/themes/custom/macro.yml +2 -0
- data/lib/memorack/template/themes/custom/pages/.gitkeep +0 -0
- data/spec/memorack_spec.rb +115 -15
- data/spec/patches/git/0001-add-HISTORY.patch +15 -0
- data/spec/patches/git/0002-change-HISTORY.patch +19 -0
- data/spec/patches/git/0003-index.html.patch +75 -0
- data/spec/patches/macro.patch +20 -0
- data/spec/patches/plugin.patch +87 -0
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86c45efe555619b9ccb0baf170a9ec452f0fa52e
|
4
|
+
data.tar.gz: b012723ff47cef6d9887501fd28c88d3d6a5fcfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
26
|
-
$ memorack build
|
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
|
70
|
+
├── content/ -- Content directory for memo
|
71
71
|
│ └── README.md -- Sample file(remove it)
|
72
|
-
|
73
|
-
|
72
|
+
├── plugins/ -- Plugins directory
|
73
|
+
└── themes/
|
74
|
+
└── custom/ -- Default theme
|
74
75
|
├── config.json -- Configuration
|
75
|
-
|
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
|
+
0.2.0
|
data/lib/memorack/builder.rb
CHANGED
@@ -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
|
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
|
data/lib/memorack/cli.rb
CHANGED
@@ -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: '
|
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
|
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
|
|
data/lib/memorack/core.rb
CHANGED
@@ -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: '
|
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],
|
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 =
|
79
|
-
|
80
|
-
locals
|
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
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
144
|
+
nil
|
93
145
|
end
|
94
146
|
|
95
147
|
# 設定ファイルを読込む
|
96
148
|
def read_config(theme, options = {})
|
97
149
|
@themes ||= []
|
98
150
|
@options_chain = []
|
99
|
-
@
|
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
|
-
|
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(
|
333
|
+
path = File.join(dir, "#{template}.#{ext}")
|
167
334
|
return path if File.exists?(path)
|
168
335
|
}
|
169
336
|
else
|
170
|
-
path = File.join(
|
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 =
|
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[:
|
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
|
-
|
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
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
263
|
-
fullpath = file_search(path_info, @options)
|
545
|
+
fullpath = file_search(path_info, @options, exts)
|
264
546
|
|
265
|
-
|
266
|
-
|
267
|
-
|
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
|