utopia 0.9.61 → 0.10.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.
@@ -0,0 +1,12 @@
1
+
2
+ class NilClass
3
+ def maybe?
4
+ end
5
+ end
6
+
7
+ class Object
8
+ # A helper that allows you to avoid excessive number of i
9
+ def maybe?
10
+ yield self
11
+ end
12
+ end
@@ -15,7 +15,7 @@ class String
15
15
  end
16
16
 
17
17
  def to_title
18
- (" " + self).gsub(/[ \-_](.)/){" " + $1.upcase}.strip
18
+ self.gsub(/(^|[ \-_])(.)/){" " + $2.upcase}.strip
19
19
  end
20
20
 
21
21
  def to_snake
@@ -121,7 +121,14 @@ module Utopia
121
121
  return [200, {}, []]
122
122
  else
123
123
  response = Rack::Response.new
124
- node.process!(request, response)
124
+
125
+ attributes = {}
126
+
127
+ if request.controller
128
+ attributes = request.controller.to_hash
129
+ end
130
+
131
+ node.process!(request, response, attributes)
125
132
  return response.finish
126
133
  end
127
134
  else
@@ -21,10 +21,6 @@ module Utopia
21
21
  attr :tag
22
22
  end
23
23
 
24
- # Nodes typically represent XNODE files on the disk.
25
- # You can get a list of Links from a current directory. This comprises of all
26
- # files ending in ".xnode".
27
-
28
24
  class Transaction
29
25
  class State
30
26
  def initialize(tag, node)
@@ -37,6 +33,7 @@ module Utopia
37
33
  @attributes = tag.to_hash
38
34
 
39
35
  @content = nil
36
+ @deferred = []
40
37
  end
41
38
 
42
39
  attr :attributes
@@ -45,6 +42,14 @@ module Utopia
45
42
  attr :node
46
43
  attr :tags
47
44
 
45
+ attr :deferred
46
+
47
+ def defer(&block)
48
+ @deferred << block
49
+
50
+ Tag.closed("deferred", :id => @deferred.size - 1).to_html
51
+ end
52
+
48
53
  def [](key)
49
54
  @attributes[key.to_s]
50
55
  end
@@ -118,12 +123,12 @@ module Utopia
118
123
 
119
124
  attr :request
120
125
  attr :response
121
-
126
+
122
127
  # Begin tags represents a list from outer to inner most tag.
123
128
  # At any point in parsing xml, begin_tags is a list of the inner most tag,
124
129
  # then the next outer tag, etc. This list is used for doing dependent lookups.
125
130
  attr :begin_tags
126
-
131
+
127
132
  # End tags represents a list of execution order. This is the order that end tags
128
133
  # have appeared when evaluating nodes.
129
134
  attr :end_tags
@@ -218,21 +223,22 @@ module Utopia
218
223
  else
219
224
  current.tag_end(tag)
220
225
  end
221
-
226
+
222
227
  return nil
223
228
  end
224
229
 
225
230
  def render_node(node, attributes = {})
226
231
  state = State.new(attributes, node)
227
232
  @begin_tags << state
228
-
233
+
229
234
  return tag_end
230
235
  end
231
236
 
237
+ # Takes an instance of Tag
232
238
  def lookup(tag)
233
239
  result = tag
234
240
  node = nil
235
-
241
+
236
242
  @begin_tags.reverse_each do |state|
237
243
  result = state.lookup(result)
238
244
 
@@ -240,11 +246,11 @@ module Utopia
240
246
 
241
247
  return result if Node === result
242
248
  end
243
-
249
+
244
250
  @end_tags.reverse_each do |state|
245
251
  return state.node.lookup(result) if state.node.respond_to? :lookup
246
252
  end
247
-
253
+
248
254
  return nil
249
255
  end
250
256
 
@@ -293,7 +299,14 @@ module Utopia
293
299
  end
294
300
 
295
301
  def lookup(tag)
296
- return @controller.lookup_tag(tag.name, parent_path)
302
+ from_path = parent_path
303
+
304
+ # If the current node is called 'foo', we can't lookup 'foo' in the current directory or we will likely have infinite recursion.
305
+ if tag.name == @uri_path.basename
306
+ from_path = from_path.dirname
307
+ end
308
+
309
+ return @controller.lookup_tag(tag.name, from_path)
297
310
  end
