utopia 0.12.6 → 1.0.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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -2
  3. data/Gemfile +6 -0
  4. data/README.md +48 -14
  5. data/Rakefile +5 -0
  6. data/bin/utopia +132 -15
  7. data/lib/utopia.rb +13 -10
  8. data/lib/utopia/content.rb +140 -0
  9. data/lib/utopia/content/link.rb +124 -0
  10. data/lib/utopia/content/links.rb +228 -0
  11. data/lib/utopia/content/node.rb +387 -0
  12. data/lib/utopia/content/processor.rb +128 -0
  13. data/lib/utopia/content/tag.rb +102 -0
  14. data/lib/utopia/controller.rb +137 -0
  15. data/lib/utopia/controller/action.rb +112 -0
  16. data/lib/utopia/controller/base.rb +174 -0
  17. data/lib/utopia/{middleware/controller → controller}/variables.rb +36 -38
  18. data/lib/utopia/exception_handler.rb +79 -0
  19. data/lib/utopia/extensions/array.rb +2 -2
  20. data/lib/utopia/localization.rb +143 -0
  21. data/lib/utopia/mail_exceptions.rb +136 -0
  22. data/lib/utopia/middleware.rb +7 -22
  23. data/lib/utopia/path.rb +150 -60
  24. data/lib/utopia/redirector.rb +152 -0
  25. data/lib/utopia/{extensions/hash.rb → session.rb} +4 -6
  26. data/lib/utopia/session/encrypted_cookie.rb +46 -48
  27. data/lib/utopia/{middleware/directory_index.rb → session/lazy_hash.rb} +44 -27
  28. data/lib/utopia/static.rb +255 -0
  29. data/lib/utopia/tags/deferred.rb +12 -8
  30. data/lib/utopia/tags/environment.rb +18 -6
  31. data/lib/utopia/tags/node.rb +12 -8
  32. data/lib/utopia/tags/override.rb +12 -12
  33. data/lib/utopia/version.rb +1 -1
  34. data/setup/.bowerrc +3 -0
  35. data/{lib/utopia/setup → setup}/Gemfile +1 -1
  36. data/setup/Rakefile +4 -0
  37. data/{lib/utopia/setup → setup}/cache/head/readme.txt +0 -0
  38. data/{lib/utopia/setup → setup}/cache/meta/readme.txt +0 -0
  39. data/setup/config.ru +64 -0
  40. data/{lib/utopia/setup → setup}/lib/readme.txt +0 -0
  41. data/{lib/utopia/setup → setup}/pages/_heading.xnode +0 -0
  42. data/{lib/utopia/setup → setup}/pages/_page.xnode +1 -1
  43. data/{lib/utopia/setup → setup}/pages/_static/icon.png +0 -0
  44. data/setup/pages/_static/site.css +70 -0
  45. data/{lib/utopia/setup → setup}/pages/errors/exception.xnode +0 -0
  46. data/{lib/utopia/setup → setup}/pages/errors/file-not-found.xnode +0 -0
  47. data/{lib/utopia/setup → setup}/pages/links.yaml +0 -0
  48. data/setup/pages/welcome/index.xnode +17 -0
  49. data/{lib/utopia/setup → setup}/public/readme.txt +0 -0
  50. data/spec/utopia/content/link_spec.rb +108 -0
  51. data/spec/utopia/content/links/foo/index.xnode +0 -0
  52. data/spec/utopia/content/links/foo/links.yaml +2 -0
  53. data/spec/utopia/content/links/foo/test.de.xnode +0 -0
  54. data/spec/utopia/content/links/foo/test.en.xnode +0 -0
  55. data/spec/utopia/content/links/links.yaml +9 -0
  56. data/spec/utopia/content/links/welcome.xnode +0 -0
  57. data/spec/utopia/content/localized/five/index.en.xnode +0 -0
  58. data/spec/utopia/content/localized/four/index.en.xnode +0 -0
  59. data/spec/utopia/content/localized/four/index.zh.xnode +0 -0
  60. data/spec/utopia/content/localized/four/links.yaml +4 -0
  61. data/spec/utopia/content/localized/links.yaml +16 -0
  62. data/spec/utopia/content/localized/one.xnode +0 -0
  63. data/spec/utopia/content/localized/three/index.xnode +0 -0
  64. data/spec/utopia/content/localized/two.en.xnode +0 -0
  65. data/spec/utopia/content/localized/two.zh.xnode +0 -0
  66. data/spec/utopia/content/node/ordered/first.xnode +0 -0
  67. data/spec/utopia/content/node/ordered/index.xnode +0 -0
  68. data/spec/utopia/content/node/ordered/links.yaml +4 -0
  69. data/spec/utopia/content/node/ordered/second.xnode +0 -0
  70. data/spec/utopia/content/node/related/foo.en.xnode +0 -0
  71. data/spec/utopia/content/node/related/foo.ja.xnode +0 -0
  72. data/spec/utopia/content/node/related/links.yaml +4 -0
  73. data/spec/utopia/content/node_spec.rb +63 -0
  74. data/spec/utopia/{middleware/content_spec.rb → content/processor_spec.rb} +34 -23
  75. data/spec/utopia/content_spec.rb +87 -0
  76. data/spec/utopia/content_spec.ru +10 -0
  77. data/spec/utopia/{middleware/controller_spec.rb → controller_spec.rb} +61 -16
  78. data/spec/utopia/controller_spec.ru +4 -0
  79. data/spec/utopia/extensions_spec.rb +6 -17
  80. data/spec/utopia/localization_spec.rb +60 -0
  81. data/spec/utopia/localization_spec.ru +11 -0
  82. data/{lib/utopia/tags.rb → spec/utopia/middleware_spec.rb} +8 -14
  83. data/spec/utopia/{middleware/content_root → pages}/_heading.xnode +0 -0
  84. data/spec/utopia/pages/content/_show-value.xnode +1 -0
  85. data/spec/utopia/pages/content/test-partial.xnode +1 -0
  86. data/spec/utopia/pages/controller/controller.rb +28 -0
  87. data/spec/utopia/pages/controller/index.xnode +1 -0
  88. data/spec/utopia/pages/controller/nested/controller.rb +4 -0
  89. data/spec/utopia/{middleware/content_root → pages}/index.xnode +0 -0
  90. data/spec/utopia/pages/localized.de.txt +1 -0
  91. data/spec/utopia/pages/localized.en.txt +1 -0
  92. data/spec/utopia/pages/localized.jp.txt +1 -0
  93. data/spec/utopia/pages/node/index.xnode +1 -0
  94. data/spec/utopia/pages/test.txt +1 -0
  95. data/spec/utopia/path_spec.rb +109 -0
  96. data/spec/utopia/rack_spec.rb +2 -0
  97. data/spec/utopia/session_spec.rb +82 -0
  98. data/spec/utopia/session_spec.ru +20 -0
  99. data/spec/utopia/spec_helper.rb +16 -0
  100. data/{lib/utopia/extensions/string.rb → spec/utopia/static_spec.rb} +24 -15
  101. data/spec/utopia/static_spec.ru +4 -0
  102. data/utopia.gemspec +3 -3
  103. metadata +138 -54
  104. data/lib/utopia/extensions/regexp.rb +0 -33
  105. data/lib/utopia/link.rb +0 -288
  106. data/lib/utopia/middleware/all.rb +0 -33
  107. data/lib/utopia/middleware/content.rb +0 -157
  108. data/lib/utopia/middleware/content/node.rb +0 -386
  109. data/lib/utopia/middleware/content/processor.rb +0 -123
  110. data/lib/utopia/middleware/controller.rb +0 -130
  111. data/lib/utopia/middleware/controller/action.rb +0 -121
  112. data/lib/utopia/middleware/controller/base.rb +0 -184
  113. data/lib/utopia/middleware/exception_handler.rb +0 -80
  114. data/lib/utopia/middleware/localization.rb +0 -147
  115. data/lib/utopia/middleware/localization/name.rb +0 -69
  116. data/lib/utopia/middleware/mail_exceptions.rb +0 -138
  117. data/lib/utopia/middleware/redirector.rb +0 -146
  118. data/lib/utopia/middleware/requester.rb +0 -126
  119. data/lib/utopia/middleware/static.rb +0 -295
  120. data/lib/utopia/setup.rb +0 -60
  121. data/lib/utopia/setup/config.ru +0 -47
  122. data/lib/utopia/setup/pages/_static/background.png +0 -0
  123. data/lib/utopia/setup/pages/_static/site.css +0 -48
  124. data/lib/utopia/setup/pages/welcome/index.xnode +0 -7
  125. data/lib/utopia/tag.rb +0 -105
  126. data/lib/utopia/tags/all.rb +0 -34
