milk 0.0.6 → 0.0.7

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.
Files changed (67) hide show
  1. data/Rakefile +4 -0
  2. data/lib/milk.rb +1 -0
  3. data/lib/milk/application.rb +52 -12
  4. data/lib/milk/component.rb +30 -16
  5. data/lib/milk/component.rb.~1~ +141 -0
  6. data/lib/milk/fields/login.haml +36 -25
  7. data/lib/milk/fields/markdown_field.haml +1 -1
  8. data/lib/milk/fields/xhtml.haml +19 -30
  9. data/lib/milk/page.rb +10 -6
  10. data/lib/milk/page.rb.~1~ +118 -0
  11. data/lib/milk/tasks.rb +9 -12
  12. data/milk.gemspec +1 -1
  13. data/site_template/config.ru +2 -1
  14. data/site_template/config/foot.yaml +3 -5
  15. data/site_template/config/foot.yaml.~1~ +2 -0
  16. data/site_template/config/foot.yaml.~2~ +2 -0
  17. data/site_template/config/foot.yaml.~3~ +1 -0
  18. data/site_template/config/foot.yaml.~4~ +3 -0
  19. data/site_template/config/foot.yaml.~5~ +3 -0
  20. data/site_template/config/head.yaml +1 -10
  21. data/site_template/config/head.yaml.~1~ +2 -0
  22. data/site_template/config/head.yaml.~2~ +2 -0
  23. data/site_template/config/head.yaml.~3~ +1 -0
  24. data/site_template/config/head.yaml.~4~ +18 -0
  25. data/site_template/config/head.yaml.~5~ +18 -0
  26. data/site_template/design/{reset.sass → 0-reset.sass} +0 -0
  27. data/site_template/design/{text.sass → 1-text.sass} +0 -0
  28. data/site_template/design/body.haml +1 -3
  29. data/site_template/design/button.haml +1 -1
  30. data/site_template/design/button.rb +1 -1
  31. data/site_template/design/foot.haml +1 -3
  32. data/site_template/design/foot.sass +0 -1
  33. data/site_template/design/head.haml +3 -6
  34. data/site_template/design/head.sass +24 -22
  35. data/site_template/design/page.haml +1 -2
  36. data/site_template/pages/About.yaml +5 -6
  37. data/site_template/pages/Home.yaml +5 -6
  38. data/site_template/pages/Home.yaml.~1~ +14 -0
  39. data/site_template/pages/Home.yaml.~2~ +14 -0
  40. data/site_template/pages/Home.yaml.~3~ +14 -0
  41. data/site_template/pages/Home.yaml.~4~ +14 -0
  42. data/site_template/pages/Home.yaml.~5~ +14 -0
  43. data/site_template/pages/News.yaml +5 -6
  44. data/site_template/pages/NotFound.yaml +5 -6
  45. data/site_template/pages/Products.yaml +5 -6
  46. data/site_template/public/js/jquery-1.3.2.min.js +19 -0
  47. data/site_template/public/js/jquery-ui-1.7.2.custom.min.js +34 -0
  48. data/site_template/public/js/jquery.json-1.3.min.js +37 -0
  49. data/site_template/public/skin/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  50. data/site_template/public/skin/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  51. data/site_template/public/skin/images/ui-bg_flat_10_000000_40x100.png +0 -0
  52. data/site_template/public/skin/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  53. data/site_template/public/skin/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  54. data/site_template/public/skin/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  55. data/site_template/public/skin/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  56. data/site_template/public/skin/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  57. data/site_template/public/skin/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  58. data/site_template/public/skin/images/ui-icons_222222_256x240.png +0 -0
  59. data/site_template/public/skin/images/ui-icons_228ef1_256x240.png +0 -0
  60. data/site_template/public/skin/images/ui-icons_ef8c08_256x240.png +0 -0
  61. data/site_template/public/skin/images/ui-icons_ffd27a_256x240.png +0 -0
  62. data/site_template/public/skin/images/ui-icons_ffffff_256x240.png +0 -0
  63. data/site_template/public/skin/jquery-ui-1.7.2.custom.css +406 -0
  64. data/site_template/public/style/style.css +63 -61
  65. metadata +42 -6
  66. data/lib/milk/fields/component_view.haml +0 -2
  67. data/milk-0.0.5.gem +0 -0
