nitro 0.24.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/CHANGELOG +279 -0
  2. data/ProjectInfo +7 -7
  3. data/doc/AUTHORS +4 -2
  4. data/doc/RELEASES +96 -1
  5. data/lib/nitro.rb +5 -2
  6. data/lib/nitro/adapter/cgi.rb +1 -1
  7. data/lib/nitro/adapter/webrick.rb +7 -5
  8. data/lib/nitro/caching/output.rb +3 -2
  9. data/lib/nitro/cgi/utils.rb +8 -4
  10. data/lib/nitro/compiler.rb +9 -5
  11. data/lib/nitro/compiler/include.rb +42 -0
  12. data/lib/nitro/compiler/markup.rb +1 -1
  13. data/lib/nitro/compiler/morphing.rb +120 -50
  14. data/lib/nitro/compiler/squeeze.rb +2 -2
  15. data/lib/nitro/context.rb +9 -0
  16. data/lib/nitro/controller.rb +8 -4
  17. data/lib/nitro/dispatcher.rb +5 -5
  18. data/lib/nitro/dispatcher/nice.rb +16 -5
  19. data/lib/nitro/element.rb +30 -8
  20. data/lib/nitro/helper.rb +56 -0
  21. data/lib/nitro/{mixin → helper}/benchmark.rb +1 -1
  22. data/lib/nitro/{mixin → helper}/buffer.rb +1 -2
  23. data/lib/nitro/{mixin → helper}/debug.rb +1 -1
  24. data/lib/nitro/{mixin/helper.rb → helper/default.rb} +4 -4
  25. data/lib/nitro/{mixin → helper}/form.rb +3 -3
  26. data/lib/nitro/{mixin → helper}/javascript.rb +17 -1
  27. data/lib/nitro/{mixin → helper}/pager.rb +1 -1
  28. data/lib/nitro/{mixin → helper}/rss.rb +3 -3
  29. data/lib/nitro/{mixin → helper}/table.rb +1 -1
  30. data/lib/nitro/{mixin → helper}/xhtml.rb +2 -2
  31. data/lib/nitro/{mixin → helper}/xml.rb +1 -1
  32. data/lib/nitro/render.rb +16 -8
  33. data/lib/nitro/scaffold.rb +6 -6
  34. data/lib/nitro/server/runner.rb +12 -0
  35. data/lib/nitro/session/drbserver.rb +16 -1
  36. data/proto/public/js/builder.js +97 -0
  37. data/proto/public/js/controls.js +18 -5
  38. data/proto/public/js/dragdrop.js +8 -5
  39. data/proto/public/js/effects.js +185 -4
  40. data/proto/public/js/prototype.js +432 -178
  41. data/proto/public/js/scriptaculous.js +6 -2
  42. data/proto/public/js/slider.js +226 -0
  43. data/proto/public/js/unittest.js +363 -0
  44. data/proto/public/media/nitro.png +0 -0
  45. data/{script → proto/script}/scgi_ctl +0 -0
  46. data/{script → proto/script}/scgi_service +16 -8
  47. data/proto/src/skin.rb +24 -0
  48. data/{lib → src}/part/admin.rb +0 -0
  49. data/src/part/admin/controller.rb +47 -0
  50. data/{lib → src}/part/admin/skin.rb +0 -0
  51. data/src/part/admin/template/denied.xhtml +1 -0
  52. data/{lib → src}/part/admin/template/index.xhtml +0 -0
  53. data/test/nitro/{mixin → helper}/tc_pager.rb +2 -2
  54. data/test/nitro/{mixin → helper}/tc_rss.rb +3 -3
  55. data/test/nitro/{mixin → helper}/tc_table.rb +3 -3
  56. data/test/nitro/{mixin → helper}/tc_xhtml.rb +3 -3
  57. data/test/nitro/tc_caching.rb +4 -1
  58. data/test/nitro/tc_controller.rb +2 -2
  59. data/test/nitro/tc_element.rb +30 -0
  60. data/test/nitro/tc_helper.rb +36 -0
  61. data/test/nitro/tc_render.rb +1 -1
  62. metadata +70 -38
  63. data/lib/nitro/mixin/markup.rb +0 -122
  64. data/lib/part/admin/controller.rb +0 -28
  65. data/proto/README +0 -11
  66. data/proto/doc/README +0 -1
  67. data/proto/scgi.rb +0 -333
