nitro 0.20.0 → 0.21.0

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 (115) hide show
  1. data/CHANGELOG +752 -543
  2. data/INSTALL +38 -38
  3. data/README +264 -225
  4. data/Rakefile +48 -49
  5. data/bin/nitro +3 -3
  6. data/bin/nitrogen +6 -6
  7. data/doc/AUTHORS +10 -10
  8. data/doc/CHANGELOG.1 +1939 -1939
  9. data/doc/CHANGELOG.2 +954 -954
  10. data/doc/LICENSE +3 -3
  11. data/doc/MIGRATION +28 -0
  12. data/doc/RELEASES +814 -643
  13. data/doc/config.txt +5 -5
  14. data/install.rb +7 -17
  15. data/lib/nitro.rb +38 -9
  16. data/lib/nitro/adapter/cgi.rb +311 -312
  17. data/lib/nitro/adapter/fastcgi.rb +18 -25
  18. data/lib/nitro/adapter/webrick.rb +128 -137
  19. data/lib/nitro/adapter/wee.rb +51 -0
  20. data/lib/nitro/caching.rb +20 -20
  21. data/lib/nitro/caching/actions.rb +43 -43
  22. data/lib/nitro/caching/fragments.rb +46 -46
  23. data/lib/nitro/caching/invalidation.rb +11 -11
  24. data/lib/nitro/caching/output.rb +65 -65
  25. data/lib/nitro/caching/stores.rb +67 -67
  26. data/lib/nitro/compiler.rb +262 -0
  27. data/lib/nitro/compiler/elements.rb +0 -0
  28. data/lib/nitro/compiler/errors.rb +65 -0
  29. data/lib/nitro/compiler/localization.rb +25 -0
  30. data/lib/nitro/compiler/markup.rb +19 -0
  31. data/lib/nitro/compiler/shaders.rb +206 -0
  32. data/lib/nitro/compiler/squeeze.rb +20 -0
  33. data/lib/nitro/compiler/xslt.rb +61 -0
  34. data/lib/nitro/context.rb +87 -88
  35. data/lib/nitro/controller.rb +151 -158
  36. data/lib/nitro/cookie.rb +34 -34
  37. data/lib/nitro/dispatcher.rb +195 -186
  38. data/lib/nitro/element.rb +132 -126
  39. data/lib/nitro/element/java_script.rb +6 -6
  40. data/lib/nitro/flash.rb +66 -66
  41. data/lib/nitro/mail.rb +192 -192
  42. data/lib/nitro/mixin/buffer.rb +66 -0
  43. data/lib/nitro/mixin/debug.rb +16 -16
  44. data/lib/nitro/mixin/form.rb +88 -0
  45. data/lib/nitro/mixin/helper.rb +2 -2
  46. data/lib/nitro/mixin/javascript.rb +108 -108
  47. data/lib/nitro/mixin/markup.rb +144 -0
  48. data/lib/nitro/mixin/pager.rb +202 -202
  49. data/lib/nitro/mixin/rss.rb +67 -0
  50. data/lib/nitro/mixin/table.rb +63 -0
  51. data/lib/nitro/mixin/xhtml.rb +75 -0
  52. data/lib/nitro/mixin/xml.rb +124 -0
  53. data/lib/nitro/render.rb +183 -359
  54. data/lib/nitro/request.rb +140 -140
  55. data/lib/nitro/response.rb +27 -27
  56. data/lib/nitro/routing.rb +21 -21
  57. data/lib/nitro/scaffold.rb +124 -118
  58. data/lib/nitro/server.rb +117 -80
  59. data/lib/nitro/server/runner.rb +341 -0
  60. data/lib/nitro/service.rb +12 -12
  61. data/lib/nitro/service/xmlrpc.rb +22 -22
  62. data/lib/nitro/session.rb +122 -120
  63. data/lib/nitro/session/drb.rb +9 -9
  64. data/lib/nitro/session/drbserver.rb +34 -34
  65. data/lib/nitro/template.rb +171 -155
  66. data/lib/nitro/testing/assertions.rb +90 -90
  67. data/lib/nitro/testing/context.rb +16 -16
  68. data/lib/nitro/testing/testcase.rb +34 -34
  69. data/proto/conf/lhttpd.conf +9 -9
  70. data/proto/public/error.xhtml +75 -75
  71. data/proto/public/index.xhtml +18 -18
  72. data/proto/public/js/behaviour.js +65 -65
  73. data/proto/public/js/controls.js +1 -1
  74. data/proto/public/js/prototype.js +3 -3
  75. data/proto/public/settings.xhtml +61 -61
  76. data/proto/run.rb +1 -5
  77. data/test/nitro/adapter/raw_post1.bin +0 -0
  78. data/test/nitro/adapter/tc_cgi.rb +57 -57
  79. data/test/nitro/adapter/tc_webrick.rb +4 -4
  80. data/test/nitro/mixin/tc_pager.rb +25 -25
  81. data/test/nitro/mixin/tc_rss.rb +24 -0
  82. data/test/nitro/mixin/tc_table.rb +31 -0
  83. data/test/nitro/mixin/tc_xhtml.rb +13 -0
  84. data/test/nitro/tc_caching.rb +10 -10
  85. data/test/nitro/tc_context.rb +8 -8
  86. data/test/nitro/tc_controller.rb +48 -48
  87. data/test/nitro/tc_cookie.rb +6 -6
  88. data/test/nitro/tc_dispatcher.rb +64 -64
  89. data/test/nitro/tc_element.rb +27 -27
  90. data/test/nitro/tc_flash.rb +31 -31
  91. data/test/nitro/tc_mail.rb +63 -63
  92. data/test/nitro/tc_server.rb +26 -26
  93. data/test/nitro/tc_session.rb +9 -9
  94. data/test/nitro/tc_template.rb +19 -19
  95. data/test/public/blog/list.xhtml +1 -1
  96. metadata +31 -37
  97. data/lib/nitro/buffering.rb +0 -45
  98. data/lib/nitro/builder/form.rb +0 -104
  99. data/lib/nitro/builder/rss.rb +0 -104
  100. data/lib/nitro/builder/table.rb +0 -80
  101. data/lib/nitro/builder/xhtml.rb +0 -132
  102. data/lib/nitro/builder/xml.rb +0 -131
  103. data/lib/nitro/conf.rb +0 -36
  104. data/lib/nitro/environment.rb +0 -21
  105. data/lib/nitro/errors.rb +0 -69
  106. data/lib/nitro/localization.rb +0 -153
  107. data/lib/nitro/markup.rb +0 -147
  108. data/lib/nitro/output.rb +0 -24
  109. data/lib/nitro/runner.rb +0 -348
  110. data/lib/nitro/shaders.rb +0 -206
  111. data/test/nitro/builder/tc_rss.rb +0 -23
  112. data/test/nitro/builder/tc_table.rb +0 -30
  113. data/test/nitro/builder/tc_xhtml.rb +0 -39
  114. data/test/nitro/builder/tc_xml.rb +0 -56
  115. data/test/nitro/tc_localization.rb +0 -49
