lotus-helpers 0.0.0 → 0.1.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.
- checksums.yaml +4 -4
- data/{LICENSE.txt → LICENSE.md} +0 -0
- data/README.md +198 -6
- data/lib/lotus/helpers.rb +22 -2
- data/lib/lotus/helpers/escape_helper.rb +271 -0
- data/lib/lotus/helpers/html_helper.rb +192 -0
- data/lib/lotus/helpers/html_helper/empty_html_node.rb +59 -0
- data/lib/lotus/helpers/html_helper/html_builder.rb +296 -0
- data/lib/lotus/helpers/html_helper/html_node.rb +69 -0
- data/lib/lotus/helpers/routing_helper.rb +52 -0
- data/lib/lotus/helpers/version.rb +4 -1
- data/lotus-helpers.gemspec +14 -10
- metadata +46 -13
- data/.gitignore +0 -22
- data/Gemfile +0 -4
- data/Rakefile +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97a8fa23a2691afc98472ad1155025367148d2ca
|
4
|
+
data.tar.gz: 731d5dca8b9da7d4177ca6e8f51c260e88055f53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7298684737de0d27f28beaf7d1ba969ee37f0cc7de543c0e81d6063d2b915bf39a12e1794ad7d479956ba6c8854d49b439b4c4cab614ae1e1f959de5fca11c61
|
7
|
+
data.tar.gz: 142c218a581680c85c7d6f207988d787436d85467fdacfd9a0a7d54a29c74d3adb77960fabb5a1f0a18d030f25f26e4bbe2058dda57b184276a89877fc5dca48
|
data/{LICENSE.txt → LICENSE.md}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -1,29 +1,221 @@
|
|
1
1
|
# Lotus::Helpers
|
2
2
|
|
3
|
-
|
3
|
+
View helpers for Ruby applications
|
4
|
+
|
5
|
+
## Status
|
6
|
+
|
7
|
+
[](https://badge.fury.io/rb/lotus-helpers)
|
8
|
+
[](https://travis-ci.org/lotus/helpers?branch=master)
|
9
|
+
[](https://coveralls.io/r/lotus/helpers)
|
10
|
+
[](https://codeclimate.com/github/lotus/helpers)
|
11
|
+
[](https://gemnasium.com/lotus/helpers)
|
12
|
+
[](http://inch-ci.org/github/lotus/helpers)
|
13
|
+
|
14
|
+
## Contact
|
15
|
+
|
16
|
+
* Home page: http://lotusrb.org
|
17
|
+
* Mailing List: http://lotusrb.org/mailing-list
|
18
|
+
* API Doc: http://rdoc.info/gems/lotus-helpers
|
19
|
+
* Bugs/Issues: https://github.com/lotus/helpers/issues
|
20
|
+
* Support: http://stackoverflow.com/questions/tagged/lotus-ruby
|
21
|
+
* Chat: https://gitter.im/lotus/chat
|
22
|
+
|
23
|
+
## Rubies
|
24
|
+
|
25
|
+
__Lotus::Helpers__ supports Ruby (MRI) 2+ and JRuby 1.7 (with 2.0 mode).
|
4
26
|
|
5
27
|
## Installation
|
6
28
|
|
7
29
|
Add this line to your application's Gemfile:
|
8
30
|
|
9
|
-
|
31
|
+
```ruby
|
32
|
+
gem 'lotus-helpers'
|
33
|
+
```
|
10
34
|
|
11
35
|
And then execute:
|
12
36
|
|
13
|
-
|
37
|
+
```shell
|
38
|
+
$ bundle
|
39
|
+
```
|
14
40
|
|
15
41
|
Or install it yourself as:
|
16
42
|
|
17
|
-
|
43
|
+
```shell
|
44
|
+
$ gem install lotus-helpers
|
45
|
+
```
|
18
46
|
|
19
47
|
## Usage
|
20
48
|
|
21
|
-
|
49
|
+
`Lotus::Helpers` offers a set of utilities to enrich web views.
|
50
|
+
|
51
|
+
### HTML helper
|
52
|
+
|
53
|
+
HTML5 markup generator (`#html`).
|
54
|
+
|
55
|
+
View:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
module Users
|
59
|
+
class Show
|
60
|
+
include Lotus::Helpers
|
61
|
+
|
62
|
+
def sidebar
|
63
|
+
html.aside(id: 'sidebar') do
|
64
|
+
p "Languages", class: 'title'
|
65
|
+
|
66
|
+
ul do
|
67
|
+
li "Italian"
|
68
|
+
li "English"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
Template:
|
77
|
+
|
78
|
+
```erb
|
79
|
+
<%= sidebar %>
|
80
|
+
```
|
81
|
+
|
82
|
+
Output:
|
83
|
+
|
84
|
+
```html
|
85
|
+
<aside id="sidebar">
|
86
|
+
<p class="title">Languages</p>
|
87
|
+
|
88
|
+
<ul>
|
89
|
+
<li>Italian</li>
|
90
|
+
<li>English</li>
|
91
|
+
</ul>
|
92
|
+
</aside>
|
93
|
+
```
|
94
|
+
|
95
|
+
### Escape helper
|
96
|
+
|
97
|
+
HTML (`#h`), HTML attribute (`#ha`) and URL (`#hu`) escape helpers.
|
98
|
+
|
99
|
+
View:
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
module Users
|
103
|
+
class Show
|
104
|
+
include Lotus::Helpers
|
105
|
+
|
106
|
+
def home_page_link
|
107
|
+
%(<a href="#{ hu(user.home_page_url) }" title="#{ ha(user.name} }'s website">#{ h(user.website_name) }</a>)
|
108
|
+
end
|
109
|
+
|
110
|
+
def code_snippet
|
111
|
+
raw user.code_snippet
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
117
|
+
Template:
|
118
|
+
|
119
|
+
```erb
|
120
|
+
<%= home_page_link %>
|
121
|
+
<%= code_snippet %>
|
122
|
+
```
|
123
|
+
|
124
|
+
Output:
|
125
|
+
|
126
|
+
```html
|
127
|
+
<a href="https://example.org" title="Maria's website">My Blog</a>
|
128
|
+
<code>puts "Hello, World!"</code>
|
129
|
+
```
|
130
|
+
|
131
|
+
### Routing helper
|
132
|
+
|
133
|
+
Lotus and Lotus::Router integration (`#routes`).
|
134
|
+
|
135
|
+
View:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
module Home
|
139
|
+
class Index
|
140
|
+
include Lotus::Helpers
|
141
|
+
|
142
|
+
def link_to_home
|
143
|
+
%(<a href="#{ routes.home_path }">Home</a>)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
Template:
|
150
|
+
|
151
|
+
```erb
|
152
|
+
<%= link_to_home %>
|
153
|
+
```
|
154
|
+
|
155
|
+
Output:
|
156
|
+
|
157
|
+
```html
|
158
|
+
<a href="/">Home</a>
|
159
|
+
```
|
160
|
+
|
161
|
+
## Philosophy
|
162
|
+
|
163
|
+
All the Lotus helpers are modules to include.
|
164
|
+
|
165
|
+
Most of the time they inject **private** methods.
|
166
|
+
This restriction prevents helper methods to be used on the outside (eg. in a template).
|
167
|
+
|
168
|
+
We want to encourage developers to use **meaningful** and **simple APIs** in their templates.
|
169
|
+
|
170
|
+
### Bad style example
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
module Users
|
174
|
+
class Show
|
175
|
+
include Lotus::Helpers
|
176
|
+
end
|
177
|
+
end
|
178
|
+
```
|
179
|
+
|
180
|
+
```erb
|
181
|
+
<%= format_number user.followers_count %>
|
182
|
+
```
|
183
|
+
|
184
|
+
This style increases the complexity of the template and it makes testing hard.
|
185
|
+
|
186
|
+
### Good style example
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
module Users
|
190
|
+
class Show
|
191
|
+
include Lotus::Helpers
|
192
|
+
|
193
|
+
def followers_count
|
194
|
+
format_number user.followers_count
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
```
|
199
|
+
|
200
|
+
```erb
|
201
|
+
<%= followers_count %>
|
202
|
+
```
|
203
|
+
|
204
|
+
This simplifies the markup.
|
205
|
+
In order to test the value that will be printed becomes easier: `Users::Show#followers_count`.
|
206
|
+
|
207
|
+
## Versioning
|
208
|
+
|
209
|
+
__Lotus::Helpers__ uses [Semantic Versioning 2.0.0](http://semver.org)
|
22
210
|
|
23
211
|
## Contributing
|
24
212
|
|
25
|
-
1. Fork it ( https://github.com/
|
213
|
+
1. Fork it ( https://github.com/lotus/helpers/fork )
|
26
214
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
215
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
216
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
217
|
5. Create a new Pull Request
|
218
|
+
|
219
|
+
## Copyright
|
220
|
+
|
221
|
+
Copyright © 2014-2015 Luca Guidi – Released under MIT License
|
data/lib/lotus/helpers.rb
CHANGED
@@ -1,7 +1,27 @@
|
|
1
|
-
require
|
1
|
+
require 'lotus/helpers/version'
|
2
|
+
require 'lotus/helpers/html_helper'
|
3
|
+
require 'lotus/helpers/escape_helper'
|
4
|
+
require 'lotus/helpers/routing_helper'
|
2
5
|
|
3
6
|
module Lotus
|
7
|
+
# View helpers for Ruby applications
|
8
|
+
#
|
9
|
+
# @since 0.1.0
|
4
10
|
module Helpers
|
5
|
-
#
|
11
|
+
# Override for Module.included
|
12
|
+
#
|
13
|
+
# It injects all the available helpers.
|
14
|
+
#
|
15
|
+
# @since 0.1.0
|
16
|
+
# @api private
|
17
|
+
#
|
18
|
+
# @see http://www.ruby-doc.org/core/Module.html#method-i-included
|
19
|
+
def self.included(base)
|
20
|
+
base.class_eval do
|
21
|
+
include Lotus::Helpers::HtmlHelper
|
22
|
+
include Lotus::Helpers::EscapeHelper
|
23
|
+
include Lotus::Helpers::RoutingHelper
|
24
|
+
end
|
25
|
+
end
|
6
26
|
end
|
7
27
|
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
require 'lotus/utils/escape'
|
2
|
+
|
3
|
+
module Lotus
|
4
|
+
module Helpers
|
5
|
+
# Escape helpers
|
6
|
+
#
|
7
|
+
# You can include this module inside your view and
|
8
|
+
# the view will have access all methods.
|
9
|
+
#
|
10
|
+
# By including <tt>Lotus::Helpers::EscapeHelper</tt> it will inject private
|
11
|
+
# methods as markup escape utilities.
|
12
|
+
#
|
13
|
+
# @since 0.1.0
|
14
|
+
module EscapeHelper
|
15
|
+
private
|
16
|
+
# Escape the given HTML tag content.
|
17
|
+
#
|
18
|
+
# This should be used only for untrusted contents: user input.
|
19
|
+
#
|
20
|
+
# This should be used only for tag contents.
|
21
|
+
# To escape tag attributes please use <tt>Lotus::Helpers::EscapeHelper#escape_html_attribute</tt>.
|
22
|
+
#
|
23
|
+
# @param input [String] the input
|
24
|
+
#
|
25
|
+
# @return [String] the escaped string
|
26
|
+
#
|
27
|
+
# @since 0.1.0
|
28
|
+
#
|
29
|
+
# @see Lotus::Helpers::EscapeHelper#escape_html_attribute
|
30
|
+
#
|
31
|
+
# @example Basic usage
|
32
|
+
# require 'lotus/helpers/escape_helper'
|
33
|
+
#
|
34
|
+
# class MyView
|
35
|
+
# include Lotus::Helpers::EscapeHelper
|
36
|
+
#
|
37
|
+
# def good_content
|
38
|
+
# h "hello"
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# def evil_content
|
42
|
+
# h "<script>alert('xss')</script>"
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# view = MyView.new
|
47
|
+
#
|
48
|
+
# view.good_content
|
49
|
+
# # => "hello"
|
50
|
+
#
|
51
|
+
# view.evil_content
|
52
|
+
# # => "<script>alert('xss')</script>"
|
53
|
+
#
|
54
|
+
# @example With HTML builder
|
55
|
+
# #
|
56
|
+
# # CONTENTS ARE AUTOMATICALLY ESCAPED
|
57
|
+
# #
|
58
|
+
# require 'lotus/helpers'
|
59
|
+
#
|
60
|
+
# class MyView
|
61
|
+
# include Lotus::Helpers
|
62
|
+
#
|
63
|
+
# def evil_content
|
64
|
+
# html.div do
|
65
|
+
# "<script>alert('xss')</script>"
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# view = MyView.new
|
71
|
+
# view.evil_content
|
72
|
+
# # => "<div>\n<script>alert('xss')</script></div>"
|
73
|
+
def escape_html(input)
|
74
|
+
Utils::Escape.html(input)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @since 0.1.0
|
78
|
+
alias_method :h, :escape_html
|
79
|
+
|
80
|
+
# Escape the given HTML tag attribute.
|
81
|
+
#
|
82
|
+
# This MUST be used for escaping HTML tag attributes.
|
83
|
+
#
|
84
|
+
# This should be used only for untrusted contents: user input.
|
85
|
+
#
|
86
|
+
# This can also be used to escape tag contents, but it's slower.
|
87
|
+
# For this purpose use <tt>Lotus::Helpers::EscapeHelper#escape_html</tt>.
|
88
|
+
#
|
89
|
+
# @param input [String] the input
|
90
|
+
#
|
91
|
+
# @return [String] the escaped string
|
92
|
+
#
|
93
|
+
# @since 0.1.0
|
94
|
+
#
|
95
|
+
# @see Lotus::Helpers::EscapeHelper#escape_html
|
96
|
+
#
|
97
|
+
# @example Basic usage
|
98
|
+
# require 'lotus/helpers/escape_helper'
|
99
|
+
#
|
100
|
+
# class MyView
|
101
|
+
# include Lotus::Helpers::EscapeHelper
|
102
|
+
#
|
103
|
+
# def good_attribute
|
104
|
+
# attribute = "small"
|
105
|
+
#
|
106
|
+
# %(<span class="#{ ha(attribute) }">hello</span>
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# def evil_attribute
|
110
|
+
# attribute = %(" onclick="javascript:alert('xss')" id=")
|
111
|
+
#
|
112
|
+
# %(<span class="#{ ha(attribute) }">hello</span>
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# view = MyView.new
|
117
|
+
#
|
118
|
+
# view.good_attribute
|
119
|
+
# # => %(<span class="small">hello</span>)
|
120
|
+
#
|
121
|
+
# view.evil_attribute
|
122
|
+
# # => %(<span class="" onclick="javascript:alert('xss')" id="">hello</span>
|
123
|
+
#
|
124
|
+
# @example With HTML builder
|
125
|
+
# #
|
126
|
+
# # ATTRIBUTES AREN'T AUTOMATICALLY ESCAPED
|
127
|
+
# #
|
128
|
+
# require 'lotus/helpers'
|
129
|
+
#
|
130
|
+
# class MyView
|
131
|
+
# include Lotus::Helpers
|
132
|
+
#
|
133
|
+
# def evil_attribute
|
134
|
+
# user_input_attribute = %(" onclick="javascript:alert('xss')" id=")
|
135
|
+
#
|
136
|
+
# html.span id: 'greet', class: ha(user_input_attribute) do
|
137
|
+
# "hello"
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# view = MyView.new
|
143
|
+
# view.evil_attribute
|
144
|
+
# # => %(<span class="" onclick="javascript:alert('xss')" id="">hello</span>
|
145
|
+
def escape_html_attribute(input)
|
146
|
+
Utils::Escape.html_attribute(input)
|
147
|
+
end
|
148
|
+
|
149
|
+
# @since 0.1.0
|
150
|
+
alias_method :ha, :escape_html_attribute
|
151
|
+
|
152
|
+
# Escape an URL to be used in HTML attributes
|
153
|
+
#
|
154
|
+
# This allows only URLs with whitelisted schemes to pass the filter.
|
155
|
+
# Everything else is stripped.
|
156
|
+
#
|
157
|
+
# Default schemes are:
|
158
|
+
#
|
159
|
+
# * http
|
160
|
+
# * https
|
161
|
+
# * mailto
|
162
|
+
#
|
163
|
+
# If you want to allow a different set of schemes, you should pass it as
|
164
|
+
# second argument.
|
165
|
+
#
|
166
|
+
# This should be used only for untrusted contents: user input.
|
167
|
+
#
|
168
|
+
# @param input [String] the input
|
169
|
+
# @param schemes [Array<String>] an optional array of whitelisted schemes
|
170
|
+
#
|
171
|
+
# @return [String] the escaped string
|
172
|
+
#
|
173
|
+
# @since 0.1.0
|
174
|
+
#
|
175
|
+
# @see Lotus::Utils::Escape.url
|
176
|
+
# @see Lotus::Utils::Escape::DEFAULT_URL_SCHEMES
|
177
|
+
#
|
178
|
+
# @example Basic usage
|
179
|
+
# require 'lotus/helpers/escape_helper'
|
180
|
+
#
|
181
|
+
# class MyView
|
182
|
+
# include Lotus::Helpers::EscapeHelper
|
183
|
+
#
|
184
|
+
# def good_url
|
185
|
+
# url = "http://lotusrb.org"
|
186
|
+
#
|
187
|
+
# %(<a href="#{ hu(url) }">Lotus</a>
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
# def evil_url
|
191
|
+
# url = "javascript:alert('xss')"
|
192
|
+
#
|
193
|
+
# %(<a href="#{ hu(url) }">Evil</a>
|
194
|
+
# end
|
195
|
+
# end
|
196
|
+
#
|
197
|
+
# view = MyView.new
|
198
|
+
#
|
199
|
+
# view.good_url
|
200
|
+
# # => %(<a href="http://lotusrb.org">Lotus</a>)
|
201
|
+
#
|
202
|
+
# view.evil_url
|
203
|
+
# # => %(<a href="">Evil</a>)
|
204
|
+
#
|
205
|
+
# @example Custom schemes
|
206
|
+
# require 'lotus/helpers/escape_helper'
|
207
|
+
#
|
208
|
+
# class MyView
|
209
|
+
# include Lotus::Helpers::EscapeHelper
|
210
|
+
#
|
211
|
+
# def ftp_link
|
212
|
+
# schemes = ['ftp', 'ftps']
|
213
|
+
# url = 'ftps://ftp.example.org'
|
214
|
+
#
|
215
|
+
# %(<a href="#{ hu(url, schemes) }">FTP</a>
|
216
|
+
# end
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
# view = MyView.new
|
220
|
+
#
|
221
|
+
# view.ftp_link
|
222
|
+
# # => %(<a href="ftps://ftp.example.org">FTP</a>)
|
223
|
+
def escape_url(input, schemes = Utils::Escape::DEFAULT_URL_SCHEMES)
|
224
|
+
Utils::Escape.url(input, schemes)
|
225
|
+
end
|
226
|
+
|
227
|
+
# @since 0.1.0
|
228
|
+
alias_method :hu, :escape_url
|
229
|
+
|
230
|
+
# Bypass escape.
|
231
|
+
#
|
232
|
+
# Please notice that this can be really dangerous.
|
233
|
+
# Use at your own peril.
|
234
|
+
#
|
235
|
+
# @param input [String] the input
|
236
|
+
#
|
237
|
+
# @return [Lotus::Utils::Escape::SafeString] the string marked as safe string
|
238
|
+
#
|
239
|
+
# @since 0.1.0
|
240
|
+
#
|
241
|
+
# @example
|
242
|
+
# require 'lotus/helpers/escape_helper'
|
243
|
+
#
|
244
|
+
# class MyView
|
245
|
+
# include Lotus::Helpers::EscapeHelper
|
246
|
+
#
|
247
|
+
# def good_content
|
248
|
+
# raw "<p>hello</p>"
|
249
|
+
# end
|
250
|
+
#
|
251
|
+
# def evil_content
|
252
|
+
# raw "<script>alert('xss')</script>"
|
253
|
+
# end
|
254
|
+
# end
|
255
|
+
#
|
256
|
+
# view = MyView.new
|
257
|
+
#
|
258
|
+
# view.good_content
|
259
|
+
# # => "<p>hello</p>"
|
260
|
+
#
|
261
|
+
# #
|
262
|
+
# # !!! WE HAVE OPENED OUR APPLICATION TO AN XSS ATTACK !!!
|
263
|
+
# #
|
264
|
+
# view.evil_content
|
265
|
+
# # => "<script>alert('xss')</script>"
|
266
|
+
def raw(input)
|
267
|
+
Utils::Escape::SafeString.new(input)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|