298
311
 
299
312
  def parent_path
@@ -336,9 +349,9 @@ module Utopia
336
349
  transaction.parse_xml(xml_data)
337
350
  end
338
351
 
339
- def process!(request, response)
352
+ def process!(request, response, attributes = {})
340
353
  transaction = Transaction.new(request, response)
341
- response.write(transaction.render_node(self))
354
+ response.write(transaction.render_node(self, attributes))
342
355
  end
343
356
  end
344
357
 
@@ -20,22 +20,70 @@ module Utopia
20
20
  module Middleware
21
21
 
22
22
  class Controller
23
+ module Direct
24
+ def process!(path, request)
25
+ return nil unless path.dirname == self.class.uri_path
26
+
27
+ passthrough(path, request)
28
+ end
29
+ end
30
+
23
31
  CONTROLLER_RB = "controller.rb"
24
32
 
25
33
  class Variables
26
- def [](key)
27
- instance_variable_get("@#{key}")
34
+ def initialize
35
+ @controllers = [Object.new]
36
+ end
37
+
38
+ def << controller
39
+ @controllers << controller
40
+ end
41
+
42
+ def fetch(key)
43
+ @controllers.reverse_each do |controller|
44
+ if controller.instance_variables.include?(key)
45
+ return controller.instance_variable_get(key)
46
+ end
47
+ end
48
+
49
+ if block_given?
50
+ yield key
51
+ else
52
+ raise KeyError.new(key)
53
+ end
54
+ end
55
+
56
+ def to_hash
57
+ attributes = {}
58
+
59
+ @controllers.each do |controller|
60
+ controller.instance_variables.each do |name|
61
+ key = name[1..-1]
62
+
63
+ # Instance variables that start with an underscore are considered private and not exposed:
64
+ next if key.start_with?('_')
65
+
66
+ attributes[key] = controller.instance_variable_get(name)
67
+ end
68
+ end
69
+
70
+ return attributes
71
+ end
72
+
73
+ def [] key
74
+ fetch("@#{key}".to_sym) { nil }
28
75
  end
29
76
 
30
- def []=(key, value)
31
- instance_variable_set("@#{key}", value)
77
+ # Deprecated - to support old code:
78
+ def []= key, value
79
+ @controllers.first.instance_variable_set("@#{key}".to_sym, value)
32
80
  end
33
81
  end
34
82
 
35
83
  class Base
36
84
  def initialize(controller)
37
- @controller = controller
38
- @actions = {}
85
+ @_controller = controller
86
+ @_actions = {}
39
87
 
40
88
  methods.each do |method_name|
41
89
  next unless method_name.match(/on_(.*)$/)
@@ -43,12 +91,15 @@ module Utopia
43
91
  action($1.split("_")) do |path, request|
44
92
  # LOG.debug("Controller: #{method_name}")
45
93
  self.send(method_name, path, request)
94
+
95
+ # Don't pass the result back, instead use pass! or respond!
96
+ nil
46
97
  end
47
98
  end
48
99
  end
49
100
 
50
101
  def action(path, options = {}, &block)
51
- cur = @actions
102
+ cur = @_actions
52
103
 
53
104
  path.reverse.each do |name|
54
105
  cur = cur[name] ||= {}
@@ -58,7 +109,7 @@ module Utopia
58
109
  end
59
110
 
60
111
  def lookup(path)
61
- cur = @actions
112
+ cur = @_actions
62
113
 
63
114
  path.components.reverse.each do |name|
64
115
  cur = cur[name]
@@ -71,23 +122,49 @@ module Utopia
71
122
  end
72
123
  end
73
124
 
74
- # Given a request, call an associated action if one exists
125
+ # Given a request, call an associated action if one exists.
75
126
  def passthrough(path, request)
76
127
  action = lookup(path)
77
128
 
78
129
  if action
79
- return respond_with(action.call(path, request))
130
+ variables = request.controller
131
+ clone = self.dup
132
+
133
+ variables << clone
134
+
135
+ response = catch(:response) do
136
+ clone.instance_exec(path, request, &action)
137
+
138
+ # By default give nothing - i.e. keep on processing:
139
+ nil
140
+ end
141
+
142
+ if response
143
+ return clone.respond_with(*response)
144
+ end
80
145
  end
