weaver 0.8.0 → 0.8.1
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 +5 -5
- data/Rakefile +1 -1
- data/bin/console +3 -3
- data/exe/weaver +112 -122
- data/lib/weaver.rb +24 -2654
- data/lib/weaver/element_types/accordion.rb +122 -0
- data/lib/weaver/element_types/action.rb +38 -0
- data/lib/weaver/element_types/code.rb +81 -0
- data/lib/weaver/element_types/dynamic_table.rb +324 -0
- data/lib/weaver/element_types/dynamic_table_cell.rb +16 -0
- data/lib/weaver/element_types/form.rb +47 -0
- data/lib/weaver/element_types/form_elements.rb +297 -0
- data/lib/weaver/element_types/javascript_object.rb +28 -0
- data/lib/weaver/element_types/modal_dialog.rb +68 -0
- data/lib/weaver/element_types/panel.rb +124 -0
- data/lib/weaver/element_types/row.rb +117 -0
- data/lib/weaver/element_types/tabs.rb +75 -0
- data/lib/weaver/element_types/textfield_javascript.rb +58 -0
- data/lib/weaver/elements.rb +406 -0
- data/lib/weaver/page_types/center_page.rb +25 -0
- data/lib/weaver/page_types/empty_page.rb +26 -0
- data/lib/weaver/page_types/nav_page.rb +39 -0
- data/lib/weaver/page_types/nonnav_page.rb +35 -0
- data/lib/weaver/page_types/page.rb +234 -0
- data/lib/weaver/page_types/raw_page.rb +17 -0
- data/lib/weaver/page_types/sidenav_page.rb +119 -0
- data/lib/weaver/page_types/structured_page.rb +19 -0
- data/lib/weaver/page_types/topnav_page.rb +167 -0
- data/lib/weaver/version.rb +1 -1
- data/lib/weaver/weave.rb +44 -0
- data/weaver.gemspec +27 -24
- metadata +37 -13
@@ -0,0 +1,25 @@
|
|
1
|
+
module Weaver
|
2
|
+
# Page where all content is centered
|
3
|
+
class CenterPage < Page
|
4
|
+
def initialize(title, global_settings, options, &block)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate(level)
|
9
|
+
elem = Elements.new(self, {})
|
10
|
+
elem.instance_eval(&@block)
|
11
|
+
|
12
|
+
@body_class = 'gray-bg'
|
13
|
+
@content = <<-CONTENT
|
14
|
+
<div class="middle-box text-center animated fadeInDown">
|
15
|
+
<div>
|
16
|
+
#{elem.generate}
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
CONTENT
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Weaver::Weave.register_page_type(:center_page, Weaver::CenterPage)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Weaver
|
2
|
+
# Empty page
|
3
|
+
class EmptyPage < Page
|
4
|
+
def initialize(title, global_settings, options, &block)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate(level)
|
9
|
+
elem = Elements.new(self, {})
|
10
|
+
elem.instance_eval(&@block)
|
11
|
+
@body_class = 'gray-bg'
|
12
|
+
@content = <<-CONTENT
|
13
|
+
<div id="wrapper">
|
14
|
+
<div class="wrapper-content">
|
15
|
+
<div class="container">
|
16
|
+
#{elem.generate}
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
CONTENT
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Weaver::Weave.register_page_type(:empty_page, Weaver::EmptyPage)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'weaver/page_types/structured_page'
|
2
|
+
module Weaver
|
3
|
+
# Pages with navigation menus
|
4
|
+
class NavPage < StructuredPage
|
5
|
+
def initialize(title, global_settings, options, &block)
|
6
|
+
super
|
7
|
+
@menu = Menu.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def menu(&block)
|
11
|
+
@menu.instance_eval(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def brand(text, link = '/')
|
15
|
+
@brand = text
|
16
|
+
@brand_link = link
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Menu used in nav pages
|
21
|
+
class Menu
|
22
|
+
attr_accessor :items
|
23
|
+
def initialize
|
24
|
+
@items = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def nav(name, icon = :question, url = nil, options = {}, &block)
|
28
|
+
if url && !block
|
29
|
+
@items << { name: name, link: url, icon: icon, options: options }
|
30
|
+
elsif block
|
31
|
+
menu = Menu.new
|
32
|
+
menu.instance_eval(&block)
|
33
|
+
@items << { name: name, menu: menu, icon: icon, options: options }
|
34
|
+
else
|
35
|
+
@items << { name: name, link: '#', icon: icon, options: options }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'weaver/page_types/structured_page'
|
2
|
+
module Weaver
|
3
|
+
# Page with no navigation bar
|
4
|
+
class NonNavPage < StructuredPage
|
5
|
+
def initialize(title, global_settings, options, &block)
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def generate(level)
|
10
|
+
instance_eval &@block
|
11
|
+
rows = @rows.map do |row|
|
12
|
+
<<-ENDROW
|
13
|
+
<div class="row #{row.extra_classes}">
|
14
|
+
#{row.generate}
|
15
|
+
</div>
|
16
|
+
ENDROW
|
17
|
+
end.join
|
18
|
+
|
19
|
+
@body_class = 'gray-bg'
|
20
|
+
|
21
|
+
@content = <<-CONTENT
|
22
|
+
<div id="wrapper">
|
23
|
+
<div class="wrapper-content">
|
24
|
+
<div class="container">
|
25
|
+
#{rows}
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
CONTENT
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Weaver::Weave.register_page_type(:nonnav_page, Weaver::NonNavPage)
|
@@ -0,0 +1,234 @@
|
|
1
|
+
module Weaver
|
2
|
+
# Base page class
|
3
|
+
class Page
|
4
|
+
attr_accessor :scripts, :onload_scripts
|
5
|
+
|
6
|
+
def initialize(title, global_settings, options, &block)
|
7
|
+
@title = title
|
8
|
+
@content = ''
|
9
|
+
@body_class = nil
|
10
|
+
@anchors = {}
|
11
|
+
@global_settings = global_settings
|
12
|
+
@options = options
|
13
|
+
@scripts = []
|
14
|
+
@top_content = ''
|
15
|
+
|
16
|
+
@scripts_once = {}
|
17
|
+
@onload_scripts = []
|
18
|
+
|
19
|
+
@requested_scripts = {}
|
20
|
+
@requested_css = {}
|
21
|
+
|
22
|
+
@background = Elements.new(self, @anchors)
|
23
|
+
|
24
|
+
@block = Proc.new &block
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_anchor(name)
|
28
|
+
@anchors[name] = [] unless @anchors[name]
|
29
|
+
|
30
|
+
anchor_array = @anchors[name]
|
31
|
+
|
32
|
+
anchor_name = "#{name}#{anchor_array.length}"
|
33
|
+
anchor_array << anchor_name
|
34
|
+
|
35
|
+
anchor_name
|
36
|
+
end
|
37
|
+
|
38
|
+
def root
|
39
|
+
@global_settings[:root]
|
40
|
+
end
|
41
|
+
|
42
|
+
def request_js(path)
|
43
|
+
@requested_scripts[path] = true
|
44
|
+
end
|
45
|
+
|
46
|
+
def request_css(path)
|
47
|
+
@requested_css[path] = true
|
48
|
+
end
|
49
|
+
|
50
|
+
def on_page_load(script)
|
51
|
+
@onload_scripts << script
|
52
|
+
end
|
53
|
+
|
54
|
+
def write_script_once(script)
|
55
|
+
@scripts_once[script] = true
|
56
|
+
end
|
57
|
+
|
58
|
+
def background(&block)
|
59
|
+
@background.instance_eval(&block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def top(&block)
|
63
|
+
elem = Elements.new(self, @anchors)
|
64
|
+
elem.instance_eval(&block)
|
65
|
+
|
66
|
+
@top_content = elem.generate
|
67
|
+
end
|
68
|
+
|
69
|
+
def generate(back_folders, options = {})
|
70
|
+
if @options[:cache_file]
|
71
|
+
expired = @options[:cache_expired]
|
72
|
+
cache_exist = File.exist?("cache/cachedpage#{@options[:cache_file]}")
|
73
|
+
|
74
|
+
if cache_exist && !expired
|
75
|
+
puts "Weaver Hit cache for file: #{@options[:cache_file]}"
|
76
|
+
puts "- expired: #{expired}"
|
77
|
+
puts "- cache_exist: #{cache_exist}"
|
78
|
+
return File.read("cache/cachedpage#{@options[:cache_file]}")
|
79
|
+
end
|
80
|
+
puts "Weaver Miss cache for file: #{@options[:cache_file]}"
|
81
|
+
puts "- expired: #{expired}"
|
82
|
+
puts "- cache_exist: #{cache_exist}"
|
83
|
+
end
|
84
|
+
|
85
|
+
scripts = @scripts.join("\n")
|
86
|
+
|
87
|
+
mod = '../' * back_folders
|
88
|
+
|
89
|
+
style = <<-ENDSTYLE
|
90
|
+
<link href="#{mod}css/style.css" rel="stylesheet">
|
91
|
+
ENDSTYLE
|
92
|
+
|
93
|
+
style = '' if options[:style] == :empty
|
94
|
+
|
95
|
+
body_tag = '<body>'
|
96
|
+
|
97
|
+
body_tag = "<body class='#{@body_class}'>" if @body_class
|
98
|
+
|
99
|
+
loading_bar = ''
|
100
|
+
loading_bar = "<script src='#{mod}js/plugins/pace/pace.min.js'></script>" if @loading_bar_visible
|
101
|
+
|
102
|
+
extra_scripts = @requested_scripts.map do |key, _value|
|
103
|
+
<<-SCRIPT_DECL
|
104
|
+
<script src="#{mod}#{key}"></script>
|
105
|
+
SCRIPT_DECL
|
106
|
+
end.join "\n"
|
107
|
+
|
108
|
+
extra_css = @requested_css.map do |key, _value|
|
109
|
+
<<-STYLESHEET_DECL
|
110
|
+
<link href="#{mod}#{key}" rel="stylesheet">
|
111
|
+
STYLESHEET_DECL
|
112
|
+
end.join "\n"
|
113
|
+
|
114
|
+
extra_one_time_scripts = @scripts_once.map do |key, _value|
|
115
|
+
<<-SCRIPT_DECL
|
116
|
+
#{key}
|
117
|
+
SCRIPT_DECL
|
118
|
+
end.join "\n"
|
119
|
+
|
120
|
+
onload_scripts = @onload_scripts.map do |value|
|
121
|
+
<<-SCRIPT_DECL
|
122
|
+
#{value}
|
123
|
+
SCRIPT_DECL
|
124
|
+
end.join "\n"
|
125
|
+
|
126
|
+
extra_stuff = ''
|
127
|
+
|
128
|
+
if @global_settings[:mixpanel_token]
|
129
|
+
extra_stuff += '<!-- start Mixpanel --><script type="text/javascript">(function(e,a){if(!a.__SV){var b=window;try{var c,l,i,j=b.location,g=j.hash;c=function(a,b){return(l=a.match(RegExp(b+"=([^&]*)")))?l[1]:null};g&&c(g,"state")&&(i=JSON.parse(decodeURIComponent(c(g,"state"))),"mpeditor"===i.action&&(b.sessionStorage.setItem("_mpcehash",g),history.replaceState(i.desiredHash||"",e.title,j.pathname+j.search)))}catch(m){}var k,h;window.mixpanel=a;a._i=[];a.init=function(b,c,f){function e(b,a){var c=a.split(".");2==c.length&&(b=b[c[0]],a=c[1]);b[a]=function(){b.push([a].concat(Array.prototype.slice.call(arguments,
|
130
|
+
0)))}}var d=a;"undefined"!==typeof f?d=a[f]=[]:f="mixpanel";d.people=d.people||[];d.toString=function(b){var a="mixpanel";"mixpanel"!==f&&(a+="."+f);b||(a+=" (stub)");return a};d.people.toString=function(){return d.toString(1)+".people (stub)"};k="disable time_event track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
|
131
|
+
for(h=0;h<k.length;h++)e(d,k[h]);a._i.push([b,c,f])};a.__SV=1.2;b=e.createElement("script");b.type="text/javascript";b.async=!0;b.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===e.location.protocol&&"//cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js";c=e.getElementsByTagName("script")[0];c.parentNode.insertBefore(b,c)}})(document,window.mixpanel||[]);
|
132
|
+
mixpanel.init("' + @global_settings[:mixpanel_token] + '");</script><!-- end Mixpanel -->'
|
133
|
+
end
|
134
|
+
|
135
|
+
if @global_settings[:google_tracking_code]
|
136
|
+
extra_stuff += <<-GOOGLE
|
137
|
+
<!-- Global site tag (gtag.js) - Google Analytics -->
|
138
|
+
<script async src="https://www.googletagmanager.com/gtag/js?id=#{@global_settings[:google_tracking_code]}"></script>
|
139
|
+
<script>
|
140
|
+
window.dataLayer = window.dataLayer || [];
|
141
|
+
function gtag(){dataLayer.push(arguments);}
|
142
|
+
gtag('js', new Date());
|
143
|
+
|
144
|
+
gtag('config', '#{@global_settings[:google_tracking_code]}');
|
145
|
+
</script>
|
146
|
+
GOOGLE
|
147
|
+
end
|
148
|
+
|
149
|
+
result = <<-SKELETON
|
150
|
+
<!DOCTYPE html>
|
151
|
+
<html>
|
152
|
+
<!-- Generated using weaver: https://github.com/davidsiaw/weaver -->
|
153
|
+
<head>
|
154
|
+
|
155
|
+
<meta charset="utf-8">
|
156
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
157
|
+
|
158
|
+
<title>#{@title}</title>
|
159
|
+
|
160
|
+
<link href="#{mod}css/bootstrap.min.css" rel="stylesheet">
|
161
|
+
<link href="#{mod}font-awesome/css/font-awesome.css" rel="stylesheet">
|
162
|
+
<link href="#{mod}css/plugins/iCheck/custom.css" rel="stylesheet">
|
163
|
+
|
164
|
+
#{style}
|
165
|
+
|
166
|
+
<link href="#{mod}css/animate.css" rel="stylesheet">
|
167
|
+
|
168
|
+
#{extra_css}
|
169
|
+
|
170
|
+
#{extra_stuff}
|
171
|
+
|
172
|
+
</head>
|
173
|
+
|
174
|
+
#{body_tag}
|
175
|
+
|
176
|
+
<div id="background" style="z-index: -999; position:absolute; left:0px; right:0px; width:100%; height:100%">
|
177
|
+
#{@background.generate}
|
178
|
+
</div>
|
179
|
+
|
180
|
+
<div id="content" style="z-index: 0">
|
181
|
+
#{@top_content}
|
182
|
+
#{@content}
|
183
|
+
</div>
|
184
|
+
|
185
|
+
<!-- Mainly scripts -->
|
186
|
+
<script src="#{mod}js/jquery-3.1.1.min.js"></script>
|
187
|
+
<script src="#{mod}js/jquery-ui-1.10.4.min.js"></script>
|
188
|
+
<script src="#{mod}js/bootstrap.min.js"></script>
|
189
|
+
<script src="#{mod}js/plugins/metisMenu/jquery.metisMenu.js"></script>
|
190
|
+
<script src="#{mod}js/plugins/slimscroll/jquery.slimscroll.min.js"></script>
|
191
|
+
<script type="text/x-mathjax-config">
|
192
|
+
MathJax.Hub.Config({
|
193
|
+
asciimath2jax: {
|
194
|
+
delimiters: [['$$$MATH$$$','$$$ENDMATH$$$']]
|
195
|
+
}
|
196
|
+
});
|
197
|
+
</script>
|
198
|
+
<script src="#{mod}js/MathJax/MathJax.js?config=AM_HTMLorMML-full" async></script>
|
199
|
+
|
200
|
+
#{extra_scripts}
|
201
|
+
|
202
|
+
|
203
|
+
<!-- Custom and plugin javascript -->
|
204
|
+
<script src="#{mod}js/weaver.js"></script>
|
205
|
+
#{loading_bar}
|
206
|
+
|
207
|
+
<script>
|
208
|
+
#{scripts}
|
209
|
+
#{extra_one_time_scripts}
|
210
|
+
|
211
|
+
$( document ).ready(function() {
|
212
|
+
|
213
|
+
#{onload_scripts}
|
214
|
+
|
215
|
+
});
|
216
|
+
</script>
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
</body>
|
221
|
+
|
222
|
+
</html>
|
223
|
+
|
224
|
+
SKELETON
|
225
|
+
|
226
|
+
if @options[:cache_file]
|
227
|
+
FileUtils.mkdir_p 'cache'
|
228
|
+
File.write("cache/cachedpage#{@options[:cache_file]}", result)
|
229
|
+
end
|
230
|
+
|
231
|
+
result
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Weaver
|
2
|
+
# Raw oage with no html
|
3
|
+
class RawPage < Page
|
4
|
+
def initialize(title, global_settings, options, &block)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
def generate(_back_folders, _options = {})
|
9
|
+
elem = Elements.new(self, {})
|
10
|
+
elem.instance_eval(&@block)
|
11
|
+
|
12
|
+
elem.generate
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Weaver::Weave.register_page_type(:raw_page, Weaver::RawPage)
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'weaver/page_types/nav_page'
|
2
|
+
module Weaver
|
3
|
+
class SideNavPage < NavPage
|
4
|
+
def initialize(title, global_settings, options, &block)
|
5
|
+
super
|
6
|
+
@body_class = "#{@body_class} fixed-sidebar"
|
7
|
+
end
|
8
|
+
|
9
|
+
def keep_icons_when_hidden
|
10
|
+
arr = @body_class.to_s.split(' ')
|
11
|
+
@body_class = arr.reject { |x| x == 'fixed-sidebar' }.join(' ')
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate(level)
|
15
|
+
instance_eval &@block
|
16
|
+
rows = @rows.map do |row|
|
17
|
+
<<-ENDROW
|
18
|
+
<div class="row #{row.extra_classes}" style="#{row.style}">
|
19
|
+
#{row.generate}
|
20
|
+
</div>
|
21
|
+
ENDROW
|
22
|
+
end.join
|
23
|
+
|
24
|
+
menu = @menu
|
25
|
+
|
26
|
+
navigation = Elements.new(self, @anchors)
|
27
|
+
navigation.instance_eval do
|
28
|
+
menu.items.each do |item|
|
29
|
+
li item[:options] do
|
30
|
+
if item.key? :menu
|
31
|
+
|
32
|
+
hyperlink '/#' do
|
33
|
+
icon item[:icon]
|
34
|
+
span class: 'nav-label' do
|
35
|
+
text item[:name]
|
36
|
+
end
|
37
|
+
span class: 'fa arrow' do
|
38
|
+
text ''
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
open = ''
|
43
|
+
open = 'collapse in' if item[:options][:open]
|
44
|
+
ul class: "nav nav-second-level #{open}" do
|
45
|
+
item[:menu].items.each do |inneritem|
|
46
|
+
li inneritem[:options] do
|
47
|
+
if inneritem.key?(:menu)
|
48
|
+
raise 'Second level menu not supported'
|
49
|
+
else
|
50
|
+
hyperlink (inneritem[:link]).to_s do
|
51
|
+
icon inneritem[:icon]
|
52
|
+
span class: 'nav-label' do
|
53
|
+
text inneritem[:name]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
elsif
|
61
|
+
hyperlink (item[:link]).to_s do
|
62
|
+
icon item[:icon]
|
63
|
+
span class: 'nav-label' do
|
64
|
+
text item[:name]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
brand_content = ''
|
73
|
+
|
74
|
+
if @brand
|
75
|
+
brand_content = <<-BRAND_CONTENT
|
76
|
+
|
77
|
+
<li>
|
78
|
+
<a href="#{root}"><i class="fa fa-home"></i> <span class="nav-label">#{@brand}</span> <span class="label label-primary pull-right"></span></a>
|
79
|
+
</li>
|
80
|
+
BRAND_CONTENT
|
81
|
+
end
|
82
|
+
|
83
|
+
@loading_bar_visible = true
|
84
|
+
@content =
|
85
|
+
<<-ENDBODY
|
86
|
+
<div id="wrapper">
|
87
|
+
|
88
|
+
<nav class="navbar-default navbar-static-side" role="navigation">
|
89
|
+
<div class="sidebar-collapse">
|
90
|
+
<ul class="nav" id="side-menu">
|
91
|
+
|
92
|
+
#{brand_content}
|
93
|
+
#{navigation.generate}
|
94
|
+
|
95
|
+
</ul>
|
96
|
+
</div>
|
97
|
+
</nav>
|
98
|
+
<div id="page-wrapper" class="gray-bg">
|
99
|
+
<div class="row border-bottom">
|
100
|
+
<nav class="navbar navbar-static-top " role="navigation" style="margin-bottom: 0">
|
101
|
+
<div class="navbar-header">
|
102
|
+
<a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i> </a>
|
103
|
+
</div>
|
104
|
+
<ul class="nav navbar-top-links navbar-right">
|
105
|
+
<!-- NAV RIGHT -->
|
106
|
+
</ul>
|
107
|
+
</nav>
|
108
|
+
</div>
|
109
|
+
#{rows}
|
110
|
+
</div>
|
111
|
+
</div>
|
112
|
+
ENDBODY
|
113
|
+
|
114
|
+
super
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
Weaver::Weave.register_page_type(:sidenav_page, Weaver::SideNavPage)
|