@@ -15,7 +15,7 @@ class CgiAdapter
15
15
 
16
16
  def self.start(server)
17
17
  cgi = CGI.new
18
- CgiUtils.process(server, cgi, cgi, cgi)
18
+ Cgi.process(server, cgi, cgi, cgi)
19
19
  =begin
20
20
  context = Context.new(server)
21
21
  context.headers = ENV
@@ -134,7 +134,8 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
134
134
 
135
135
  # gmosx: make compatible with fastcgi.
136
136
  context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//)
137
- context.headers['REQUEST_URI'] << '/'
137
+ # context.headers['REQUEST_URI'] << '/'
138
+ context.headers['REQUEST_URI'] = '/' + context.headers['REQUEST_URI']
138
139
 
139
140
  Cgi.parse_params(context)
140
141
  Cgi.parse_cookies(context)
@@ -161,9 +162,9 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
161
162
  # Try to rewrite the path to a filename.
162
163
 
163
164
  def rewrite(req)
164
- if req.path == '/'
165
+ if req.path_info == '/'
165
166
  req.instance_variable_set(:@path_info, '/index.html')
166
- elsif req.path =~ /^([^.]+)$/
167
+ elsif req.path_info =~ /^([^.]+)$/
167
168
  req.instance_variable_set(:@path_info, "#{$1}/index.html")
168
169
  end
169
170
  end
@@ -171,9 +172,9 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
171
172
  # Rewrite back to the original path.
172
173
 
173
174
  def unrewrite(req)
174
- if req.path == '/'
175
+ if req.path_info == '/index.html'
175
176
  req.instance_variable_set(:@path_info, '/')
176
- elsif req.path =~ /^([^.]+).html$/
177
+ elsif req.path_info =~ /^([^.]+)\/index.html$/
177
178
  req.instance_variable_set(:@path_info, $1)
178
179
  end
179
180
  end
@@ -183,3 +184,4 @@ end
183
184
 
184
185
  # * George Moschovitis <gm@navel.gr>
185
186
  # * Guillaume Pierronnet <guillaume.pierronnet@laposte.net>
187
+ # * Bryan Soto <bryan.a.soto@gmail.com>
@@ -44,7 +44,7 @@ module Caching
44
44
  def output_cache_path(path)
45
45
  filename = ((path.empty? || path == '/') ? 'index.html' : path.dup)
46
46
  # filename.gsub!(/\/$/, '')
47
- filename << 'index.html' unless (filename.split('/').last || filename).include? '.'
47
+ filename << '/index.html' unless (filename.split('/').last || filename).include? '.'
48
48
  return output_cache_root + '/' + filename
49
49
  end
50
50
 
@@ -66,9 +66,10 @@ module Caching
66
66
  # gmosx: is this the right thing to do?
67
67
  end
68
68
  end
69
+ alias_method :delete_output, :expire_output
69
70
 
70
71
  def caching_allowed?
71
- !@request.post?
72
+ not (@request.post? or @request.uri =~ /\?/)
72
73
  end
73
74
 
74
75
  end
@@ -5,25 +5,29 @@ module Nitro
5
5
  module Request
6
6
 
7
7
  # Some useful mini methods for browser testing.
8
+ # TODO: add testing for mac IE (an other platforms)
8
9
 
10
+ # Different servers hold user agent in differnet
11
+ # strings (unify this).
12
+
9
13
  def user_agent
10
14
  headers['HTTP_USER_AGENT'] || headers['USER-AGENT']
11
15
  end
12
16
 
13
17
  def from_gecko?
14
- headers['USER-AGENT'] =~ /Gecko/
18
+ user_agent =~ /Gecko/
15
19
  end
16
20
  alias_method :from_mozilla?, :from_gecko?
17
21
 
18
22
  def from_ie?
19
- headers['USER-AGENT'] =~ /MSIE/
23
+ user_agent =~ /MSIE/
20
24
  end