81
146
 
82
147
  return nil
83
148
  end
84
149
 
85
150
  def call(env)
86
- @controller.app.call(env)
151
+ @_controller.app.call(env)
152
+ end
153
+
154
+ def respond! (*args)
155
+ throw :response, args
87
156
  end
88
157
 
89
- def redirect(target, status = 302)
90
- {:redirect => target, :status => status}
158
+ def ignore!
159
+ throw :response, nil
160
+ end
161
+
162
+ def redirect! (target, status = 302)
163
+ respond! :redirect => target, :status => status
164
+ end
165
+
166
+ def fail!(error = :bad_request)
167
+ respond! error
91
168
  end
92
169
 
93
170
  def respond_with(*args)
@@ -133,8 +210,16 @@ module Utopia
133
210
  passthrough(path, request)
134
211
  end
135
212
 
213
+ def self.base_path
214
+ self.const_get(:BASE_PATH)
215
+ end
216
+
217
+ def self.uri_path
218
+ self.const_get(:URI_PATH)
219
+ end
220
+
136
221
  def self.require_local(path)
137
- require(File.join(const_get('BASE_PATH'), path))
222
+ require File.join(base_path, path)
138
223
  end
139
224
  end
140
225
 
@@ -179,8 +264,8 @@ module Utopia
179
264
 
180
265
  if File.exist?(controller_path)
181
266
  klass = Class.new(Base)
182
- klass.const_set('BASE_PATH', base_path)
183
- klass.const_set('URI_PATH', uri_path)
267
+ klass.const_set(:BASE_PATH, base_path)
268
+ klass.const_set(:URI_PATH, uri_path)
184
269
 
185
270
  $LOAD_PATH.unshift(base_path)
186
271
 
@@ -196,6 +281,7 @@ module Utopia
196
281
 
197
282
  def fetch_controllers(path)
198
283
  controllers = []
284
+
199
285
  path.ascend do |parent_path|
200
286
  controllers << lookup(parent_path)
201
287
  end
@@ -204,7 +290,7 @@ module Utopia
204
290
  end
205
291
 
206
292
  def call(env)
207
- env["utopia.controller"] ||= Variables.new
293
+ variables = (env["utopia.controller"] ||= Variables.new)
208
294
 
209
295
  request = Rack::Request.new(env)
210
296
 
@@ -32,15 +32,18 @@ module Utopia
32
32
  :text => [
33
33
  "html", "css", "js", "txt", "rtf", "xml", "pdf"
34
34
  ],
35
+ :fonts => [
36
+ "otf", ["eot", "application/vnd.ms-fontobject"], "ttf", "woff"
37
+ ],
35
38
  :archive => [
36
39
  "zip", "tar", "tgz", "tar.gz", "tar.bz2", ["dmg", "application/x-apple-diskimage"],
37
40
  ["torrent", "application/x-bittorrent"]
38
41
  ],
39
42
  :images => [
40
- "png", "gif", "jpeg", "tiff"
43
+ "png", "gif", "jpeg", "tiff", "svg"
41
44
  ],
42
45
  :default => [
43
- :media, :text, :archive, :images
46
+ :media, :text, :archive, :images, :fonts
44
47
  ]
45
48
  }
46
49
 
@@ -9,6 +9,8 @@ module Utopia
9
9
  class Path
10
10
  SEPARATOR = "/"
11
11
 
12
+ include Comparable
13
+
12
14
  def initialize(components)
13
15
  # To ensure we don't do anything stupid we freeze the components
14
16
  @components = components.dup.freeze
@@ -191,7 +193,7 @@ module Utopia
191
193
  end
192
194
  end
193
195
 
194
- def == other
196
+ def starts_with? other
195
197
  other.components.each_with_index do |part, index|
196
198
  return false if @components[index] != part
197
199
  end
@@ -11,7 +11,7 @@
11
11
  <?r end ?>
12
12
 
13
13
  <link rel="icon" type="image/png" href="/_static/icon.png" />
14
- <link rel="stylesheet" href="/_static/site.css" type="text/css" media="screen" charset="utf-8" />
14
+ <link rel="stylesheet" href="/_static/site.css" type="text/css" media="screen" />
15
15
  </head>