@@ -1,33 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'pathname'
22
-
23
- warn "require 'utopia/middleware/all' is deprecated. Require 'utopia' instead."
24
-
25
- Pathname.new(__FILE__).dirname.entries.each do |path|
26
- next unless /\.rb$/ === path.to_s
27
-
28
- name = File.basename(path.to_s, ".rb")
29
-
30
- if name != "all"
31
- require "utopia/middleware/#{name}"
32
- end
33
- end
@@ -1,157 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'utopia/middleware'
22
- require 'utopia/link'
23
- require 'utopia/path'
24
- require 'utopia/tags'
25
-
26
- require 'utopia/middleware/content/node'
27
- require 'utopia/middleware/content/processor'
28
- require 'trenni/template'
29
-
30
- module Utopia
31
- module Middleware
32
-
33
- class Content
34
- def initialize(app, options = {})
35
- @app = app
36
-
37
- @root = File.expand_path(options[:root] || Utopia::Middleware::default_root)
38
-
39
- # Set to hash to enable caching
40
- @nodes = {}
41
- @files = nil
42
-
43
- @tags = options[:tags] || {}
44
- end
45
-
46
- attr :root
47
- attr :passthrough
48
-
49
- def fetch_xml(path)
50
- read_file = lambda { Trenni::Template.load(path) }
51
-
52
- if @files
53
- @files.fetch(path) do |key|
54
- @files[key] = read_file.call
55
- end
56
- else
57
- read_file.call
58
- end
59
- end
60
-
61
- # Look up a named tag such as <entry />
62
- def lookup_tag(name, parent_path)
63
- if @tags.key? name
64
- return @tags[name]
65
- elsif Utopia::Tags.all.key? name
66
- return Utopia::Tags.all[name]
67
- end
68
-
69
- if String === name && name.index("/")
70
- name = Path.create(name)
71
- end
72
-
73
- if Path === name
74
- name = parent_path + name
75
- name_path = name.components.dup
76
- name_path[-1] += ".xnode"
77
- else
78
- name_path = name + ".xnode"
79
- end
80
-
81
- parent_path.ascend do |dir|
82
- tag_path = File.join(root, dir.components, name_path)
83
-
84
- if File.exist? tag_path
85
- return Node.new(self, dir + name, parent_path + name, tag_path)
86
- end
87
-
88
- if String === name_path
89
- tag_path = File.join(root, dir.components, "_" + name_path)
90
-
91
- if File.exist? tag_path
92
- return Node.new(self, dir + name, parent_path + name, tag_path)
93
- end
94
- end
95
- end
96
-
97
- return nil
98
- end
99
-
100
- def lookup_node(request_path)
101
- name = request_path.basename
102
- name_xnode = name + ".xnode"
103
-
104
- node_path = File.join(@root, request_path.dirname.components, name_xnode)
105
-
106
- if File.exist? node_path
107
- return Node.new(self, request_path.dirname + name, request_path, node_path)
108
- end
109
-
110
- return nil
111
- end
112
-
113
- def call(env)
114
- request = Rack::Request.new(env)
115
- path = Path.create(request.path_info).to_absolute
116
-
117
- # Check if the request is to a non-specific index.
118
- name, extensions = path.basename.split(".", 2)
119
- directory_path = File.join(@root, path.dirname.components, name)
120
-
121
- if File.directory? directory_path
122
- if extensions
123
- index_path = [name, "index.#{extensions}"]
124
- else
125
- index_path = [name, "index"]
126
- end
127
-
128
- return [307, {"Location" => path.dirname.join(index_path).to_s}, []]
129
- end
130
-
131
- # Otherwise look up the node
132
- node = lookup_node(path)
133
-
134
- if node
135
- if request.head?
136
- return [200, {}, []]
137
- else
138
- response = Rack::Response.new
139
-
140
- attributes = {}
141
-
142
- if request.controller
143
- attributes = request.controller.to_hash
144
- end
145
-
146
- node.process!(request, response, attributes)
147
-
148
- return response.finish
149
- end
150
- else
151
- return @app.call(env)
152
- end
153
- end
154
- end
155
-
156
- end
157
- end
@@ -1,386 +0,0 @@
1
- # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'set'
22
-
23
- require 'utopia/middleware/content/processor'
24
- require 'utopia/link'
25
-
26
- module Utopia
27
-
28
- module Middleware
29
- class Content
30
- class UnbalancedTagError < StandardError
31
- def initialize(tag)
32
- @tag = tag
33
-
34
- super("Unbalanced tag #{tag.name}")
35
- end
36
-
37
- attr :tag
38
- end
39
-
40
- class Transaction
41
- class State
42
- def initialize(tag, node)
43
- @node = node
44
-
45
- @buffer = StringIO.new
46
- @overrides = {}
47
-
48
- @tags = []
49
- @attributes = tag.to_hash
50
-
51
- @content = nil
52
- @deferred = []
53
- end
54
-
55
- attr :attributes
56
- attr :overrides
57
- attr :content
58
- attr :node
59
- attr :tags
60
-
61
- attr :deferred
62
-
63
- def defer(value = nil, &block)
64
- @deferred << block
65
-
66
- Tag.closed("deferred", :id => @deferred.size - 1).to_html
67
- end
68
-
69
- def [](key)
70
- @attributes[key.to_s]
71
- end
72
-
73
- def call(transaction)
74
- @content = @buffer.string
75
- @buffer = StringIO.new
76
-
77
- if node.respond_to? :call
78
- node.call(transaction, self)
79
- else
80
- transaction.parse_xml(@content)
81
- end
82
-
83
- return @buffer.string
84
- end
85
-
86
- def lookup(tag)
87
- if override = @overrides[tag.name]
88
- if override.respond_to? :call
89
- return override.call(tag)
90
- elsif String === override
91
- return Tag.new(override, tag.attributes)
92
- else
93
- return override
94
- end
95
- else
96
- return tag
97
- end
98
- end
99
-
100
- def cdata(text)
101
- @buffer.write(text)
102
- end
103
-
104
- def markup(text)
105
- cdata(text)
106
- end
107
-
108
- def tag_complete(tag)
109
- tag.write_full_html(@buffer)
110
- end
111
-
112
- def tag_begin(tag)
113
- @tags << tag
114
- tag.write_open_html(@buffer)
115
- end
116
-
117
- def tag_end(tag)
118
- raise UnbalancedTagError(tag) unless @tags.pop.name == tag.name
119
-
120
- tag.write_close_html(@buffer)
121
- end
122
- end
123
-
124
- def initialize(request, response)
125
- @begin_tags = []
126
- @end_tags = []
127
-
128
- @request = request
129
- @response = response
130
- end
131
-
132
- def binding
133
- super
134
- end
135
-
136
- def parse_xml(xml_data)
137
- Processor.parse_xml(xml_data, self)
138
- end
139
-
140
- attr :request
141
- attr :response
142
-
143
- # Begin tags represents a list from outer to inner most tag.
144
- # At any point in parsing xml, begin_tags is a list of the inner most tag,
145
- # then the next outer tag, etc. This list is used for doing dependent lookups.
146
- attr :begin_tags
147
-
148
- # End tags represents a list of execution order. This is the order that end tags
149
- # have appeared when evaluating nodes.
150
- attr :end_tags
151
-
152
- def attributes
153
- return current.attributes
154
- end
155
-
156
- def current
157
- @begin_tags[-1]
158
- end
159
-
160
- def content
161
- @end_tags[-1].content
162
- end
163
-
164
- def parent
165
- end_tags[-2]
166
- end
167
-
168
- def first
169
- @begin_tags[0]
170
- end
171
-
172
- def tag(name, attributes = {}, &block)
173
- tag = Tag.new(name, attributes)
174
-
175
- node = tag_begin(tag)
176
-
177
- yield node if block_given?
178
-
179
- tag_end(tag)
180
- end
181
-
182
- def tag_complete(tag, node = nil)
183
- if tag.name == "content"
184
- current.markup(content)
185
- else
186
- node ||= lookup(tag)
187
-
188
- if node
189
- tag_begin(tag, node)
190
- tag_end(tag)
191
- else
192
- current.tag_complete(tag)
193
- end
194
- end
195
- end
196
-
197
- def tag_begin(tag, node = nil)
198
- node ||= lookup(tag)
199
-
200
- if node
201
- state = State.new(tag, node)
202
- @begin_tags << state
203
-
204
- if node.respond_to? :tag_begin
205
- node.tag_begin(self, state)
206
- end
207
-
208
- return node
209
- end
210
-
211
- current.tag_begin(tag)
212
-
213
- return nil
214
- end
215
-
216
- def cdata(text)
217
- current.cdata(text)
218
- end
219
-
220
- def deferred_tag(*args, &block)
221
- if block_given?
222
- current.defer(&block)
223
- else
224
- current.defer do
225
- tag(*args)
226
- end
227
- end
228
- end
229
-
230
- def tag_end(tag = nil)
231
- top = current
232
-
233
- if top.tags.empty?
234
- if top.node.respond_to? :tag_end
235
- top.node.tag_end(self, top)
236
- end
237
-
238
- @end_tags << top
239
- buffer = top.call(self)
240
-
241
- @begin_tags.pop
242
- @end_tags.pop
243
-
244
- if current
245
- current.markup(buffer)
246
- end
247
-
248
- return buffer
249
- else
250
- current.tag_end(tag)
251
- end
252
-
253
- return nil
254
- end
255
-
256
- def render_node(node, attributes = {})
257
- state = State.new(attributes, node)
258
- @begin_tags << state
259
-
260
- return tag_end
261
- end
262
-
263
- # Takes an instance of Tag
264
- def lookup(tag)
265
- result = tag
266
- node = nil
267
-
268
- @begin_tags.reverse_each do |state|
269
- result = state.lookup(result)
270
-
271
- node ||= state.node if state.node.respond_to? :lookup
272
-
273
- return result if Node === result
274
- end
275
-
276
- @end_tags.reverse_each do |state|
277
- return state.node.lookup(result) if state.node.respond_to? :lookup
278
- end
279
-
280
- return nil
281
- end
282
-
283
- def method_missing(name, *args)
284
- @begin_tags.reverse_each do |state|
285
- if state.node.respond_to? name
286
- return state.node.send(name, *args)
287
- end
288
- end
289
-
290
- super
291
- end
292
- end
293
-
294
- class Node
295
- def initialize(controller, uri_path, request_path, file_path)
296
- @controller = controller
297
-
298
- @uri_path = uri_path
299
- @request_path = request_path
300
- @file_path = file_path
301
- end
302
-
303
- attr :request_path
304
- attr :uri_path
305
- attr :file_path
306
-
307
- def link
308
- return Link.new(:file, uri_path)
309
- end
310
-
311
- def lookup_node(path)
312
- @controller.lookup_node(path)
313
- end
314
-
315
- def local_path(path = ".", base = nil)
316
- path = Path.create(path)
317
- root = Pathname.new(@controller.root)
318
-
319
- if path.absolute?
320
- return root.join(*path.components)
321
- else
322
- base ||= uri_path.dirname
323
- return root.join(*(base + path).components)
324
- end
325
- end
326
-
327
- def lookup(tag)
328
- from_path = parent_path
329
-
330
- # If the current node is called 'foo', we can't lookup 'foo' in the current directory or we will likely have infinite recursion.
331
- if tag.name == @uri_path.basename
332
- from_path = from_path.dirname
333
- end
334
-
335
- return @controller.lookup_tag(tag.name, from_path)
336
- end
337
-
338
- def parent_path
339
- uri_path.dirname
340
- end
341
-
342
- def links(path = ".", options = {}, &block)
343
- path = uri_path.dirname + Path.create(path)
344
- links = Links.index(@controller.root, path, options)
345
-
346
- if block_given?
347
- links.each &block
348
- else
349
- links
350
- end
351
- end
352
-
353
- def related_links
354
- name = @uri_path.basename.split(".").first
355
- links = Links.index(@controller.root, uri_path.dirname, :name => name, :indices => true)
356
- end
357
-
358
- def siblings_path
359
- name = @uri_path.basename.split(".").first
360
-
361
- if name == "index"
362
- @uri_path.dirname(2)
363
- else
364
- @uri_path.dirname
365
- end
366
- end
367
-
368
- def sibling_links(options = {})
369
- return Links.index(@controller.root, siblings_path, options)
370
- end
371
-
372
- def call(transaction, state)
373
- xml_data = @controller.fetch_xml(@file_path).result(transaction.binding)
374
-
375
- transaction.parse_xml(xml_data)
376
- end
377
-
378
- def process!(request, response, attributes = {})
379
- transaction = Transaction.new(request, response)
380
- response.write(transaction.render_node(self, attributes))
381
- end
382
- end
383
-
384
- end
385
- end
386
- end