File without changes
@@ -0,0 +1,65 @@
1
+ require 'facet/string/demodulize'
2
+
3
+ module Nitro
4
+
5
+ class ActionCompileError < SyntaxError
6
+ SOURCE_CODE_RADIUS = 5
7
+
8
+ attr_accessor :original_excpetion
9
+
10
+ def initialize(source_code, filename, original_exception)
11
+ @source_code = source_code.split("\n")
12
+ @filename = filename
13
+ @original_exception = original_exception
14
+ end
15
+
16
+ def line_number
17
+ trace = @original_exception.backtrace.join
18
+
19
+ if trace.include?(":in `class_eval'")
20
+ trace.scan(/:([0-9]*):in `class_eval'/).first.first.to_i
21
+ else
22
+ 1
23
+ end
24
+ end
25
+
26
+ def source_extract(indent = 0)
27
+ ln = line_number
28
+ start_line = [ln - SOURCE_CODE_RADIUS, 0].max
29
+ end_line = [ln + SOURCE_CODE_RADIUS - 1, @source_code.length].min
30
+
31
+ number = start_line
32
+ extract = @source_code[start_line..end_line].collect do |line|
33
+ number += 1
34
+ line = line.gsub(/; @out << %\^/, ' ?>').gsub(/\^;/, '<?r ')
35
+ if number == line_number
36
+ "#{' ' * indent}#{number}: #{line}"
37
+ else
38
+ "#{' ' * indent}#{number}: #{line}"
39
+ end
40
+ end
41
+
42
+ return extract.join("\n")
43
+ end
44
+
45
+ def backtrace
46
+ @original_exception.backtrace.collect do |line|
47
+ line.gsub("#{Nitro::LibPath}/", '')
48
+ end.compact
49
+ end
50
+
51
+ def to_s
52
+ "#{self.class.to_s.demodulize} (#{@original_exception.class}): '#@filename' at line ##{line_number}"
53
+ end
54
+
55
+ def message
56
+ "#{to_s}\n#{source_extract}"
57
+ end
58
+ end
59
+
60
+ class TemplateCompileError < ActionCompileError
61
+ end
62
+
63
+ end
64
+
65
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,25 @@
1
+ require 'glue/localization'
2
+
3
+ module Glue
4
+
5
+ class Localization
6
+
7
+ class << self
8
+
9
+ # Transform localization macros.
10
+
11
+ def transform(text)
12
+ # handle symbols
13
+ text.gsub!(/\[\[\:(.*?)\]\]/, '#{@lc[\1]}')
14
+
15
+ # handle strings
16
+ text.gsub!(/\[\[(.*?)\]\]/, '#{@lc["\1"]}')
17
+
18
+ return text
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,19 @@
1
+ require 'nitro/mixin/markup'
2
+
3
+ module Nitro
4
+
5
+ module Markup
6
+
7
+ # Transform the markup macros.
8
+ # Maps #(..) to :sanitize.
9
+ # Maps #|..| to :markup.
10
+
11
+ def self.transform(text)
12
+ text.gsub!(/\#\((.*?)\)/, '#{sanitize(\1)}')
13
+ text.gsub!(/\#\|(.*?)\|/, '#{markup(\1)}')
14
+ return text
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,206 @@
1
+ require 'nitro/template'
2
+ require 'nitro/element'
3
+
4
+ module Nitro
5
+
6
+ # A shader defines a transformation-pipeline that tansforms
7
+ # the .xhtml files to actual ruby code ready for evaluation
8
+ # (compilation) by the engine.
9
+ #
10
+ # Shaders employ a folded-filter design.
11
+ #--
12
+ # TODO: pipeline stage mixin to be reused in filters too.
13
+ #++
14
+
15
+ class Shader
16
+
17
+ # the next stage in the Shader pipeline.
18
+
19
+ attr :next_stage
20
+
21
+ def initialize(next_stage = nil)
22
+ @next_stage = next_stage
23
+ end
24
+
25
+ # Process the text and optionally update the hash.
26
+ # The hash is a short, unique representation of the
27
+ # input text, typically used as a caching key.
28
+
29
+ def process(hash, text)
30
+ process_next(hash, text)
31
+ end
32
+
33
+ # Set the next stage of the pipeline.
34
+
35
+ def << (next_stage = nil)
36
+ @next_stage = next_stage
37
+ return self
38
+ end
39
+
40
+ # Process the next stage of the pipeline.
41
+
42
+ def process_next(hash, text)
43
+ if @next_stage
44
+ return @next_stage.process(hash, text)
45
+ else
46
+ return hash, text
47
+ end
48
+ end
49
+ end
50
+
51
+ # Convert the xhtml script to actual Ruby code, ready
52
+ # to be evaluated.
53
+
54
+ class RubyShader < Shader
55
+ include TemplateMixin
56
+
57
+ # Convert the xhtml script to actual Ruby code, ready
58
+ # to be evaluated.
59
+ #--
60
+ # Investigate:
61
+ # perhaps xl:href should be used to be XLink compatible?
62
+ #++
63
+
64
+ def process(hash, text)
65
+ text = compile_template(text)
66
+ process_next(hash, text)
67
+ end
68
+
69
+ # Loads and statically includes a file.
70
+
71
+ def load_statically_included(filename)
72
+ Logger.debug "Statically including '#{filename}'" if $DBG
73
+
74
+ text = File.read(filename)
75
+ text.gsub!(/<\?xml.*\?>/, '')
76
+ text.gsub!(/<\/?root(.*?)>/m, ' ');
77
+
78
+ return text
79
+ end
80
+
81
+ end
82
+
83
+ # Apply an XSL transformation to the script code.
84
+ # There is no need to keep post xsl. I can reuse the
85
+ # same xsl by calling transform again.
86
+
87
+ class XSLTShader < Shader
88
+
89
+ # The name
90
+
91
+ attr :name
92
+
93
+ # The xslt filename.
94
+
95
+ attr :xsl_filename
96
+
97
+ # The xslt transformer.
98
+
99
+ attr :xslt
100
+
101
+ # Last modified time of the xslt.
102
+
103
+ attr :mtime
104
+
105
+ def initialize(xsl_filename, next_stage = nil)
106
+
107
+ # leave this require here. only inlcude the xslt
108
+ # library if the project needs it.
109
+
110
+ require "xml/xslt"
111
+
112
+ @name = File.basename(xsl_filename, '.*')
113
+ @xsl_filename = xsl_filename
114
+ @xslt = XML::XSLT.new
115
+ @next_stage = next_stage
116
+ end
117
+
118
+ # Transform the given text.
119
+
120
+ def process(hash, text)
121
+ parse_xsl()
122
+ @xslt.xml = text
123
+ hash += @name
124
+ Logger.debug "Applying xsl '#{@xsl_filename}' to template" if $DBG
125
+ process_next(hash, xslt.serve)
126
+ end
127
+
128
+ private
129
+
130
+ # Parse the xsl.
131
+
132
+ def parse_xsl
133
+ Logger.debug "Parsing xsl '#{@xsl_filename}'" if $DBG
134
+ @mtime = File.mtime(@xsl_filename)
135
+ @xslt.xsl = File.read(@xsl_filename)
136
+ end
137
+
138
+ end
139
+
140
+ # Compress the inline xhtml. Does not touch the ruby code.
141
+
142
+ class CompressShader < Shader
143
+
144
+ # Compress the inline xhtml. Does not touch the ruby code.
145
+
146
+ def process(hash, text)
147
+ text.gsub!(/\@out \<\< \%\^(.*?)\^/m) do |match|
148
+ c = $1.gsub(/^(\s*)/m, '').squeeze(" \t").tr("\n", '').tr("\t", ' ')
149
+ "@out << %{#{c}}"
150
+ end
151
+
152
+ process_next(hash, text)
153
+ end
154
+
155
+ end
156
+
157
+ # MorphingShader
158
+
159
+ class MorphingShader < Shader
160
+
161
+ def process(hash, text)
162
+
163
+ # <tag if="x">..</tag>
164
+ # <tag unless="x">..</tag>
165
+
166
+ text.gsub!(/<(\w*?)([^>]*?)(if|unless)=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
167
+ %{<?r #$3 #$4 ?>
168
+ <#$1#$2#$5>#$6</#$1>
169
+ <?r end ?>}
170
+ end
171
+
172
+ # <tag times="x">..</tag>
173
+
174
+ text.gsub!(/<(\w*?)([^>]*?)times=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
175
+ %{<?r #$3.times do ?>
176
+ <#$1#$2#$4>#$5</#$1>
177
+ <?r end ?>}
178
+ end
179
+
180
+ # <tag each="x">..</tag>
181
+
182
+ text.gsub!(/<(\w*?)([^>]*?)each=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
183
+ %{<?r for #$3 ?>
184
+ <#$1#$2#$4>#$5</#$1>
185
+ <?r end ?>}
186
+ end
187
+
188
+ process_next(hash, text)
189
+ end
190
+
191
+ end
192
+
193
+ # ElementsShader
194
+
195
+ class ElementsShader < Shader
196
+
197
+ def process(hash, text)
198
+ text = ElementProcessor.render(text)
199
+ process_next(hash, text)
200
+ end
201
+
202
+ end
203
+
204
+ end
205
+
206
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,20 @@
1
+ module Nitro::Compiler
2
+
3
+ # Compress the inline xhtml. Does not touch the ruby code.
4
+
5
+ class Squeeze
6
+
7
+ # Compresses the inline xhtml. Does not touch the ruby code.
8
+
9
+ def transform(text)
10
+ return text.gsub(/\@out \<\< \%\^(.*?)\^/m) do |match|
11
+ c = $1.gsub(/^(\s*)/m, '').squeeze(" \t").tr("\n", '').tr("\t", ' ')
12
+ "@out << %{#{c}}"
13
+ end
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+
20
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,61 @@
1
+ require 'sync'
2
+
3
+ require 'xml/xslt'
4
+
5
+ module Nitro
6
+
7
+ # Apply XSL transformation.
8
+
9
+ class XSLTransform
10
+ @@sync = Sync.new
11
+
12
+ class << self
13
+
14
+ # The xslt filename.
15
+
16
+ attr :xsl_filename
17
+
18
+ # The xslt transformer.
19
+
20
+ attr :xslt
21
+
22
+ def initialize(xsl_filename, next_stage = nil)
23
+
24
+ # leave this require here. only inlcude the xslt
25
+ # library if the project needs it.
26
+
27
+ require "xml/xslt"
28
+
29
+ @name = File.basename(xsl_filename, '.*')
30
+ @xsl_filename = xsl_filename
31
+ @xslt = XML::XSLT.new
32
+ @next_stage = next_stage
33
+ end
34
+
35
+ # Transform the given xml.
36
+
37
+ def transform(text)
38
+
39
+ parse_xsl()
40
+ @xslt.xml = text
41
+ hash += @name
42
+ Logger.debug "Applying xsl '#{@xsl_filename}' to template" if $DBG
43
+ process_next(hash, xslt.serve)
44
+ end
45
+
46
+ private
47
+
48
+ # Parse the xsl.
49
+
50
+ def parse_xsl
51
+ Logger.debug "Parsing xsl '#{@xsl_filename}'" if $DBG
52
+ @mtime = File.mtime(@xsl_filename)
53
+ @xslt.xsl = File.read(@xsl_filename)
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ # * George Moschovitis <gm@navel.gr>
data/lib/nitro/context.rb CHANGED
@@ -2,101 +2,100 @@ require 'nitro/request'
2
2
  require 'nitro/response'
3
3
  require 'nitro/render'
4
4
  require 'nitro/session'
5
- require 'nitro/output'
6
5
  require 'nitro/adapter/cgi.rb'
7
6
 
8
7
  module Nitro
9
-
8
+
10
9
  # Encapsulates an HTTP processing cycle context.
11
10
  # Integrates the Request and the Response.
12
11
 
13
12
  class Context
14
- include Request
15
- include Response
16
- include Render
17
-
18
- # The configuration parameters.
19
-
20
- attr_accessor :conf
21
-
22
- # The session contains variables that stay alive
23
- # for the full user session. Session variables
24
- # should be generally avoided. This variable
25
- # becomes populated ONLY if needed.
26
-
27
- attr_reader :session
28
-
29
- # The dispatcher.
30
-
31
- attr_accessor :dispatcher
32
-
33
- def initialize(conf)
34
- @conf = conf
35
- @dispatcher = @conf.dispatcher
36
- @context = self
37
-
38
- # initialize response.
39
-
40
- @status = CgiUtils::STATUS_OK
41
- @response_headers = { 'Content-Type' => 'text/html' }
42
-
43
- # initialize the output buffer.
44
-
45
- @out = OutputBuffer.new
46
- end
47
-
48
- # Close the context, should be called at the
49
- # end of the HTTP request handling code.
50
-
51
- def close
52
- @session.sync if @session
53
- end
54
- alias_method :finish, :close
55
-
56
- #--
57
- # FIXME: something more elegant/efficient.
58
- #++
59
-
60
- def out
61
- if @out == '(error)'
62
- @out = ''
63
- render '/error'
64
- @out
65
- else
66
- @out
67
- end
68
- end
69
-
70
- # Lazy lookup of the session to avoid costly cookie
71
- # lookup when not needed.
72
-
73
- def session
74
- @session || @session = Session.lookup(self)
75
- end
76
-
77
- # Populate an object from request parameters.
78
- # This is a truly dangerous method.
79
-
80
- EXCLUDED_PARAMETERS = %w{ oid name }
81
-
82
- def fill(obj, name = nil)
83
- # if an object is passed create an instance.
84
- obj = obj.new if obj.is_a?(Class)
85
-
86
- @params.each do |param, val|
87
- begin
88
- # gmosx: DO NOT escape by default !!!
89
- if not EXCLUDED_PARAMETERS.include?(param)
90
- obj.send("__force_#{param}", val)
91
- end
92
- rescue NameError
93
- next
94
- end
95
- end
96
-
97
- return obj
98
- end
99
- alias_method :populate, :fill
13
+ include Request
14
+ include Response
15
+ include Render
16
+
17
+ # The configuration parameters.
18
+
19
+ attr_accessor :conf
20
+
21
+ # The session contains variables that stay alive
22
+ # for the full user session. Session variables
23
+ # should be generally avoided. This variable
24
+ # becomes populated ONLY if needed.
25
+
26
+ attr_reader :session
27
+
28
+ # The dispatcher.
29
+
30
+ attr_accessor :dispatcher
31
+
32
+ def initialize(conf)
33
+ @conf = conf
34
+ @dispatcher = @conf.dispatcher
35
+ @context = self
36
+
37
+ # initialize response.
38
+
39
+ @status = CgiUtils::STATUS_OK
40
+ @response_headers = { 'Content-Type' => 'text/html' }
41
+
42
+ # initialize the output buffer.
43
+
44
+ @out = OutputBuffer.new
45
+ end
46
+
47
+ # Close the context, should be called at the
48
+ # end of the HTTP request handling code.
49
+
50
+ def close
51
+ @session.sync if @session
52
+ end
53
+ alias_method :finish, :close
54
+
55
+ #--
56
+ # FIXME: something more elegant/efficient.
57
+ #++
58
+
59
+ def out
60
+ if @out == '(error)'
61
+ @out = ''
62
+ render '/error'
63
+ @out
64
+ else
65
+ @out
66
+ end
67
+ end
68
+
69
+ # Lazy lookup of the session to avoid costly cookie
70
+ # lookup when not needed.
71
+
72
+ def session
73
+ @session || @session = Session.lookup(self)
74
+ end
75
+
76
+ # Populate an object from request parameters.
77
+ # This is a truly dangerous method.
78
+
79
+ EXCLUDED_PARAMETERS = %w{ oid name }
80
+
81
+ def fill(obj, name = nil)
82
+ # if an object is passed create an instance.
83
+ obj = obj.new if obj.is_a?(Class)
84
+
85
+ @params.each do |param, val|
86
+ begin
87
+ # gmosx: DO NOT escape by default !!!
88
+ if not EXCLUDED_PARAMETERS.include?(param)
89
+ obj.send("__force_#{param}", val)
90
+ end
91
+ rescue NameError
92
+ next
93
+ end
94
+ end
95
+
96
+ return obj
97
+ end
98
+ alias_method :populate, :fill
100
99
  end
101
100
 
102
101
  end