haml_coffee_assets 0.0.1 → 0.2.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.
- data/README.md +107 -42
- data/lib/haml_coffee_assets/engine.rb +12 -6
- data/lib/haml_coffee_assets/haml_coffee.rb +4 -2
- data/lib/haml_coffee_assets/haml_coffee_assets.js +41 -12
- data/lib/haml_coffee_assets/haml_coffee_template.rb +1 -1
- data/lib/haml_coffee_assets/version.rb +1 -1
- data/lib/js/haml-coffee.js +813 -269
- metadata +4 -4
data/README.md
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
-
#
|
1
|
+
# Haml Coffee Assets [](http://travis-ci.org/netzpirat/haml_coffee_assets)
|
2
2
|
|
3
|
-
|
4
|
-
pipeline.
|
3
|
+
Haml Coffee Assets compiles [Haml CoffeeScript](https://github.com/netzpirat/haml-coffee) templates in the Rails 3.1
|
4
|
+
asset pipeline, so you can use them as JavaScript templates in your JavaScript heavy Rails application.
|
5
5
|
|
6
|
-
Tested on MRI Ruby 1.8.7, 1.9.2, REE and the latest
|
6
|
+
Tested on MRI Ruby 1.8.7, 1.9.2, 1.9.3, REE and the latest version of JRuby.
|
7
7
|
|
8
|
-
|
8
|
+
**Please note that I'm using haml-coffee from my fork until
|
9
|
+
[my pull request](https://github.com/9elements/haml-coffee/pull/7) is merged.**
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
## Haml Coffee
|
12
|
+
|
13
|
+
Haml Coffee allows you to write inline [CoffeeScript](http://jashkenas.github.com/coffee-script/) in your
|
14
|
+
[HAML](http://haml-lang.com/) JavaScript templates:
|
12
15
|
|
13
16
|
```haml
|
14
17
|
#cart
|
@@ -27,7 +30,7 @@ HamlCoffee allows you to write inline [CoffeeScript](http://jashkenas.github.com
|
|
27
30
|
|
28
31
|
## Installation
|
29
32
|
|
30
|
-
The simplest way to install
|
33
|
+
The simplest way to install Haml Coffee Assets is to use [Bundler](http://gembundler.com/).
|
31
34
|
Add `haml_coffee_assets` and `execjs` to your `Gemfile`:
|
32
35
|
|
33
36
|
```ruby
|
@@ -37,15 +40,18 @@ group :assets do
|
|
37
40
|
end
|
38
41
|
```
|
39
42
|
|
40
|
-
And require the `hamlcoffee.js` in your `application.js.coffee
|
43
|
+
And require the `hamlcoffee.js` in your `app/assets/javascripts/application.js.coffee`:
|
41
44
|
|
42
45
|
```coffeescript
|
43
46
|
#= require hamlcoffee
|
44
47
|
```
|
45
48
|
|
49
|
+
This provides the default escaping and the global context functions. Read more about it in the configuration section
|
50
|
+
below.
|
51
|
+
|
46
52
|
### JavaScript runtimes
|
47
53
|
|
48
|
-
|
54
|
+
Haml Coffee Assets uses [ExecJS](https://github.com/sstephenson/execjs) to pick the best runtime to evaluate the
|
49
55
|
CoffeeScript and generate the JavaScript template.
|
50
56
|
|
51
57
|
* With CRuby you want to use a V8 JavaScript Engine or Mozilla SpiderMonkey.
|
@@ -117,77 +123,125 @@ Windows operating systems.
|
|
117
123
|
|
118
124
|
## Usage
|
119
125
|
|
120
|
-
You should place all your
|
121
|
-
your `application.js.coffee`:
|
126
|
+
You should place all your Haml Coffee templates in the `app/assets/templates` directory and include all templates from
|
127
|
+
your `app/assets/javascripts/application.js.coffee`:
|
122
128
|
|
123
129
|
```coffeescript
|
124
130
|
#= require_tree ../templates
|
125
131
|
```
|
126
132
|
|
127
|
-
Now you can start to add your
|
128
|
-
`.hamlc` extension to be recognized by
|
133
|
+
Now you can start to add your Haml Coffee templates to your template directory. Make sure all your templates have a
|
134
|
+
`.hamlc` extension to be recognized by Haml Coffee Assets.
|
129
135
|
|
130
|
-
**Note:**
|
131
|
-
processor by using `.jst.hamlc` as extension, and if you do, the
|
136
|
+
**Note:** Haml Coffee already generates a JavaScript Template, so there is not need to pass it to the `JST` Sprocket
|
137
|
+
processor by using `.jst.hamlc` as extension, and if you do, the Haml Coffee templates will not work.
|
132
138
|
|
133
139
|
## Configuration
|
134
140
|
|
141
|
+
### Document format
|
142
|
+
|
143
|
+
By default all Haml Coffee templates are rendered to a HTML5 document. You can choose between the following output
|
144
|
+
formats:
|
145
|
+
|
146
|
+
* html
|
147
|
+
* html4
|
148
|
+
* xhtml
|
149
|
+
|
150
|
+
If you prefer another HTML format than HTML5, you can set it in your `config/application.rb`:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
config.hamlcoffee.format = 'xhtml'
|
154
|
+
```
|
155
|
+
|
135
156
|
### Template namespace
|
136
157
|
|
137
|
-
By default all
|
158
|
+
By default all Haml Coffee templates are registered under the `JST` namespace.
|
138
159
|
|
139
|
-
Example
|
160
|
+
**Example:**
|
140
161
|
|
141
|
-
A template
|
162
|
+
A template `app/assets/templates/header.hamlc` with the given content:
|
142
163
|
|
143
164
|
```haml
|
144
165
|
%header
|
145
166
|
%h2= title
|
146
167
|
```
|
147
168
|
|
148
|
-
will be accessible in your browser as `JST
|
169
|
+
will be accessible in your browser as `JST['header']`. You can now render the precompiled template and pass the data
|
170
|
+
to be rendered:
|
149
171
|
|
150
172
|
```javascript
|
151
|
-
JST
|
173
|
+
JST['header'].render({ title: 'Hello Haml Coffee' })
|
152
174
|
```
|
153
175
|
|
154
|
-
If you prefer another namespace, you can set it in your `application.rb`:
|
176
|
+
If you prefer another namespace, you can set it in your `config/application.rb`:
|
155
177
|
|
156
178
|
```ruby
|
157
|
-
config.hamlcoffee.namespace = 'HAML'
|
179
|
+
config.hamlcoffee.namespace = 'window.HAML'
|
158
180
|
```
|
159
181
|
|
182
|
+
#### Template name
|
183
|
+
|
184
|
+
The name under which the template can be addressed in the namespace depends not only from the filename, but also on
|
185
|
+
the directory name.
|
186
|
+
|
187
|
+
The following examples assumes a configured namespace `window.JST` and the asset template directory
|
188
|
+
`app/assets/templates`:
|
189
|
+
|
190
|
+
* `app/assets/templates/login.hamlc` will become `JST['login']`
|
191
|
+
* `app/assets/templates/users/new.hamlc` will become `JST['users/new']`
|
192
|
+
* `app/assets/templates/shared/form/address.hamlc` will become `JST['shared/form/address']`
|
193
|
+
|
160
194
|
### Escaping
|
161
195
|
|
162
|
-
|
163
|
-
|
196
|
+
All generated output by running CoffeeScript in your template is being escaped, but you can disable escaping of either
|
197
|
+
the attributes or the generated Html.
|
198
|
+
|
199
|
+
#### Attribute escaping
|
164
200
|
|
165
|
-
You can
|
201
|
+
You can toggle attribute escaping in your `config/application.rb`:
|
166
202
|
|
167
203
|
```ruby
|
168
|
-
config.hamlcoffee.
|
204
|
+
config.hamlcoffee.escapeAttributes = false
|
169
205
|
```
|
170
206
|
|
171
|
-
|
207
|
+
#### HTML escaping
|
208
|
+
|
209
|
+
You can toggle HTML escaping in your `config/application.rb`:
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
config.hamlcoffee.escapeHtml = false
|
213
|
+
```
|
214
|
+
|
215
|
+
#### Custom escape function
|
216
|
+
|
217
|
+
By default your code block in your Haml Coffee template will be escaped through the `HAML.escape` function that is
|
218
|
+
provided in the `hamlcoffee.js` script.
|
219
|
+
|
220
|
+
You can set another escaping function in your `config/application.rb`:
|
172
221
|
|
173
222
|
```ruby
|
174
|
-
config.hamlcoffee.
|
223
|
+
config.hamlcoffee.customHtmlEscape = 'App.myEscape'
|
175
224
|
```
|
176
225
|
|
177
|
-
Your custom escape function must take the unescaped text as parameter and returns the
|
178
|
-
The following
|
226
|
+
Your custom escape function must take the unescaped text as parameter and returns the escaped text.
|
227
|
+
The following default implementation comes with `hamlcoffee.js`:
|
179
228
|
|
180
229
|
```coffeescript
|
181
|
-
App.myEscape = (text) ->
|
230
|
+
App.myEscape = (text) ->
|
231
|
+
('' + text)
|
232
|
+
.replace(/&/g, '&')
|
233
|
+
.replace(/</g, '<')
|
234
|
+
.replace(/>/g, '>')
|
235
|
+
.replace(/"/g, '"')
|
182
236
|
```
|
183
237
|
|
184
|
-
### Global
|
238
|
+
### Global context
|
185
239
|
|
186
|
-
|
240
|
+
Haml Coffee Assets allows you to configure a global context function that gets merged into the local template context for
|
187
241
|
each template.
|
188
242
|
|
189
|
-
There is a example implementation provided in the `
|
190
|
-
from
|
243
|
+
There is a example implementation provided in the `hamlcoffee.js` that can use the `extend` like functions
|
244
|
+
from the listed frameworks to merge the global and the local conext data:
|
191
245
|
|
192
246
|
* jQuery
|
193
247
|
* Underscore.js
|
@@ -195,17 +249,28 @@ from these frameworks:
|
|
195
249
|
* MooTools
|
196
250
|
* Zepto.js
|
197
251
|
|
198
|
-
If you use one of these, than you can simply override `HAML.globals` and return the global
|
252
|
+
If you use one of these, than you can simply override `HAML.globals` and return the global context data:
|
199
253
|
|
200
254
|
```coffeescript
|
201
255
|
HAML.globals = ->
|
202
256
|
{
|
203
|
-
|
257
|
+
isAuthenticated: App.isAuthenticated()
|
204
258
|
isAdmin: App.currentUser.hasRole('admin')
|
205
259
|
}
|
206
260
|
```
|
207
261
|
|
208
|
-
|
262
|
+
Now you can use the properties from the global context in every template:
|
263
|
+
|
264
|
+
```haml
|
265
|
+
.not-found-error
|
266
|
+
%h1= I18n.t('js.app.notfound.error', { route: @route })
|
267
|
+
- if @isAuthenticated
|
268
|
+
%p= I18n.t('js.app.notfound.homepage')
|
269
|
+
- else
|
270
|
+
%p= I18n.t('js.app.notfound.login')
|
271
|
+
```
|
272
|
+
|
273
|
+
If you like to use your own implementation, simply configure your context function in your `config/application.rb`:
|
209
274
|
|
210
275
|
```ruby
|
211
276
|
config.hamlcoffee.context = 'App.globalTemplateContext'
|
@@ -217,9 +282,9 @@ or disable the global context completely:
|
|
217
282
|
config.hamlcoffee.context = false
|
218
283
|
```
|
219
284
|
|
220
|
-
Your custom context function must take the local context as parameter and returns the merged context
|
221
|
-
The following example
|
222
|
-
context:
|
285
|
+
Your custom context function must take the local context as parameter and returns the merged context data.
|
286
|
+
The following example uses the _.underscore `extend` function to merge the global context data with the
|
287
|
+
passed local context data:
|
223
288
|
|
224
289
|
```coffeescript
|
225
290
|
App.globalTemplateContext = (locals) -> _.extend({}, {
|
@@ -9,9 +9,12 @@ module HamlCoffeeAssets
|
|
9
9
|
config.hamlcoffee = ActiveSupport::OrderedOptions.new
|
10
10
|
|
11
11
|
DEFAULT_CONFIG = {
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
12
|
+
:format => 'html5',
|
13
|
+
:namespace => 'window.JST',
|
14
|
+
:escapeHtml => true,
|
15
|
+
:escapeAttributes => true,
|
16
|
+
:customHtmlEscape => 'HAML.escape',
|
17
|
+
:context => 'HAML.context'
|
15
18
|
}
|
16
19
|
|
17
20
|
# Initialize Haml Coffee Assets after Sprockets
|
@@ -26,9 +29,12 @@ module HamlCoffeeAssets
|
|
26
29
|
options = DEFAULT_CONFIG.merge(app.config.hamlcoffee)
|
27
30
|
|
28
31
|
HamlCoffee.configure do |config|
|
29
|
-
config.namespace
|
30
|
-
config.
|
31
|
-
config.
|
32
|
+
config.namespace = options[:namespace]
|
33
|
+
config.format = options[:format]
|
34
|
+
config.escapeHtml = options[:escapeHtml]
|
35
|
+
config.escapeAttributes = options[:escapeAttributes]
|
36
|
+
config.customHtmlEscape = options[:customHtmlEscape]
|
37
|
+
config.context = options[:context]
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
@@ -7,7 +7,7 @@ module HamlCoffeeAssets
|
|
7
7
|
module HamlCoffee
|
8
8
|
class << self
|
9
9
|
|
10
|
-
mattr_accessor :namespace, :
|
10
|
+
mattr_accessor :namespace, :format, :escapeHtml, :escapeAttributes, :customHtmlEscape, :context
|
11
11
|
|
12
12
|
# Configure HamlCoffee
|
13
13
|
#
|
@@ -22,7 +22,9 @@ module HamlCoffeeAssets
|
|
22
22
|
# @return [String] the compiled template in JavaScript
|
23
23
|
#
|
24
24
|
def compile(name, source)
|
25
|
-
runtime.call('HamlCoffeeAssets.compile',
|
25
|
+
runtime.call('HamlCoffeeAssets.compile',
|
26
|
+
namespace, name, source, format,
|
27
|
+
escapeHtml, escapeAttributes, customHtmlEscape, context)
|
26
28
|
end
|
27
29
|
|
28
30
|
private
|
@@ -15,15 +15,25 @@ var HamlCoffeeAssets = (function(){
|
|
15
15
|
var Compiler = require('/compiler.js');
|
16
16
|
|
17
17
|
/**
|
18
|
-
* Test if the argument is present
|
18
|
+
* Test if the string argument is present
|
19
19
|
*
|
20
|
-
* @param object [
|
20
|
+
* @param object [String] the string to test
|
21
21
|
* @return [Boolean] whether the object is present
|
22
22
|
*/
|
23
|
-
function
|
23
|
+
function isStringPresent(object) {
|
24
24
|
return toString.call(object) === '[object String]' && object.length !== 0
|
25
25
|
}
|
26
26
|
|
27
|
+
/**
|
28
|
+
* Test if the boolean argument is present
|
29
|
+
*
|
30
|
+
* @param object [Boolean] the boolean to test
|
31
|
+
* @return [Boolean] whether the object is present
|
32
|
+
*/
|
33
|
+
function isBooleanPresent(object) {
|
34
|
+
return toString.call(object) === '[object Boolean]'
|
35
|
+
}
|
36
|
+
|
27
37
|
return {
|
28
38
|
|
29
39
|
/**
|
@@ -32,28 +42,47 @@ var HamlCoffeeAssets = (function(){
|
|
32
42
|
* @param namespace [String] the template namespace
|
33
43
|
* @param name [String] the name of the template that is registered to the namespace
|
34
44
|
* @param source [String] the template source code to be compiled
|
35
|
-
* @param
|
45
|
+
* @param escapeHtml [Boolean] whether to escape HTML output by default or not
|
46
|
+
* @param escapeAttributes [Boolean] whether to escape HTML attributes output by default or not
|
47
|
+
* @param customHtmlEscape [String] the name of the function to escape the output
|
36
48
|
* @param context [String] the name of the function to merge contexts
|
37
49
|
*/
|
38
|
-
compile: function(namespace, name, source,
|
50
|
+
compile: function(namespace, name, source, format, escapeHtml, escapeAttributes, customHtmlEscape, context) {
|
39
51
|
|
40
52
|
var compiler, jst;
|
41
53
|
|
42
|
-
if (!
|
43
|
-
|
54
|
+
if (!isStringPresent(namespace)) {
|
55
|
+
namespace = 'window.HAML'
|
44
56
|
}
|
45
57
|
|
46
|
-
if (
|
47
|
-
|
48
|
-
} else {
|
49
|
-
compiler = new Compiler({ escape_html: false });
|
58
|
+
if (!isStringPresent(format)) {
|
59
|
+
format = 'html5'
|
50
60
|
}
|
51
61
|
|
62
|
+
if (!isBooleanPresent(escapeHtml)) {
|
63
|
+
escapeHtml = true
|
64
|
+
}
|
65
|
+
|
66
|
+
if (!isBooleanPresent(escapeAttributes)) {
|
67
|
+
escapeAttributes = true
|
68
|
+
}
|
69
|
+
|
70
|
+
if (!isStringPresent(customHtmlEscape)) {
|
71
|
+
customHtmlEscape = 'window.HAML.escape'
|
72
|
+
}
|
73
|
+
|
74
|
+
compiler = new Compiler({
|
75
|
+
format: format,
|
76
|
+
escapeHtml: escapeHtml,
|
77
|
+
escapeAttributes: escapeAttributes,
|
78
|
+
customHtmlEscape: customHtmlEscape
|
79
|
+
});
|
80
|
+
|
52
81
|
compiler.parse(source);
|
53
82
|
|
54
83
|
jst = CoffeeScript.compile(compiler.render(name, namespace));
|
55
84
|
|
56
|
-
if (
|
85
|
+
if (isStringPresent(context)) {
|
57
86
|
jst = jst.replace('fn.call(context);', 'fn.call(' + context +'(context));');
|
58
87
|
}
|
59
88
|
|