16
16
 
17
17
  <body>
@@ -5,6 +5,13 @@
5
5
  module Utopia
6
6
 
7
7
  class Tag
8
+ def self.closed(name, attributes = {})
9
+ tag = Tag.new(name, attributes)
10
+ tag.closed = true
11
+
12
+ return tag
13
+ end
14
+
8
15
  def initialize(name, attributes = {})
9
16
  @name = name
10
17
  @attributes = attributes
@@ -45,7 +52,11 @@ module Utopia
45
52
  buf.write "<#{name}"
46
53
 
47
54
  @attributes.each do |key, value|
48
- buf.write " #{key}=\"#{value}\""
55
+ if value
56
+ buf.write " #{key}=\"#{value}\""
57
+ else
58
+ buf.write " #{key}"
59
+ end
49
60
  end
50
61
 
51
62
  if terminate
@@ -0,0 +1,13 @@
1
+ # This file is part of the "Utopia Framework" project, and is released under the MIT license.
2
+ # Copyright 2010 Samuel Williams. All rights reserved.
3
+ # See <utopia.rb> for licensing details.
4
+
5
+ require 'utopia/tags'
6
+
7
+ Utopia::Tags.create("deferred") do |transaction, state|
8
+ id = state[:id].to_i
9
+
10
+ procedure = transaction.parent.deferred[id]
11
+
12
+ procedure.call(transaction, state)
13
+ end
@@ -6,6 +6,24 @@ require 'strscan'
6
6
 
7
7
  module Utopia
8
8
  class Trenni
9
+ # The output variable that will be used in templates:
10
+ OUT = '_out'
11
+
12
+ # Returns the output produced by calling the given block.
13
+ def self.capture(*args, &block)
14
+ out = eval(OUT, block.binding)
15
+ top = out.size
16
+
17
+ block.call *args
18
+
19
+ return out.pop(out.size - top).join
20
+ end
21
+
22
+ # Returns the buffer used for capturing output.
23
+ def self.buffer(binding)
24
+ eval(OUT, binding)
25
+ end
26
+
9
27
  class Buffer
10
28
  def initialize
11
29
  @parts = []
@@ -16,7 +34,7 @@ module Utopia
16
34
  def text(text)
17
35
  text = text.gsub('\\', '\\\\\\').gsub('@', '\\@')
18
36
 
19
- @parts << "_out << %q@#{text}@ ; "
37
+ @parts << "#{OUT} << %q@#{text}@ ; "
20
38
  end
21
39
 
22
40
  def expression(text)
@@ -24,11 +42,11 @@ module Utopia
24
42
  end
25
43
 
26
44
  def output(text)
27
- @parts << "_out << (#{text}) ; "
45
+ @parts << "#{OUT} << (#{text}) ; "
28
46
  end
29
47
 
30
48
  def code
31
- parts = ['_out = [] ; '] + @parts + ['_out.join']
49
+ parts = ["#{OUT} = [] ; "] + @parts + ["#{OUT}.join"]
32
50
 
33
51
  code = parts.join
34
52
  end
@@ -5,8 +5,8 @@
5
5
  module Utopia
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 9
9
- TINY = 61
8
+ MINOR = 10
9
+ TINY = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, TINY].join('.')
12
12
  end
@@ -26,7 +26,9 @@ module Utopia
26
26
 
27
27
  class Scanner < StringScanner
28
28
  CDATA = /[^<]+/m
