utopia 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.gitignore +17 -0
  2. data/.travis.yml +9 -0
  3. data/Gemfile +8 -0
  4. data/README.md +72 -0
  5. data/Rakefile +9 -0
  6. data/bin/utopia +42 -13
  7. data/lib/utopia/extensions/array.rb +19 -3
  8. data/lib/utopia/extensions/date.rb +19 -3
  9. data/lib/utopia/extensions/hash.rb +19 -3
  10. data/lib/utopia/extensions/maybe.rb +19 -0
  11. data/lib/utopia/extensions/rack.rb +21 -3
  12. data/lib/utopia/extensions/regexp.rb +19 -3
  13. data/lib/utopia/extensions/string.rb +19 -3
  14. data/lib/utopia/http.rb +56 -0
  15. data/lib/utopia/link.rb +19 -3
  16. data/lib/utopia/middleware/all.rb +19 -3
  17. data/lib/utopia/middleware/content/node.rb +21 -5
  18. data/lib/utopia/middleware/content/processor.rb +118 -0
  19. data/lib/utopia/middleware/content.rb +22 -7
  20. data/lib/utopia/middleware/controller.rb +19 -7
  21. data/lib/utopia/middleware/directory_index.rb +19 -3
  22. data/lib/utopia/middleware/localization/name.rb +19 -3
  23. data/lib/utopia/middleware/localization.rb +19 -3
  24. data/lib/utopia/middleware/logger.rb +19 -3
  25. data/lib/utopia/middleware/redirector.rb +19 -5
  26. data/lib/utopia/middleware/requester.rb +19 -3
  27. data/lib/utopia/middleware/static.rb +20 -6
  28. data/lib/utopia/middleware.rb +22 -5
  29. data/lib/utopia/path.rb +26 -6
  30. data/lib/utopia/session/encrypted_cookie.rb +19 -3
  31. data/lib/utopia/setup/Gemfile +8 -0
  32. data/lib/utopia/setup/config.ru +4 -13
  33. data/lib/utopia/setup.rb +25 -4
  34. data/lib/utopia/tag.rb +45 -24
  35. data/lib/utopia/tags/all.rb +19 -3
  36. data/lib/utopia/tags/deferred.rb +19 -3
  37. data/lib/utopia/tags/environment.rb +29 -0
  38. data/lib/utopia/tags/node.rb +19 -3
  39. data/lib/utopia/tags/override.rb +19 -3
  40. data/lib/utopia/tags.rb +19 -3
  41. data/lib/utopia/time_store.rb +19 -3
  42. data/lib/utopia/version.rb +20 -10
  43. data/lib/utopia.rb +20 -17
  44. data/test/content_root/_heading.xnode +1 -0
  45. data/test/content_root/index.xnode +1 -0
  46. data/test/test_content_middleware.rb +86 -0
  47. data/test/test_path.rb +32 -0
  48. data/utopia.gemspec +31 -0
  49. metadata +56 -42
  50. data/ext/utopia/xnode/fast_scanner/extconf.rb +0 -6
  51. data/ext/utopia/xnode/fast_scanner/parser.c +0 -289
  52. data/lib/utopia/http_status_codes.rb +0 -39
  53. data/lib/utopia/middleware/benchmark.rb +0 -29
  54. data/lib/utopia/middleware/filter.rb +0 -35
  55. data/lib/utopia/tags/env.rb +0 -13
  56. data/lib/utopia/tags/fortune.rb +0 -9
  57. data/lib/utopia/tags/gallery.rb +0 -275
  58. data/lib/utopia/tags/google_analytics.rb +0 -21
  59. data/lib/utopia/trenni.rb +0 -149
  60. data/lib/utopia/xnode/processor.rb +0 -86
  61. data/lib/utopia/xnode/scanner.rb +0 -159
  62. data/lib/utopia/xnode.rb +0 -6
