el 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+
2
+ ## Cache Manager
3
+
4
+ Allows to cache the result of an arbitrary block and use the result on consequent requests.
5
+
6
+ *Note: Value is not stored if block returns false or nil.*
7
+
8
+ Cache can be cleared by calling `clear_cache!` method.
9
+
10
+ If called without params, all cache will be cleared.
11
+
12
+ To clear only specific blocks, pass their IDs as params.
13
+
14
+ **Example:**
15
+
16
+ ```ruby
17
+ class App < E
18
+
19
+ def index
20
+ @db_items = cache :db_items do
21
+ # fetching items
22
+ end
23
+ @banners = cache :banners do
24
+ # render banners partial
25
+ end
26
+ # ...
27
+ end
28
+
29
+ def products
30
+ cache do
31
+ # fetch and render products
32
+ end
33
+ end
34
+
35
+ after do
36
+ if 'some condition occurred'
37
+ # clearing cache only for @banners and @db_items
38
+ clear_cache! :banners, :db_items
39
+ end
40
+ if 'some another condition occurred'
41
+ # clearing all cache
42
+ clear_cache!
43
+ end
44
+ end
45
+ end
46
+ ```
47
+
48
+
49
+ By default, the cache will be kept in memory.<br>
50
+ If you want to use a different pool, set it by using `cache_pool` at app level.
51
+
52
+ Just make sure your pool behaves like a Hash,
53
+ Meant it should respond to `[]=`, `[]`, `delete` and `clear`.
54
+
55
+
56
+ ```ruby
57
+ # controllers...
58
+
59
+ app = E.new do
60
+ cache_pool SomePool
61
+ mount Something
62
+ end
63
+ app.run
64
+ ```
65
+
66
+ **[ [contents &uarr;](https://github.com/espresso/espresso-lungo#use) ]**
@@ -0,0 +1,64 @@
1
+
2
+ ## content_for
3
+
4
+ Allow to capture content and then render it into a different place:
5
+
6
+ ```ruby
7
+ content_for :assets do
8
+ js_tag :jquery
9
+ end
10
+
11
+ # later in views
12
+ yield_content :assets
13
+ #=> '<script src="jquery.js" type="text/javascript"></script>'
14
+ ```
15
+
16
+ Use `content_for?` to check whether content block exists for some key:
17
+
18
+ ```ruby
19
+ p content_for?(:assets)
20
+ #=> #<Proc:0x00...
21
+
22
+ p content_for?(:blah)
23
+ #=> nil
24
+ ```
25
+
26
+ It is also possible to pass any variables into content block:
27
+
28
+ ```ruby
29
+ content_for :account do |name, email|
30
+ form_tag! do
31
+ input_tag(value: name) +
32
+ input_tag(value: email)
33
+ end
34
+ end
35
+
36
+ # somewhere in views
37
+ yield_content :account, :foo, 'foo@bar.com'
38
+ #=> '<form><input value="foo"><input value="foo@bar.com"></form>'
39
+ ```
40
+
41
+ Please note that content block will be executed every time you call `yield_content`.
42
+
43
+ If you are using same content block multiple times on same page please consider to assign the result to a variable and use it repeatedly to avoid performance decreasing.
44
+
45
+ **[ [contents &uarr;](https://github.com/espresso/espresso-lungo#use) ]**
46
+
47
+ ## capture_html
48
+
49
+ Execute given content block and return the result.
50
+
51
+ Useful when you need to display same snippet multiple times and want it rendered only once.
52
+
53
+ ```ruby
54
+ html = capture_html do
55
+ js_tag(:jquery) +
56
+ css_tag(:ui)
57
+ end
58
+
59
+ puts html
60
+ #=> <script src="jquery.js" type="text/javascript"></script>
61
+ #=> <link href="ui.css" media="all" type="text/css" rel="stylesheet">
62
+ ```
63
+
64
+ **[ [contents &uarr;](https://github.com/espresso/espresso-lungo#use) ]**
@@ -0,0 +1,201 @@
1
+
2
+ ## Generic Tags
3
+
4
+ `Espresso Lungo` comes with a set of useful helpers aimed at generating HTML in plain Ruby:
5
+
6
+ ```ruby
7
+ div_tag 'some text'
8
+ #=> <div>some text</div>
9
+ ```
10
+
11
+ HTML attributes can be passed via options Hash:
12
+
13
+ ```ruby
14
+ h1_tag 'Welcome!', class: 'well'
15
+ #=> <h1 class="well">Welcome!</h1>
16
+ ```
17
+
18
+ Content can be provided via block:
19
+
20
+ ```ruby
21
+ script_tag do
22
+ // some js here
23
+ end
24
+ #=> <script>
25
+ #=> // some js here
26
+ #=> </script>
27
+ ```
28
+
29
+ **Important!** Any content, provided via first argument or block, will be HTML escaped!
30
+ To emit content as is, use bang methods and MAKE SURE you do not pass any untrusted input into HTML helpers!
31
+
32
+ **Default Behavior:**
33
+
34
+ ```ruby
35
+ div_tag 'some <evil> string'
36
+ #=> <div>some &lt;evil&gt; string</div>
37
+ ```
38
+
39
+ **Bang helpers wont escape output! Use with care!**
40
+
41
+ ```ruby
42
+ div_tag! 'some <evil> string'
43
+ #=> <div>some <evil> string</div>
44
+ ```
45
+
46
+ Though bang methods are mostly dangerous, they are necessary when using nested tags:
47
+
48
+ ```ruby
49
+ div_tag! do # without bang <b> tag will be escaped
50
+ b_tag 'some <evil> string'
51
+ end
52
+ #=> <div><b>some &lt;evil&gt; string</b></div>
53
+ ```
54
+
55
+ The main concern when using nested tags is to not mix helpers with any untrusted input.
56
+
57
+ **Note:** when using multiple tags you have to concat them, otherwise only the last one will be shown:
58
+
59
+ **Wrong:**
60
+
61
+ ```ruby
62
+ form_tag! do
63
+ input_tag(name: :name)
64
+ input_tag(name: :email)
65
+ end
66
+ #=> <form><input name="email"></form>
67
+ ```
68
+
69
+ **Correct:**
70
+
71
+ ```ruby
72
+ form_tag! do
73
+ input_tag(name: :name) + # or <<
74
+ input_tag(name: :email)
75
+ end
76
+ #=> <form><input name="name"><input name="email"></form>
77
+ ```
78
+
79
+ **[ [contents &uarr;](https://github.com/espresso/espresso-lungo#use) ]**
80
+
81
+
82
+ ## link_to
83
+
84
+ `link_to` allow to build a HTML &lt;a&gt; tag.
85
+
86
+ If first param is a valid action, the URL of given action will be used.
87
+
88
+ Action accepted as a symbol or a string representing action name and format.
89
+
90
+ Action can also be passed in deRESTified form, eg. `:read` instead of `:post_read`
91
+
92
+ ```ruby
93
+ class App < E
94
+ format '.html'
95
+
96
+ def read
97
+ link_to :read #=> <a href="/app/read" ...
98
+ link_to 'read.html' #=> <a href="/app/read.html" ...
99
+ link_to 'read.xml' #=> <a href="read.xml" ... - not translated, used as is
100
+ end
101
+
102
+ def post_write
103
+ link_to :post_write #=> <a href="/app/write" ... - works but it is tedious, use :write instead
104
+ link_to :write #=> <a href="/app/write" ...
105
+ link_to 'write.html' #=> <a href="/app/write.html" ...
106
+ link_to '/something' #=> <a href="/something" ... - not translated, used as is
107
+ end
108
+ end
109
+ ```
110
+
111
+ When you need to create a link to an arbitrary controller, use `base_url`, `route` or `[]` of target controller:
112
+
113
+ ```ruby
114
+ class News < E
115
+ format '.html'
116
+
117
+ def home
118
+ # ...
119
+ end
120
+
121
+ def get_read id = nil
122
+ # ...
123
+ end
124
+
125
+ end
126
+
127
+ link_to News.base_url #=> <a href="/news" ...
128
+ link_to News[:home] #=> <a href="/news/home" ...
129
+ link_to News['home.html'] #=> <a href="/news/home.html" ...
130
+ link_to News[:get_read] #=> <a href="/news/read" ...
131
+ link_to News[:read] #=> <a href="/news/read" ...
132
+ link_to News['read.html'] #=> <a href="/news/read.html" ...
133
+
134
+ link_to News.route(:read, 100) #=> <a href="/news/read/100" ...
135
+ link_to News.route(:read, '100.html') #=> <a href="/news/read/100.html" ...
136
+ ```
137
+
138
+
139
+ If `nil` passed as first argument, a void link will be created:
140
+
141
+ ```ruby
142
+ link_to nil, 'something'
143
+ #=> <a href="javascript:void(null);>something</a>
144
+ ```
145
+
146
+ Anchor can be passed via second argument.
147
+
148
+ If it is missing, the link will be used as anchor:
149
+
150
+ ```ruby
151
+ link_to :something
152
+ #=> <a href="/something">/something</a>
153
+
154
+ link_to :foo, 'bar'
155
+ #=> <a href="/foo">bar</a>
156
+ ```
157
+
158
+ Anchor can also be passed as a block:
159
+
160
+ ```ruby
161
+ link_to(:foo) { 'bar' }
162
+ #=> <a href="/foo>bar</a>
163
+ ```
164
+
165
+
166
+ **Important!** Anchor will be HTML escaped:
167
+
168
+ ```ruby
169
+ link_to(:foo) { 'some <evil>' }
170
+ #=> <a href="/foo>some &lt;evil&gt;</a>
171
+ ```
172
+
173
+ To emit content as is, use bang method instead and make sure you do not pass any untrusted content to `link_to` helper:
174
+
175
+
176
+ ```ruby
177
+ link_to! :foo, 'some <evil>'
178
+ #=> <a href="/foo>some <evil></a>
179
+ ```
180
+
181
+ Also you'll need bang helper when you build nested tags:
182
+
183
+ ```ruby
184
+ link_to! :foo do
185
+ b_tag 'some text'
186
+ end
187
+ #=> <a href="/foo><b>some text</b></a>
188
+ ```
189
+
190
+
191
+ Attributes can be passed as a hash via last argument:
192
+
193
+ ```ruby
194
+ link_to :foo, target: '_blank'
195
+ #=> <a href="/foo" target="_blank">/foo</a>
196
+
197
+ link_to :foo, :bar, target: '_blank'
198
+ #=> <a href="/foo" target="_blank">bar</a>
199
+ ```
200
+
201
+ **[ [contents &uarr;](https://github.com/espresso/espresso-lungo#use) ]**
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+
3
+ version = '0.5.0'
4
+ Gem::Specification.new do |s|
5
+
6
+ s.name = 'el'
7
+ s.version = version
8
+ s.authors = ['Silviu Rusu']
9
+ s.email = ['slivuz@gmail.com']
10
+ s.homepage = 'https://github.com/espresso/espresso-lungo'
11
+ s.summary = 'el-%s' % version
12
+ s.description = 'Espresso Lungo - Extra Libs for Espresso Framework'
13
+
14
+ s.required_ruby_version = '>= 1.9.2'
15
+ s.add_dependency 'e', '>= 0.4.8'
16
+ s.add_dependency 'sprockets'
17
+
18
+ s.add_development_dependency 'bundler'
19
+
20
+ s.require_paths = ['lib']
21
+ s.files = Dir['**/{*,.[a-z]*}'].reject {|e| e =~ /\.(gem|lock)\Z/}
22
+ s.licenses = ['MIT']
23
+ end
@@ -0,0 +1,11 @@
1
+ require 'e'
2
+ require 'sprockets'
3
+
4
+ require 'el/constants'
5
+ require 'el/tag_factory'
6
+ require 'el/content_helpers'
7
+ require 'el/assets'
8
+ require 'el/cache'
9
+ require 'el/crud'
10
+ require 'el/ipcm'
11
+ require 'el/utils'
@@ -0,0 +1,126 @@
1
+ module EL
2
+ class AssetsMapper
3
+ include TagFactory
4
+
5
+ attr_reader :baseurl, :wd
6
+
7
+ # @example
8
+ #
9
+ # assets_mapper :vendor do
10
+ #
11
+ # js_tag :jquery
12
+ #
13
+ # chdir 'jquery-ui'
14
+ # js_tag 'js/jquery-ui.min'
15
+ # css_tag 'css/jquery-ui.min'
16
+ #
17
+ # cd '../bootstrap'
18
+ # js_tag 'js/bootstrap.min'
19
+ # css_tag 'css/bootstrap'
20
+ # end
21
+ #
22
+ # #=> <script src="/vendor/jquery.js" ...
23
+ # #=> <script src="/vendor/jquery-ui/js/jquery-ui.min.js" ...
24
+ # #=> <link href="/vendor/jquery-ui/css/jquery-ui.min.css" ...
25
+ # #=> <script src="/vendor/bootstrap/js/bootstrap.min.js" ...
26
+ # #=> <link href="/vendor/bootstrap/css/bootstrap.css" ...
27
+ #
28
+ def initialize baseurl, opts = {}, &proc
29
+ @opts = Hash[opts]
30
+ @suffix = @opts.delete(:suffix) || ''
31
+ baseurl = baseurl.to_s.dup.strip
32
+ baseurl.empty? ? baseurl = nil : (baseurl =~ /\/\Z/ || baseurl << '/')
33
+ @baseurl, @wd = baseurl.freeze, nil
34
+ proc && self.instance_exec(&proc)
35
+ end
36
+
37
+ (%w[js css] + EConstants::IMAGE_TAGS).each do |tag|
38
+ define_method tag + '_tag' do |src, attrs={}|
39
+ super src, attrs.merge(suffix: @suffix)
40
+ end
41
+ end
42
+
43
+ def chdir path = nil
44
+ return @wd = nil unless path
45
+ wd = []
46
+ if (path = path.to_s) =~ /\A\//
47
+ path = path.sub(/\A\/+/, '')
48
+ path = path.empty? ? [] : [path]
49
+ else
50
+ dirs_back, path = path.split(/\/+/).partition { |c| c == '..' }
51
+ if @wd
52
+ wd_chunks = @wd.split(/\/+/)
53
+ wd = wd_chunks[0, wd_chunks.size - dirs_back.size] || []
54
+ end
55
+ end
56
+ @wd = (wd + path << '').compact.join('/').freeze
57
+ end
58
+ alias :cd :chdir
59
+
60
+ private
61
+ def assets_url path = nil
62
+ chunks = [baseurl, wd, path] # assigning array to a variable
63
+ chunks.select! {|c| c && c.size > 0} # and work on it
64
+ File.join(*chunks) # is 2x faster than array#select {...}
65
+ end
66
+
67
+ end
68
+ end
69
+
70
+ class E
71
+ include EL::TagFactory
72
+
73
+ def assets *args, &proc
74
+ app.assets *args, &proc
75
+ end
76
+
77
+ def assets_mapper *args, &proc
78
+ EL::AssetsMapper.new *args, &proc
79
+ end
80
+
81
+ private
82
+ def assets_url path = nil
83
+ path ?
84
+ (app.assets_url ? File.join(app.assets_url, path.to_s) : path.to_s) :
85
+ (app.assets_url ? app.assets_url : '')
86
+ end
87
+
88
+ end
89
+
90
+ class EBuilder
91
+
92
+ # set the baseurl for assets.
93
+ # by default, assets URL is empty.
94
+ #
95
+ # @example assets_url not set
96
+ # script_tag 'master.js'
97
+ # => <script src="master.js"
98
+ # style_tag 'theme.css'
99
+ # => <link href="theme.css"
100
+ #
101
+ # @example assets_url set to /assets
102
+ #
103
+ # script_tag 'master.js'
104
+ # => <script src="/assets/master.js"
105
+ # style_tag 'theme.css'
106
+ # => <link href="/assets/theme.css"
107
+ #
108
+ # @note
109
+ # by default, Sprockets will be used to serve static files.
110
+ # to disable this, set second argument to false.
111
+ #
112
+ def assets_url url = nil, server = true
113
+ return @assets_url if @assets_url
114
+ url = url.to_s.dup.strip
115
+ url = url =~ /\A[\w|\d]+\:\/\//i ? url : EUtils.rootify_url(url)
116
+ @assets_url = (url =~ /\/\Z/ ? url : String.new(url) << '/').freeze
117
+ return unless server
118
+ mount_application(assets, @assets_url, on: :GET)
119
+ end
120
+ alias assets_map assets_url
121
+
122
+ def assets
123
+ @sprockets_env ||= Sprockets::Environment.new(root)
124
+ end
125
+
126
+ end