amber 0.2.6 → 0.3.8
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 +7 -0
- data/LICENSE +14 -1
- data/README.md +88 -19
- data/bin/amber +26 -13
- data/lib/amber.rb +25 -39
- data/lib/amber/cli.rb +25 -1
- data/lib/amber/i18n.rb +43 -0
- data/lib/amber/render/apache.rb +44 -0
- data/lib/amber/render/asset.rb +28 -2
- data/lib/amber/render/helpers/blog_helper.rb +35 -0
- data/lib/amber/render/helpers/date_helper.rb +14 -0
- data/lib/amber/render/helpers/haml_helper.rb +9 -0
- data/lib/amber/render/helpers/html_helper.rb +30 -8
- data/lib/amber/render/helpers/navigation_helper.rb +31 -32
- data/lib/amber/render/layout.rb +2 -1
- data/lib/amber/render/template.rb +24 -11
- data/lib/amber/render/view.rb +31 -12
- data/lib/amber/server.rb +122 -56
- data/lib/amber/site.rb +171 -29
- data/lib/amber/site_configuration.rb +26 -11
- data/lib/amber/static_page.rb +34 -20
- data/lib/amber/static_page/filesystem.rb +3 -7
- data/lib/amber/static_page/page_properties.rb +7 -0
- data/lib/amber/static_page/render.rb +47 -31
- data/lib/amber/templates/apache_config.erb +12 -0
- data/lib/amber/templates/apache_config_with_prefix.erb +14 -0
- data/lib/amber/templates/htaccess.erb +176 -0
- data/lib/amber/version.rb +5 -0
- data/locales/rails-i18n/af.yml +201 -0
- data/locales/rails-i18n/ar.yml +274 -0
- data/locales/rails-i18n/az.yml +192 -0
- data/locales/rails-i18n/bg.yml +192 -0
- data/locales/rails-i18n/bn.yml +175 -0
- data/locales/rails-i18n/bs.yml +243 -0
- data/locales/rails-i18n/ca.yml +192 -0
- data/locales/rails-i18n/cs.yml +210 -0
- data/locales/rails-i18n/cy.yml +242 -0
- data/locales/rails-i18n/da.yml +198 -0
- data/locales/rails-i18n/de-AT.yml +202 -0
- data/locales/rails-i18n/de-CH.yml +206 -0
- data/locales/rails-i18n/de.yml +202 -0
- data/locales/rails-i18n/el.yml +198 -0
- data/locales/rails-i18n/en-AU.yml +198 -0
- data/locales/rails-i18n/en-CA.yml +207 -0
- data/locales/rails-i18n/en-GB.yml +198 -0
- data/locales/rails-i18n/en-IE.yml +198 -0
- data/locales/rails-i18n/en-IN.yml +198 -0
- data/locales/rails-i18n/en-NZ.yml +198 -0
- data/locales/rails-i18n/en-US.yml +204 -0
- data/locales/rails-i18n/en-ZA.yml +204 -0
- data/locales/rails-i18n/en.yml +204 -0
- data/locales/rails-i18n/eo.yml +194 -0
- data/locales/rails-i18n/es-419.yml +207 -0
- data/locales/rails-i18n/es-AR.yml +198 -0
- data/locales/rails-i18n/es-CL.yml +192 -0
- data/locales/rails-i18n/es-CO.yml +198 -0
- data/locales/rails-i18n/es-CR.yml +198 -0
- data/locales/rails-i18n/es-EC.yml +204 -0
- data/locales/rails-i18n/es-MX.yml +204 -0
- data/locales/rails-i18n/es-PA.yml +204 -0
- data/locales/rails-i18n/es-PE.yml +177 -0
- data/locales/rails-i18n/es-US.yml +198 -0
- data/locales/rails-i18n/es-VE.yml +198 -0
- data/locales/rails-i18n/es.yml +192 -0
- data/locales/rails-i18n/et.yml +192 -0
- data/locales/rails-i18n/eu.yml +192 -0
- data/locales/rails-i18n/fa.yml +192 -0
- data/locales/rails-i18n/fi.yml +192 -0
- data/locales/rails-i18n/fr-CA.yml +200 -0
- data/locales/rails-i18n/fr-CH.yml +200 -0
- data/locales/rails-i18n/fr.yml +214 -0
- data/locales/rails-i18n/gl.yml +171 -0
- data/locales/rails-i18n/he.yml +194 -0
- data/locales/rails-i18n/hi-IN.yml +192 -0
- data/locales/rails-i18n/hi.yml +192 -0
- data/locales/rails-i18n/hr.yml +236 -0
- data/locales/rails-i18n/hu.yml +192 -0
- data/locales/rails-i18n/id.yml +193 -0
- data/locales/rails-i18n/is.yml +212 -0
- data/locales/rails-i18n/iso-639-2/csb.yml +203 -0
- data/locales/rails-i18n/iso-639-2/dsb.yml +208 -0
- data/locales/rails-i18n/iso-639-2/fur.yml +192 -0
- data/locales/rails-i18n/iso-639-2/gsw-CH.yml +196 -0
- data/locales/rails-i18n/iso-639-2/hsb.yml +207 -0
- data/locales/rails-i18n/iso-639-2/pap-AW.yml +205 -0
- data/locales/rails-i18n/iso-639-2/pap-CW.yml +205 -0
- data/locales/rails-i18n/iso-639-2/scr.yml +236 -0
- data/locales/rails-i18n/it-CH.yml +198 -0
- data/locales/rails-i18n/it.yml +204 -0
- data/locales/rails-i18n/ja.yml +194 -0
- data/locales/rails-i18n/km.yml +54 -0
- data/locales/rails-i18n/kn.yml +192 -0
- data/locales/rails-i18n/ko.yml +190 -0
- data/locales/rails-i18n/lo.yml +227 -0
- data/locales/rails-i18n/lt.yml +217 -0
- data/locales/rails-i18n/lv.yml +229 -0
- data/locales/rails-i18n/mk.yml +198 -0
- data/locales/rails-i18n/mn.yml +198 -0
- data/locales/rails-i18n/ms.yml +200 -0
- data/locales/rails-i18n/nb.yml +205 -0
- data/locales/rails-i18n/ne.yml +198 -0
- data/locales/rails-i18n/nl.yml +204 -0
- data/locales/rails-i18n/nn.yml +201 -0
- data/locales/rails-i18n/or.yml +192 -0
- data/locales/rails-i18n/pl.yml +236 -0
- data/locales/rails-i18n/pt-BR.yml +206 -0
- data/locales/rails-i18n/pt.yml +200 -0
- data/locales/rails-i18n/rm.yml +223 -0
- data/locales/rails-i18n/ro.yml +205 -0
- data/locales/rails-i18n/ru.yml +256 -0
- data/locales/rails-i18n/sk.yml +206 -0
- data/locales/rails-i18n/sl.yml +205 -0
- data/locales/rails-i18n/sr.yml +236 -0
- data/locales/rails-i18n/sv.yml +192 -0
- data/locales/rails-i18n/sw.yml +190 -0
- data/locales/rails-i18n/ta.yml +204 -0
- data/locales/rails-i18n/th.yml +166 -0
- data/locales/rails-i18n/tl.yml +224 -0
- data/locales/rails-i18n/tr.yml +204 -0
- data/locales/rails-i18n/uk.yml +250 -0
- data/locales/rails-i18n/ur.yml +204 -0
- data/locales/rails-i18n/uz.yml +250 -0
- data/locales/rails-i18n/vi.yml +198 -0
- data/locales/rails-i18n/wo.yml +198 -0
- data/locales/rails-i18n/zh-CN.yml +203 -0
- data/locales/rails-i18n/zh-HK.yml +204 -0
- data/locales/rails-i18n/zh-TW.yml +203 -0
- data/locales/rails-i18n/zh-YUE.yml +204 -0
- metadata +164 -74
data/lib/amber/server.rb
CHANGED
|
@@ -15,8 +15,9 @@ module Amber
|
|
|
15
15
|
|
|
16
16
|
def initialize(options)
|
|
17
17
|
@site = options[:site]
|
|
18
|
+
@host = options[:host]
|
|
18
19
|
@port = options[:port]
|
|
19
|
-
@server = WEBrick::HTTPServer.new :Port => @port, :BindAddress =>
|
|
20
|
+
@server = WEBrick::HTTPServer.new :Port => @port, :BindAddress => @host, :DocumentRoot => @site.dest_dir
|
|
20
21
|
@server.mount '/', StaticPageServlet, self
|
|
21
22
|
end
|
|
22
23
|
|
|
@@ -30,6 +31,9 @@ module Amber
|
|
|
30
31
|
|
|
31
32
|
class StaticPageServlet < WEBrick::HTTPServlet::FileHandler
|
|
32
33
|
|
|
34
|
+
RENDERABLE_ASSET_RE = /(#{Amber::Render::Asset::SOURCE_MAP.keys.join('|')})$/
|
|
35
|
+
ASSET_RE = /\.(jpg|jpeg|png|gif|webm|css|js|ico)$/
|
|
36
|
+
|
|
33
37
|
def initialize(http_server, amber_server)
|
|
34
38
|
@logger = http_server.logger
|
|
35
39
|
@server = amber_server
|
|
@@ -37,77 +41,139 @@ module Amber
|
|
|
37
41
|
end
|
|
38
42
|
|
|
39
43
|
def do_GET(request, response)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if request.path !~ /\.[a-z]{2,4}$/
|
|
44
|
-
locale = get_locale(request)
|
|
45
|
-
if !locale
|
|
46
|
-
location = "http://localhost:#{@server.port}/#{I18n.default_locale}#{request.path.sub(/\/$/,'')}"
|
|
47
|
-
@logger.info "Redirect %s ==> %s" % [request.path, location]
|
|
48
|
-
response.header['Location'] = location
|
|
49
|
-
response.status = 307
|
|
50
|
-
return
|
|
51
|
-
end
|
|
44
|
+
if path_needs_to_be_prefixed?(request.path)
|
|
45
|
+
redirect_with_prefix(request, response)
|
|
46
|
+
return
|
|
52
47
|
end
|
|
53
48
|
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
path = strip_locale_and_prefix(request.path)
|
|
50
|
+
|
|
51
|
+
if renderable_asset?(path)
|
|
52
|
+
@logger.info "Rendering asset file %s" % asset_source_file(path)
|
|
53
|
+
render_asset(path, request, response)
|
|
56
54
|
super(request, response)
|
|
55
|
+
elsif static_file_exists?(request.path)
|
|
56
|
+
@logger.info "Serve static file %s" % static_file_path(request.path)
|
|
57
|
+
super(request, response)
|
|
58
|
+
elsif static_file_exists?(path)
|
|
59
|
+
request = request.clone
|
|
60
|
+
request.instance_variable_set(:@path_info, "/"+path)
|
|
61
|
+
@logger.info "Serve static file with locale prefix %s" % static_file_path(path)
|
|
62
|
+
super(request, response)
|
|
63
|
+
elsif path !~ ASSET_RE
|
|
64
|
+
render_page(path, request, response)
|
|
57
65
|
else
|
|
58
|
-
|
|
59
|
-
@server.site.load_pages
|
|
60
|
-
page = @server.site.find_page_by_path(path)
|
|
61
|
-
if page
|
|
62
|
-
@logger.info "Serving Page %s" % page.path.join('/')
|
|
63
|
-
response.status = 200
|
|
64
|
-
response.content_type = "text/html; charset=utf-8"
|
|
65
|
-
# always refresh the page we are fetching
|
|
66
|
-
Amber::Render::Layout.reload
|
|
67
|
-
@server.site.render
|
|
68
|
-
page.render_to_file(dest_dir, :force => true)
|
|
69
|
-
file = page.destination_file(dest_dir, locale)
|
|
70
|
-
if File.exists?(file)
|
|
71
|
-
content = File.read(file)
|
|
72
|
-
else
|
|
73
|
-
file = page.destination_file(dest_dir, I18n.default_locale)
|
|
74
|
-
if File.exists?(file)
|
|
75
|
-
content = File.read(file)
|
|
76
|
-
else
|
|
77
|
-
view = Render::View.new(page, @server.site)
|
|
78
|
-
content = view.render(:text => "No file found at #{file}")
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
response.body = content
|
|
82
|
-
else
|
|
83
|
-
request = request.clone
|
|
84
|
-
request.instance_variable_set(:@path_info, "/" + strip_locale(request.path_info))
|
|
85
|
-
@logger.info "Serve static file %s" % File.join(dest_dir, request.path_info)
|
|
86
|
-
super(request, response)
|
|
87
|
-
end
|
|
66
|
+
super(request, response)
|
|
88
67
|
end
|
|
89
68
|
end
|
|
90
|
-
#rescue Exception => exc
|
|
91
|
-
# @logger.error exc.to_s
|
|
92
|
-
# @logger.error exc.backtrace
|
|
93
|
-
# response.status = 500
|
|
94
|
-
# response.content_type = 'text/text'
|
|
95
|
-
# response.body = exc.to_s + "\n\n\n\n" + exc.backtrace
|
|
96
69
|
|
|
97
70
|
private
|
|
98
71
|
|
|
99
|
-
def
|
|
100
|
-
|
|
72
|
+
def strip_locale_and_prefix(path)
|
|
73
|
+
# The path comes to the server as URL escaped codes, that are then
|
|
74
|
+
# converty to ascii. But these codes might be utf-8 characters, so we force
|
|
75
|
+
# utf-8 encouding to allows non-ascii paths. I am not sure if always forcing
|
|
76
|
+
# will be a problem.
|
|
77
|
+
path = path.force_encoding('utf-8')
|
|
78
|
+
if @server.site.path_prefix
|
|
79
|
+
path = path.sub(%r{^/?#{Regexp.escape(@server.site.path_prefix)}}, '')
|
|
80
|
+
end
|
|
81
|
+
path.sub(%r{^/?(#{Amber::POSSIBLE_LANGUAGE_CODES.join('|')})(/|$)}, '').sub(%r{/$}, '')
|
|
101
82
|
end
|
|
102
83
|
|
|
103
|
-
def get_locale(
|
|
104
|
-
match = /\/(#{Amber::POSSIBLE_LANGUAGE_CODES.join('|')})(\/|$)/.match(
|
|
84
|
+
def get_locale(path)
|
|
85
|
+
match = /\/(#{Amber::POSSIBLE_LANGUAGE_CODES.join('|')})(\/|$)/.match(path)
|
|
105
86
|
if match.nil?
|
|
106
87
|
nil
|
|
107
88
|
else
|
|
108
89
|
match[1]
|
|
109
90
|
end
|
|
110
91
|
end
|
|
111
|
-
end
|
|
112
92
|
|
|
93
|
+
def path_needs_to_be_prefixed?(path)
|
|
94
|
+
if @server.site.path_prefix
|
|
95
|
+
path !~ /\.[a-z]{2,4}$/ && (
|
|
96
|
+
path !~ %r{^/?#{Regexp.escape(@server.site.path_prefix)}} ||
|
|
97
|
+
get_locale(path).nil?
|
|
98
|
+
)
|
|
99
|
+
else
|
|
100
|
+
path !~ /\.[a-z]{2,4}$/ && get_locale(path).nil?
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def redirect_with_prefix(request, response)
|
|
105
|
+
path = request.path.gsub(%r{^/|/$}, '')
|
|
106
|
+
location = ["http://localhost:#{@server.port}", @server.site.path_prefix, I18n.default_locale, path].compact.join('/')
|
|
107
|
+
@logger.info "Redirect %s ==> %s" % [request.path, location]
|
|
108
|
+
response.header['Location'] = location
|
|
109
|
+
response.status = 307
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def dst_dir
|
|
113
|
+
@server.site.dest_dir
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def src_dir
|
|
117
|
+
@server.site.pages_dir
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def static_file_exists?(path)
|
|
121
|
+
File.file?(File.join(dst_dir, path))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def static_file_path(path)
|
|
125
|
+
File.join(dst_dir, path)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def render_page(path, request, response)
|
|
129
|
+
locale = get_locale(request.path)
|
|
130
|
+
@server.site.load_pages
|
|
131
|
+
page = @server.site.find_page_by_path(path, locale)
|
|
132
|
+
if page
|
|
133
|
+
@logger.info "Serving Page %s" % page.path.join('/')
|
|
134
|
+
response.status = 200
|
|
135
|
+
response.content_type = "text/html; charset=utf-8"
|
|
136
|
+
# always refresh the page we are fetching
|
|
137
|
+
Amber::Render::Layout.reload
|
|
138
|
+
@server.site.render
|
|
139
|
+
page.render_to_file(dst_dir, :force => true)
|
|
140
|
+
file = page.destination_file(dst_dir, locale)
|
|
141
|
+
if File.exists?(file)
|
|
142
|
+
content = File.read(file)
|
|
143
|
+
else
|
|
144
|
+
file = page.destination_file(dst_dir, I18n.default_locale)
|
|
145
|
+
if File.exists?(file)
|
|
146
|
+
content = File.read(file)
|
|
147
|
+
else
|
|
148
|
+
view = Render::View.new(page, @server.site)
|
|
149
|
+
content = view.render(:text => "No file found at #{file}")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
response.body = content
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def renderable_asset?(path)
|
|
157
|
+
path =~ RENDERABLE_ASSET_RE && asset_source_file(path)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def asset_source_file(path)
|
|
161
|
+
dest_suffix = File.extname(path)
|
|
162
|
+
base_path = path.sub(RENDERABLE_ASSET_RE, '')
|
|
163
|
+
Amber::Render::Asset::SOURCE_MAP[dest_suffix].each do |source_suffix|
|
|
164
|
+
source_file_path = File.join(src_dir, base_path + source_suffix)
|
|
165
|
+
if File.exists?(source_file_path)
|
|
166
|
+
return source_file_path
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
return nil
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def render_asset(path, request, response)
|
|
173
|
+
src_file = asset_source_file(path)
|
|
174
|
+
dst_file = [dst_dir, path].join
|
|
175
|
+
Amber::Render::Asset.render(src_file, dst_file)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
end
|
|
113
179
|
end
|
data/lib/amber/site.rb
CHANGED
|
@@ -9,32 +9,39 @@ module Amber
|
|
|
9
9
|
attr_accessor :root
|
|
10
10
|
attr_accessor :continue_on_error
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
# @config is the primary SiteConfiguration
|
|
13
|
+
def_delegators :@config, :pages_dir, :dest_dir, :locales, :default_locale, :path_prefix
|
|
13
14
|
|
|
14
15
|
def initialize(root_dir)
|
|
15
16
|
@continue_on_error = true
|
|
16
17
|
@config = SiteConfiguration.load(self, root_dir)
|
|
17
18
|
end
|
|
18
19
|
|
|
20
|
+
def add_config(config)
|
|
21
|
+
@config.children << config
|
|
22
|
+
end
|
|
23
|
+
|
|
19
24
|
def load_pages
|
|
20
25
|
@root = nil
|
|
21
|
-
@pages_by_path = {}
|
|
22
|
-
@pages_by_name = {}
|
|
26
|
+
@pages_by_path = {} # hash of pages keyed by page path
|
|
27
|
+
@pages_by_name = {} # hash of pages keyed by page name
|
|
23
28
|
@page_list = PageArray.new
|
|
24
|
-
@dir_list = []
|
|
25
|
-
@
|
|
26
|
-
add_mount_point(mp)
|
|
27
|
-
mp.reset_timestamp
|
|
28
|
-
end
|
|
29
|
-
end
|
|
29
|
+
@dir_list = [] # an array of non-page directories
|
|
30
|
+
@page_paths = [] # an array of page paths, used for greping through paths.
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
end
|
|
32
|
+
# some paths are specific to only one locale (e.g aliases)
|
|
33
|
+
@pages_by_locale_path = POSSIBLE_LANGUAGES.keys.inject(Hash.new({})) {|h,locale| h[locale] = {}; h}
|
|
34
|
+
|
|
35
|
+
add_configuration(@config)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
#def reload_pages_if_needed
|
|
39
|
+
# if @pages_by_path.nil? || @config.pages_changed?
|
|
40
|
+
# puts "Reloading pages ................."
|
|
41
|
+
# load_pages
|
|
42
|
+
# end
|
|
43
|
+
#end
|
|
44
|
+
|
|
38
45
|
def render
|
|
39
46
|
@page_list.each do |page|
|
|
40
47
|
page.render_to_file(@config.dest_dir)
|
|
@@ -46,6 +53,10 @@ module Amber
|
|
|
46
53
|
Render::Asset.render_dir(src, dst)
|
|
47
54
|
putc '.'; $stdout.flush
|
|
48
55
|
end
|
|
56
|
+
if @config.short_paths
|
|
57
|
+
render_short_path_symlinks
|
|
58
|
+
end
|
|
59
|
+
Render::Apache.write_htaccess(@config, @config.pages_dir, @config.dest_dir)
|
|
49
60
|
puts
|
|
50
61
|
end
|
|
51
62
|
|
|
@@ -62,6 +73,13 @@ module Amber
|
|
|
62
73
|
@config.dest_dir = dest_dir
|
|
63
74
|
end
|
|
64
75
|
|
|
76
|
+
#
|
|
77
|
+
# find pages by a filter.
|
|
78
|
+
# filter is a string composing a path segment.
|
|
79
|
+
# For example:
|
|
80
|
+
# "chat/security"
|
|
81
|
+
# Which would match "/services/chat/security" but not "/services/security"
|
|
82
|
+
#
|
|
65
83
|
def find_pages(filter)
|
|
66
84
|
filter = filter.downcase
|
|
67
85
|
if filter =~ /\//
|
|
@@ -89,54 +107,100 @@ module Amber
|
|
|
89
107
|
@page_list
|
|
90
108
|
end
|
|
91
109
|
|
|
92
|
-
def find_page_by_path(path)
|
|
93
|
-
|
|
110
|
+
def find_page_by_path(path, locale=I18n.default_locale)
|
|
111
|
+
if locale.is_a? String
|
|
112
|
+
if I18n.locale_available?(locale)
|
|
113
|
+
locale = locale.to_sym
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
if path.is_a? Array
|
|
117
|
+
path = path.join('/')
|
|
118
|
+
end
|
|
119
|
+
@pages_by_locale_path[locale][path] || @pages_by_path[path]
|
|
94
120
|
end
|
|
95
121
|
|
|
96
122
|
def find_page_by_name(name)
|
|
97
123
|
@pages_by_name[name]
|
|
98
124
|
end
|
|
99
125
|
|
|
126
|
+
#
|
|
127
|
+
# returns the shortest possible path for a page, such that the path doesn't collide with
|
|
128
|
+
# another page or another page's aliases.
|
|
129
|
+
#
|
|
130
|
+
def shortest_path(page)
|
|
131
|
+
path_so_far = []
|
|
132
|
+
page.path.reverse.each do |path_segment|
|
|
133
|
+
path_so_far.push(path_segment)
|
|
134
|
+
path_str = path_so_far.join('/')
|
|
135
|
+
if @pages_by_path[path_str].nil? && short_paths[path_str] == page
|
|
136
|
+
return path_so_far
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
return []
|
|
140
|
+
end
|
|
141
|
+
|
|
100
142
|
private
|
|
101
143
|
|
|
102
|
-
def
|
|
144
|
+
def add_configuration(config)
|
|
145
|
+
config.reset_timestamp
|
|
146
|
+
|
|
103
147
|
# create base_page
|
|
104
148
|
base_page = begin
|
|
105
|
-
if
|
|
106
|
-
@root = StaticPage.new(nil, 'root',
|
|
149
|
+
if config.path.nil?
|
|
150
|
+
@root = StaticPage.new(nil, 'root', config.pages_dir)
|
|
107
151
|
add_page(@root)
|
|
108
152
|
@root
|
|
109
153
|
else
|
|
110
|
-
name = File.basename(
|
|
111
|
-
page = StaticPage.new(find_parent(
|
|
154
|
+
name = File.basename(config.path)
|
|
155
|
+
page = StaticPage.new(find_parent(config.path), name, config.pages_dir, config.path_prefix)
|
|
112
156
|
add_page(page)
|
|
113
157
|
page
|
|
114
158
|
end
|
|
115
159
|
end
|
|
116
|
-
base_page.
|
|
160
|
+
base_page.config = config
|
|
117
161
|
|
|
118
162
|
# load menu and locals
|
|
119
|
-
I18n.load_path += Dir[File.join(
|
|
163
|
+
I18n.load_path += Dir[File.join(config.locales_dir, '/*.{rb,yml,yaml}')] if config.locales_dir
|
|
120
164
|
|
|
121
165
|
# add the full directory tree
|
|
122
166
|
base_page.scan_directory_tree do |page, asset_dir|
|
|
123
167
|
add_page(page) if page
|
|
124
168
|
@dir_list << asset_dir if asset_dir
|
|
125
169
|
end
|
|
126
|
-
@page_paths
|
|
170
|
+
@page_paths += @pages_by_path.keys
|
|
171
|
+
|
|
172
|
+
# recursively add sub-sites
|
|
173
|
+
config.children.each do |sub_config|
|
|
174
|
+
add_configuration(sub_config)
|
|
175
|
+
end
|
|
127
176
|
end
|
|
128
177
|
|
|
178
|
+
#
|
|
179
|
+
# registers a page with the site, indexing the page path in our various hashes
|
|
180
|
+
#
|
|
129
181
|
def add_page(page)
|
|
130
182
|
@pages_by_name[page.name] = page
|
|
131
183
|
@pages_by_path[page.path.join('/')] = page
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
184
|
+
add_aliases(I18n.default_locale, page, @pages_by_path)
|
|
185
|
+
page.locales.each do |locale|
|
|
186
|
+
next if locale == I18n.default_locale
|
|
187
|
+
add_aliases(locale, page, @pages_by_locale_path[locale])
|
|
188
|
+
end
|
|
189
|
+
@page_list << page
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
#
|
|
193
|
+
# registers a page's aliases with the site
|
|
194
|
+
#
|
|
195
|
+
def add_aliases(locale, page, path_hash)
|
|
196
|
+
page.aliases(locale).each do |alias_path|
|
|
197
|
+
alias_path_str = alias_path.join('/')
|
|
198
|
+
if path_hash[alias_path_str]
|
|
199
|
+
Amber.logger.warn "WARNING: page `#{page.path.join('/')}` has alias `#{alias_path_str}`, but this path is already taken by `#{path_hash[alias_path_str].path.join('/')}` (locale = #{locale})."
|
|
135
200
|
else
|
|
136
|
-
|
|
201
|
+
path_hash[alias_path_str] = page
|
|
137
202
|
end
|
|
138
203
|
end
|
|
139
|
-
@page_list << page
|
|
140
204
|
end
|
|
141
205
|
|
|
142
206
|
def find_parent(path)
|
|
@@ -150,5 +214,83 @@ module Amber
|
|
|
150
214
|
return @root
|
|
151
215
|
end
|
|
152
216
|
|
|
217
|
+
#
|
|
218
|
+
# adds symlinks for all possible 'short paths' for every page.
|
|
219
|
+
# this works by:
|
|
220
|
+
# (1) examine all pages in order of longest path depth and assign 'short paths' for each page.
|
|
221
|
+
# (2) examine all short paths in order of shortest path depth and create symlinks
|
|
222
|
+
#
|
|
223
|
+
def render_short_path_symlinks
|
|
224
|
+
short_paths.each do |path, page|
|
|
225
|
+
page.link_page_aliases(@config.dest_dir, [path])
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
#
|
|
230
|
+
# returns a hash containing all the automatically determined shortest paths for every page.
|
|
231
|
+
# the data structure looks like so:
|
|
232
|
+
#
|
|
233
|
+
# {
|
|
234
|
+
# "ddd" => <page 'bbb/ddd'>,
|
|
235
|
+
# "ccc" => <page 'bbb/ccc'>,
|
|
236
|
+
# "red" => <page 'autoalias/red'>,
|
|
237
|
+
# "blue"=> <page 'autoalias/blue'>,
|
|
238
|
+
# "red/blue" => <page 'autoalias/red/blue'>
|
|
239
|
+
# }
|
|
240
|
+
#
|
|
241
|
+
# short_paths does not include the normal paths or normal aliases, just the automatic short path aliases.
|
|
242
|
+
#
|
|
243
|
+
def short_paths
|
|
244
|
+
@short_paths ||= begin
|
|
245
|
+
hash = {}
|
|
246
|
+
pages_in_path_depth_order.each do |record|
|
|
247
|
+
page = record[:page]
|
|
248
|
+
path = record[:path]
|
|
249
|
+
next if path.length == 1
|
|
250
|
+
path_prefix = path.dup
|
|
251
|
+
path.length.times do |depth|
|
|
252
|
+
path_prefix.shift
|
|
253
|
+
path_str = path_prefix.join('/')
|
|
254
|
+
if @pages_by_path[path_str].nil? && hash[path_str].nil?
|
|
255
|
+
hash[path_str] = page
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
# debug:
|
|
260
|
+
#hash.each do |path, record|
|
|
261
|
+
# puts "#{record[:page].path.join('/')} => #{record[:path].join('/')}"
|
|
262
|
+
#end
|
|
263
|
+
hash
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
#
|
|
268
|
+
# Returns an array like this:
|
|
269
|
+
#
|
|
270
|
+
# [
|
|
271
|
+
# {:page => <page1>, :path => ['a', 'page1']},
|
|
272
|
+
# {:page => <page2>, :path => ['a','b', 'page2']},
|
|
273
|
+
# ]
|
|
274
|
+
#
|
|
275
|
+
# This array is sorted by the depth of the path (shortest first)
|
|
276
|
+
# Pages will appear multiple times (once for each path, including aliases)
|
|
277
|
+
#
|
|
278
|
+
def pages_in_path_depth_order
|
|
279
|
+
paths = {}
|
|
280
|
+
@page_list.each do |page|
|
|
281
|
+
paths[page.path] ||= page
|
|
282
|
+
locales = page.locales
|
|
283
|
+
locales << I18n.default_locale unless locales.include? I18n.default_locale
|
|
284
|
+
locales.each do |locale|
|
|
285
|
+
page.aliases(locale).each do |alias_path|
|
|
286
|
+
paths[alias_path] ||= page
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
paths.collect{|path, page| {page:page, path:path}}.sort{|a,b|
|
|
291
|
+
a[:path].length <=> a[:path].length
|
|
292
|
+
}
|
|
293
|
+
end
|
|
294
|
+
|
|
153
295
|
end
|
|
154
296
|
end
|