@@ -1,289 +0,0 @@
1
- #include "ruby.h"
2
-
3
- #define OPENED_TAG 0
4
- #define CLOSED_TAG 1
5
-
6
- static VALUE rb_XNode;
7
- static VALUE rb_XNode_ScanError;
8
- static VALUE rb_XNode_Scanner;
9
-
10
- static ID rb_XNode_CDATA_Callback;
11
- static ID rb_XNode_BeginTag_Callback;
12
- static ID rb_XNode_FinishTag_Callback;
13
- static ID rb_XNode_Attribute_Callback;
14
- static ID rb_XNode_Comment_Callback;
15
- static ID rb_XNode_Instruction_Callback;
16
- static ID rb_XNode_Comment_Callback;
17
-
18
- #define NewObject(type) (type*)malloc(sizeof(type))
19
-
20
- typedef struct {
21
- VALUE delegate;
22
- VALUE content;
23
- } XNode_Scanner;
24
-
25
- typedef char Character;
26
- typedef Character * Iterator;
27
-
28
- static void XNode_Scanner_Mark(XNode_Scanner * scanner) {
29
- rb_gc_mark(scanner->delegate);
30
- rb_gc_mark(scanner->content);
31
- }
32
-
33
- static void XNode_Scanner_Free(XNode_Scanner * scanner) {
34
- free(scanner);
35
- }
36
-
37
- static VALUE XNode_Scanner_Allocate(VALUE klass) {
38
- XNode_Scanner * scanner = NewObject(XNode_Scanner);
39
-
40
- return Data_Wrap_Struct(klass, XNode_Scanner_Mark, XNode_Scanner_Free, scanner);
41
- }
42
-
43
- static VALUE XNode_Scanner_Initialize(VALUE self, VALUE delegate, VALUE content) {
44
- Check_Type(content, T_STRING);
45
-
46
- XNode_Scanner * scanner;
47
-
48
- Data_Get_Struct(self, XNode_Scanner, scanner);
49
-
50
- scanner->delegate = delegate;
51
- scanner->content = content;
52
-
53
- return Qnil;
54
- }
55
-
56
- static VALUE rb_str_from_iterators(Iterator start, Iterator end) {
57
- return rb_str_new(start, end - start);
58
- }
59
-
60
- static int is_whitespace(Iterator i) {
61
- return (*i == ' ' || *i == '\r' || *i == '\n' || *i == '\t');
62
- }
63
-
64
- static int is_tag_character(Iterator i) {
65
- return (*i == '<' || *i == '>' || *i == '/');
66
- }
67
-
68
- static int is_tag_name(Iterator i) {
69
- return !(is_whitespace(i) || is_tag_character(i));
70
- }
71
-
72
- static Iterator expect_character(XNode_Scanner * scanner, Iterator start, Iterator end, Character c) {
73
- if (start >= end || *start != c) {
74
- VALUE message = rb_str_new2("Expected Character ");
75
- rb_str_cat(message, &c, 1);
76
- VALUE exception = rb_exc_new3(rb_XNode_ScanError, message);
77
- rb_exc_raise(exception);
78
- }
79
-
80
- return start + 1;
81
- }
82
-
83
- static Iterator skip_whitespace(Iterator start, Iterator end) {
84
- while (start < end) {
85
- if (!is_whitespace(start))
86
- break;
87
-
88
- ++start;
89
- }
90
-
91
- return start;
92
- }
93
-
94
- static Iterator XNode_Scanner_Parse_CDATA(XNode_Scanner * scanner, Iterator start, Iterator end) {
95
- Iterator cdata_start = start;
96
-
97
- while (start < end && *start != '<') {
98
- ++start;
99
- }
100
-
101
- Iterator cdata_end = start;
102
-
103
- if (cdata_start != cdata_end) {
104
- VALUE cdata = rb_str_from_iterators(cdata_start, cdata_end);
105
- rb_funcall(scanner->delegate, rb_XNode_CDATA_Callback, 1, cdata);
106
- }
107
-
108
- return start;
109
- }
110
-
111
- static Iterator XNode_Scanner_Parse_Attributes(XNode_Scanner * scanner, Iterator start, Iterator end) {
112
- while (start < end && !is_tag_character(start)) {
113
- start = skip_whitespace(start, end);
114
-
115
- Iterator attribute_name_start = start;
116
-
117
- while (start < end && *start != '=') {
118
- ++start;
119
- }
120
-
121
- Iterator attribute_name_end = start;
122
-
123
- start = expect_character(scanner, start, end, '=');
124
- start = expect_character(scanner, start, end, '"');
125
-
126
- Iterator attribute_value_start = start;
127
-
128
- while (start < end && *start != '"') {
129
- ++start;
130
- }
131
-
132
- Iterator attribute_value_end = start;
133
- start = expect_character(scanner, start, end, '"');
134
-
135
- VALUE attribute_name = rb_str_from_iterators(attribute_name_start, attribute_name_end);
136
- VALUE attribute_value = rb_str_from_iterators(attribute_value_start, attribute_value_end);
137
- rb_funcall(scanner->delegate, rb_XNode_Attribute_Callback, 2, attribute_name, attribute_value);
138
-
139
- start = skip_whitespace(start, end);
140
- }
141
-
142
- return start;
143
- }
144
-
145
- static Iterator XNode_Scanner_Parse_Tag_Normal(XNode_Scanner * scanner, Iterator start, Iterator end, int begin_tag_type) {
146
- Iterator tag_name_start = start;
147
- int finish_tag_type;
148
-
149
- while (start < end && is_tag_name(start)) {
150
- ++start;
151
- }
152
-
153
- Iterator tag_name_end = start;
154
-
155
- VALUE tag_name = rb_str_from_iterators(tag_name_start, tag_name_end);
156
- rb_funcall(scanner->delegate, rb_XNode_BeginTag_Callback, 2, tag_name, INT2FIX(begin_tag_type));
157
-
158
- start = skip_whitespace(start, end);
159
-
160
- if (!is_tag_character(start))
161
- start = XNode_Scanner_Parse_Attributes(scanner, start, end);
162
-
163
- if (*start == '/') {
164
- if (begin_tag_type == CLOSED_TAG) {
165
- VALUE exception = rb_exc_new2(rb_XNode_ScanError, "Tag cannot be closed at both ends!");
166
- rb_exc_raise(exception);
167
- }
168
-
169
- finish_tag_type = CLOSED_TAG;
170
- start += 2;
171
- } else if (*start == '>') {
172
- finish_tag_type = OPENED_TAG;
173
- ++start;
174
- }
175
-
176
- rb_funcall(scanner->delegate, rb_XNode_FinishTag_Callback, 2, INT2FIX(begin_tag_type), INT2FIX(finish_tag_type));
177
-
178
- return start;
179
- }
180
-
181
- static Iterator XNode_Scanner_Parse_Tag_Comment(XNode_Scanner * scanner, Iterator start, Iterator end) {
182
- Iterator comment_start = start;
183
-
184
- while (start < end && *start != '>') {
185
- ++start;
186
- }
187
-
188
- Iterator comment_end = start;
189
-
190
- start = expect_character(scanner, start, end, '>');
191
-
192
- VALUE comment = rb_str_from_iterators(comment_start, comment_end);
193
- rb_funcall(scanner->delegate, rb_XNode_Comment_Callback, 1, comment);
194
-
195
- return start;
196
- }
197
-
198
- static Iterator XNode_Scanner_Parse_Tag_Instruction(XNode_Scanner * scanner, Iterator start, Iterator end) {
199
- Iterator instruction_start = start;
200
-
201
- while ((start+1) < end && *start != '?' && *(start+1) != '>') {
202
- ++start;
203
- }
204
-
205
- Iterator instruction_end = start;
206
-
207
- start = expect_character(scanner, start, end, '?');
208
- start = expect_character(scanner, start, end, '>');
209
-
210
- VALUE instruction = rb_str_from_iterators(instruction_start, instruction_end);
211
- rb_funcall(scanner->delegate, rb_XNode_Instruction_Callback, 1, instruction);
212
-
213
- return start;
214
- }
215
-
216
- static Iterator XNode_Scanner_Parse_Tag(XNode_Scanner * scanner, Iterator start, Iterator end) {
217
- if (*start == '<') {
218
- ++start;
219
-
220
- if (*start == '/') {
221
- ++start;
222
- start = XNode_Scanner_Parse_Tag_Normal(scanner, start, end, CLOSED_TAG);
223
- } else if (*start == '!') {
224
- ++start;
225
- start = XNode_Scanner_Parse_Tag_Comment(scanner, start, end);
226
- } else if (*start == '?') {
227
- ++start;
228
- start = XNode_Scanner_Parse_Tag_Instruction(scanner, start, end);
229
- } else {
230
- start = XNode_Scanner_Parse_Tag_Normal(scanner, start, end, OPENED_TAG);
231
- }
232
- }
233
-
234
- return start;
235
- }
236
-
237
- static Iterator XNode_Scanner_Parse_Document(XNode_Scanner * scanner) {
238
- Iterator current, start, end;
239
-
240
- start = RSTRING(scanner->content)->ptr;
241
- end = start + RSTRING(scanner->content)->len;
242
-
243
- while (start < end) {
244
- current = start;
245
-
246
- current = XNode_Scanner_Parse_CDATA(scanner, current, end);
247
- current = XNode_Scanner_Parse_Tag(scanner, current, end);
248
-
249
- if (current == start) {
250
- /* We did not parse anything! */
251
- VALUE message = rb_str_new2("Parser Stuck at ");
252
-
253
- int len = 10;
254
- if (current + len > end)
255
- len = end - current;
256
-
257
- rb_str_cat(message, current, len);
258
- VALUE exception = rb_exc_new3(rb_XNode_ScanError, message);
259
- rb_exc_raise(exception);
260
- }
261
-
262
- start = current;
263
- }
264
- }
265
-
266
- static VALUE XNode_Scanner_Parse(VALUE self) {
267
- XNode_Scanner * scanner;
268
-
269
- Data_Get_Struct(self, XNode_Scanner, scanner);
270
-
271
- XNode_Scanner_Parse_Document(scanner);
272
- }
273
-
274
- void Init_xnode() {
275
- rb_XNode = rb_define_module("XNode");
276
- rb_XNode_ScanError = rb_define_class_under(rb_XNode, "ScanError", rb_eStandardError);
277
- rb_XNode_Scanner = rb_define_class_under(rb_XNode, "Scanner", rb_cObject);
278
-
279
- rb_define_alloc_func(rb_XNode_Scanner, XNode_Scanner_Allocate);
280
- rb_define_method(rb_XNode_Scanner, "initialize", XNode_Scanner_Initialize, 2);
281
- rb_define_method(rb_XNode_Scanner, "parse", XNode_Scanner_Parse, 0);
282
-
283
- rb_XNode_CDATA_Callback = rb_intern("cdata");
284
- rb_XNode_BeginTag_Callback = rb_intern("begin_tag");
285
- rb_XNode_FinishTag_Callback = rb_intern("finish_tag");
286
- rb_XNode_Attribute_Callback = rb_intern("attribute");
287
- rb_XNode_Comment_Callback = rb_intern("comment");
288
- rb_XNode_Instruction_Callback = rb_intern("instruction");
289
- }
@@ -1,39 +0,0 @@
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
- module Utopia
6
-
7
- HTTP_STATUS_CODES = {
8
- :success => 200,
9
- :created => 201,
10
- :accepted => 202,
11
- :moved => 301,
12
- :found => 302,
13
- :see_other => 303,
14
- :not_modified => 304,
15
- :redirect => 307,
16
- :bad_request => 400,
17
- :unauthorized => 401,
18
- :forbidden => 403,
19
- :not_found => 404,
20
- :unsupported_method => 405,
21
- :gone => 410,
22
- :teapot => 418,
23
- :error => 500,
24
- :unimplemented => 501,
25
- :unavailable => 503
26
- }
27
-
28
- HTTP_STATUS_DESCRIPTIONS = {
29
- 400 => "Bad Request",
30
- 401 => "Permission Denied",
31
- 403 => "Access Forbidden",
32
- 404 => "Resource Not Found",
33
- 405 => "Unsupported Method",
34
- 416 => "Byte range unsatisfiable",
35
- 500 => "Internal Server Error",
36
- 501 => "Not Implemented",
37
- 503 => "Service Unavailable"
38
- }
39
- end
@@ -1,29 +0,0 @@
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/middleware'
6
-
7
- module Utopia
8
- module Middleware
9
-
10
- class Benchmark
11
- def initialize(app, options = {})
12
- @app = app
13
- @tag = options[:tag] || "{{benchmark}}"
14
- end
15
-
16
- def call(env)
17
- start = Time.now
18
- response = @app.call(env)
19
- finish = Time.now
20
-
21
- time = "%0.4f" % (finish - start)
22
- env['rack.errors'].puts "Benchmark: Request #{env["PATH_INFO"]} took #{time}s"
23
-
24
- return response
25
- end
26
- end
27
-
28
- end
29
- end
@@ -1,35 +0,0 @@
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
- require 'utopia/middleware'
5
-
6
- module Utopia
7
- module Middleware
8
-
9
- # This class filters a incoming request and only executes a given block if it matches the given filter path.
10
- class Filter
11
- def initialize(app, filter, &block)
12
- @app = app
13
- @filter = filter
14
- branch = Rack::Builder.new(&block)
15
- branch.run(@app)
16
- @process = branch.to_app
17
- end
18
-
19
- def applicable(request)
20
- return request.path.index(@filter) != nil
21
- end
22
-
23
- def call(env)
24
- request = Rack::Request.new(env)
25
-
26
- if applicable(request)
27
- @process.call(env)
28
- else
29
- @app.call(env)
30
- end
31
- end
32
- end
33
-
34
- end
35
- end
@@ -1,13 +0,0 @@
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("env") do |transaction, state|
8
- only = state[:only].split(",").collect(&:to_sym) rescue []
9
-
10
- if defined?(UTOPIA_ENV) && only.include?(UTOPIA_ENV)
11
- transaction.parse_xml(state.content)
12
- end
13
- end
@@ -1,9 +0,0 @@
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("fortune") do |transaction, state|
8
- "<pre>#{`fortune`.to_html}</pre>"
9
- end
@@ -1,275 +0,0 @@
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
- require 'RMagick'
8
- require 'fileutils'
9
-
10
- class Utopia::Tags::Gallery
11
- module Processes
12
- class Thumbnail
13
- def initialize(size = [800, 800])
14
- @size = size
15
- end
16
-
17
- def call(img)
18
- # Only resize an image if it is bigger than the given size.
19
- if (img.columns > @size[0] || img.rows > @size[1])
20
- img.resize_to_fit(*@size)
21
- else
22
- img
23
- end
24
- end
25
-
26
- def default_extension(path)
27
- ext = path.original.extension
28
-
29
- case ext
30
- when /pdf/i
31
- return "png"
32
- else
33
- return ext.downcase
34
- end
35
- end
36
- end
37
-
38
- # Resize the image to fit within the specified dimensions while retaining the aspect ratio of the original image. If necessary, crop the image in the larger dimension.
39
- class CropThumbnail < Thumbnail
40
- def call(img)
41
- img.resize_to_fill(*@size)
42
- end
43
- end
44
-
45
- class DocumentThumbnail < Thumbnail
46
- def call(img)
47
- img = super(img)
48
-
49
- shadow = img.dup
50
-
51
- shadow = shadow.colorize(1, 1, 1, 'gray50')
52
- shadow.background_color = 'transparent'
53
- shadow.border!(10, 10, 'transparent')
54
-
55
- shadow = shadow.gaussian_blur_channel(5, 5, Magick::AlphaChannel)
56
-
57
- shadow.composite(img, 5, 5, Magick::OverCompositeOp)
58
- end
59
-
60
- def default_extension(path)
61
- return "png"
62
- end
63
- end
64
-
65
- class PhotoThumbnail < Thumbnail
66
- def call(img)
67
- img = super(img)
68
-
69
- shadow = img.dup
70
-
71
- shadow = shadow.colorize(1, 1, 1, '#999999ff')
72
- shadow.background_color = 'transparent'
73
- shadow.border!(10, 10, '#99999900')
74
-
75
- shadow = shadow.gaussian_blur_channel(5, 5, Magick::AlphaChannel)
76
-
77
- shadow.composite(img, 5, 5, Magick::OverCompositeOp)
78
- end
79
-
80
- def default_extension(path)
81
- return "png"
82
- end
83
- end
84
- end
85
-
86
- CACHE_DIR = "_cache"
87
- PROCESSES = {
88
- :pdf_thumbnail => Processes::DocumentThumbnail.new([300, 300]),
89
- :photo_thumbnail => Processes::PhotoThumbnail.new([300, 300]),
90
- :large => Processes::Thumbnail.new([800, 800]),
91
- :square_thumbnail => Processes::CropThumbnail.new([300, 300]),
92
- :thumbnail => Processes::Thumbnail.new([300, 300])
93
- }
94
-
95
- class ImagePath
96
- def initialize(original_path)
97
- @original_path = original_path
98
- @cache_root = @original_path.dirname + CACHE_DIR
99
-
100
- @extensions = {}
101
- end
102
-
103
- attr :cache_root
104
- attr :extensions
105
-
106
- def original
107
- @original_path
108
- end
109
-
110
- def self.append_suffix(name, suffix, extension = nil)
111
- components = name.split(".")
112
-
113
- components.insert(-2, suffix)
114
-
115
- if (extension)
116
- components[-1] = extension
117
- end
118
-
119
- return components.join(".")
120
- end
121
-
122
- def processed(process = nil)
123
- if process
124
- name = @original_path.basename
125
- return cache_root + ImagePath.append_suffix(name, process.to_s, @extensions[process.to_sym])
126
- else
127
- return @original_path
128
- end
129
- end
130
-
131
- def to_html(process = nil)
132
- Tag.new("img", {"src" => path(process)}).to_html
133
- end
134
-
135
- def to_s
136
- @original_path.to_s
137
- end
138
-
139
- def method_missing(name, *args)
140
- return processed(name.to_s)
141
- end
142
- end
143
-
144
- class ImageMetadata
145
- def initialize(metadata)
146
- @metadata = metadata
147
- end
148
-
149
- attr :metadata
150
-
151
- def [] (key)
152
- @metadata[key.to_s]
153
- end
154
-
155
- def to_s
156
- @metadata['caption'] || ''
157
- end
158
-
159
- # A bit of a hack to ease migration.
160
- def to_html
161
- to_s.to_html
162
- end
163
- end
164
-
165
- def initialize(node, path)
166
- @node = node
167
- @path = path
168
- end
169
-
170
- def metadata
171
- metadata_path = @node.local_path(@path + "gallery.yaml")
172
-
173
- if File.exist? metadata_path
174
- return YAML::load(File.read(metadata_path))
175
- else
176
- return {}
177
- end
178
- end
179
-
180
- def images(options = {})
181
- options[:filter] ||= /(jpg|png)$/i
182
-
183
- paths = []
184
- local_path = @node.local_path(@path)
185
-
186
- Dir.entries(local_path).each do |filename|
187
- next unless filename.match(options[:filter])
188
-
189
- fullpath = File.join(local_path, filename)
190
-
191
- paths << ImagePath.new(@path + filename)
192
- end
193
-
194
- if options[:process]
195
- paths.each do |path|
196
- processed_image(path, options[:process])
197
- end
198
- end
199
-
200
- return paths
201
- end
202
-
203
- def processed_image(image_path, processes)
204
- # Create the local cache directory if it doesn't exist already
205
- local_cache_path = @node.local_path(image_path.cache_root)
206
-
207
- unless File.exist? local_cache_path
208
- FileUtils.mkdir local_cache_path
209
- end
210
-
211
- # Calculate the new name for the processed image
212
- local_original_path = @node.local_path(image_path.original)
213
-
214
- if processes.kind_of? String
215
- processes = processes.split(",").collect{|p| p.split(":")}
216
- end
217
-
218
- processes.each do |process_name, extension|
219
- process_name = process_name.to_sym
220
-
221
- process = PROCESSES[process_name]
222
- extension ||= process.default_extension(image_path)
223
-
224
- image_path.extensions[process_name] = extension if extension
225
-
226
- local_processed_path = @node.local_path(image_path.processed(process_name))
227
-
228
- unless File.exists? local_processed_path
229
- image = Magick::ImageList.new(local_original_path)
230
- image.scene = 0
231
-
232
- processed_image = process.call(image)
233
- processed_image.write(local_processed_path)
234
-
235
- # Run GC to free up any memory.
236
- processed_image = nil
237
- GC.start if defined? GC
238
- end
239
- end
240
- end
241
-
242
- def self.call(transaction, state)
243
- gallery = new(transaction.end_tags[-2].node, Utopia::Path.create(state["path"] || "./"))
244
- metadata = gallery.metadata
245
- metadata.default = {}
246
-
247
- tag_name = state["tag"] || "img"
248
- gallery_class = state["class"] || "gallery"
249
-
250
- options = {}
251
- options[:process] = state["process"]
252
- options[:filter] = Regexp.new("(#{state["filetypes"]})$", "i") if state["filetypes"]
253
-
254
- filter = Regexp.new(state["filter"], Regexp::IGNORECASE) if state["filter"]
255
-
256
- transaction.tag("div", "class" => gallery_class) do |node|
257
- images = gallery.images(options).sort do |a, b|
258
- if (metadata[a.original.basename]["order"] && metadata[b.original.basename]["order"])
259
- metadata[a.original.basename]["order"] <=> metadata[b.original.basename]["order"]
260
- else
261
- a.original.basename <=> b.original.basename
262
- end
263
- end
264
-
265
- images.each do |path|
266
- next if filter and !filter.match(path.original.basename)
267
-
268
- alt = ImageMetadata.new(metadata[path.original.basename])
269
- transaction.tag(tag_name, "src" => path, "alt" => alt)
270
- end
271
- end
272
- end
273
- end
274
-
275
- Utopia::Tags.register("gallery", Utopia::Tags::Gallery)
@@ -1,21 +0,0 @@
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("google_analytics") do |transaction, state|
8
- html = <<EOF
9
- <script type="text/javascript">
10
- var _gaq = _gaq || []; _gaq.push(['_setAccount', #{state[:id].to_quoted_string}]); _gaq.push(['_trackPageview']);
11
- (function() {
12
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
13
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
14
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
15
- })();
16
- </script>
17
- EOF
18
-
19
-
20
- transaction.cdata(html)
21
- end