utopia 0.10.0 → 0.11.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 (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