milk 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/milk.rb +64 -40
- data/lib/milk/application.rb +37 -16
- data/lib/milk/component.rb +23 -28
- data/lib/milk/field.rb +7 -18
- data/lib/milk/page.rb +19 -25
- data/lib/milk/tasks.rb +6 -7
- data/milk.gemspec +56 -45
- data/site_template/Rakefile +5 -0
- data/site_template/bootstrap.rb +71 -0
- data/site_template/config.ru +1 -3
- data/site_template/{config → data/global}/foot.yaml +0 -0
- data/site_template/{config → data/global}/head.yaml +4 -4
- data/site_template/{pages → data/pages}/About.yaml +3 -3
- data/site_template/{pages → data/pages}/Home.yaml +4 -3
- data/site_template/{pages → data/pages}/News.yaml +3 -3
- data/site_template/{pages → data/pages}/NotFound.yaml +3 -3
- data/site_template/{pages → data/pages}/Products.yaml +3 -3
- data/site_template/lib/components/body.rb +6 -0
- data/site_template/lib/components/button.rb +19 -0
- data/site_template/lib/components/foot.rb +6 -0
- data/site_template/lib/components/head.rb +6 -0
- data/site_template/lib/fields/checkbox_field.rb +4 -0
- data/{lib/milk → site_template/lib}/fields/component_array.rb +0 -0
- data/site_template/lib/fields/dropdown_field.rb +4 -0
- data/{lib/milk → site_template/lib}/fields/image_chooser.rb +0 -0
- data/{lib/milk → site_template/lib}/fields/markdown_field.rb +0 -0
- data/{lib/milk → site_template/lib}/fields/page_chooser.rb +1 -1
- data/{lib/milk → site_template/lib}/fields/sprite_chooser.rb +1 -1
- data/{lib/milk → site_template/lib}/fields/text_field.rb +0 -0
- data/site_template/public/js/edit.js +121 -0
- data/site_template/public/js/form_validate.js +51 -0
- data/site_template/public/js/login.js +9 -0
- data/site_template/public/style/960.css +96 -0
- data/site_template/public/style/edit.css +29 -0
- data/site_template/public/style/login.css +12 -0
- data/site_template/public/style/reset.css +33 -0
- data/site_template/public/style/text.css +25 -0
- data/site_template/public/style/view.css +10 -0
- data/site_template/{design → templates}/960.sass +0 -0
- data/site_template/{design → templates/components}/body.haml +0 -0
- data/site_template/{design → templates/components}/button.haml +0 -0
- data/site_template/{design → templates/components}/foot.haml +0 -0
- data/site_template/{design → templates/components}/head.haml +0 -0
- data/site_template/templates/dependencies.haml +8 -0
- data/{lib/milk/fields/component.haml → site_template/templates/edit.component.haml} +0 -0
- data/site_template/templates/edit.haml +38 -0
- data/site_template/templates/edit.sass +91 -0
- data/site_template/templates/fields/checkbox_field.haml +1 -0
- data/{lib/milk → site_template/templates}/fields/component_array.haml +0 -0
- data/site_template/templates/fields/dropdown_field.haml +3 -0
- data/{lib/milk → site_template/templates}/fields/image_chooser.haml +0 -0
- data/{lib/milk → site_template/templates}/fields/markdown_field.haml +0 -0
- data/site_template/templates/fields/page_chooser.haml +3 -0
- data/{lib/milk → site_template/templates}/fields/sprite_chooser.haml +0 -0
- data/{lib/milk → site_template/templates}/fields/text_field.haml +0 -0
- data/site_template/templates/login.haml +37 -0
- data/site_template/templates/login.sass +35 -0
- data/site_template/{design/0-reset.sass → templates/reset.sass} +0 -0
- data/site_template/{design/1-text.sass → templates/text.sass} +0 -0
- data/site_template/{design/xhtml.haml → templates/view.haml} +2 -3
- data/site_template/{design/page.haml → templates/view.page.haml} +0 -0
- data/site_template/{design/head.sass → templates/view.sass} +10 -0
- metadata +56 -45
- data/lib/milk/fields/login.haml +0 -90
- data/lib/milk/fields/page_chooser.haml +0 -3
- data/lib/milk/fields/xhtml.haml +0 -253
- data/lib/milk/haxe.rb +0 -139
- data/site_template/config/config.yaml +0 -31
- data/site_template/config/users.yaml +0 -18
- data/site_template/design/body.rb +0 -4
- data/site_template/design/button.rb +0 -16
- data/site_template/design/foot.rb +0 -4
- data/site_template/design/foot.sass +0 -3
- data/site_template/design/head.rb +0 -4
- data/site_template/design/page.sass +0 -7
- data/site_template/design/sprites.sass +0 -0
data/lib/milk/fields/xhtml.haml
DELETED
@@ -1,253 +0,0 @@
|
|
1
|
-
!!! xml
|
2
|
-
!!! 1.1
|
3
|
-
%html{:xmlns =>"http://www.w3.org/1999/xhtml"}
|
4
|
-
%head
|
5
|
-
%title&= "Editing \"#{@pagename}\""
|
6
|
-
%style{:type=>"text/css"}
|
7
|
-
:sass
|
8
|
-
body, html
|
9
|
-
:border 0
|
10
|
-
:margin 0
|
11
|
-
:padding 0
|
12
|
-
body.busy
|
13
|
-
:cursor busy
|
14
|
-
div.component
|
15
|
-
&:hover
|
16
|
-
:border 10px solid #08f
|
17
|
-
#admin-title
|
18
|
-
:position absolute
|
19
|
-
:margin 0
|
20
|
-
:top 5px
|
21
|
-
:left 10px
|
22
|
-
:line-height 1em
|
23
|
-
:font-size 20px
|
24
|
-
:font-family monaco,monospace
|
25
|
-
|
26
|
-
#toolbar
|
27
|
-
:position absolute
|
28
|
-
:left 0
|
29
|
-
:bottom 0
|
30
|
-
:right 0
|
31
|
-
:padding 3px
|
32
|
-
.toolitem
|
33
|
-
:font-size 12px
|
34
|
-
:cursor pointer
|
35
|
-
:line-height 1em
|
36
|
-
:padding 2px 5px 2px 2px
|
37
|
-
.ui-icon
|
38
|
-
:float left
|
39
|
-
:line-height 1em
|
40
|
-
#frame
|
41
|
-
:position absolute
|
42
|
-
:top 0px
|
43
|
-
:left 0px
|
44
|
-
:right 0px
|
45
|
-
:bottom 0px
|
46
|
-
#left
|
47
|
-
:font-size 11px
|
48
|
-
:position absolute
|
49
|
-
:top 0px
|
50
|
-
:left 0px
|
51
|
-
:width 250px
|
52
|
-
:bottom 0px
|
53
|
-
h4
|
54
|
-
:font-size 14px
|
55
|
-
h3
|
56
|
-
:font-size 13px
|
57
|
-
#divider
|
58
|
-
:position absolute
|
59
|
-
:top 0px
|
60
|
-
:left 250px
|
61
|
-
:width 5px
|
62
|
-
:bottom 0px
|
63
|
-
|
64
|
-
#fields
|
65
|
-
:position absolute
|
66
|
-
:top 0px
|
67
|
-
:bottom 35px
|
68
|
-
:overflow auto
|
69
|
-
:left 0px
|
70
|
-
:right 0
|
71
|
-
.ui-accordion-content
|
72
|
-
:padding 10px
|
73
|
-
h4
|
74
|
-
:margin 0
|
75
|
-
.field-content
|
76
|
-
:margin-bottom 10px
|
77
|
-
input
|
78
|
-
:width 95%
|
79
|
-
:padding 2px
|
80
|
-
textarea
|
81
|
-
:width 100%
|
82
|
-
:min-height 330px
|
83
|
-
.sprite-select
|
84
|
-
.sprite-option
|
85
|
-
:padding 4px
|
86
|
-
:margin 2px
|
87
|
-
:float left
|
88
|
-
:cursor pointer
|
89
|
-
|
90
|
-
#preview
|
91
|
-
:position absolute
|
92
|
-
:top 0px
|
93
|
-
:left 255px
|
94
|
-
:right 0
|
95
|
-
:width auto
|
96
|
-
:bottom 0px
|
97
|
-
:overflow auto
|
98
|
-
|
99
|
-
|
100
|
-
%link{ :rel => "shortcut icon", :href => "/favicon.ico", :type => "image/x-icon"}/
|
101
|
-
%link{ :href => "/skin/jquery-ui-1.7.2.custom.css", :media => "screen", :rel => "stylesheet", :type => "text/css" }/
|
102
|
-
%link{ :href => "/style/style.css", :media => "screen", :rel => "stylesheet", :type => "text/css" }/
|
103
|
-
%script{:src=>"/js/jquery-1.3.2.min.js", :type=>"text/javascript"}
|
104
|
-
%script{:src=>"/js/jquery.json-1.3.min.js", :type=>"text/javascript"}
|
105
|
-
%script{:src=>"/js/jquery-ui-1.7.2.custom.min.js", :type=>"text/javascript"}
|
106
|
-
%body
|
107
|
-
#frame
|
108
|
-
#left
|
109
|
-
.ui-widget-overlay
|
110
|
-
%form#fields{:method => "post", :action => "/"+@pagename}
|
111
|
-
%h3
|
112
|
-
%a{:href => "#"} Page Settings
|
113
|
-
%div
|
114
|
-
%input{:type=>"hidden", :name=>"class", :value=>self.class.to_s}
|
115
|
-
-to_yaml_properties.each do |name|
|
116
|
-
- next if name == :@components
|
117
|
-
- fieldname = name.to_s.sub('@','')
|
118
|
-
.field
|
119
|
-
%h4= fieldname.capitalize + ":"
|
120
|
-
.field-content
|
121
|
-
%input{:type=>"text", :name=>fieldname, :value=>instance_variable_get(name)}
|
122
|
-
-@components.each_with_index do |component, i|
|
123
|
-
= component.edit("components:#{i}")
|
124
|
-
#toolbar{:class=>'ui-widget ui-widget-header'}
|
125
|
-
%button#save_button.toolitem{:title=>'Save changes and go to live page.'}
|
126
|
-
%span{:class=>'ui-icon ui-icon-disk'}
|
127
|
-
Save
|
128
|
-
%button#cancel_button.toolitem{:title=>'Cancel changes and go to live page.'}
|
129
|
-
%span{:class=>'ui-icon ui-icon-cancel'}
|
130
|
-
Cancel
|
131
|
-
%button#logout_button.toolitem{:title=>'Cancel changes and logout and go to live page.'}
|
132
|
-
%span{:class=>'ui-icon ui-icon-locked'}
|
133
|
-
Logout
|
134
|
-
#preview
|
135
|
-
= preview
|
136
|
-
#divider.ui-widget-header
|
137
|
-
|
138
|
-
:javascript
|
139
|
-
function on_click_sprite(e)
|
140
|
-
{
|
141
|
-
// Look up some useful variables
|
142
|
-
var current = e.currentTarget;
|
143
|
-
var sprite_select = $(current.parentNode);
|
144
|
-
var peers = $(".sprite-option", sprite_select);
|
145
|
-
var hidden_input = $('input', sprite_select)[0];
|
146
|
-
var inner_span = $('span', current)[0];
|
147
|
-
|
148
|
-
// Set the value on the hidden input
|
149
|
-
hidden_input.value = inner_span.title;
|
150
|
-
|
151
|
-
// Move the highlight
|
152
|
-
peers.removeClass('ui-state-highlight');
|
153
|
-
$(current).addClass('ui-state-highlight');
|
154
|
-
update_preview(50);
|
155
|
-
}
|
156
|
-
|
157
|
-
function jsonify(form)
|
158
|
-
{
|
159
|
-
var data = {}
|
160
|
-
$("input, textarea, select", form).each(function (i, field){
|
161
|
-
var parts = field.name.split(':');
|
162
|
-
var root = data;
|
163
|
-
var part = parts[0];
|
164
|
-
var numeric_regexp = /[0-9]+/;
|
165
|
-
for(i=0;i<parts.length-1;i++)
|
166
|
-
{
|
167
|
-
if (!root[part])
|
168
|
-
{
|
169
|
-
if (numeric_regexp.test(part))
|
170
|
-
root[part]={};
|
171
|
-
else
|
172
|
-
root[part]=[];
|
173
|
-
}
|
174
|
-
root = root[part];
|
175
|
-
part = parts[i + 1];
|
176
|
-
}
|
177
|
-
root[part] = field.value;
|
178
|
-
});
|
179
|
-
return $.toJSON(data);
|
180
|
-
}
|
181
|
-
|
182
|
-
function do_update_preview()
|
183
|
-
{
|
184
|
-
var preview = $("#preview");
|
185
|
-
$("body").addClass("busy")
|
186
|
-
$.ajax({
|
187
|
-
type: "POST",
|
188
|
-
url: $("form")[0].action,
|
189
|
-
contentType: "application/json",
|
190
|
-
data: jsonify($("form")[0]),
|
191
|
-
success: function(msg){
|
192
|
-
preview.html(msg);
|
193
|
-
$("body").removeClass("busy")
|
194
|
-
}
|
195
|
-
});
|
196
|
-
}
|
197
|
-
|
198
|
-
function update_preview(timeout)
|
199
|
-
{
|
200
|
-
clearTimeout(window.preview_timeout);
|
201
|
-
window.preview_timeout = setTimeout(do_update_preview, timeout);
|
202
|
-
}
|
203
|
-
|
204
|
-
|
205
|
-
$(function() {
|
206
|
-
$("#left").resizable({handles: "e", resize: function(event, ui) {
|
207
|
-
$("#divider").css("left", ui.size.width);
|
208
|
-
$("#preview").css("left", ui.size.width+5);
|
209
|
-
}});
|
210
|
-
$(".sub-fields").accordion({
|
211
|
-
collapsible: true,
|
212
|
-
autoHeight: false,
|
213
|
-
active: false
|
214
|
-
});
|
215
|
-
var sections = $("#fields").accordion({
|
216
|
-
autoHeight: false
|
217
|
-
});
|
218
|
-
|
219
|
-
$(".sprite-option").click(on_click_sprite);
|
220
|
-
$(".toolitem, .sprite-option")
|
221
|
-
.addClass("ui-state-default ui-corner-all")
|
222
|
-
.hover(
|
223
|
-
function() { $(this).addClass('ui-state-hover'); },
|
224
|
-
function() { $(this).removeClass('ui-state-hover'); }
|
225
|
-
);
|
226
|
-
$("#fields select, #fields input, #fields textarea").change(function(){
|
227
|
-
update_preview(100);
|
228
|
-
});
|
229
|
-
$("#fields select, #fields input, #fields textarea").keyup(function(){
|
230
|
-
update_preview(1000);
|
231
|
-
});
|
232
|
-
$("#save_button").click(function(){
|
233
|
-
$.ajax({
|
234
|
-
type: "PUT",
|
235
|
-
url: $("form")[0].action,
|
236
|
-
contentType: "application/json",
|
237
|
-
data: jsonify($("form")[0]),
|
238
|
-
success: function(msg){
|
239
|
-
window.location = $("form")[0].action.replace('https://', 'http://');
|
240
|
-
}
|
241
|
-
});
|
242
|
-
});
|
243
|
-
|
244
|
-
$("#cancel_button").click(function(){
|
245
|
-
window.location = $("form")[0].action.replace('https://', 'http://');
|
246
|
-
});
|
247
|
-
$("#logout_button").click(function(){
|
248
|
-
window.location = "/logout?dest="+$("form")[0].action.replace('https://', 'http://');
|
249
|
-
});
|
250
|
-
|
251
|
-
});
|
252
|
-
|
253
|
-
|
data/lib/milk/haxe.rb
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
module Milk
|
2
|
-
class Haxe
|
3
|
-
HAXE_HEADER_REGEX = /^\/\/ COMPILE_FLAGS (.*)$/
|
4
|
-
HAXE_BIN = Milk::BIN_DIR+"/haxe"
|
5
|
-
ENV['HAXE_LIBRARY_PATH'] = File.absolute_path(Milk::BIN_DIR+"/../haxe/std")
|
6
|
-
HAXE_DIR = Milk::COMPONENTS_DIR + "/haxe"
|
7
|
-
|
8
|
-
def initialize(page_name)
|
9
|
-
@page_name = page_name
|
10
|
-
base_path = HAXE_DIR + "/" + @page_name
|
11
|
-
@haxe = base_path + ".hx"
|
12
|
-
@haxe_swf = @haxe + ".swf"
|
13
|
-
@swfmill = base_path + ".xml"
|
14
|
-
@swfmill_swf = @swfmill + ".swf"
|
15
|
-
|
16
|
-
raise PageNotFoundError if not File.file? @haxe
|
17
|
-
|
18
|
-
# Compile swfmill resource if it exists and the binary is nonexistant/outdated
|
19
|
-
if File.file? @swfmill
|
20
|
-
if (not (File.file?(@swfmill_swf)) or (File.mtime(@swfmill) > File.mtime(@swfmill_swf)))
|
21
|
-
compile_swfmill
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Compile haxe binary if nonexistant/outdated
|
26
|
-
# if a swfmill resource exists, it can outdate the main swf too
|
27
|
-
if (not (File.file?(@haxe_swf)) \
|
28
|
-
or (File.mtime(@haxe) > File.mtime(@haxe_swf)) \
|
29
|
-
or (File.file?(@swfmill_swf) \
|
30
|
-
and File.mtime(@swfmill_swf) > File.mtime(@haxe_swf) \
|
31
|
-
) \
|
32
|
-
)
|
33
|
-
compile_haxe
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def render(mode='view')
|
38
|
-
open(@haxe_swf)
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def popen3(*cmd)
|
44
|
-
pw = IO::pipe # pipe[0] for read, pipe[1] for write
|
45
|
-
pr = IO::pipe
|
46
|
-
pe = IO::pipe
|
47
|
-
|
48
|
-
pid = fork{
|
49
|
-
# child
|
50
|
-
fork{
|
51
|
-
# grandchild
|
52
|
-
pw[1].close
|
53
|
-
STDIN.reopen(pw[0])
|
54
|
-
pw[0].close
|
55
|
-
|
56
|
-
pr[0].close
|
57
|
-
STDOUT.reopen(pr[1])
|
58
|
-
pr[1].close
|
59
|
-
|
60
|
-
pe[0].close
|
61
|
-
STDERR.reopen(pe[1])
|
62
|
-
pe[1].close
|
63
|
-
|
64
|
-
exec(*cmd)
|
65
|
-
}
|
66
|
-
exit!(0)
|
67
|
-
}
|
68
|
-
|
69
|
-
pw[0].close
|
70
|
-
pr[1].close
|
71
|
-
pe[1].close
|
72
|
-
Process.waitpid(pid)
|
73
|
-
pi = [pw[1], pr[0], pe[0]]
|
74
|
-
pw[1].sync = true
|
75
|
-
if defined? yield
|
76
|
-
begin
|
77
|
-
return yield(*pi)
|
78
|
-
ensure
|
79
|
-
pi.each{|p| p.close unless p.closed?}
|
80
|
-
end
|
81
|
-
end
|
82
|
-
pi
|
83
|
-
end
|
84
|
-
|
85
|
-
def run_command(*command)
|
86
|
-
popen3(*command) do |stdin, stdout, stderr|
|
87
|
-
stdin.close
|
88
|
-
error = stderr.read
|
89
|
-
if error.length > 0
|
90
|
-
raise ExternalCompilerError.new(error.inspect)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def compile_swfmill
|
96
|
-
command = ["swfmill", "simple", @swfmill, @swfmill_swf]
|
97
|
-
Dir.chdir(Milk::HAXE_DIR)
|
98
|
-
run_command *command
|
99
|
-
end
|
100
|
-
|
101
|
-
def compile_haxe
|
102
|
-
command = [HAXE_BIN,
|
103
|
-
"-swf-version", "9", "--flash-strict",
|
104
|
-
"-swf", @haxe_swf,
|
105
|
-
"-main", @page_name,
|
106
|
-
"-cp", Milk::HAXE_DIR]
|
107
|
-
open @haxe, "r" do |file|
|
108
|
-
line = file.readline
|
109
|
-
if HAXE_HEADER_REGEX =~ line
|
110
|
-
HAXE_HEADER_REGEX.match(line)[1].split(' ').each do |item|
|
111
|
-
command.push(item)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
if File.file? @swfmill_swf
|
116
|
-
# For some reason, haxe doesn't like a full path here, so convert
|
117
|
-
# to relative.
|
118
|
-
command.push('-swf-lib')
|
119
|
-
command.push(@swfmill_swf.split("/").last)
|
120
|
-
end
|
121
|
-
run_command *command
|
122
|
-
end
|
123
|
-
|
124
|
-
end
|
125
|
-
|
126
|
-
# An exception raised by haxe or swfmill.
|
127
|
-
class ExternalCompilerError < StandardError
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# This file contains global settings for the milk site
|
2
|
-
---
|
3
|
-
|
4
|
-
# SECRET is the site specific key used to encrypt the cookies sent for authentication.
|
5
|
-
#
|
6
|
-
# It is very important that this key be both long and unique to each site you build.
|
7
|
-
#
|
8
|
-
# My method is to pick two secret passphrases and concatenating the md5 of them together
|
9
|
-
#
|
10
|
-
# >> require 'digest/md5'
|
11
|
-
# => true
|
12
|
-
# >> Digest::MD5.hexdigest("Milk") + Digest::MD5.hexdigest("Rocks")
|
13
|
-
# => "e89b2cbb7d11825a67459af2249064de5cdfbc0ea6e85d2cc3dd5ddec72ffe1a"
|
14
|
-
SECRET: "098f6bcd4621d373cade4e832627b4f6ad0234829205b9033196ba818f7a872b"
|
15
|
-
|
16
|
-
# USE_CACHE is an advanced option for sites that need super high performance. When
|
17
|
-
# this option is set to true, then every time a page is saved, a static html file is
|
18
|
-
# created and saved to [MILK_ROOT]/public/cache/[pagename]/index.html
|
19
|
-
#
|
20
|
-
# In order to use these cache files your apache or nginx server needs to have a rewrite
|
21
|
-
# rule that looks here first and uses the static files if they exist.
|
22
|
-
#
|
23
|
-
# As an example, here is the relevent part of my nginx config:
|
24
|
-
#
|
25
|
-
# # Enable loading page cache files directly
|
26
|
-
# rewrite ^/$ /cache/Home/index.html;
|
27
|
-
# rewrite ^((/[A-Z][A-Za-z]*)+)$ /cache/$1/index.html;
|
28
|
-
USE_CACHE: false
|
29
|
-
|
30
|
-
# You can create any other site wide globals for use in templates here
|
31
|
-
SITE_NAME: "Sample Site"
|
@@ -1,18 +0,0 @@
|
|
1
|
-
---
|
2
|
-
# This file contains the emails, names and hashed passwords for
|
3
|
-
# all users of the site.
|
4
|
-
#
|
5
|
-
# Hash is a simple md5 of the password for now, future versions of
|
6
|
-
# Milk may use something more secure.
|
7
|
-
#
|
8
|
-
# To create the md5 hash in irb do the following:
|
9
|
-
#
|
10
|
-
# >> require 'digest/md5'
|
11
|
-
# => true
|
12
|
-
# >> Digest::MD5.hexdigest("test")
|
13
|
-
# => "098f6bcd4621d373cade4e832627b4f6"
|
14
|
-
#
|
15
|
-
# Note the default login is admin@example.com/test
|
16
|
-
admin@example.com:
|
17
|
-
name: Sample Admin
|
18
|
-
hash: 098f6bcd4621d373cade4e832627b4f6
|