nitro 0.26.0 → 0.27.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +312 -0
- data/INSTALL +3 -1
- data/ProjectInfo +6 -9
- data/README +32 -5
- data/Rakefile +5 -1
- data/bin/nitrogen +3 -60
- data/doc/MIGRATION +24 -0
- data/doc/RELEASES +141 -0
- data/doc/lhttpd.txt +3 -0
- data/lib/glue/magick.rb +38 -0
- data/lib/glue/thumbnails.rb +3 -0
- data/lib/glue/webfile.rb +137 -0
- data/lib/nitro.rb +1 -1
- data/lib/nitro/adapter/acgi.rb +235 -0
- data/lib/nitro/adapter/cgi.rb +16 -17
- data/lib/nitro/adapter/scgi.rb +4 -4
- data/lib/nitro/adapter/webrick.rb +9 -2
- data/lib/nitro/cgi.rb +49 -49
- data/lib/nitro/cgi/response.rb +4 -0
- data/lib/nitro/cgi/stream.rb +7 -7
- data/lib/nitro/cgi/utils.rb +2 -1
- data/lib/nitro/compiler.rb +47 -4
- data/lib/nitro/compiler/elements.rb +40 -20
- data/lib/nitro/compiler/layout.rb +21 -0
- data/lib/nitro/compiler/localization.rb +3 -1
- data/lib/nitro/compiler/markup.rb +2 -0
- data/lib/nitro/compiler/morphing.rb +16 -4
- data/lib/nitro/compiler/script.rb +109 -0
- data/lib/nitro/context.rb +10 -10
- data/lib/nitro/dispatcher.rb +4 -2
- data/lib/nitro/element.rb +107 -26
- data/lib/nitro/element/{java_script.rb → javascript.rb} +7 -1
- data/lib/nitro/flash.rb +4 -1
- data/lib/nitro/helper.rb +15 -0
- data/lib/nitro/helper/benchmark.rb +8 -2
- data/lib/nitro/helper/form.rb +3 -3
- data/lib/nitro/helper/form/controls.rb +131 -29
- data/lib/nitro/helper/{dojo.rb → form/test.xhtml} +0 -0
- data/lib/nitro/helper/javascript.rb +69 -59
- data/lib/nitro/helper/{scriptaculous.rb → javascript/dojo.rb} +0 -0
- data/lib/nitro/helper/javascript/morphing.rb +163 -0
- data/lib/nitro/helper/javascript/prototype.rb +96 -0
- data/lib/nitro/helper/javascript/scriptaculous.rb +18 -0
- data/lib/nitro/helper/layout.rb +42 -0
- data/lib/nitro/helper/table.rb +190 -27
- data/lib/nitro/{adapter → helper}/wee.rb +9 -3
- data/lib/nitro/render.rb +23 -17
- data/lib/nitro/scaffolding.rb +19 -2
- data/lib/nitro/server.rb +4 -8
- data/lib/nitro/server/runner.rb +28 -6
- data/lib/nitro/session.rb +7 -7
- data/lib/nitro_and_og.rb +2 -0
- data/proto/public/Makefile.acgi +40 -0
- data/proto/public/acgi.c +138 -0
- data/proto/public/js/builder.js +7 -3
- data/proto/public/js/controls.js +32 -12
- data/proto/public/js/dragdrop.js +4 -3
- data/proto/public/js/effects.js +111 -62
- data/proto/public/js/scriptaculous.js +10 -13
- data/proto/public/js/slider.js +88 -31
- data/proto/public/scaffold/new.xhtml +2 -2
- data/setup.rb +1585 -0
- data/src/part/admin.rb +6 -0
- data/src/part/admin/controller.rb +3 -3
- data/src/part/admin/skin.rb +1 -8
- data/test/nitro/adapter/tc_webrick.rb +2 -0
- data/test/nitro/tc_controller_aspect.rb +1 -1
- data/test/nitro/tc_element.rb +5 -6
- data/test/nitro/tc_table.rb +66 -0
- metadata +277 -271
- data/doc/architecture.txt +0 -2
- data/doc/bugs.txt +0 -15
- data/doc/tutorial.txt +0 -26
- data/install.rb +0 -37
- data/lib/nitro/compiler/script_generator.rb +0 -14
- data/lib/nitro/compiler/shaders.rb +0 -206
- data/lib/nitro/helper/prototype.rb +0 -49
- data/lib/nitro/scaffold/relations.rb +0 -54
data/lib/nitro/cgi/response.rb
CHANGED
@@ -16,10 +16,14 @@ module Response
|
|
16
16
|
|
17
17
|
attr_accessor :response_cookies
|
18
18
|
|
19
|
+
# Return the content type for this response.
|
20
|
+
|
19
21
|
def content_type
|
20
22
|
@response_headers['Content-Type']
|
21
23
|
end
|
22
24
|
|
25
|
+
# Set the content type for this response.
|
26
|
+
|
23
27
|
def content_type=(ctype)
|
24
28
|
@response_headers['Content-Type'] = ctype
|
25
29
|
end
|
data/lib/nitro/cgi/stream.rb
CHANGED
@@ -4,14 +4,12 @@ module Nitro
|
|
4
4
|
|
5
5
|
module Render
|
6
6
|
|
7
|
-
# Enable streaming mode for the current
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# object for streaming.
|
7
|
+
# Enable streaming mode for the current HTTP Response.
|
8
|
+
# You can optionally provide an existing IO object for
|
9
|
+
# streaming.
|
11
10
|
#--
|
12
|
-
# This code is considered a hack fix.
|
13
|
-
#
|
14
|
-
# it stays in the distribution.
|
11
|
+
# This code is considered a hack fix. But it still is useful
|
12
|
+
# so for the moment it stays in the distribution.
|
15
13
|
#++
|
16
14
|
|
17
15
|
def stream(io = nil)
|
@@ -41,3 +39,5 @@ module Render
|
|
41
39
|
end
|
42
40
|
|
43
41
|
end
|
42
|
+
|
43
|
+
# * Guillaume Pierronnet <guillaume.pierronnet@laposte.net>
|
data/lib/nitro/cgi/utils.rb
CHANGED
data/lib/nitro/compiler.rb
CHANGED
@@ -6,14 +6,17 @@ require 'nitro/compiler/elements'
|
|
6
6
|
require 'nitro/compiler/errors'
|
7
7
|
require 'nitro/compiler/markup'
|
8
8
|
require 'nitro/compiler/morphing'
|
9
|
+
require 'nitro/compiler/script'
|
9
10
|
require 'nitro/compiler/include'
|
10
11
|
require 'nitro/compiler/cleanup'
|
12
|
+
require 'nitro/compiler/layout'
|
11
13
|
|
12
14
|
module Nitro
|
13
15
|
|
14
16
|
# The Compiler transforms published methods (actions) and
|
15
17
|
# assorted template files (views) into specialized code that
|
16
|
-
# responds to a URI.
|
18
|
+
# responds to a URI. The generated action methods are injects
|
19
|
+
# in the Controller that handles the URI.
|
17
20
|
|
18
21
|
class Compiler
|
19
22
|
unless const_defined? :PROTO_TEMPLATE_ROOT
|
@@ -23,7 +26,14 @@ class Compiler
|
|
23
26
|
# The controller for this compiler.
|
24
27
|
|
25
28
|
attr_accessor :controller
|
29
|
+
|
30
|
+
# The compiler stages (compilers) can create multiple variables
|
31
|
+
# or accumulation bufffers to communicate with each other.
|
32
|
+
# Typically javascript and css acc-buffers are used. This is
|
33
|
+
# the shared memory used by the compilers.
|
26
34
|
|
35
|
+
attr_accessor :shared
|
36
|
+
|
27
37
|
# Set to true to force reloading of code and templates for
|
28
38
|
# each request. Extremely useful during development. Must be
|
29
39
|
# turned off in production servers to avoid the severe
|
@@ -33,6 +43,7 @@ class Compiler
|
|
33
43
|
|
34
44
|
def initialize(controller = nil)
|
35
45
|
@controller = controller
|
46
|
+
@shared = {}
|
36
47
|
end
|
37
48
|
|
38
49
|
# Action names with double underscores (__) are converted
|
@@ -92,9 +103,11 @@ class Compiler
|
|
92
103
|
|
93
104
|
def transform_template(template)
|
94
105
|
template = StaticInclude.transform(template)
|
95
|
-
template = Morphing.transform(template)
|
96
|
-
|
106
|
+
template = Morphing.transform(template, self)
|
107
|
+
# template = LayoutCompiler.transform(template, self)
|
108
|
+
template = Elements.transform(template, self)
|
97
109
|
template = Markup.transform(template)
|
110
|
+
template = ScriptCompiler.transform(template, self)
|
98
111
|
template = Cleanup.transform(template)
|
99
112
|
template = Template.transform(template)
|
100
113
|
end
|
@@ -121,10 +134,40 @@ class Compiler
|
|
121
134
|
end
|
122
135
|
end
|
123
136
|
|
124
|
-
# Compiles an action.
|
137
|
+
# Compiles an action. The generated action combines the
|
138
|
+
# action supplied by the programmer and an optional template
|
139
|
+
# in an optimized method to handle the input URI.
|
125
140
|
#
|
126
141
|
# Passes the action name and the parent action name in the
|
127
142
|
# @action_name and @parent_action_name respectively.
|
143
|
+
#
|
144
|
+
# === Example
|
145
|
+
#
|
146
|
+
# def my_method
|
147
|
+
# template_root/my_method.xhtml
|
148
|
+
#
|
149
|
+
# are combined in:
|
150
|
+
#
|
151
|
+
# def my_method_action
|
152
|
+
#
|
153
|
+
# This generated method is called by the dispatcher.
|
154
|
+
#
|
155
|
+
# === Template root overloading
|
156
|
+
#
|
157
|
+
# Nitro provides a nice method of template_root overloading
|
158
|
+
# that allows you to use OOP principles with templates.
|
159
|
+
# Lets say you have the following controller inheritance.
|
160
|
+
#
|
161
|
+
# SpecificController < BaseController < Nitro::Controller
|
162
|
+
#
|
163
|
+
# When the compiler tries to find a template for the
|
164
|
+
# SpecificController, it first looks into SC's template root.
|
165
|
+
# If no suitable template is found, it looks into
|
166
|
+
# BaseController's template_root etc. The final template_root
|
167
|
+
# is always the Nitro proto dir (the prototype application).
|
168
|
+
# This way you can reuse Controllers and templates and only
|
169
|
+
# overriding the templates as required by placing a template
|
170
|
+
# with the same name in the more specific template root.
|
128
171
|
#--
|
129
172
|
# TODO: cleanup this method.
|
130
173
|
#++
|
@@ -9,7 +9,7 @@ module Nitro
|
|
9
9
|
# A compiler that handles the processing of Elements
|
10
10
|
|
11
11
|
class Elements # :nodoc: all
|
12
|
-
|
12
|
+
|
13
13
|
class Listener # :nodoc: all
|
14
14
|
include REXML::StreamListener
|
15
15
|
|
@@ -28,21 +28,36 @@ class Elements # :nodoc: all
|
|
28
28
|
def tag_start(name, attributes)
|
29
29
|
# check if the name starts with the element prefix, or
|
30
30
|
# is capitalized.
|
31
|
+
|
31
32
|
if name =~ PREFIX_RE or name =~ CAPITALIZED_RE
|
32
33
|
name = name.split(':')[1].camelize if name =~ PREFIX_RE
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
|
35
|
+
# First try to use Nitro::Element::xxx then ::xxx
|
36
|
+
|
37
|
+
if klass = Nitro::Element.const_get(name) || Object.const_get(name)
|
38
|
+
unless klass.ancestors.include? Nitro::Element
|
39
|
+
if Element.auto_extend
|
40
|
+
klass.send(:include, Nitro::ElementMixin)
|
41
|
+
else
|
42
|
+
Logger.error "Invalid element class '#{name}', does not extend Nitro::Element"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
Logger.error "The class of this element tag '#{name}' does not exist"
|
47
|
+
end
|
48
|
+
|
49
|
+
if klass and obj = klass.new
|
50
|
+
attributes.each do | k, v |
|
51
|
+
obj.instance_variable_set("@#{k}", v)
|
52
|
+
end
|
53
|
+
|
54
|
+
@stack.push [obj, @buffer, @parent]
|
55
|
+
|
56
|
+
@buffer = obj._text
|
57
|
+
@parent.add_child(obj) if @parent
|
58
|
+
|
59
|
+
@parent = obj
|
60
|
+
end
|
46
61
|
else # This is a static element.
|
47
62
|
attrs = []
|
48
63
|
|
@@ -88,19 +103,23 @@ class Elements # :nodoc: all
|
|
88
103
|
self.new.parse(source)
|
89
104
|
end
|
90
105
|
|
91
|
-
def transform(source)
|
92
|
-
self.new.transform(source)
|
106
|
+
def transform(source, compiler)
|
107
|
+
self.new.transform(source, compiler)
|
93
108
|
end
|
94
109
|
end
|
95
110
|
|
96
111
|
# Expand the elemens found in source.
|
112
|
+
#--
|
113
|
+
# gmosx, FIXME: optimize this, how?
|
114
|
+
# gmosx, FIXME: this is a hack fix, improve.
|
115
|
+
# TODO:farms why is cleanup called this many times?!?!? ... waste of gsubs
|
116
|
+
#++
|
97
117
|
|
98
|
-
def transform(source)
|
118
|
+
def transform(source, compiler)
|
99
119
|
listener = Listener.new
|
120
|
+
|
100
121
|
REXML::Document.parse_stream(source, listener)
|
101
|
-
|
102
|
-
# gmosx, FIXME: this is a hack fix, improve.
|
103
|
-
# TODO:farms why is cleanup called this many times?!?!? ... waste of gsubs
|
122
|
+
|
104
123
|
return listener.buffer
|
105
124
|
end
|
106
125
|
end
|
@@ -109,6 +128,7 @@ end
|
|
109
128
|
|
110
129
|
unless const_defined? :ElementProcessor
|
111
130
|
ElementProcessor = Elements
|
131
|
+
ElementCompiler = Elements
|
112
132
|
end
|
113
133
|
|
114
134
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nitro
|
2
|
+
|
3
|
+
# A compiler that handles Rails style simplistic layouts.
|
4
|
+
# Perhaps this will be useful for some people that are comming
|
5
|
+
# from Rails.
|
6
|
+
|
7
|
+
class LayoutCompiler # :nodoc: all
|
8
|
+
|
9
|
+
def self.transform(source, compiler)
|
10
|
+
if layout = compiler.controller.ann.self[:layout]
|
11
|
+
return "<#{layout}>#{source}</#{layout}>"
|
12
|
+
else
|
13
|
+
return source
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
# * George Moschovitis <gm@navel.gr>
|
@@ -12,14 +12,19 @@ module Nitro
|
|
12
12
|
|
13
13
|
# The base morpher class. Morphers are triggered
|
14
14
|
# by a special 'key' attribute in the xml stream and
|
15
|
-
# transform the owner element.
|
15
|
+
# transform the owner element.
|
16
|
+
#
|
17
|
+
# key = attribute 'key'
|
18
|
+
# name = element name
|
19
|
+
# attributes = alement attributes
|
16
20
|
|
17
21
|
class Morpher
|
18
|
-
def initialize(key, name, attributes)
|
22
|
+
def initialize(key, name, attributes, compiler = nil)
|
19
23
|
@key = key
|
20
24
|
@name = name
|
21
25
|
@attributes = attributes
|
22
26
|
@value = @attributes[@key]
|
27
|
+
@compiler = compiler
|
23
28
|
end
|
24
29
|
|
25
30
|
def before_start(buffer); end
|
@@ -148,6 +153,12 @@ class Morphing
|
|
148
153
|
class Listener # :nodoc: all
|
149
154
|
include REXML::StreamListener
|
150
155
|
|
156
|
+
# The compiler that calls this compiling stage. Useful
|
157
|
+
# for advanced morphing effects and inter-stage
|
158
|
+
# communication.
|
159
|
+
|
160
|
+
attr_accessor :compiler
|
161
|
+
|
151
162
|
attr_accessor :buffer
|
152
163
|
|
153
164
|
def initialize
|
@@ -167,7 +178,7 @@ class Morphing
|
|
167
178
|
|
168
179
|
Morphing.morphers.each do |key, morpher_class|
|
169
180
|
if attributes.has_key? key
|
170
|
-
morphers << morpher_class.new(key, name, attributes)
|
181
|
+
morphers << morpher_class.new(key, name, attributes, compiler)
|
171
182
|
end
|
172
183
|
end
|
173
184
|
|
@@ -214,8 +225,9 @@ class Morphing
|
|
214
225
|
"</#{name}>"
|
215
226
|
end
|
216
227
|
|
217
|
-
def self.transform(source)
|
228
|
+
def self.transform(source, compiler = nil)
|
218
229
|
listener = Listener.new
|
230
|
+
listener.compiler = compiler
|
219
231
|
REXML::Document.parse_stream(source, listener)
|
220
232
|
return listener.buffer
|
221
233
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'nano/kernel/constant'
|
2
|
+
|
3
|
+
require 'nitro/helper/javascript'
|
4
|
+
|
5
|
+
module Nitro
|
6
|
+
|
7
|
+
# Generates client-side javascript code.
|
8
|
+
|
9
|
+
module ScriptCompiler
|
10
|
+
extend JavascriptHelper
|
11
|
+
|
12
|
+
def self.transform(text, compiler)
|
13
|
+
begin
|
14
|
+
client = constant("#{compiler.controller}::Client")
|
15
|
+
rescue Object
|
16
|
+
client = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
if client
|
20
|
+
client.send :include, Nitro::ScriptGenerator
|
21
|
+
client = client.new
|
22
|
+
|
23
|
+
functions = {}
|
24
|
+
|
25
|
+
text.scan(/__nc_(.*)\(\)/) do |match|
|
26
|
+
functions[match.first] = true
|
27
|
+
end
|
28
|
+
|
29
|
+
script = ''
|
30
|
+
|
31
|
+
for fun in functions.keys
|
32
|
+
begin
|
33
|
+
client.buffer = ''
|
34
|
+
ret = client.send(fun.to_sym)
|
35
|
+
|
36
|
+
# the function code is accumulated in the client
|
37
|
+
# buffer.
|
38
|
+
|
39
|
+
function_code = client.buffer
|
40
|
+
|
41
|
+
# if the client action returs a String append it to
|
42
|
+
# the function code.
|
43
|
+
|
44
|
+
function_code << ret if ret.is_a?(String)
|
45
|
+
|
46
|
+
script << %{
|
47
|
+
function __nc_#{fun}() {
|
48
|
+
#{function_code}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
rescue => ex
|
52
|
+
Logger.debug ex.inspect if $DBG
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Inject css in the head tag.
|
57
|
+
|
58
|
+
if css_buffer = compiler.shared[:css_buffer]
|
59
|
+
text.sub!(/<\/head>/) do |match|
|
60
|
+
%{
|
61
|
+
<style>
|
62
|
+
#{css_buffer}
|
63
|
+
</style>
|
64
|
+
</head>
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Inject required javascript files in the head tag.
|
70
|
+
|
71
|
+
if required_files = compiler.shared[:js_required_files]
|
72
|
+
text.sub!(/<\/head>/) do |match|
|
73
|
+
%{
|
74
|
+
#{include_script *required_files.keys}
|
75
|
+
</head>
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Inject javascript just before the end of the
|
81
|
+
# template.
|
82
|
+
#--
|
83
|
+
# gmosx: injection happens at the end, so that the DOM
|
84
|
+
# tree is created. Dunno if this is valid xhtml though.
|
85
|
+
#++
|
86
|
+
|
87
|
+
js_buffer = compiler.shared[:js_buffer]
|
88
|
+
|
89
|
+
if script or js_buffer
|
90
|
+
text.sub!(/<\/html>/) do |match|
|
91
|
+
%{
|
92
|
+
<script type="text/javascript">
|
93
|
+
#{script}
|
94
|
+
#{js_buffer}
|
95
|
+
</script>
|
96
|
+
</html>
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
return text
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
# * George Moschovitis <gm@navel.gr>
|