amber 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +661 -0
- data/README.md +114 -0
- data/bin/amber +71 -0
- data/lib/amber.rb +76 -0
- data/lib/amber/cli.rb +98 -0
- data/lib/amber/logger.rb +21 -0
- data/lib/amber/menu.rb +141 -0
- data/lib/amber/page_array.rb +61 -0
- data/lib/amber/render/asset.rb +55 -0
- data/lib/amber/render/autolink.rb +78 -0
- data/lib/amber/render/bracketlink.rb +33 -0
- data/lib/amber/render/helpers/haml_helper.rb +54 -0
- data/lib/amber/render/helpers/html_helper.rb +75 -0
- data/lib/amber/render/helpers/language_helper.rb +25 -0
- data/lib/amber/render/helpers/navigation_helper.rb +203 -0
- data/lib/amber/render/layout.rb +66 -0
- data/lib/amber/render/table_of_contents.rb +383 -0
- data/lib/amber/render/template.rb +158 -0
- data/lib/amber/render/view.rb +189 -0
- data/lib/amber/server.rb +113 -0
- data/lib/amber/site.rb +154 -0
- data/lib/amber/site_configuration.rb +132 -0
- data/lib/amber/static_page.rb +151 -0
- data/lib/amber/static_page/filesystem.rb +270 -0
- data/lib/amber/static_page/page_properties.rb +124 -0
- data/lib/amber/static_page/property_set.rb +78 -0
- data/lib/amber/static_page/render.rb +122 -0
- metadata +203 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Array of StaticPages
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'bigdecimal'
|
6
|
+
|
7
|
+
module Amber
|
8
|
+
class PageArray < Array
|
9
|
+
|
10
|
+
def limit(num)
|
11
|
+
PageArray.new(self[0..(num-1)])
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# available options:
|
16
|
+
#
|
17
|
+
# :locale -- the locale to use when comparing attributes
|
18
|
+
# :direction -- either :asc or :desc
|
19
|
+
# :numeric -- if true, attributes are cast as numbers before comparison
|
20
|
+
#
|
21
|
+
def order_by(attr, options={})
|
22
|
+
locale = options[:locale] || I18n.locale
|
23
|
+
direction = options[:direction] || :asc
|
24
|
+
array = sort do |a,b|
|
25
|
+
if direction == :desc
|
26
|
+
a, b = b, a
|
27
|
+
end
|
28
|
+
a_prop = a.prop(locale, attr)
|
29
|
+
b_prop = b.prop(locale, attr)
|
30
|
+
if options[:numeric]
|
31
|
+
a_prop = to_numeric(a_prop)
|
32
|
+
b_prop = to_numeric(b_prop)
|
33
|
+
end
|
34
|
+
if a_prop.nil? && b_prop.nil?
|
35
|
+
0
|
36
|
+
elsif a_prop.nil?
|
37
|
+
1
|
38
|
+
elsif b_prop.nil?
|
39
|
+
-1
|
40
|
+
else
|
41
|
+
a_prop <=> b_prop
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# remove pages from the results that have no value set for the attr
|
45
|
+
array.delete_if do |page|
|
46
|
+
page.prop(locale, attr).nil?
|
47
|
+
end
|
48
|
+
return PageArray.new.replace array
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_numeric(anything)
|
52
|
+
num = BigDecimal.new(anything.to_s)
|
53
|
+
if num.frac == 0
|
54
|
+
num.to_i
|
55
|
+
else
|
56
|
+
num.to_f
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#
|
2
|
+
# For rendering things that are assets, like sass files.
|
3
|
+
# Maybe images too?
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'sass'
|
7
|
+
|
8
|
+
module Amber
|
9
|
+
module Render
|
10
|
+
class Asset
|
11
|
+
|
12
|
+
RENDER_MAP = {
|
13
|
+
'.sass' => {:method => 'render_sass', :new_suffix => '.css', :args => [:sass]},
|
14
|
+
'.scss' => {:method => 'render_sass', :new_suffix => '.css', :args => [:scss]}
|
15
|
+
}
|
16
|
+
|
17
|
+
def self.render(src_file, dst_file)
|
18
|
+
unless Dir.exists?(File.dirname(dst_file))
|
19
|
+
FileUtils.mkdir_p(File.dirname(dst_file))
|
20
|
+
end
|
21
|
+
File.unlink(dst_file) if File.exists?(dst_file)
|
22
|
+
src_ext = File.extname(src_file)
|
23
|
+
renderer = RENDER_MAP[src_ext]
|
24
|
+
if renderer
|
25
|
+
content = self.send(renderer[:method], *([src_file] + renderer[:args]))
|
26
|
+
new_dst_file = dst_file.sub(/#{Regexp.escape(src_ext)}$/, renderer[:new_suffix])
|
27
|
+
File.open(new_dst_file,'w') do |w|
|
28
|
+
w.write(content)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
File.link(src_file, dst_file)
|
32
|
+
end
|
33
|
+
rescue SystemCallError => exc
|
34
|
+
Amber.log_exception(exc)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.render_dir(src_dir, dst_dir)
|
38
|
+
Dir.chdir(src_dir) do
|
39
|
+
Dir.glob('*').each do |file|
|
40
|
+
next if File.directory?(file) || file =~ /^\./
|
41
|
+
src_file = File.join(src_dir, file)
|
42
|
+
dst_file = File.join(dst_dir, file)
|
43
|
+
render(src_file, dst_file)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.render_sass(src_file, syntax)
|
49
|
+
engine = Sass::Engine.new(File.read(src_file), :syntax => syntax)
|
50
|
+
engine.render
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# adapted from https://github.com/tenderlove/rails_autolink
|
3
|
+
# MIT license
|
4
|
+
|
5
|
+
module Amber::Render::Autolink
|
6
|
+
|
7
|
+
def self.auto_link(text)
|
8
|
+
auto_link_email_addresses(auto_link_urls(text))
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
AUTO_LINK_RE = %r{
|
14
|
+
(?: ((?:ed2k|ftp|http|https|irc|mailto|news|gopher|nntp|telnet|webcal|xmpp|callto|feed|svn|urn|aim|rsync|tag|ssh|sftp|rtsp|afs|file):)// | www\. )
|
15
|
+
[^\s<\u00A0]+
|
16
|
+
}ix
|
17
|
+
|
18
|
+
# regexps for determining context, used high-volume
|
19
|
+
AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, /<\/a>/i]
|
20
|
+
|
21
|
+
AUTO_EMAIL_LOCAL_RE = /[\w.!#\$%&'*\/=?^`{|}~+-]/
|
22
|
+
AUTO_EMAIL_RE = /[\w.!#\$%+-]\.?#{AUTO_EMAIL_LOCAL_RE}*@[\w-]+(?:\.[\w-]+)+/
|
23
|
+
|
24
|
+
BRACKETS = { ']' => '[', ')' => '(', '}' => '{' }
|
25
|
+
|
26
|
+
WORD_PATTERN = RUBY_VERSION < '1.9' ? '\w' : '\p{Word}'
|
27
|
+
|
28
|
+
# Turns all urls into clickable links. If a block is given, each url
|
29
|
+
# is yielded and the result is used as the link text.
|
30
|
+
def self.auto_link_urls(text)
|
31
|
+
text.gsub(AUTO_LINK_RE) do
|
32
|
+
scheme, href = $1, $&
|
33
|
+
punctuation = []
|
34
|
+
|
35
|
+
if auto_linked?($`, $')
|
36
|
+
# do not change string; URL is already linked
|
37
|
+
href
|
38
|
+
else
|
39
|
+
# don't include trailing punctuation character as part of the URL
|
40
|
+
while href.sub!(/[^#{WORD_PATTERN}\/-]$/, '')
|
41
|
+
punctuation.push $&
|
42
|
+
if opening = BRACKETS[punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
|
43
|
+
href << punctuation.pop
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
#link_text = block_given?? yield(href) : href
|
49
|
+
link_text = href.sub(/^#{scheme}\/\//,'')
|
50
|
+
href = 'http://' + href unless scheme
|
51
|
+
%(<a href="#{href}">#{link_text}</a>) + punctuation.reverse.join('')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Turns all email addresses into clickable links.
|
57
|
+
def self.auto_link_email_addresses(text)
|
58
|
+
text.gsub(AUTO_EMAIL_RE) do
|
59
|
+
text = $&
|
60
|
+
|
61
|
+
if auto_linked?($`, $')
|
62
|
+
text
|
63
|
+
else
|
64
|
+
#display_text = (block_given?) ? yield(text) : text
|
65
|
+
#display_text = text
|
66
|
+
text.gsub!('@', '@').gsub!('.', '.')
|
67
|
+
%(<a href="mailto:#{text}">#{text}</a>)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Detects already linked context or position in the middle of a tag
|
73
|
+
def self.auto_linked?(left, right)
|
74
|
+
(left =~ AUTO_LINK_CRE[0] and right =~ AUTO_LINK_CRE[1]) or
|
75
|
+
(left.rindex(AUTO_LINK_CRE[2]) and $' !~ AUTO_LINK_CRE[3])
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#
|
4
|
+
# bracket links are links in the form [[label => target]] or [[page-name]]
|
5
|
+
#
|
6
|
+
|
7
|
+
module Amber::Render::Bracketlink
|
8
|
+
|
9
|
+
# linking using double square brackets
|
10
|
+
BRACKET_LINK_RE = /
|
11
|
+
\[\[ # start [[
|
12
|
+
([^\[\]]+) # $text : one or more characters that are not [ or ] ($1)
|
13
|
+
\]\] # end ]]
|
14
|
+
/x
|
15
|
+
|
16
|
+
def self.bracket_link(text, &block)
|
17
|
+
text.gsub(BRACKET_LINK_RE) do |m|
|
18
|
+
link_text = $~[1].strip
|
19
|
+
if link_text =~ /^.+\s*[-=]>\s*.+$/
|
20
|
+
# link_text == "from -> to"
|
21
|
+
from, to = link_text.split(/\s*[-=]>\s*/)[0..1]
|
22
|
+
from = "" unless from.instance_of? String # \ sanity check for
|
23
|
+
to = "" unless from.instance_of? String # / badly formed links
|
24
|
+
else
|
25
|
+
# link_text == "to" (ie, no link label)
|
26
|
+
from = nil
|
27
|
+
to = link_text
|
28
|
+
end
|
29
|
+
yield(from, to)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module HamlHelper
|
4
|
+
|
5
|
+
#
|
6
|
+
# acts like haml_tag, capture_haml, or haml_concat, depending on how it is called.
|
7
|
+
#
|
8
|
+
# two or more args --> like haml_tag
|
9
|
+
# one arg and a block --> like haml_tag
|
10
|
+
# zero args and a block --> like capture_haml
|
11
|
+
# one arg and no block --> like haml_concat
|
12
|
+
#
|
13
|
+
# additionally, we allow the use of more than one class.
|
14
|
+
#
|
15
|
+
# some examples of these usages:
|
16
|
+
#
|
17
|
+
# def display_robot(robot)
|
18
|
+
# haml do # like capture_haml
|
19
|
+
# haml '.head', robot.head_html # like haml_tag
|
20
|
+
# haml '.head' do # same
|
21
|
+
# haml robot.head_html
|
22
|
+
# end
|
23
|
+
# haml '.body.metal', robot.body_html # like haml_tag, but with multiple classes
|
24
|
+
# haml '<a href="/x">link</a>' # like haml_concat
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# wrapping the helper in a capture_haml call is very useful, because then
|
29
|
+
# the helper can be used wherever a normal helper would be.
|
30
|
+
#
|
31
|
+
def haml(name=nil, *args, &block)
|
32
|
+
if name
|
33
|
+
if args.empty? and block.nil?
|
34
|
+
haml_concat name
|
35
|
+
else
|
36
|
+
if name =~ /^(.*?\.[^\.]*)(\..*)$/
|
37
|
+
# allow chaining of classes if there are multiple '.' in the first arg
|
38
|
+
name = $1
|
39
|
+
classes = $2.gsub('.',' ')
|
40
|
+
hsh = args.detect{|i| i.is_a?(Hash)}
|
41
|
+
unless hsh
|
42
|
+
hsh = {}
|
43
|
+
args << hsh
|
44
|
+
end
|
45
|
+
hsh[:class] = classes
|
46
|
+
end
|
47
|
+
haml_tag(name, *args, &block)
|
48
|
+
end
|
49
|
+
else
|
50
|
+
capture_haml(&block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Amber
|
2
|
+
module Render
|
3
|
+
module HtmlHelper
|
4
|
+
|
5
|
+
def html_head_base
|
6
|
+
href = (['..'] * @page.path.count).join('/')
|
7
|
+
"<base href=\"#{href}\" />"
|
8
|
+
end
|
9
|
+
|
10
|
+
#
|
11
|
+
# three forms:
|
12
|
+
#
|
13
|
+
# (1) link('page-name')
|
14
|
+
# (2) link('label' => 'page-name')
|
15
|
+
# (3) link('label' => 'https://url')
|
16
|
+
#
|
17
|
+
# both accept optional options hash:
|
18
|
+
#
|
19
|
+
# (1) link('page-name', :class => 'x')
|
20
|
+
# (2) link('label' => 'page-name', :class => 'x')
|
21
|
+
#
|
22
|
+
def link(name, options=nil)
|
23
|
+
options = nil if options && !options.is_a?(Hash)
|
24
|
+
if name.is_a? Hash
|
25
|
+
klass = name.delete(:class)
|
26
|
+
label, name = name.to_a.first
|
27
|
+
if label.is_a? Symbol
|
28
|
+
label = I18n.t label
|
29
|
+
end
|
30
|
+
else
|
31
|
+
klass = options[:class] if options
|
32
|
+
end
|
33
|
+
if name =~ /^#/ || name =~ /^http/ || name =~ /\./
|
34
|
+
path = name
|
35
|
+
label ||= name
|
36
|
+
else
|
37
|
+
if index = name.index('#')
|
38
|
+
anchor = name[index..-1]
|
39
|
+
name_without_anchor = name[0..(index-1)]
|
40
|
+
else
|
41
|
+
anchor = ''
|
42
|
+
name_without_anchor = name
|
43
|
+
end
|
44
|
+
page = @site.find_page(name_without_anchor)
|
45
|
+
if page
|
46
|
+
label ||= page.nav_title
|
47
|
+
path = page_path(page) + anchor
|
48
|
+
else
|
49
|
+
puts "warning: dead link to `#{name_without_anchor}` from page `/#{I18n.locale}/#{@page.path.join('/')}`"
|
50
|
+
label ||= name_without_anchor
|
51
|
+
label += ' [dead link]'
|
52
|
+
path = name_without_anchor
|
53
|
+
end
|
54
|
+
end
|
55
|
+
if klass
|
56
|
+
%(<a href="#{path}" class="#{klass}">#{label}</a>)
|
57
|
+
else
|
58
|
+
%(<a href="#{path}">#{label}</a>)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# returns the shortest possible path. this would be nice to support some day, but more difficult with statically rendered sites.
|
64
|
+
#
|
65
|
+
def page_path(page, locale=I18n.locale)
|
66
|
+
if page.prop(locale, :alias)
|
67
|
+
"/#{locale}/#{page.prop(locale, :alias).first}/#{page.name}"
|
68
|
+
else
|
69
|
+
"/#{locale}/#{page.path.join('/')}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Amber
|
2
|
+
module Render
|
3
|
+
module LanguageHelper
|
4
|
+
|
5
|
+
def t(*args)
|
6
|
+
I18n.t(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def translation_missing?
|
10
|
+
!@page.content_file_exists?(I18n.locale)
|
11
|
+
end
|
12
|
+
|
13
|
+
# return array of arrays, each array with: language_name, language_code, current_url_with_locale_switch
|
14
|
+
#
|
15
|
+
# [ ['English', :en, 'en/about-us'] ]
|
16
|
+
#
|
17
|
+
def available_languages
|
18
|
+
@site.locales.collect { |locale|
|
19
|
+
[Amber::POSSIBLE_LANGUAGES[locale][0], locale, "/"+([locale]+current_page_path).join('/')]
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module Amber
|
2
|
+
module Render
|
3
|
+
module NavigationHelper
|
4
|
+
|
5
|
+
def has_navigation?
|
6
|
+
if current_page_path.empty? || @site.menu.nil?
|
7
|
+
false
|
8
|
+
else
|
9
|
+
submenu = @site.menu.submenu(current_page_path.first)
|
10
|
+
if submenu
|
11
|
+
second_level_children_count = submenu.size
|
12
|
+
if second_level_children_count.nil?
|
13
|
+
false
|
14
|
+
else
|
15
|
+
second_level_children_count >= 1
|
16
|
+
end
|
17
|
+
else
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# yields each item
|
25
|
+
#
|
26
|
+
def top_navigation_items(options={})
|
27
|
+
if !@site.menu
|
28
|
+
yield({})
|
29
|
+
else
|
30
|
+
first = 'first'
|
31
|
+
if options[:include_home]
|
32
|
+
active = current_page_path.empty? ? 'active' : ''
|
33
|
+
yield({:class => [first, active].compact.join(' '), :href => menu_item_path(@site.menu), :label => menu_item_title(@site.menu)})
|
34
|
+
first = nil
|
35
|
+
end
|
36
|
+
@site.menu.each do |item|
|
37
|
+
active = current_page_path.first == item.name ? 'active' : ''
|
38
|
+
yield({:class => [first, active].compact.join(' '), :href => menu_item_path(item), :label => menu_item_title(item)})
|
39
|
+
first = nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# yields each item
|
46
|
+
#
|
47
|
+
def navigation_items(menu=nil, level=1, &block)
|
48
|
+
if menu.nil?
|
49
|
+
menu = site.menu.submenu(current_page_path.first)
|
50
|
+
end
|
51
|
+
if menu
|
52
|
+
menu.each do |item|
|
53
|
+
title = menu_item_title(item)
|
54
|
+
if title
|
55
|
+
yield({
|
56
|
+
:href => menu_item_path(item),
|
57
|
+
:level => level,
|
58
|
+
:active => path_active_class(current_page_path, item),
|
59
|
+
:label => title
|
60
|
+
})
|
61
|
+
end
|
62
|
+
if path_open?(current_page_path, item)
|
63
|
+
navigation_items(item.submenu, level+1, &block)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def current_page_path
|
70
|
+
@current_page_path ||= begin
|
71
|
+
if @page
|
72
|
+
@page.path
|
73
|
+
#elsif params[:page].is_a? String
|
74
|
+
# params[:page].split('/')
|
75
|
+
else
|
76
|
+
[]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def menu_item_path(item)
|
82
|
+
"/" + ([I18n.locale]+item.path).join('/')
|
83
|
+
end
|
84
|
+
|
85
|
+
def menu_item_title(item)
|
86
|
+
page = @site.find_page_by_path(item.path_str) || @site.find_page_by_name(item.name)
|
87
|
+
if page
|
88
|
+
page.nav_title(I18n.locale)
|
89
|
+
else
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# inserts an directory index built from the page's children
|
96
|
+
#
|
97
|
+
# options:
|
98
|
+
# :levels -- the max levels to descend, default is 1
|
99
|
+
# :page -- StaticPage instance or nil
|
100
|
+
# :include_toc -- true or false
|
101
|
+
# :order_by -- arguments to PageArray#order_by
|
102
|
+
# :heading -- heading level to use
|
103
|
+
#
|
104
|
+
def child_summaries(options={})
|
105
|
+
page = options.delete(:page) || @page
|
106
|
+
unless page.is_a?(StaticPage)
|
107
|
+
page = @site.find_pages(page)
|
108
|
+
end
|
109
|
+
return "" if page.nil? or page.children.empty?
|
110
|
+
|
111
|
+
levels_max = options[:levels] || 1
|
112
|
+
level = options.delete(:level) || 1
|
113
|
+
heading = options.delete(:heading) || 2
|
114
|
+
locale = @locals[:locale]
|
115
|
+
menu = submenu_for_page(page)
|
116
|
+
if menu && menu.children.any?
|
117
|
+
children = menu.children
|
118
|
+
elsif options[:order_by]
|
119
|
+
children = page.children.order_by(*options[:order_by])
|
120
|
+
else
|
121
|
+
children = page.children
|
122
|
+
end
|
123
|
+
|
124
|
+
haml do
|
125
|
+
children.each do |child|
|
126
|
+
child_page = child.is_a?(Amber::Menu) ? page.child(child.name) : child
|
127
|
+
next unless child_page
|
128
|
+
haml "h#{heading}" do
|
129
|
+
haml :a, child_page.nav_title(locale), :href => page_path(child_page)
|
130
|
+
end
|
131
|
+
if summary = child_page.prop(locale, 'summary')
|
132
|
+
haml :p, summary
|
133
|
+
end
|
134
|
+
if options[:include_toc]
|
135
|
+
toc_html = render_toc(child_page, :locale => locale)
|
136
|
+
haml toc_html
|
137
|
+
end
|
138
|
+
if level < levels_max
|
139
|
+
haml(child_summaries({
|
140
|
+
:page => child_page,
|
141
|
+
:levels => levels_max,
|
142
|
+
:level => level+1,
|
143
|
+
:include_toc => options[:include_toc],
|
144
|
+
:order_by => options[:order_by],
|
145
|
+
:heading => heading+1
|
146
|
+
}))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
rescue Exception => exc
|
151
|
+
Amber.log_exception(exc)
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
#
|
157
|
+
# returns string 'active', 'semi-active', or ''
|
158
|
+
#
|
159
|
+
def path_active_class(page_path, menu_item)
|
160
|
+
active = ''
|
161
|
+
if menu_item.path == page_path
|
162
|
+
active = 'active'
|
163
|
+
elsif menu_item.path_prefix_of?(page_path)
|
164
|
+
if menu_item.leaf_for_path?(page_path)
|
165
|
+
active = 'active'
|
166
|
+
else
|
167
|
+
active = 'semi-active'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
active
|
171
|
+
end
|
172
|
+
|
173
|
+
#
|
174
|
+
# returns true if menu_item represents an parent of page
|
175
|
+
#
|
176
|
+
def path_open?(page_path, menu_item)
|
177
|
+
menu_item.path == page_path || menu_item.path_prefix_of?(page_path)
|
178
|
+
end
|
179
|
+
|
180
|
+
def submenu_for_page(page)
|
181
|
+
menu = @site.menu
|
182
|
+
page.path.each do |segment|
|
183
|
+
menu = menu.submenu(segment)
|
184
|
+
end
|
185
|
+
return menu
|
186
|
+
rescue
|
187
|
+
return nil
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
=begin
|
196
|
+
|
197
|
+
def act_as(page)
|
198
|
+
page = site.find_page(page)
|
199
|
+
@current_page_path = page.path
|
200
|
+
page_body(page)
|
201
|
+
end
|
202
|
+
|
203
|
+
=end
|