memorack 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|