data/Rakefile CHANGED
@@ -3,6 +3,10 @@ task :gem do
3
3
  exec "gem build milk.gemspec"
4
4
  end
5
5
 
6
+ desc "Delete gems"
7
+ task :clean do
8
+ exec "rm *.gem"
9
+ end
6
10
 
7
11
  desc "Run Sample site to test framework"
8
12
  task :sample_test do
@@ -39,6 +39,7 @@ module Milk
39
39
  autoload :Haxe, "milk/haxe"
40
40
  autoload :Field, "milk/field"
41
41
  autoload :Fields, "milk/field"
42
+
42
43
  end
43
44
 
44
45
  # Autoload the components of the user space app into the root namespace for easy use
@@ -4,6 +4,12 @@ module Milk
4
4
  PAGE_PATH_REGEX = /^\/([a-zA-Z0-9_]+(\/[a-zA-Z0-9_]+)*)+\/*$/
5
5
  EDIT_PATH_REGEX = /^\/([a-zA-Z0-9_]+(\/[a-zA-Z0-9_]+)*)+\/edit\/*$/
6
6
 
7
+ attr_reader :req
8
+
9
+ def initialize(require_ssl=false)
10
+ @require_ssl = require_ssl
11
+ end
12
+
7
13
  def route
8
14
  path = @req.path_info
9
15
 
@@ -16,6 +22,7 @@ module Milk
16
22
  regex = /(.*)/
17
23
 
18
24
  # Route the request to the right callback
25
+ https = @req.env['HTTPS'] == 'on'
19
26
  action = case
20
27
  when @req.get?
21
28
  case
@@ -23,7 +30,11 @@ module Milk
23
30
  :logout
24
31
  when path =~ EDIT_PATH_REGEX
25
32
  regex = EDIT_PATH_REGEX
26
- :edit
33
+ if @require_ssl && !https
34
+ :https_redirect
35
+ else
36
+ :edit
37
+ end
27
38
  when path =~ PAGE_PATH_REGEX
28
39
  regex = PAGE_PATH_REGEX
29
40
  :view
@@ -52,7 +63,6 @@ module Milk
52
63
  if (action == :view || action == :edit)
53
64
  begin
54
65
  page = Milk::Page.find(page_name)
55
- page.instance_variable_set(:@app, self)
56
66
  rescue Milk::PageNotFoundError
57
67
  action = :not_found
58
68
  end
@@ -60,7 +70,6 @@ module Milk
60
70
 
61
71
  if (action == :preview || action == :save)
62
72
  page = Milk::Page.json_unserialize(YAML.load(@req.body.read), page_name)
63
- page.instance_variable_set(:@app, self)
64
73
  end
65
74
 
66
75
  if !@user && [:edit, :save, :delete].include?(action)
@@ -103,17 +112,21 @@ module Milk
103
112
 
104
113
  def login()
105
114
  email = @req.params['email']
106
- user = users[email]
107
- if user
108
- expected = user["hash"]
109
- actual = hash(email, @req.params['password'])
110
- if actual == expected
111
- @resp.set_cookie('auth', :path => "/", :value => obfuscate(email))
115
+ if email.length > 0
116
+ user = users[email]
117
+ if user
118
+ expected = user["hash"]
119
+ actual = hash(email, @req.params['password'])
120
+ if actual == expected
121
+ @resp.set_cookie('auth', :path => "/", :value => obfuscate(email), :secure=>@require_ssl, :httponly=>true)
122
+ else
123
+ flash "Incorrect password for user #{email}"
124
+ end
112
125
  else
113
- flash "Incorrect password for user #{email}"
126
+ flash "User #{email} not found"
114
127
  end
115
128
  else
116
- flash "User #{email} not found"
129
+ flash "Please enter user email and password"
117
130
  end
118
131
  @resp.redirect(@req.params['dest'])
119
132
  end
@@ -153,14 +166,24 @@ module Milk
153
166
  case action
154
167
  when :not_found
155
168
  @resp.status = 404
156
- @resp.write Milk::Page.find('NotFound').view
169
+ page = Milk::Page.find('NotFound')
170
+ Milk::Application.join_tree(page, self)
171
+ @resp.write page.view
157
172
  when :view
173
+ Milk::Application.join_tree(@page, self)
158
174
  @resp.write @page.view
175
+ when :https_redirect
176
+ @resp.redirect('https://' + @req.host + @req.fullpath)
177
+ when :http_redirect
178
+ @resp.redirect('http://' + @req.host + @req.fullpath)
159
179
  when :edit
180
+ Milk::Application.join_tree(@page, self)
160
181
  @resp.write @page.edit
161
182
  when :save
183
+ Milk::Application.join_tree(@page, self)
162
184
  @resp.write @page.save
163
185
  when :preview
186
+ Milk::Application.join_tree(@page, self)
164
187
  @resp.write @page.preview
165
188
  when :login_form
166
189
  filename = FIELDS_DIR + "/login.haml"
@@ -178,6 +201,23 @@ module Milk
178
201
  end
179
202
  @resp.finish
180
203
  end
204
+
205
+ # method that walks an object linking Milk objects to eachother
206
+ def self.join_tree(obj, parent)
207
+ if [Milk::Page, Milk::Component, Milk::Application].any? {|klass| obj.kind_of? klass}
208
+ puts "Setting #{obj}'s parent to #{parent}"
209
+ obj.parent = parent
210
+ obj.instance_variables.each do |name|
211
+ var = obj.instance_variable_get(name)
212
+ if var.class == Array
213
+ var.each do |subvar|
214
+ join_tree(subvar, obj)
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
220
+
181
221
  end
182
222
 
183
223
  class PageNotFoundError < Exception
@@ -3,12 +3,21 @@ module Milk
3
3
 
4
4
  @@local_flag = {}
5
5
 
6
+ attr_accessor :parent
7
+ @parent = nil
8
+
9
+
10
+ # Don't store global properties or backreferences to the parent
6
11
  def to_yaml_properties
7
- if respond_to? :global_properties
8
- instance_variables.select { |name| name == :page || !global_properties.member?(name) }
12
+ (if respond_to? :global_properties
13
+ instance_variables.reject { |name| global_properties.member?(name) }
9
14
  else
10
15
  instance_variables
11
- end
16
+ end).reject { |name| name == :@parent }
17
+ end
18
+
19
+ def app
20
+ page.app
12
21
  end
13
22
 
14
23
  def page
@@ -18,7 +27,6 @@ module Milk
18
27
  @parent.page
19
28
  end
20
29
  end
21
-
22
30
 
23
31
  def self.local_properties(*props)
24
32
  end
@@ -74,19 +82,27 @@ module Milk
74
82
  end
75
83
 
76
84
  def save_settings
85
+ return unless respond_to? :global_properties
86
+ yaml_file = Milk::CONFIG_DIR + "/#{system_name}.yaml"
87
+ data = {}
88
+ global_properties.each do |name|
89
+ data[name.to_s.sub('@','')] = instance_variable_get(name)
90
+ end
91
+
92
+ File.open(yaml_file, "w") do |file|
93
+ file.write(YAML.dump(data))
94
+ end
95
+ end
96
+
97
+ def system_name
98
+ self.class.to_s.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase
77
99
  end
78
100
 
79
101
  def load_settings
80
- # Only load once
81
- return unless @system_name.nil?
82
-
83
- @system_name = self.class.to_s.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase
84
- yaml_file = Milk::CONFIG_DIR + "/#{@system_name}.yaml"
102
+ yaml_file = Milk::CONFIG_DIR + "/#{system_name}.yaml"
85
103
  if File.file? yaml_file
86
- obj = YAML.load_file(yaml_file)
87
- obj.instance_variable_set(:@parent, @parent)
88
- obj.instance_variables.each do |key|
89
- self.instance_variable_set(key, obj.instance_variable_get(key)) unless self.instance_variable_get(key)
104
+ YAML.load_file(yaml_file).each_pair do |key, value|
105
+ instance_variable_set("@#{key}".to_sym, value)
90
106
  end
91
107
  end
92
108
  end
@@ -115,13 +131,11 @@ module Milk
115
131
  end
116
132
 
117
133
  def view
118
- load_settings
119
- haml_file = Milk::COMPONENTS_DIR + "/" + @system_name + ".haml"
134
+ haml_file = Milk::COMPONENTS_DIR + "/" + system_name + ".haml"
120
135
  raise "Missing template \"" + haml_file + "\"" unless File.file? haml_file
121
136
  ::Haml::Engine.new(File.read(haml_file), :filename => haml_file).render(self)
122
137
  end
123
138
 
124
-
125
139
  end
126
140
  end
127
141
 
@@ -0,0 +1,141 @@
1
+ module Milk
2
+ class Component
3
+
4
+ @@local_flag = {}
5
+
6
+ attr_accessor :parent
7
+ @parent = nil
8
+
9
+
10
+ # Don't store global properties or backreferences to the parent
11
+ def to_yaml_properties
12
+ (if respond_to? :global_properties
13
+ instance_variables.reject { |name| global_properties.member?(name) }
14
+ else
15
+ instance_variables
16
+ end).reject { |name| name == :@parent }
17
+ end
18
+
19
+ def app
20
+ page.app
21
+ end
22
+
23
+ def page
24
+ if @parent.class == Milk::Page
25
+ @parent
26
+ else
27
+ @parent.page
28
+ end
29
+ end
30
+
31
+ def self.local_properties(*props)
32
+ end
33
+
34
+ def self.global_properties(*props)
35
+ globals = props.collect{|name|"@#{name}".to_sym}
36
+ class_def :global_properties do
37
+ globals
38
+ end
39
+ end
40
+
41
+ def name
42
+ self.class.to_s
43
+ end
44
+
45
+ # All Components start out with default of no fields
46
+ def self.fields
47
+ []
48
+ end
49
+
50
+ # Assume no defaults
51
+ def self.defaults
52
+ {}
53
+ end
54
+
55
+ # Metaclass black magic to simulate appending items to a list
56
+ # This works by getting the old result of the fields class method
57
+ # and stores it in a closure, and then redefines the method, but with
58
+ # a new item appended.
59
+ def self.add_field(klass, field, label, options={})
60
+
61
+ # Merge in assumes options
62
+ options[:field] = field
63
+ options[:label] = label
64
+
65
+ # Fill in blanks with defaults
66
+ defaults.each do |k, v|
67
+ options[k] ||= v
68
+ end
69
+
70
+ field = klass.new(options)
71
+
72
+ newfields = self.fields + [field]
73
+ meta_def("fields") do
74
+ newfields
75
+ end
76
+ end
77
+
78
+ def self.method_missing(method, *args)
79
+ raise "Missing '#{method}' method" unless File.file? FIELDS_DIR+"/#{method}.rb"
80
+ klass = eval("Fields::" + method.to_s.gsub(/(^|_)(.)/) { $2.upcase })
81
+ add_field(klass, *args)
82
+ end
83
+
84
+ def save_settings
85
+ return unless respond_to? :global_properties
86
+ yaml_file = Milk::CONFIG_DIR + "/#{system_name}.yaml"
87
+ data = {}
88
+ instance_variables.each do |name|
89
+ data[name] = instance_variable_get(name)
90
+ end
91
+ File.open(yaml_file, "w") do |file|
92
+ file.write(data)
93
+ end
94
+ end
95
+
96
+ def system_name
97
+ self.class.to_s.gsub(/([a-z])([A-Z])/) { "#{$1}_#{$2}" }.downcase
98
+ end
99
+
100
+ def load_settings
101
+ yaml_file = Milk::CONFIG_DIR + "/#{system_name}.yaml"
102
+ if File.file? yaml_file
103
+ YAML.load_file(yaml_file).each_pair do |key, value|
104
+ instance_variable_set("@#{key}".to_sym, value)
105
+ end
106
+ end
107
+ end
108
+
109
+ def haml(filename, context=self, extras={})
110
+ if block_given?
111
+ Page.haml(filename, context, extras) { yield }
112
+ else
113
+ Page.haml(filename, context, extras)
114
+ end
115
+ end
116
+
117
+ def partial(filename, vars, extras={})
118
+ obj = self.dup
119
+ vars.each do |key, value|
120
+ obj.instance_variable_set("@#{key}", value)
121
+ end
122
+ haml(filename, obj, extras)
123
+ end
124
+
125
+
126
+ def edit(prefix)
127
+ @prefix = prefix
128
+ haml_file = FIELDS_DIR + "/component.haml"
129
+ ::Haml::Engine.new(File.read(haml_file), :filename => haml_file).render(self)
130
+ end
131
+
132
+ def view
133
+ haml_file = Milk::COMPONENTS_DIR + "/" + system_name + ".haml"
134
+ raise "Missing template \"" + haml_file + "\"" unless File.file? haml_file
135
+ ::Haml::Engine.new(File.read(haml_file), :filename => haml_file).render(self)
136
+ end
137
+
138
+ end
139
+ end
140
+
141
+
@@ -6,52 +6,63 @@
6
6
  %style{:type=>"text/css"}
7
7
  :sass
8
8
  !width = 400
9
- !height = 150
9
+ !height = 160
10
10
  table, #shadow, .ui-widget-shadow
11
11
  :width = !width + "px"
12
12
  :height = !height + "px"
13
- table, #shadow
13
+ table#login, #shadow
14
+ :font-size 15px
14
15
  :position absolute
15
16
  :top 50%
16
17
  :left 50%
17
18
  :margin
18
19
  :top = (-!height/2)+"px"
19
20
  :left = (-!width/2)+"px"
20
- #flash
21
- :padding 0pt 0.7em
22
- span
23
- :float left
24
- :margin-right 0.3em
25
- button
26
- :cursor pointer
27
- :line-height 1em
28
- :padding 2px 5px 2px 2px
29
- .ui-icon
30
- :float left
21
+ table#login td, table#login th
22
+ :vertical-align middle
23
+ #login
24
+ tr.ui-state-error
25
+ td
26
+ :padding 5px 10px
27
+ :font-size 12px
28
+ span
29
+ :float left
30
+ :margin-right 0.3em
31
+ .ui-widget-header
32
+ :line-height 2em
33
+ :height 2em
34
+ button
35
+ :font-size 12px
36
+ :cursor pointer
31
37
  :line-height 1em
38
+ :padding 2px 5px 2px 2px
39
+ .ui-icon
40
+ :float left
41
+ :line-height 1em
32
42
 
33
43
  %link{ :rel => "shortcut icon", :href => "/favicon.ico", :type => "image/x-icon"}/
34
- %link{ :href => "http://static.creationix.com/skins/ui-lightness/jquery-ui-1.7.1.custom.css", :media => "screen", :rel => "stylesheet", :type => "text/css" }/
44
+ %link{ :href => "/skin/jquery-ui-1.7.2.custom.css", :media => "screen", :rel => "stylesheet", :type => "text/css" }/
35
45
  %link{ :href => "/style/style.css", :media => "screen", :rel => "stylesheet", :type => "text/css" }/
36
- %script{:src=>"http://static.creationix.com/scripts/jquery-1.3.2.min.js", :type=>"text/javascript"}
37
- %script{:src=>"http://static.creationix.com/scripts/jquery.json-1.3.min.js", :type=>"text/javascript"}
38
- %script{:src=>"http://static.creationix.com/scripts/jquery-ui-1.7.1.custom.min.js", :type=>"text/javascript"}
46
+ %script{:src=>"/js/jquery-1.3.2.min.js", :type=>"text/javascript"}
47
+ %script{:src=>"/js/jquery.json-1.3.min.js", :type=>"text/javascript"}
48
+ %script{:src=>"/js/jquery-ui-1.7.2.custom.min.js", :type=>"text/javascript"}
39
49
  %body
40
- - if f = flash
41
- #flash{:class => "ui-state-error ui-corner-all"}
42
- %p
43
- %span{:class => "ui-icon ui-icon-alert"}
44
- %strong Alert:
45
- &= f
50
+ .ui-widget-overlay
46
51
  %form{:action => "/login", :method=>"post"}
47
52
  %input{:type=>"hidden", :name => "dest", :value => @req.path_info}
48
53
  #shadow
49
54
  .ui-widget-shadow
50
- %table{:class => "ui-widget ui-widget-content ui-corner-all"}
55
+ %table#login{:class => "ui-widget ui-widget-content ui-corner-all"}
51
56
  %thead
52
57
  %tr
53
- %th{:colspan=>2, :class=>"ui-widget-header ui-corner-all"}
58
+ %th{:colspan=>2, :class=>"ui-widget-header ui-corner-top"}
54
59
  &= "Please Login to edit '#{@page.pagename}'"
60
+ - if f = flash
61
+ %tr.ui-state-error{:class=>"ui-corner-all"}
62
+ %td{:colspan=>2}
63
+ %span{:class => "ui-icon ui-icon-alert",:style=>"float:left"}
64
+ %strong Alert:
65
+ &= f
55
66
  %tr
56
67
  %th Email
57
68
  %td