29
- TAG_PARAMETER = /\s*([^\s=\/>]*)=((['"])(.*?)\3)/um
29
+ # Parse an attribute in the form of key="value" or key.
30
+ ATTRIBUTE_NAME = /\s*([^\s=\/>]+)/um
31
+ ATTRIBUTE_VALUE = /=((['"])(.*?)\2)/um
30
32
 
31
33
  def initialize(callback, string)
32
34
  @callback = callback
@@ -87,8 +89,13 @@ module Utopia
87
89
  end
88
90
 
89
91
  def scan_attributes
90
- while scan(TAG_PARAMETER)
91
- @callback.attribute(self[1], self[4])
92
+ while scan(ATTRIBUTE_NAME)
93
+ name = self[1]
94
+ if scan(ATTRIBUTE_VALUE)
95
+ @callback.attribute(name, self[3])
96
+ else
97
+ @callback.attribute(name, nil)
98
+ end
92
99
  end
93
100
  end
94
101
 
metadata CHANGED
@@ -1,96 +1,109 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: utopia
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 9
8
- - 61
9
- version: 0.9.61
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.10.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Samuel Williams
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2012-06-16 00:00:00 +12:00
18
- default_executable: utopia
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-07-31 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: mime-types
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- version: "0"
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
30
22
  type: :runtime
31
- version_requirements: *id001
32
- - !ruby/object:Gem::Dependency
33
- name: rack
34
23
  prerelease: false
35
- requirement: &id002 !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- segments:
40
- - 0
41
- version: "0"
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rack
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
42
38
  type: :runtime
43
- version_requirements: *id002
44
- - !ruby/object:Gem::Dependency
45
- name: rack-cache
46
39
  prerelease: false
47
- requirement: &id003 !ruby/object:Gem::Requirement
48
- requirements:
49
- - - ">="
50
- - !ruby/object:Gem::Version
51
- segments:
52
- - 0
53
- version: "0"
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rack-cache
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
54
  type: :runtime
55
- version_requirements: *id003
56
- - !ruby/object:Gem::Dependency
57
- name: rack-contrib
58
55
  prerelease: false
59
- requirement: &id004 !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- segments:
64
- - 0
65
- version: "0"
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rack-contrib
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
66
70
  type: :runtime
67
- version_requirements: *id004
68
- - !ruby/object:Gem::Dependency
69
- name: rmagick
70
71
  prerelease: false
71
- requirement: &id005 !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- segments:
76
- - 0
77
- version: "0"
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rmagick
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
78
86
  type: :runtime
79
- version_requirements: *id005
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
80
94
  description:
81
95
  email: samuel.williams@oriontransfer.co.nz
82
- executables:
96
+ executables:
83
97
  - utopia
84
98
  extensions: []
85
-
86
99
  extra_rdoc_files: []
87
-
88
- files:
100
+ files:
89
101
  - ext/utopia/xnode/fast_scanner/extconf.rb
90
102
  - ext/utopia/xnode/fast_scanner/parser.c
91
103
  - lib/utopia/extensions/array.rb
92
104
  - lib/utopia/extensions/date.rb
93
105
  - lib/utopia/extensions/hash.rb
106
+ - lib/utopia/extensions/maybe.rb
94
107
  - lib/utopia/extensions/rack.rb
95
108
  - lib/utopia/extensions/regexp.rb
96
109
  - lib/utopia/extensions/string.rb
@@ -130,6 +143,7 @@ files:
130
143
  - lib/utopia/setup.rb
131
144
  - lib/utopia/tag.rb
132
145
  - lib/utopia/tags/all.rb
146
+ - lib/utopia/tags/deferred.rb
133
147
  - lib/utopia/tags/env.rb
134
148
  - lib/utopia/tags/fortune.rb
135
149
  - lib/utopia/tags/gallery.rb
@@ -145,35 +159,29 @@ files:
145
159
  - lib/utopia/xnode.rb
146
160
  - lib/utopia.rb
147
161
  - bin/utopia
148
- has_rdoc: true
149
162
  homepage: http://www.oriontransfer.co.nz/software/utopia
150
163
  licenses: []
151
-
152
164
  post_install_message:
153
165
  rdoc_options: []
154
-
155
- require_paths:
166
+ require_paths:
156
167
  - lib
157
- required_ruby_version: !ruby/object:Gem::Requirement
158
- requirements:
159
- - - ">="
160
- - !ruby/object:Gem::Version
161
- segments:
162
- - 0
163
- version: "0"
164
- required_rubygems_version: !ruby/object:Gem::Requirement
165
- requirements:
166
- - - ">="
167
- - !ruby/object:Gem::Version
168
- segments:
169
- - 0
170
- version: "0"
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ none: false
176
+ requirements:
177
+ - - ! '>='
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
171
180
  requirements: []
172
-
173
181
  rubyforge_project:
174
- rubygems_version: 1.3.6
182
+ rubygems_version: 1.8.23
175
183
  signing_key:
176
184
  specification_version: 3
177
185
  summary: Utopia is a framework for building websites.
178
186
  test_files: []
179
-
187
+ has_rdoc: