sinatra-hat 0.0.4
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.
- data/MIT-LICENSE +20 -0
- data/README.markdown +27 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/lib/gettext/haml.rb +36 -0
- data/lib/gettext/haml_parser.rb +64 -0
- data/lib/gettext/ruby19_fix.rb +20 -0
- data/lib/rack/fastcgi_fix.rb +14 -0
- data/lib/rack/gettext_reloader.rb +63 -0
- data/lib/sequel/utf8_fix.rb +15 -0
- data/lib/sinatra-hat.rb +153 -0
- data/lib/sinatra/reloader.rb +11 -0
- data/lib/sinatra/template_cache.rb +27 -0
- data/test/sinatra-hat_test.rb +6 -0
- data/test/test_helper.rb +9 -0
- metadata +82 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Adam Strzelecki
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Sinatra Hat
|
2
|
+
===========
|
3
|
+
This is a set of extensions for *Sinatra* and relative gems such as *Sequel*, *Haml*, *GetText*.
|
4
|
+
|
5
|
+
It adds following functions to your *Sinatra* project:
|
6
|
+
|
7
|
+
- Automatic translation using *GetText* or *Fast_Gettext* of *Haml* templates, and parser for `po` file generation
|
8
|
+
- Several fixes for *Sequel*, *Rack*
|
9
|
+
- Rack reloader for *Sinatra* and *GetText* translations
|
10
|
+
- String permalinks and date extensions
|
11
|
+
|
12
|
+
Setup
|
13
|
+
=====
|
14
|
+
### 1. Install
|
15
|
+
sudo gem install nanoant-sinatra-hat -s http://gems.github.com/
|
16
|
+
|
17
|
+
Or from source:
|
18
|
+
|
19
|
+
git clone git://github.com/nanoant/sinatra-hat.git
|
20
|
+
cd sinatra-hat && rake install
|
21
|
+
|
22
|
+
Author
|
23
|
+
======
|
24
|
+
[Adam Strzelecki](http://www.nanoant.com/)
|
25
|
+
ono@java.pl
|
26
|
+
|
27
|
+
Released under MIT license, see `MIT-LICENSE` for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "sinatra-hat"
|
8
|
+
gem.description = "Sinatra Ruby gem extensions for gettext, caching, reloading, etc."
|
9
|
+
gem.summary = "Sinatra Ruby gem extensions for gettext, caching, reloading, etc."
|
10
|
+
gem.email = "ono@java.pl"
|
11
|
+
gem.homepage = "http://github.com/nanoant/sinatra-hat"
|
12
|
+
gem.authors = ["Adam Strzelecki"]
|
13
|
+
gem.files = FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/*_test.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
if File.exist?('VERSION.yml')
|
47
|
+
config = YAML.load(File.read('VERSION.yml'))
|
48
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
49
|
+
else
|
50
|
+
version = ""
|
51
|
+
end
|
52
|
+
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
54
|
+
rdoc.title = "sinatra-hat #{version}"
|
55
|
+
rdoc.rdoc_files.include('README*')
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
+
end
|
58
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.4
|
data/lib/gettext/haml.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Haml gettext module providing gettext translation for all Haml plain text
|
2
|
+
# calls
|
3
|
+
# http://pastie.org/445295
|
4
|
+
|
5
|
+
class Haml::Engine
|
6
|
+
# Inject _ gettext into plain text and tag plain text calls
|
7
|
+
def push_plain(text, options = {})
|
8
|
+
super(_(text), options)
|
9
|
+
end
|
10
|
+
def parse_tag(line)
|
11
|
+
tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
12
|
+
nuke_inner_whitespace, action, value, last_line = super(line)
|
13
|
+
value = _(value) unless action && action != '!' || action == '!' && value[0..0] == '=' || value.empty?
|
14
|
+
# translate inline ruby code too
|
15
|
+
value.gsub!(/_\('([^']+)'\)/) {|m| '\''+_($1)+'\''} unless action != '=' || value.empty?
|
16
|
+
attributes_hashes.each{|h| h.each{|v| v.gsub!(/_\('([^']+)'\)/){|m| '\''+_($1)+'\''} if v.is_a? String} unless h.nil? || h.empty?} unless attributes_hashes.nil? || attributes_hashes.empty?
|
17
|
+
[tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
18
|
+
nuke_inner_whitespace, action, value, last_line]
|
19
|
+
end
|
20
|
+
def push_flat(line)
|
21
|
+
return super(line) if @gettext_filters.nil? || !@gettext_filters.last
|
22
|
+
text = line.full.dup
|
23
|
+
text = "" unless text.gsub!(/^#{@flat_spaces}/, '')
|
24
|
+
text = _(text) if text != ''
|
25
|
+
@filter_buffer << "#{text}\n"
|
26
|
+
end
|
27
|
+
def start_filtered(name)
|
28
|
+
@gettext_filters ||= []
|
29
|
+
@gettext_filters.push( (name == 'markdown') )
|
30
|
+
super
|
31
|
+
end
|
32
|
+
def close_filtered(filter)
|
33
|
+
@gettext_filters.pop
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Haml gettext parser module
|
2
|
+
# http://pastie.org/445297
|
3
|
+
|
4
|
+
require 'gettext/tools/rgettext'
|
5
|
+
require 'gettext/tools/parser/ruby'
|
6
|
+
require 'haml'
|
7
|
+
|
8
|
+
class String
|
9
|
+
def escape_single_quotes
|
10
|
+
self.gsub(/'/, "\\\\'")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Haml::Engine
|
15
|
+
# Overriden function that parses Haml tags
|
16
|
+
# Injects gettext call for plain text action.
|
17
|
+
def parse_tag(line)
|
18
|
+
tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
19
|
+
nuke_inner_whitespace, action, value, last_line = super(line)
|
20
|
+
@precompiled << "_('#{value.escape_single_quotes}')\n" unless action && action != '!' || action == '!' && value[0..0] == '=' || value.empty?
|
21
|
+
[tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace,
|
22
|
+
nuke_inner_whitespace, action, value, last_line]
|
23
|
+
end
|
24
|
+
# Overriden function that producted Haml plain text
|
25
|
+
# Injects gettext call for plain text action.
|
26
|
+
def push_plain(text, options = {})
|
27
|
+
@precompiled << "_('#{text.escape_single_quotes}')\n"
|
28
|
+
end
|
29
|
+
def push_flat(line)
|
30
|
+
return super(line) if @gettext_filters.nil? || !@gettext_filters.last
|
31
|
+
text = line.unstripped
|
32
|
+
return if text == ''
|
33
|
+
@precompiled << "_('#{text.escape_single_quotes}')\n"
|
34
|
+
end
|
35
|
+
def start_filtered(name)
|
36
|
+
@gettext_filters ||= []
|
37
|
+
@gettext_filters.push( (name == 'markdown') )
|
38
|
+
super
|
39
|
+
end
|
40
|
+
def close_filtered(filter)
|
41
|
+
@gettext_filters.pop
|
42
|
+
super
|
43
|
+
end
|
44
|
+
def flush_merged_text
|
45
|
+
# We override this method, becuase code generated here confuses GetText's Ruby parser
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Haml gettext parser
|
50
|
+
module HamlParser
|
51
|
+
module_function
|
52
|
+
|
53
|
+
def target?(file)
|
54
|
+
File.extname(file) == ".haml"
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse(file, ary = [])
|
58
|
+
haml = Haml::Engine.new(IO.readlines(file).join)
|
59
|
+
code = haml.precompiled.split(/$/)
|
60
|
+
GetText::RubyParser.parse_lines(file, code, ary)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
GetText::RGetText.add_parser(HamlParser)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Temporarily fixes gettext error:
|
2
|
+
# lib/gettext/locale_path.rb:77:in `%': key not found (KeyError)
|
3
|
+
|
4
|
+
if RUBY_VERSION >= "1.9.0"
|
5
|
+
|
6
|
+
module GetText
|
7
|
+
class LocalePath
|
8
|
+
def initialize(name, topdir = nil)
|
9
|
+
@name = name
|
10
|
+
if topdir
|
11
|
+
@locale_paths = ["#{topdir}/%{lang}/LC_MESSAGES/%{name}.mo", "#{topdir}/%{lang}/%{name}.mo"]
|
12
|
+
else
|
13
|
+
@locale_paths = self.class.default_path_rules
|
14
|
+
end
|
15
|
+
@locale_paths.map! {|v| v % {:name => name, :lang => '%{lang}'} }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# PATH_INFO and QUERY_STRING may not be defined when using lighttpd with server.error-handler-404 trick
|
2
|
+
class Rack::Handler::FastCGI
|
3
|
+
class <<self
|
4
|
+
alias rack_serve serve
|
5
|
+
def serve(request, app)
|
6
|
+
env = request.env
|
7
|
+
parts = env['REQUEST_URI'].to_s.split('?')
|
8
|
+
env['SCRIPT_NAME'] = ''
|
9
|
+
env['PATH_INFO'] = parts[0] if env['PATH_INFO'] == ''
|
10
|
+
env['QUERY_STRING'] = parts[1..-1].join('?') if parts.length > 1 && env['QUERY_STRING'] == ''
|
11
|
+
rack_serve(request, app)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module GetText
|
2
|
+
class Reloader < ::Rack::Reloader
|
3
|
+
def initialize(app, path, cooldown=10)
|
4
|
+
@path = path
|
5
|
+
@po = Dir.glob(File.join(@path, '**', '*.po'))
|
6
|
+
@mo = Dir.glob(File.join(@path, '**', '*.mo'))
|
7
|
+
@pot = File.join(@path, 'rbigg.pot') # Used for locking
|
8
|
+
# If there are not translations, give up
|
9
|
+
cooldown = nil unless @po && @mo && @po.size > 0 && @mo.size > 0
|
10
|
+
super(app, cooldown, Stat)
|
11
|
+
end
|
12
|
+
|
13
|
+
def safe_load(file, mtime, stderr = $stderr)
|
14
|
+
@translations += 1
|
15
|
+
stderr.puts "#{self.class}: reloaded `#{FastGettext.text_domain}' translation `#{file}'"
|
16
|
+
ensure
|
17
|
+
@mtimes[file] = mtime
|
18
|
+
end
|
19
|
+
|
20
|
+
def reload!(stderr = $stderr)
|
21
|
+
@translations = 0
|
22
|
+
super
|
23
|
+
if @translations > 0
|
24
|
+
found, stat = safe_stat(@mo.first)
|
25
|
+
if found && stat
|
26
|
+
File.open(@pot, 'r') do |f|
|
27
|
+
# Ensure we don't produce translation twice
|
28
|
+
f.flock(File::LOCK_EX)
|
29
|
+
found, mstat = safe_stat(@mo.first)
|
30
|
+
if found && mstat && mstat.mtime == stat.mtime
|
31
|
+
require 'gettext/tools'
|
32
|
+
Dir.chdir @path do
|
33
|
+
GetText.create_mofiles(:po_root => '.', :mo_root => '.')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
# Reload whole translation
|
37
|
+
FastGettext.add_text_domain(FastGettext.text_domain, :path => @path)
|
38
|
+
FastGettext.current_cache = {}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module Stat
|
45
|
+
def rotation
|
46
|
+
@po.map{|file|
|
47
|
+
found, stat = safe_stat(file)
|
48
|
+
next unless found and stat and mtime = stat.mtime
|
49
|
+
@cache[file] = found
|
50
|
+
yield(found, mtime)
|
51
|
+
}.compact
|
52
|
+
end
|
53
|
+
|
54
|
+
def safe_stat(file)
|
55
|
+
return unless file
|
56
|
+
stat = ::File.stat(file)
|
57
|
+
return file, stat if stat.file?
|
58
|
+
rescue Errno::ENOENT, Errno::ENOTDIR
|
59
|
+
@cache.delete(file) and false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Temporarily fixes Sequel Ruby 1.9 error:
|
2
|
+
# Encoding::CompatibilityError - incompatible character encodings:
|
3
|
+
# UTF-8 and ASCII-8BIT
|
4
|
+
# Since all variables are returned as ASCII-8BIT
|
5
|
+
|
6
|
+
if RUBY_VERSION >= "1.9.0"
|
7
|
+
|
8
|
+
class Sequel::Model
|
9
|
+
def self.load(row)
|
10
|
+
row.values.each{|v| v.force_encoding('utf-8') if v.is_a?(String)}
|
11
|
+
super(row)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
data/lib/sinatra-hat.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'iconv'
|
3
|
+
|
4
|
+
class Integer
|
5
|
+
def minute
|
6
|
+
self * 60
|
7
|
+
end
|
8
|
+
alias minutes minute
|
9
|
+
def hour
|
10
|
+
minute * 60
|
11
|
+
end
|
12
|
+
alias hours hour
|
13
|
+
def day
|
14
|
+
hour * 24
|
15
|
+
end
|
16
|
+
alias days day
|
17
|
+
def week
|
18
|
+
day * 7
|
19
|
+
end
|
20
|
+
alias weeks week
|
21
|
+
def month
|
22
|
+
day * 30
|
23
|
+
end
|
24
|
+
alias months month
|
25
|
+
def year
|
26
|
+
day * 365
|
27
|
+
end
|
28
|
+
alias years year
|
29
|
+
def ago
|
30
|
+
Time.now - self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Time
|
35
|
+
def year_start
|
36
|
+
d = (self - (month-1).months - (day-1).days - hour.hours - min.minutes - sec)
|
37
|
+
d - (d.day-1).days - d.hour.hours - d.min.minutes - d.sec
|
38
|
+
end
|
39
|
+
def month_start
|
40
|
+
self - (day-1).days - hour.hours - min.minutes - sec
|
41
|
+
end
|
42
|
+
def week_start
|
43
|
+
self - ((wday + 6) % 7).days - hour.hours - min.minutes - sec
|
44
|
+
end
|
45
|
+
def midnight
|
46
|
+
self - hour.hours - min.minutes - sec
|
47
|
+
end
|
48
|
+
def noon
|
49
|
+
midnight + 12.hours
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class String
|
54
|
+
def mail_utf8_subject
|
55
|
+
# 4.2 http://tools.ietf.org/html/rfc2047
|
56
|
+
'=?UTF-8?Q?'+(self.chomp.gsub(/[^ !-<>-^`-~]/){|m| m.unpack('C*').map{|c| '=%02X' % c}.join}.gsub(/\s/, '_'))+'?='
|
57
|
+
end
|
58
|
+
def cdata
|
59
|
+
"<![CDATA[#{self.gsub(/\]\]>/,']]]]><![CDATA[>')}]]>"
|
60
|
+
end
|
61
|
+
def md5
|
62
|
+
hash = Digest::MD5.new
|
63
|
+
hash << self
|
64
|
+
hash.hexdigest
|
65
|
+
end
|
66
|
+
def sha1
|
67
|
+
hash = Digest::SHA1.new
|
68
|
+
hash << self
|
69
|
+
hash.hexdigest
|
70
|
+
end
|
71
|
+
# This is Pligg style password hash
|
72
|
+
def pwdhash(salt=nil)
|
73
|
+
salt = String.random_password.md5 if salt.nil?
|
74
|
+
salt = salt[0..8]
|
75
|
+
salt+(salt+self).sha1
|
76
|
+
end
|
77
|
+
def excerpt(chars=nil)
|
78
|
+
first = split(/(?:\n\r?){2,}/)[0] || ""
|
79
|
+
return first if chars.nil?
|
80
|
+
words = first.split(' ')
|
81
|
+
pos, count = words.inject([0, 0]) do |c, v|
|
82
|
+
c[1] + v.length < chars ? [c[0] + 1, c[1] + v.length] : c
|
83
|
+
end
|
84
|
+
words[0..pos].join(' ') + ((pos == words.size) ? '' : '…')
|
85
|
+
end
|
86
|
+
def utf8_length
|
87
|
+
unpack('U*').length
|
88
|
+
end
|
89
|
+
def pad(other, extra=0)
|
90
|
+
padding = other.utf8_length - utf8_length
|
91
|
+
padding = 0 if padding < 0
|
92
|
+
' ' * (padding+extra) + self
|
93
|
+
end
|
94
|
+
def self.random_password(length=9, strength=0)
|
95
|
+
vowels = 'aeuy'
|
96
|
+
consonants = 'bdghjmnpqrstvz'
|
97
|
+
consonants += 'BDGHJLMNPQRSTVWXZ' if strength & 1 != 0
|
98
|
+
vowels += 'AEUY' if strength & 2 != 0
|
99
|
+
consonants += '23456789' if strength & 4 != 0
|
100
|
+
consonants += '@#$%' if strength & 8 != 0
|
101
|
+
password = '';
|
102
|
+
alt = rand(2)
|
103
|
+
length.times do
|
104
|
+
password += consonants[rand(consonants.size - 1)].chr if alt != 0
|
105
|
+
password += vowels[rand(vowels.size - 1)].chr if alt == 0
|
106
|
+
alt = 1 - alt
|
107
|
+
end
|
108
|
+
password
|
109
|
+
end
|
110
|
+
def comma_split
|
111
|
+
CSV.parse_line(gsub(/"\s+,/,'",').gsub(/,\s+"/,',"')).collect{|t| t.strip unless t.nil?}.delete_if{|t| t.nil? || t.empty?}
|
112
|
+
end
|
113
|
+
# http://gist.github.com/93045
|
114
|
+
def to_permalink
|
115
|
+
Iconv.iconv('ascii//translit//IGNORE', 'utf-8', self).first.gsub("'", "").gsub(/[^\x00-\x7F]+/, '').gsub(/[^a-zA-Z0-9-]+/, '-').gsub(/--+/, '-').gsub(/^-/, '').gsub(/-$/, '').downcase
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class Array
|
120
|
+
def comma_join
|
121
|
+
map{|v| s = v.gsub!(/,/,',') || v.gsub!(/"/,'""'); s ? '"'+v+'"' : v}.join(', ')
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
if defined? Rack
|
126
|
+
class Rack::Request
|
127
|
+
def url(path=nil)
|
128
|
+
url = scheme + "://"
|
129
|
+
url << host
|
130
|
+
if scheme == "https" && port != 443 ||
|
131
|
+
scheme == "http" && port != 80
|
132
|
+
url << ":#{port}"
|
133
|
+
end
|
134
|
+
url << (path ? path : fullpath)
|
135
|
+
url
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def silence_warnings
|
141
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
142
|
+
yield
|
143
|
+
ensure
|
144
|
+
$VERBOSE = old_verbose
|
145
|
+
end
|
146
|
+
|
147
|
+
if RUBY_VERSION < "1.9.0"
|
148
|
+
class Symbol
|
149
|
+
def to_proc
|
150
|
+
proc { |obj, *args| obj.send(self, *args) }
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Reload scripts and reset routes on change
|
2
|
+
class Sinatra::Reloader < Rack::Reloader
|
3
|
+
def safe_load(file, mtime, stderr = $stderr)
|
4
|
+
if file == ::Sinatra::Application.app_file
|
5
|
+
::Sinatra::Application.reset!
|
6
|
+
::Sinatra::Application.clear_cache! if ::Sinatra::Application.respond_to? :clear_cache!
|
7
|
+
stderr.puts "#{self.class}: reseting routes and cache"
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Sinatra 0.9.x Haml template cache module
|
2
|
+
|
3
|
+
# Caches Haml templates in Class instance "render_haml_#{template}" methods,
|
4
|
+
# avoiding reparsing and recompiling of the template on every page reload.
|
5
|
+
|
6
|
+
class Sinatra::Base
|
7
|
+
# Override function responsible for calling internal Haml rendering routines
|
8
|
+
def haml(template, options={}, locals={})
|
9
|
+
method = "render_haml_#{template}".to_sym
|
10
|
+
return super(template, options, locals) unless self.respond_to? method
|
11
|
+
locals = options.delete(:locals) || locals || {}
|
12
|
+
if options[:layout] != false
|
13
|
+
__send__(:render_haml_layout, locals) { __send__(method, locals) }
|
14
|
+
else
|
15
|
+
__send__(method, locals)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def render_haml(template, data, options, locals, &block)
|
19
|
+
method = "render_haml_#{template}".to_sym
|
20
|
+
::Haml::Engine.new(data, options).def_method(self.class, method, *(locals.keys))
|
21
|
+
__send__(method, locals, &block)
|
22
|
+
end
|
23
|
+
def self.clear_cache!
|
24
|
+
instance_methods.grep(/^render_haml_/).each{|m| remove_method m}
|
25
|
+
end
|
26
|
+
def clear_cache!; self.class.clear_cache! end
|
27
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-hat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Adam Strzelecki
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-21 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Sinatra Ruby gem extensions for gettext, caching, reloading, etc.
|
23
|
+
email: ono@java.pl
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README.markdown
|
30
|
+
files:
|
31
|
+
- MIT-LICENSE
|
32
|
+
- README.markdown
|
33
|
+
- Rakefile
|
34
|
+
- VERSION
|
35
|
+
- lib/gettext/haml.rb
|
36
|
+
- lib/gettext/haml_parser.rb
|
37
|
+
- lib/gettext/ruby19_fix.rb
|
38
|
+
- lib/rack/fastcgi_fix.rb
|
39
|
+
- lib/rack/gettext_reloader.rb
|
40
|
+
- lib/sequel/utf8_fix.rb
|
41
|
+
- lib/sinatra-hat.rb
|
42
|
+
- lib/sinatra/reloader.rb
|
43
|
+
- lib/sinatra/template_cache.rb
|
44
|
+
- test/sinatra-hat_test.rb
|
45
|
+
- test/test_helper.rb
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://github.com/nanoant/sinatra-hat
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.5.2
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Sinatra Ruby gem extensions for gettext, caching, reloading, etc.
|
80
|
+
test_files:
|
81
|
+
- test/sinatra-hat_test.rb
|
82
|
+
- test/test_helper.rb
|