21
25
  alias_method :from_msie?, :from_ie?
22
26
 
23
27
  def from_opera?
24
- headers['USER-AGENT'] =~ /Opera/
28
+ user_agent =~ /Opera/
25
29
  end
26
30
 
27
31
  def from_khtml?
28
- headers['USER-AGENT'] =~ /KTHML/
32
+ user_agent =~ /KTHML/
29
33
  end
30
34
  alias_method :from_safari?, :from_khtml?
31
35
 
@@ -38,7 +38,7 @@ class Compiler
38
38
  # template_root/action/index.xhtml
39
39
 
40
40
  path = "#{template_root}/#{action.gsub(/__/, '/')}/#{Template.default}.#{ext}".squeeze('/')
41
-
41
+
42
42
  unless File.exist?(path)
43
43
  # No template found!
44
44
  return nil
@@ -105,7 +105,7 @@ class Compiler
105
105
 
106
106
  code = %{
107
107
  def #{action}_action
108
- @parent_action_name = @action_name
108
+ @parent_action_name = @action_name
109
109
  @action_name = '#{action}'
110
110
  }
111
111
 
@@ -131,17 +131,21 @@ class Compiler
131
131
  param_count = klass.instance_method(action.intern).arity
132
132
 
133
133
  if param_count != 0
134
+ if param_count > 0
135
+ code << "params = Array.new(#{param_count}, nil);"
136
+ else
137
+ code << "params = [];"
138
+ end
134
139
  code << %{
135
- params = []
136
140
  if context.query_string
137
141
  context.query_string.split(/[&;]/).each_with_index do |qs, i|
138
142
  }
139
143
  # Don't pass more parameters than the action's arity.
140
144
  if param_count > 0
141
- code << "break if i >= #{param_count};"
145
+ code << "break unless i < #{param_count};"
142
146
  end
