utopia 0.9.31 → 0.9.32

Sign up to get free protection for your applications and to get access to all the features.
data/bin/utopia ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'utopia/setup'
5
+ require 'rake'
6
+
7
+ $app = Rake.application = Rake::Application.new
8
+ $app.init('Utopia')
9
+
10
+ task :setup do
11
+ Utopia::Setup.copy(Dir.getwd)
12
+
13
+ if `which thin`.strip == ""
14
+ $stderr.puts "Next, please install thin: `sudo gem install thin'."
15
+ $stderr.puts "Once you've done that, type `thin start' to start the web server."
16
+ else
17
+ $stderr.puts "Type `thin start' to start the web server."
18
+ end
19
+
20
+ if `which git`.strip == ""
21
+ $stderr.puts "Now is a good time to learn about git : http://git-scm.com/"
22
+ end
23
+
24
+ unless File.exist? '.git'
25
+ $stderr.puts "I recommend using git for version control."
26
+ end
27
+
28
+ $stderr.puts "*** Thanks for trying out Utopia! ***"
29
+ end
30
+
31
+ task :default => :setup
32
+
33
+ $app.top_level
@@ -0,0 +1,25 @@
1
+ # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
+ # Copyright 2010 Samuel Williams. All rights reserved.
3
+ # See <utopia.rb> for licensing details.
4
+
5
+ class Array
6
+ def find_index(&block)
7
+ each_with_index do |item, index|
8
+ if yield(item)
9
+ return index
10
+ end
11
+ end
12
+
13
+ return nil
14
+ end
15
+
16
+ def split_at(&block)
17
+ index = find_index(&block)
18
+
19
+ if index
20
+ return [self[0...index], self[index], self[index+1..-1]]
21
+ end
22
+
23
+ return [[], nil, []]
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
+ # Copyright 2010 Samuel Williams. All rights reserved.
3
+ # See <utopia.rb> for licensing details.
4
+
5
+ require 'active_support'
6
+
7
+ class Date
8
+ alias_method :old_cmp, :<=>
9
+
10
+ def <=> (other)
11
+ # Comparing a Date with something that has a time component truncates the time
12
+ # component, thus we need to check if the other object has a more exact comparison
13
+ # function.
14
+ if other.respond_to?(:hour)
15
+ return (other <=> self) * -1
16
+ else
17
+ old_cmp(other)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
+ # Copyright 2010 Samuel Williams. All rights reserved.
3
+ # See <utopia.rb> for licensing details.
4
+
5
+ class Hash
6
+ def symbolize_keys
7
+ inject({}) do |options, (key, value)|
8
+ options[(key.to_sym rescue key) || key] = value
9
+ options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
+ # Copyright 2010 Samuel Williams. All rights reserved.
3
+ # See <utopia.rb> for licensing details.
4
+
5
+ class Rack::Response
6
+ def do_not_cache!
7
+ self["Cache-Control"] = "no-cache, must-revalidate"
8
+ self["Expires"] = Time.now.httpdate
9
+ end
10
+
11
+ def cache!(duration = 3600)
12
+ self["Cache-Control"] = "public, max-age=#{duration}"
13
+ self["Expires"] = (Time.now + duration).httpdate
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
+ # Copyright 2010 Samuel Williams. All rights reserved.
3
+ # See <utopia.rb> for licensing details.
4
+
5
+ class Regexp
6
+ def self.starts_with(string)
7
+ return /^#{Regexp.escape(string)}/
8
+ end
9
+
10
+ def self.ends_with(string)
11
+ return /#{Regexp.escape(string)}$/
12
+ end
13
+
14
+ def self.contains(string)
15
+ return Regexp.new(string)
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
+ # Copyright 2010 Samuel Williams. All rights reserved.
3
+ # See <utopia.rb> for licensing details.
4
+
5
+ class String
6
+ HTML_ESCAPE = {"&" => "&amp;", "<" => "&lt;", ">" => "&gt;", "\"" => "&quot;"}
7
+ HTML_ESCAPE_PATTERN = Regexp.new("[" + Regexp.quote(HTML_ESCAPE.keys.join) + "]")
8
+
9
+ def to_html
10
+ gsub(HTML_ESCAPE_PATTERN){|c| HTML_ESCAPE[c]}
11
+ end
12
+
13
+ def to_title
14
+ (" " + self).gsub(/[ \-_](.)/){" " + $1.upcase}.strip
15
+ end
16
+
17
+ def to_snake
18
+ self.gsub("::", "").gsub(/([A-Z]+)/){"_" + $1.downcase}.sub(/^_+/, "")
19
+ end
20
+ end
data/lib/utopia/link.rb CHANGED
@@ -2,7 +2,10 @@
2
2
  # Copyright 2010 Samuel Williams. All rights reserved.
3
3
  # See <utopia.rb> for licensing details.
4
4
 
5
- require 'utopia/extensions'
5
+ require 'utopia/extensions/date'
6
+ require 'utopia/extensions/string'
7
+ require 'utopia/extensions/hash'
8
+ require 'utopia/extensions/array'
6
9
 
7
10
  module Utopia
8
11
 
@@ -132,7 +135,7 @@ module Utopia
132
135
  :virtual => true,
133
136
  :indices => false,
134
137
  :sort => :order,
135
- :hidden => :hidden,
138
+ :display => :display,
136
139
  :locale => nil
137
140
  }
138
141
 
@@ -196,8 +199,8 @@ module Utopia
196
199
  end
197
200
  end
198
201
 
199
- if options[:hidden]
200
- links = links.delete_if{|link| link[options[:hidden]]}
202
+ if options[:display]
203
+ links = links.delete_if{|link| link[options[:display]] == false}
201
204
  end
202
205
 
203
206
  if options[:name]
@@ -5,6 +5,8 @@
5
5
  require 'pathname'
6
6
  require 'logger'
7
7
 
8
+ require 'utopia/extensions/rack'
9
+
8
10
  module Utopia
9
11
  LOG = Logger.new($stderr)
10
12
  LOG.level = Logger::DEBUG
@@ -16,7 +18,6 @@ module Utopia
16
18
  end
17
19
  end
18
20
 
19
- require 'utopia/extensions'
20
21
  require 'utopia/path'
21
22
  require 'utopia/tag'
22
23
 
@@ -19,7 +19,7 @@ module Utopia
19
19
 
20
20
  @root = File.expand_path(options[:root] || Utopia::Middleware::default_root)
21
21
 
22
- LOG.info "#{self.class.name}: Running in #{@root}"
22
+ LOG.info "** #{self.class.name}: Running in #{@root}"
23
23
 
24
24
  # Set to hash to enable caching
25
25
  @nodes = {}
@@ -142,7 +142,7 @@ module Utopia
142
142
  @app = app
143
143
  @root = options[:root] || Utopia::Middleware::default_root
144
144
 
145
- LOG.info "#{self.class.name}: Running in #{@root}"
145
+ LOG.info "** #{self.class.name}: Running in #{@root}"
146
146
 
147
147
  @controllers = {}
148
148
  @cache_controllers = (UTOPIA_ENV == :production)
@@ -36,6 +36,10 @@ module Utopia
36
36
  end
37
37
 
38
38
  @log << record
39
+
40
+ if UTOPIA_ENV != :production
41
+ $stderr.puts ">> #{record[:method]} #{record[:url]} -> #{response[0]}"
42
+ end
39
43
  end
40
44
 
41
45
  def initialize(app, options = {})
@@ -3,6 +3,8 @@
3
3
  # See <utopia.rb> for licensing details.
4
4
 
5
5
  require 'utopia/middleware'
6
+ require 'utopia/extensions/regexp'
7
+ require 'utopia/extensions/string'
6
8
 
7
9
  module Utopia
8
10
  module Middleware
@@ -112,7 +114,7 @@ module Utopia
112
114
 
113
115
  @errors = options[:errors]
114
116
 
115
- LOG.info "#{self.class.name}: Running with #{@strings.size + @patterns.size} rules"
117
+ LOG.info "** #{self.class.name}: Running with #{@strings.size + @patterns.size} rules"
116
118
  end
117
119
 
118
120
  def redirect(uri, match_data)
@@ -13,12 +13,34 @@ module Utopia
13
13
  module Middleware
14
14
 
15
15
  class Static
16
- DEFAULT_TYPES = [
17
- "html", "css", "js", "txt", "rtf", "xml",
18
- "pdf", "zip", "tar", "tgz", "tar.gz", "tar.bz2", "dmg",
19
- "mp3", "mp4", "wav", "aiff", ["aac", "audio/x-aac"], "mov", "avi", "wmv",
20
- /^image/
21
- ]
16
+ MIME_TYPES = {
17
+ :xiph => {
18
+ "ogx" => "application/ogg",
19
+ "ogv" => "video/ogg",
20
+ "oga" => "audio/ogg",
21
+ "ogg" => "audio/ogg",
22
+ "spx" => "audio/ogg",
23
+ "flac" => "audio/flac",
24
+ "anx" => "application/annodex",
25
+ "axa" => "audio/annodex",
26
+ "xspf" => "application/xspf+xml",
27
+ },
28
+ :media => [
29
+ :xiph, "mp3", "mp4", "wav", "aiff", ["aac", "audio/x-aac"], "mov", "avi", "wmv", "mpg"
30
+ ],
31
+ :text => [
32
+ "html", "css", "js", "txt", "rtf", "xml", "pdf"
33
+ ],
34
+ :archive => [
35
+ "zip", "tar", "tgz", "tar.gz", "tar.bz2", ["dmg", "application/x-apple-diskimage"]
36
+ ],
37
+ :images => [
38
+ "png", "gif", "jpeg", "tiff"
39
+ ],
40
+ :default => [
41
+ :media, :text, :archive, :images
42
+ ]
43
+ }
22
44
 
23
45
  private
24
46
 
@@ -69,16 +91,18 @@ module Utopia
69
91
  result = {}
70
92
 
71
93
  extract_extensions = lambda do |mime_type|
94
+ # LOG.info "Extracting #{mime_type.inspect}"
72
95
  mime_type.extensions.each{|ext| result["." + ext] = mime_type.content_type}
73
96
  end
74
97
 
75
98
  types.each do |type|
76
99
  current_count = result.size
100
+ # LOG.info "Processing #{type.inspect}"
77
101
 
78
102
  begin
79
103
  case type
80
- when :defaults
81
- result = load_mime_types(DEFAULT_TYPES).merge(result)
104
+ when Symbol
105
+ result = load_mime_types(MIME_TYPES[type]).merge(result)
82
106
  when Array
83
107
  result["." + type[0]] = type[1]
84
108
  when String
@@ -98,7 +122,7 @@ module Utopia
98
122
  end
99
123
 
100
124
  if result.size == current_count
101
- LOG.warn "#{self.class.name}: Could not find any mime type for file extension #{type.inspect}"
125
+ LOG.warn "#{self.class.name}: Could not find any mime type for #{type.inspect}"
102
126
  end
103
127
  end
104
128
 
@@ -113,12 +137,13 @@ module Utopia
113
137
  if options[:types]
114
138
  @extensions = load_mime_types(options[:types])
115
139
  else
116
- @extensions = load_mime_types(DEFAULT_TYPES)
140
+ @extensions = load_mime_types(MIME_TYPES[:default])
117
141
  end
118
142
 
119
143
  @cache_control = options[:cache_control] || "public, max-age=3600"
120
144
 
121
- LOG.info "#{self.class.name}: Running in #{@root} with #{extensions.size} filetypes"
145
+ LOG.info "** #{self.class.name}: Running in #{@root} with #{extensions.size} filetypes"
146
+ # LOG.info @extensions.inspect
122
147
  end
123
148
 
124
149
  def fetch_file(path)
