moka 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/Manifest +48 -0
- data/README.rdoc +9 -0
- data/Rakefile +17 -0
- data/bin/moka +21 -0
- data/lib/commands.rb +54 -0
- data/lib/commands/compile.rb +77 -0
- data/lib/commands/delete.rb +47 -0
- data/lib/commands/group/delete.rb +59 -0
- data/lib/commands/group/group_generator.rb +115 -0
- data/lib/commands/group/inspect.rb +40 -0
- data/lib/commands/group/new.rb +2 -0
- data/lib/commands/group/template/groupdir/variables.yml +1 -0
- data/lib/commands/inspect.rb +55 -0
- data/lib/commands/lib/compiler.rb +114 -0
- data/lib/commands/lib/helpers.rb +156 -0
- data/lib/commands/lib/lipsum_constants.rb +159 -0
- data/lib/commands/lib/lipsum_helpers.rb +56 -0
- data/lib/commands/lib/page_scope.rb +29 -0
- data/lib/commands/lib/partials_inclusion.rb +42 -0
- data/lib/commands/lib/site_tree.rb +274 -0
- data/lib/commands/lib/string_inflectors.rb +13 -0
- data/lib/commands/lib/utilities.rb +45 -0
- data/lib/commands/new.rb +64 -0
- data/lib/commands/order_groups.rb +115 -0
- data/lib/commands/order_pages.rb +128 -0
- data/lib/commands/page/delete.rb +47 -0
- data/lib/commands/page/inspect.rb +35 -0
- data/lib/commands/page/new.rb +2 -0
- data/lib/commands/page/page_generator.rb +130 -0
- data/lib/commands/page/template/pagedir/variables.yml +1 -0
- data/lib/commands/server.rb +125 -0
- data/lib/commands/site/inspect.rb +28 -0
- data/lib/commands/site/new.rb +10 -0
- data/lib/commands/site/site_generator.rb +93 -0
- data/lib/commands/site/template/manifest.yml +4 -0
- data/lib/commands/site/template/project/lib/helpers.rb +1 -0
- data/lib/commands/site/template/project/site/content.erb +14 -0
- data/lib/commands/site/template/project/site/header.erb +7 -0
- data/lib/commands/site/template/project/site/layout.erb +20 -0
- data/lib/commands/site/template/project/site/navigation.erb +7 -0
- data/lib/commands/site/template/project/site/variables.yml +1 -0
- data/lib/commands/site/template/project/styles/style.sass +74 -0
- data/lib/commands/site/template/script/config/boot.rb +5 -0
- data/lib/commands/site/template/script/moka +4 -0
- data/lib/script_moka_loader.rb +14 -0
- data/lib/version.rb +10 -0
- data/moka.gemspec +39 -0
- metadata +182 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
module Moka
|
2
|
+
module LipsumHelpers
|
3
|
+
require File.expand_path('lipsum_constants.rb', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Lipsum
|
6
|
+
|
7
|
+
# If called without a block, returns a number of paragraphs of dummy text equal to count (with each paragraph enclosed in <p>...</p>). If a block is given, iteratively calls the block passing each paragraph as argument.
|
8
|
+
#
|
9
|
+
def self.paragraphs(count, &block)
|
10
|
+
if block_given?
|
11
|
+
count.to_i.times do |i|
|
12
|
+
yield LipsumConstants::PARAGRAPHS[i]
|
13
|
+
end
|
14
|
+
else
|
15
|
+
return LipsumConstants::PARAGRAPHS[0, count].collect{|p| "<p>#{p}</p>\n"}.join
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# If called without a block, returns a string of dummy text with a number of sentences equal to count (without any markup). If a block is given, iteratively calls the block passing each sentence as argument.
|
20
|
+
#
|
21
|
+
def self.sentences(count, &block)
|
22
|
+
sentences = LipsumConstants::PARAGRAPHS.join.split(/\.\s*/)
|
23
|
+
if block_given?
|
24
|
+
count.to_i.times do |i|
|
25
|
+
yield sentences[i]
|
26
|
+
end
|
27
|
+
else
|
28
|
+
return sentences[0, count].join(". ")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# If called without a block, returns a string of dummy text with a number of words equal to count (space-separated and without any markup). If a block is given, iteratively calls the block passing each word as argument.
|
33
|
+
#
|
34
|
+
# ==== Gotcha:
|
35
|
+
#
|
36
|
+
# If a block is given, the block is iteratively called passing as arguments only words more than 3 characters long. This way, nice dummy lists and menus can be generated without having to remove very short words.
|
37
|
+
#
|
38
|
+
def self.words(count, &block)
|
39
|
+
words = LipsumConstants::PARAGRAPHS.join.split(/[\W+]/)
|
40
|
+
if block_given?
|
41
|
+
shifter = 0
|
42
|
+
count.to_i.times do |i|
|
43
|
+
if words[i].size > 3
|
44
|
+
yield words[i].downcase
|
45
|
+
else
|
46
|
+
shifter += 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
return words[0, count].join(" ")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Moka
|
2
|
+
class PageScope
|
3
|
+
require File.expand_path('string_inflectors', File.dirname(__FILE__))
|
4
|
+
require File.expand_path('helpers', File.dirname(__FILE__))
|
5
|
+
require File.expand_path('partials_inclusion', File.dirname(__FILE__))
|
6
|
+
require File.expand_path('lipsum_helpers', File.dirname(__FILE__))
|
7
|
+
require File.expand_path('site_tree', File.dirname(__FILE__))
|
8
|
+
|
9
|
+
include Moka::SiteTree
|
10
|
+
include Moka::Helpers
|
11
|
+
include Moka::LipsumHelpers
|
12
|
+
include Moka::PartialsInclusion
|
13
|
+
|
14
|
+
$:.unshift(File.expand_path('project/lib', MOKA_ROOT))
|
15
|
+
require 'helpers'
|
16
|
+
|
17
|
+
def initialize(manifest, current_group_name, current_page_name)
|
18
|
+
@site = SiteNode.new("site", manifest["site"])
|
19
|
+
@current_group = @site.find_group(current_group_name)
|
20
|
+
@current_page = @current_group.find_page(current_page_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# returns a binding to the object
|
24
|
+
def get_binding
|
25
|
+
binding
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Moka
|
2
|
+
module PartialsInclusion
|
3
|
+
|
4
|
+
require File.expand_path('utilities', File.dirname(__FILE__))
|
5
|
+
|
6
|
+
# Include a partial. The method looks for a partial named as the argument and with extension .erb or .haml searching for it first in the current page directory, then in the current group directory and, finally, in the site directory. In other words, the partial which gets included is always the most specific one. If no partial with that name is found, an empty string is returned.
|
7
|
+
def partial(partial_name)
|
8
|
+
partial_name = partial_name.to_s
|
9
|
+
ext = nil
|
10
|
+
partial_dir = File.join [@current_group.name, @current_page.name]
|
11
|
+
|
12
|
+
partial_string = ""
|
13
|
+
partial_file = nil
|
14
|
+
|
15
|
+
while ext.nil? do
|
16
|
+
if File.exist?(File.expand_path("project/site/#{partial_dir}/#{partial_name}.erb", MOKA_ROOT))
|
17
|
+
partial_file = File.new(File.expand_path("project/site/#{partial_dir}/#{partial_name}.erb", MOKA_ROOT), "r")
|
18
|
+
ext = "erb"
|
19
|
+
elsif File.exist?(File.expand_path("project/site/#{partial_dir}/#{partial_name}.haml", MOKA_ROOT))
|
20
|
+
partial_file = File.new(File.expand_path("project/site/#{partial_dir}/#{partial_name}.haml", MOKA_ROOT), "r")
|
21
|
+
ext = "haml"
|
22
|
+
end
|
23
|
+
if partial_dir == "" and ext.nil?
|
24
|
+
puts "WARNING: cannot find partial file #{partial_name}.erb or #{partial_name}.haml"
|
25
|
+
break
|
26
|
+
end
|
27
|
+
partial_dir = File.dirname partial_dir
|
28
|
+
if partial_dir == "."
|
29
|
+
partial_dir = ""
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
unless partial_file.nil?
|
34
|
+
partial_string = partial_file.read
|
35
|
+
partial_file.close
|
36
|
+
end
|
37
|
+
|
38
|
+
return Moka::Utilities.eval_erb_haml(partial_string, ext, self.get_binding)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
module Moka
|
2
|
+
module SiteTree
|
3
|
+
RESERVED_NAMES = %w(path order layout name children parent site group groups pages variables vars find_child find_group find_page initialize)
|
4
|
+
|
5
|
+
class TreeNode
|
6
|
+
attr_accessor :name
|
7
|
+
attr_accessor :parent
|
8
|
+
|
9
|
+
def initialize(name, params = {}, parent = nil)
|
10
|
+
@name = name
|
11
|
+
@parent = parent
|
12
|
+
@children = NodeArray.new
|
13
|
+
@params = {"name" => @name}
|
14
|
+
@variables = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a NodeArray object containing all the children nodes of the current node
|
18
|
+
def children
|
19
|
+
return @children.sort do |a, b|
|
20
|
+
if a.respond_to?(:order) and b.respond_to?(:order)
|
21
|
+
a.send(:order) <=> b.send(:order)
|
22
|
+
else
|
23
|
+
if b.respond_to?(:order)
|
24
|
+
-1
|
25
|
+
else
|
26
|
+
1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the child node having the name equal to the string passed as argument or nil if such child does not exist
|
33
|
+
def find_child(child_name)
|
34
|
+
children.find(child_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns a Hash with the node's defined variable names (as keys) and their respective value (as values).
|
38
|
+
def variables(include_defined_in_parent = true)
|
39
|
+
unless self.parent.nil? or include_defined_in_parent == false
|
40
|
+
v = self.parent.variables
|
41
|
+
else
|
42
|
+
v = {}
|
43
|
+
end
|
44
|
+
v.merge!(@variables)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns a Hash containing the node's parameters (as keys) and their respective value (as values).
|
48
|
+
def params
|
49
|
+
@params
|
50
|
+
end
|
51
|
+
|
52
|
+
# Alias for variables
|
53
|
+
def vars(include_defined_in_parent = true)
|
54
|
+
variables(include_defined_in_parent)
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
# Creates an INSTANCE method dynamically
|
60
|
+
def create_method(name, &block)
|
61
|
+
self.metaclass.send(:define_method, name, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
class SiteNode < TreeNode
|
68
|
+
def initialize(name, params = {}, parent = nil)
|
69
|
+
super(name, params, parent)
|
70
|
+
if File.exist? File.expand_path("project/site/variables.yml", MOKA_ROOT)
|
71
|
+
site_vars = YAML.load_file(File.expand_path("project/site/variables.yml", MOKA_ROOT)) || {}
|
72
|
+
site_vars.each do |key, value|
|
73
|
+
unless RESERVED_NAMES.include? key
|
74
|
+
self.instance_variable_set "@#{key}", value
|
75
|
+
@variables[key.to_s] = value
|
76
|
+
self.create_method(key) do self.instance_variable_get("@#{key}") end
|
77
|
+
self.create_method("#{key}=") do |v| self.instance_variable_set("@#{key}", v); @variables[key.to_s] = v end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
params.each do |key, value|
|
83
|
+
key.gsub!(/\s/, "_")
|
84
|
+
if value.is_a?(Hash)
|
85
|
+
self.instance_variable_set "@#{key}", GroupNode.new(key, value, self)
|
86
|
+
@children << instance_eval("@#{key}")
|
87
|
+
else
|
88
|
+
self.instance_variable_set "@#{key}", value
|
89
|
+
@params[key.to_s] = value
|
90
|
+
end
|
91
|
+
self.create_method(key) do self.instance_variable_get("@#{key}") end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns a NodeArray object containing all the site's groups (the children of the site node)
|
96
|
+
def groups
|
97
|
+
self.children
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns the group having the name equal to the string passed as argument or nil if such group does not exist
|
101
|
+
def find_group(group_name)
|
102
|
+
children.find(group_name)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Save site variables in the variables.yml file
|
106
|
+
def save
|
107
|
+
f = File.open( File.expand_path("project/site/variables.yml", MOKA_ROOT), 'w' ) do |out|
|
108
|
+
YAML.dump( variables(false), out )
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
class GroupNode < TreeNode
|
116
|
+
attr_accessor :site
|
117
|
+
|
118
|
+
def initialize(name, params = {}, parent = nil)
|
119
|
+
super(name, params, parent)
|
120
|
+
@site = parent
|
121
|
+
|
122
|
+
if File.exist? File.expand_path("project/site/#{name}/variables.yml", MOKA_ROOT)
|
123
|
+
group_vars = YAML.load_file(File.expand_path("project/site/#{name}/variables.yml", MOKA_ROOT)) || {}
|
124
|
+
else
|
125
|
+
group_vars = {}
|
126
|
+
end
|
127
|
+
@site.variables.merge(group_vars).each do |key, value|
|
128
|
+
unless RESERVED_NAMES.include? key
|
129
|
+
self.instance_variable_set "@#{key}", value
|
130
|
+
@variables[key.to_s] = value if group_vars.keys.include? key.to_s
|
131
|
+
self.create_method(key) do self.instance_variable_get("@#{key}") end
|
132
|
+
self.create_method("#{key}=") do |v| self.instance_variable_set("@#{key}", v); @variables[key.to_s] = v end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
params.each do |key, value|
|
137
|
+
key.gsub!(/\s/, "_")
|
138
|
+
if value.is_a?(Hash)
|
139
|
+
self.instance_variable_set "@#{key}", PageNode.new(key, value, self)
|
140
|
+
@children << instance_eval("@#{key}")
|
141
|
+
else
|
142
|
+
self.instance_variable_set "@#{key}", value
|
143
|
+
@params[key.to_s] = value
|
144
|
+
end
|
145
|
+
self.create_method(key) do self.instance_variable_get("@#{key}") end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns a NodeArray object containing all the pages in the group (its children nodes)
|
150
|
+
def pages
|
151
|
+
self.children
|
152
|
+
end
|
153
|
+
|
154
|
+
# Looks for a page in the group having the name equal to the string passed as argument. Returns the page or nil if no such page was found.
|
155
|
+
def find_page(page_name)
|
156
|
+
children.find(page_name)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Save group variables in the variables.yml file
|
160
|
+
def save
|
161
|
+
f = File.open( File.expand_path("project/site/#{self.name}/variables.yml", MOKA_ROOT), 'w' ) do |out|
|
162
|
+
YAML.dump( variables(false), out )
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
class PageNode < TreeNode
|
170
|
+
attr_accessor :group
|
171
|
+
|
172
|
+
def initialize(name, params = {}, parent = nil)
|
173
|
+
super(name, params, parent)
|
174
|
+
@group = parent
|
175
|
+
|
176
|
+
if File.exist? File.expand_path("project/site/#{@group.name}/#{name}/variables.yml", MOKA_ROOT)
|
177
|
+
page_vars = YAML.load_file(File.expand_path("project/site/#{@group.name}/#{name}/variables.yml", MOKA_ROOT)) || {}
|
178
|
+
else
|
179
|
+
page_vars = {}
|
180
|
+
end
|
181
|
+
@group.variables.merge(page_vars).each do |key, value|
|
182
|
+
unless RESERVED_NAMES.include? key
|
183
|
+
self.instance_variable_set("@#{key}", value)
|
184
|
+
@variables[key.to_s] = value if page_vars.keys.include? key.to_s
|
185
|
+
self.create_method(key) do self.instance_variable_get("@#{key}") end
|
186
|
+
self.create_method("#{key}=") do |v| self.instance_variable_set("@#{key}", v); @variables[key.to_s] = v end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
params.each do |key, value|
|
191
|
+
key.gsub!(/\s/, "_")
|
192
|
+
self.instance_variable_set "@#{key}", value
|
193
|
+
@params[key.to_s] = value
|
194
|
+
self.create_method(key) do self.instance_variable_get("@#{key}") end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Save page variables in the variables.yml file
|
199
|
+
def save
|
200
|
+
f = File.open( File.expand_path("project/site/#{@group.name}/#{self.name}/variables.yml", MOKA_ROOT), 'w' ) do |out|
|
201
|
+
YAML.dump( variables(false), out )
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class NodeArray < Array
|
207
|
+
# Like an Array, but with some other helpful methods to filter, order and select elements. The methods are intended to work with elements being instances of classes extending TreeNode (like SiteNode, GroupNode or PageNode).
|
208
|
+
|
209
|
+
# Returns the element having the value of the variable name equal to the argument, or nil if such an element does not exist.
|
210
|
+
def find(name)
|
211
|
+
self.each do |c|
|
212
|
+
if c.respond_to?(:name) and c.name == name.to_s
|
213
|
+
return c
|
214
|
+
end
|
215
|
+
end
|
216
|
+
return nil
|
217
|
+
end
|
218
|
+
|
219
|
+
# Orders the elements by a variable. The elements that do not have that variable are placed last.
|
220
|
+
def order_by(ordering_var)
|
221
|
+
return self.sort do |a, b|
|
222
|
+
if a.respond_to?(ordering_var.to_sym) and b.respond_to?(ordering_var.to_sym)
|
223
|
+
a.send(ordering_var.to_sym) <=> b.send(ordering_var.to_sym)
|
224
|
+
else
|
225
|
+
if b.respond_to?(ordering_var.to_sym)
|
226
|
+
-1
|
227
|
+
else
|
228
|
+
1
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# Returns another NodeArray containing only the elements satisfying the conditions. conditions can be a Hash containing pairs variable_name => variable_value or a string to be evalued as ruby code.
|
235
|
+
#
|
236
|
+
# ==== Examples:
|
237
|
+
#
|
238
|
+
# @site.groups.where({:somevar => somevalue, :another_var => another_value})
|
239
|
+
#
|
240
|
+
# @site.groups.where("order < 5")
|
241
|
+
#
|
242
|
+
def where(conditions)
|
243
|
+
found = NodeArray.new
|
244
|
+
self.each do |c|
|
245
|
+
if conditions.is_a? Hash
|
246
|
+
satisfied = true
|
247
|
+
conditions.each do |var_name, var_value|
|
248
|
+
unless c.respond_to?(var_name.to_sym) and c.send(var_name.to_sym) == var_value
|
249
|
+
satisfied = false
|
250
|
+
break
|
251
|
+
end
|
252
|
+
end
|
253
|
+
if satisfied
|
254
|
+
found << c
|
255
|
+
end
|
256
|
+
else # conditions should be a string (or something that acts like one)
|
257
|
+
if c.instance_eval(conditions)
|
258
|
+
found << c
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
return found
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class Object
|
270
|
+
# Needed for define_method to add INSTANCE methods dynamically
|
271
|
+
def metaclass
|
272
|
+
class << self; self; end
|
273
|
+
end
|
274
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Returns the string with the first character of each word capitalized, and with underscores substituted by spaces.
|
4
|
+
def titleize
|
5
|
+
self.humanize.gsub(/\b('?[a-z])/) { $1.capitalize }
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns the string with the very first character capitalized, and with underscores substituted by spaces.
|
9
|
+
def humanize
|
10
|
+
self.gsub(/_/, " ").capitalize
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Moka
|
2
|
+
class Utilities
|
3
|
+
|
4
|
+
def self.parse_grouppage(grouppage)
|
5
|
+
# parse group:page syntax and return [page, group]
|
6
|
+
semicolon = grouppage.index ":"
|
7
|
+
unless semicolon.nil?
|
8
|
+
return [grouppage[(semicolon + 1)..-1], grouppage[0..(semicolon-1)]]
|
9
|
+
else
|
10
|
+
return [grouppage, "root"]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parse_argvalue(argvalue)
|
15
|
+
# parse argument=value syntax and return [argument, value]
|
16
|
+
equal = argvalue.index "="
|
17
|
+
unless equal.nil?
|
18
|
+
arg_name = argvalue[0..(equal-1)]
|
19
|
+
arg_value = argvalue[(equal + 1)..-1]
|
20
|
+
else
|
21
|
+
arg_name = argvalue
|
22
|
+
arg_value = nil
|
23
|
+
end
|
24
|
+
return [arg_name, arg_value]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.eval_erb_haml(code, ext, scope)
|
28
|
+
require "rubygems"
|
29
|
+
# evaluates erb or haml code
|
30
|
+
if ext == "erb"
|
31
|
+
require 'erb'
|
32
|
+
eval_string = ERB.new(code).result(scope)
|
33
|
+
elsif ext == "haml"
|
34
|
+
require 'haml'
|
35
|
+
eval_string = Haml::Engine.new(code).render(scope)
|
36
|
+
end
|
37
|
+
return eval_string
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.deepcopy(obj)
|
41
|
+
Marshal::load(Marshal::dump(obj))
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|