143
147
  code << %{
144
- params << CGI.unescape(qs.split(/=/).last)
148
+ params[i] = CGI.unescape(qs.split(/=/).last)
145
149
  end
146
150
  end
147
151
  action_return_value = #{action}(*params)
@@ -0,0 +1,42 @@
1
+ module Nitro
2
+
3
+ # Performs static includes. Typically you should include this compiler
4
+ # as the first stage of the compile pipeline.
5
+ #
6
+ # This compiler is extremely helpful, typically you would want
7
+ # to use static includes in many many cases.
8
+
9
+ class StaticInclude
10
+ #--
11
+ # FIXME: use template root of the controller.
12
+ #++
13
+
14
+ def self.transform(text)
15
+ # Statically include sub-template files.
16
+ # The target file is included at compile time.
17
+ #
18
+ # gmosx: must be xformed before the <?r pi.
19
+ #
20
+ # Example:
21
+ # <?include href="root/myfile.sx" ?>
22
+
23
+ return text.gsub(/<\?include href=["|'](.*?)["|'](.*)\?>/) do |match|
24
+ unless File.exist?(filename = "#{Template.root}/#$1")
25
+ unless File.exist?(filename = "#{Template.root}/#$1.xinc")
26
+ unless File.exist?(filename = "#{Template.root}/#$1.xhtml")
27
+ raise "Cannot include '#{Template.root}/#$1'"
28
+ end
29
+ end
30
+ end
31
+ itext = File.read(filename)
32
+ itext.gsub!(/<\?xml.*\?>/, '')
33
+ itext.gsub!(/<\/?root(.*?)>/m, ' ');
34
+ itext
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
42
+ # * George Moschovitis <gm@navel.gr>
@@ -1,4 +1,4 @@
1
- require 'nitro/mixin/markup'
1
+ require 'glue/markup'
2
2
 
3
3
  module Nitro
4
4
 
@@ -1,66 +1,136 @@
1
- module Nitro::Compiler
1
+ require 'rexml/document'
2
+ require 'rexml/streamlistener'
2
3
 
3
- # A module that expand xhtml tags to ruby code
4
- # according to some tag attributes. (if, unless, each)
5
- #--
6
- # FIXME: nested tags are not handled correctly. We should
7
- # reimplement this using REXML or something.
8
- #++
4
+ module Nitro
9
5
 
10
- module Morphing
6
+ # A compiler that handles these attribute's tags:
7
+ #
8
+ # <tag if="x">..</tag>
9
+ # <tag unless="x">..</tag>
10
+ # <tag each="x">..</tag>
11
+ # <tag times="x">..</tag>
12
+ #
13
+ # by transforming them like that
14
+ #
15
+ # <div prop1="one" if="@mycond" prop2="two">@mycond is true</div>
16
+ #
17
+ # becomes
18
+ #
19
+ # <?r if @mycond ?>
20
+ # <div prop1="one" prop2="two">@mycond is true</div>
21
+ # <?r end ?>
22
+ #
23
+ #
24
+ # <li times="3">...</li>
25
+ #
26
+ # becomes
27
+ #
28
+ # <?r 3.times do ?>
29
+ # <li>...</li>
30
+ # <?r end ?>
31
+ #
32
+ #
33
+ # <li each="item in array">my item is #{item}</li>
34
+ #
35
+ # becomes
36
+ #
37
+ # <?r for item in array ?>
38
+ # <li>my item is #{item}</li>
39
+ # <?r end ?>
11
40
 
12
- def self.transform(input_text)
13
- text = input_text.dup
14
- # <tag if="x">..</tag>
15
- # <tag unless="x">..</tag>
16
- #
17
- # example:
18
- #
19
- # <div prop1="one" if="@mycond" prop2="two">@mycond is true</div>
20
- #
21
- # becomes
22
- #
23
- # <?r if @mycond ?>
24
- # <div prop1="one" prop2="two">@mycond is true</div>
25
- # <?r end ?>
41
+ class Morphing
26
42
 
27
- text.gsub!(/<(\w*?)([^>]*?)(if|unless)=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
28
- %{<?r #$3 #$4 ?>
29
- <#$1#$2#$5>#$6</#$1>
30
- <?r end ?>}
43
+ class Listener # :nodoc: all
44
+ include REXML::StreamListener
45
+
46
+ attr_reader :buffer
47
+
48
+ def initialize
49
+ super
50
+ @buffer = ''
51
+ @stack = []
52
+ @depth = 0
31
53
  end
32
-
33
- # <tag times="x">..</tag>
34
-
35
- text.gsub!(/<(\w*?)([^>]*?)times=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
36
- %{<?r #$3.times do ?>
37
- <#$1#$2#$4>#$5</#$1>
38
- <?r end ?>}
54
+
55
+ def tag_start(name, attributes)
56
+ if attr = attributes.detect { |k, v| %w{if unless for each times}.include?(k) }
57
+ temp_buffer =
58
+ if attr[0] == 'times'
59
+ "<?r #{attr[1]}.times do ?>"
60
+ elsif (attr[0] == 'for' or attr[0] == 'each') and attr[1] =~ / in /
61
+ "<?r for #{attr[1]} ?>"
62
+ elsif attr[0] == 'if' or attr[0] == 'unless'
63
+ "<?r #{attr[0]} #{attr[1]} ?>"
64
+ else
65
+ Logger.info "Morphing: #{attr[0]} attribute found but was not suitable for morphing" if $DBG
66
+ false
67
+ end
68
+ if temp_buffer
69
+ @buffer << temp_buffer
70
+ attributes.delete(attr[0])
71
+ @stack.push(@depth)
72
+ end
73
+ end
74
+
75
+ attrs = attributes.collect do | k, v |
76
+ %|#{k}="#{v}"|
77
+ end
78
+
79
+ attrs = attrs.empty? ? "" : " " + attrs.join(' ')
80
+ @depth += 1
81
+ @buffer << "<#{name}#{attrs}>"
39
82
  end
40
83
 
41
- # <tag each="x">..</tag>
42
- #
43
- # example:
44
- #
45
- # <li each="item in array">my item is #{item}</li>
46
- #
47
- # becomes
48
- #
49
- # <?r for item in array ?>
50
- # <li>my item is #{item}</li>
51
- # <?r end ?>
52
-
53
- text.gsub!(/<(\w*?)([^>]*?)each=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
54
- %{<?r for #$3 ?>
55
- <#$1#$2#$4>#$5</#$1>
56
- <?r end ?>}
84
+ def tag_end(name)
85
+ @depth -= 1
86
+ @buffer << "</#{name}>"
87
+ if @stack.last == @depth
88
+ @buffer << "\n<?r end ?>"
89
+ @stack.pop
90
+ end
57
91
  end
58
92
 
59
- text
93
+ def text(str)
94
+ @buffer << str
95
+ end
96
+
97
+ def instruction(name, attributes)
98
+ @buffer << "<?#{name}#{attributes}?>"
99
+ end
60
100
  end
101
+
102
+ def self.transform(source)
103
+ listener = Listener.new
104
+ REXML::Document.parse_stream(source, listener)
105
+ return listener.buffer
106
+ end
107
+
108
+ end
61
109
 
62
110
  end
63
111
 
112
+ if __FILE__ == $0
113
+ puts Nitro::Morphing.transform(<<EOF)
114
+ <body>
115
+ <child attr1="attr1" if="test" attr2="attr2">
116
+ <mytag>
117
+ this is texxt
118
+ <one if="@qsdf">
119
+ qqqqq
120
+ </one>
121
+ </mytag>
122
+ </child>
123
+ <child times="4">
124
+ <mytag>
125
+ qqqqq
126
+ </mytag>
127
+ <one if="@qsdf">
128
+ text
129
+ </one>
130
+ </child>
131
+ </body>
132
+ EOF
64
133
  end
65
134
 
66
135
  # * George Moschovitis <gm@navel.gr>
136
+ # * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>
@@ -1,4 +1,4 @@
1
- module Nitro::Compiler
1
+ module Nitro
2
2
 
3
3
  # Compress the inline xhtml. Does not touch the ruby code.
4
4
 
@@ -6,7 +6,7 @@ class Squeeze
6
6
 
7
7
  # Compresses the inline xhtml. Does not touch the ruby code.
8
8
 
9
- def transform(text)
9
+ def self.transform(text)
10
10
  return text.gsub(/\@out \<\< \%\^(.*?)\^/m) do |match|
11
11
  c = $1.gsub(/^(\s*)/m, '').squeeze(" \t").tr("\n", '').tr("\t", ' ')
12
12
  "@out << %{#{c}}"
data/lib/nitro/context.rb CHANGED
@@ -80,6 +80,15 @@ class Context
80
80
  @session || @session = Session.lookup(self)
81
81
  end
82
82
 
83
+ # Lookup the controller for this request.
84
+ #--
85
+ # FIXME: improve this! BUGGY
86
+ #++
87
+
88
+ def controller
89
+ @dispatcher.controllers[@base || '/']
90
+ end
91
+
83
92
  # Populate an object from request parameters.
84
93
  # This is a truly dangerous method.
85
94
  #
@@ -1,14 +1,14 @@
1
1
  require 'mega/annotation'
2
2
 
3
3
  require 'glue/aspects'
4
- require 'glue/helper'
4
+ require 'glue/markup'
5
5
 
6
6
  require 'nitro'
7
7
  require 'nitro/render'
8
8
  require 'nitro/scaffold'
9
9
  require 'nitro/caching'
10
10
  require 'nitro/flash'
11
- require 'nitro/mixin/markup'
11
+ require 'nitro/helper'
12
12
 
13
13
  module Nitro
14
14
 
@@ -40,7 +40,7 @@ module Publishable
40
40
  include Render
41
41
  include Glue::Aspects
42
42
  include Flashing
43
- include Glue::Helpers
43
+ include Helpers
44
44
 
45
45
  # Override this method as needed. Unless overriden
46
46
  # this method is initialized by the Dispatcher to
@@ -136,7 +136,11 @@ class Controller
136
136
  include Publishable
137
137
  include Scaffolding
138
138
  include Caching
139
- include Markup
139
+ include Helpers
140
+ helper Markup
140
141
  end
141
142
 
142
143
  end
144
+
145
+ # * George Moschovitis <gm@navel.gr>
146
+