@@ -0,0 +1,39 @@
1
+
2
+ require 'utopia/version'
3
+ require 'fileutils'
4
+ require 'find'
5
+ require 'rake'
6
+
7
+ module Utopia
8
+ module Setup
9
+ ROOT = File.join(File.dirname(__FILE__), "setup", "")
10
+ DIRECTORIES = ["access_log", "cache", "cache/meta", "cache/head", "lib", "pages", "public"]
11
+
12
+ def self.copy(to, config = {})
13
+ $stderr.puts "Copying files from #{ROOT} to #{to}..."
14
+ Find.find(ROOT) do |src|
15
+ dst = File.join(to, src[ROOT.size..-1])
16
+
17
+ if File.directory?(src)
18
+ FileUtils.mkdir_p(dst)
19
+ else
20
+ if File.exist? dst
21
+ $stderr.puts "File already exists: #{dst}!"
22
+ else
23
+ $stderr.puts "Copying #{src} to #{dst}..."
24
+ FileUtils.cp(src, dst)
25
+ end
26
+ end
27
+ end
28
+
29
+ DIRECTORIES.each do |path|
30
+ FileUtils.mkdir_p(File.join(to, path))
31
+ end
32
+
33
+ $stderr.puts "Updating config.ru..."
34
+ config_ru = File.join(to, "config.ru")
35
+ buf = File.read(config_ru).gsub('$UTOPIA_VERSION', Utopia::VERSION::STRING.dump)
36
+ File.open(config_ru, "w") { |fp| fp.write(buf) }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env rackup
2
+
3
+ UTOPIA_ENV = (ENV['UTOPIA_ENV'] || ENV['RACK_ENV'] || :development).to_sym
4
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "lib")
5
+
6
+ # It is recommended that you always explicity specify the version of the gem you are using.
7
+ gem 'utopia', $UTOPIA_VERSION
8
+ require 'utopia/middleware/all'
9
+ require 'utopia/tags/env'
10
+
11
+ gem 'rack-contrib'
12
+ require 'rack/contrib'
13
+
14
+ # Utopia relies heavily on accurately caching resources
15
+ gem 'rack-cache'
16
+ require 'rack/cache'
17
+
18
+ if UTOPIA_ENV == :development
19
+ use Rack::ShowExceptions
20
+ else
21
+ use Utopia::Middleware::ExceptionHandler, "/errors/exception"
22
+
23
+ # Fill out these details to receive email reports of exceptions when running in a production environment.
24
+ # use Rack::MailExceptions do |mail|
25
+ # mail.from $MAIL_EXCEPTIONS_FROM
26
+ # mail.to $MAIL_EXCEPTIONS_TO
27
+ # mail.subject "Website Error: %s"
28
+ # end
29
+ end
30
+
31
+ use Rack::ContentLength
32
+ use Utopia::Middleware::Logger
33
+
34
+ use Utopia::Middleware::Redirector, {
35
+ :strings => {
36
+ '/' => '/welcome/index',
37
+ '/utopia' => 'http://www.oriontransfer.co.nz/software/utopia/demo'
38
+ },
39
+ :errors => {
40
+ 404 => "/errors/file-not-found"
41
+ }
42
+ }
43
+
44
+ use Utopia::Middleware::Requester
45
+ use Utopia::Middleware::DirectoryIndex
46
+ use Utopia::Middleware::Controller
47
+ use Utopia::Middleware::Static
48
+
49
+ if UTOPIA_ENV == :production
50
+ use Rack::Cache, {
51
+ :metastore => "file:#{Utopia::Middleware::default_root("cache/meta")}",
52
+ :entitystore => "file:#{Utopia::Middleware::default_root("cache/body")}",
53
+ :verbose => false
54
+ }
55
+ end
56
+
57
+ use Utopia::Middleware::Content
58
+
59
+ run lambda { [404, {}, []] }
@@ -0,0 +1 @@
1
+ You can add additional code for your application in this directory, and require it directly from the config.ru.
@@ -0,0 +1,2 @@
1
+ <?r @title ||= content ?>
2
+ <h1><content/></h1>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <?r response["Content-Type"] = "text/html; charset=utf-8" ?>
5
+ <?r response["Cache-Control"] = "max-age=3600" ?>
6
+
7
+ <?r if title = (attributes["title"] || @title) ?>
8
+ <title>#{title.gsub(/<.*?>/, "")} - Utopia</title>
9
+ <?r else ?>
10
+ <title>Utopia</title>
11
+ <?r end ?>
12
+
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" />
15
+ </head>
16
+
17
+ <body class="ledlighting">
18
+ <div id="header">
19
+ </div>
20
+
21
+ <div id="page">
22
+ <content />
23
+ </div>
24
+ </body>
25
+ </html>
@@ -0,0 +1,51 @@
1
+ /* Copyright (c) 2010 Orion Transfer Ltd. All Rights Reserved. */
2
+
3
+ body, p, ol, ul, blockquote {
4
+ font-family: "Skia", verdana, arial, helvetica, sans-serif;
5
+ line-height: 18px;
6
+
7
+ color: #339;
8
+ }
9
+
10
+ h1, h2, h3, h4, h5, h6 {
11
+ font-family: menlo, monospace;
12
+ color: #303;
13
+
14
+ margin-top: 2em;
15
+ margin-bottom: 1em;
16
+ }
17
+
18
+ body {
19
+ background: url(/_static/background.png) #fff center no-repeat fixed;
20
+ padding: 50px;
21
+ }
22
+
23
+ img {
24
+ border: none;
25
+ }
26
+
27
+ a {
28
+ color: #33a;
29
+ }
30
+
31
+ a:hover {
32
+ color: #55c;
33
+ }
34
+
35
+ p, dl, h3 {
36
+ line-height: 1.4em;
37
+ margin: 1em;
38
+ }
39
+
40
+ h3 {
41
+ border-bottom: 1px solid #ccf;
42
+ }
43
+
44
+ ul {
45
+ line-height: 1.4em;
46
+ margin-bottom: 1em;
47
+ }
48
+
49
+ h3, h4, h5, h6 {
50
+ font-weight: normal;
51
+ }
@@ -0,0 +1,5 @@
1
+ <page>
2
+ <heading>Exception</heading>
3
+
4
+ <p>It seems like something didn't quite work out as expected!</p>
5
+ </page>
@@ -0,0 +1,5 @@
1
+ <page>
2
+ <heading>File Not Found</heading>
3
+
4
+ <p>The file you requested is unfortunately not available at this time!</p>
5
+ </page>
@@ -0,0 +1,2 @@
1
+ errors:
2
+ display: false
@@ -0,0 +1,7 @@
1
+ <page>
2
+ <heading>Welcome to Utopia</heading>
3
+
4
+ <p>Utopia is designed to simply your life. It is not an application development framework. It is not a content management system. It does not require a database. It isn't model view controller. It is simply a platform on which websites can be easily developed with a minimum of effort.</p>
5
+
6
+ <p><a href="http://www.oriontransfer.co.nz/utopia/setup">Utopia Project Page &amp; Documentation</a></p>
7
+ </page>
@@ -0,0 +1 @@
1
+ This directory is required by Apache/Phusion Passenger.
@@ -3,10 +3,10 @@
3
3
  # See <utopia.rb> for licensing details.
4
4
 
5
5
  module Utopia
6
- module VERSION #:nodoc:
6
+ module VERSION
7
7
  MAJOR = 0
8
8
  MINOR = 9
9
- TINY = 31
9
+ TINY = 32
10
10
 
11
11
  STRING = [MAJOR, MINOR, TINY].join('.')
12
12
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 31
9
- version: 0.9.31
8
+ - 32
9
+ version: 0.9.32
10
10
  platform: ruby
11
11
  authors:
12
12
  - Samuel Williams
@@ -14,8 +14,8 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-16 00:00:00 +12:00
18
- default_executable:
17
+ date: 2010-05-19 00:00:00 +12:00
18
+ default_executable: utopia
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: mime-types
@@ -91,8 +91,8 @@ dependencies:
91
91
  version_requirements: *id006
92
92
  description:
93
93
  email: samuel.williams@oriontransfer.co.nz
94
- executables: []
95
-
94
+ executables:
95
+ - utopia
96
96
  extensions: []
97
97
 
98
98
  extra_rdoc_files: []
@@ -101,7 +101,12 @@ files:
101
101
  - ext/utopia/xnode/fast_scanner/extconf.rb
102
102
  - ext/utopia/xnode/fast_scanner/parser.c
103
103
  - lib/utopia/etanni.rb
104
- - lib/utopia/extensions.rb
104
+ - lib/utopia/extensions/array.rb
105
+ - lib/utopia/extensions/date.rb
106
+ - lib/utopia/extensions/hash.rb
107
+ - lib/utopia/extensions/rack.rb
108
+ - lib/utopia/extensions/regexp.rb
109
+ - lib/utopia/extensions/string.rb
105
110
  - lib/utopia/http_status_codes.rb
106
111
  - lib/utopia/link.rb
107
112
  - lib/utopia/middleware/all.rb
@@ -119,6 +124,19 @@ files:
119
124
  - lib/utopia/middleware.rb
120
125
  - lib/utopia/path.rb
121
126
  - lib/utopia/session/encrypted_cookie.rb
127
+ - lib/utopia/setup/config.ru
128
+ - lib/utopia/setup/lib/readme.txt
129
+ - lib/utopia/setup/pages/_heading.xnode
130
+ - lib/utopia/setup/pages/_page.xnode
131
+ - lib/utopia/setup/pages/_static/background.png
132
+ - lib/utopia/setup/pages/_static/icon.png
133
+ - lib/utopia/setup/pages/_static/site.css
134
+ - lib/utopia/setup/pages/errors/exception.xnode
135
+ - lib/utopia/setup/pages/errors/file-not-found.xnode
136
+ - lib/utopia/setup/pages/links.yaml
137
+ - lib/utopia/setup/pages/welcome/index.xnode
138
+ - lib/utopia/setup/public/readme.txt
139
+ - lib/utopia/setup.rb
122
140
  - lib/utopia/tag.rb
123
141
  - lib/utopia/tags/all.rb
124
142
  - lib/utopia/tags/env.rb
@@ -134,6 +152,7 @@ files:
134
152
  - lib/utopia/xnode/scanner.rb
135
153
  - lib/utopia/xnode.rb
136
154
  - lib/utopia.rb
155
+ - bin/utopia
137
156
  has_rdoc: true
138
157
  homepage: http://www.oriontransfer.co.nz/software/utopia
139
158
  licenses: []
@@ -1,90 +0,0 @@
1
- # This file is part of the "Utopia Framework" project, and is licensed under the GNU AGPLv3.
2
- # Copyright 2010 Samuel Williams. All rights reserved.
3
- # See <utopia.rb> for licensing details.
4
-
5
- require 'active_support'
6
-
7
- class Date
8
- alias_method :old_cmp, :<=>
9
-
10
- def <=> (other)
11
- # Comparing a Date with something that has a time component truncates the time
12
- # component, thus we need to check if the other object has a more exact comparison
13
- # function.
14
- if other.respond_to?(:hour)
15
- return (other <=> self) * -1
16
- else
17
- old_cmp(other)
18
- end
19
- end
20
- end
21
-
22
- class Regexp
23
- def self.starts_with(string)
24
- return /^#{Regexp.escape(string)}/
25
- end
26
-
27
- def self.ends_with(string)
28
- return /#{Regexp.escape(string)}$/
29
- end
30
-
31
- def self.contains(string)
32
- return Regexp.new(string)
33
- end
34
- end
35
-
36
- class String
37
- HTML_ESCAPE = {"&" => "&amp;", "<" => "&lt;", ">" => "&gt;", "\"" => "&quot;"}
38
- HTML_ESCAPE_PATTERN = Regexp.new("[" + Regexp.quote(HTML_ESCAPE.keys.join) + "]")
39
-
40
- def to_html
41
- gsub(HTML_ESCAPE_PATTERN){|c| HTML_ESCAPE[c]}
42
- end
43
-
44
- def to_title
45
- (" " + self).gsub(/[ \-_](.)/){" " + $1.upcase}.strip
46
- end
47
-
48
- def to_snake
49
- self.gsub("::", "").gsub(/([A-Z]+)/){"_" + $1.downcase}.sub(/^_+/, "")
50
- end
51
- end
52
-
53
- class Hash
54
- def symbolize_keys
55
- inject({}) do |options, (key, value)|
56
- options[(key.to_sym rescue key) || key] = value
57
- options
58
- end
59
- end
60
- end
61
-
62
- class Array
63
- def find_index(&block)
64
- each_with_index do |item, index|
65
- if yield(item)
66
- return index
67
- end
68
- end
69
-
70
- return nil
71
- end
72
-
73
- def split_at(&block)
74
- index = find_index(&block)
75
-
76
- if index
77
- return [self[0...index], self[index], self[index+1..-1]]
78
- end
79
-
80
- return [[], nil, []]
81
- end
82
- end
83
-
84
- if defined? Rack
85
- class Rack::Request
86
- def self.new(*args)
87
- super(*args)
88
- end
89
- end
90
- end