haml_coffee_assets 0.3.0 → 0.4.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 +144 -40
- data/lib/haml_coffee_assets/engine.rb +24 -14
- data/lib/haml_coffee_assets/haml_coffee.rb +31 -3
- data/lib/haml_coffee_assets/haml_coffee_assets.js +16 -3
- data/lib/haml_coffee_assets/version.rb +1 -1
- data/lib/js/haml-coffee.js +78 -35
- data/vendor/assets/javascripts/hamlcoffee.js.coffee.erb +88 -0
- metadata +21 -21
- data/vendor/assets/javascripts/hamlcoffee.js +0 -85
data/README.md
CHANGED
@@ -160,14 +160,14 @@ A template `app/assets/templates/header.hamlc` with the given content:
|
|
160
160
|
|
161
161
|
```haml
|
162
162
|
%header
|
163
|
-
%h2= title
|
163
|
+
%h2= @title
|
164
164
|
```
|
165
165
|
|
166
166
|
will be accessible in your browser as `JST['header']`. You can now render the precompiled template and pass the data
|
167
167
|
to be rendered:
|
168
168
|
|
169
169
|
```javascript
|
170
|
-
JST['header']
|
170
|
+
JST['header']({ title: 'Hello Haml Coffee' })
|
171
171
|
```
|
172
172
|
|
173
173
|
If you prefer another namespace, you can set it in your `config/application.rb`:
|
@@ -209,45 +209,13 @@ You can toggle HTML escaping in your `config/application.rb`:
|
|
209
209
|
config.hamlcoffee.escapeHtml = false
|
210
210
|
```
|
211
211
|
|
212
|
-
|
213
|
-
|
214
|
-
By default your code block in your Haml Coffee template will be escaped through the `HAML.escape` function that is
|
215
|
-
provided in the `hamlcoffee.js` script.
|
212
|
+
### Uglify generated HTML
|
216
213
|
|
217
|
-
|
214
|
+
By default all generated HTML is indented to have a nice reading experience. If you like to ignore indention to have a
|
215
|
+
better rendering performance, you can enable the uglify option in your `config/application.rb`:
|
218
216
|
|
219
217
|
```ruby
|
220
|
-
config.hamlcoffee.
|
221
|
-
```
|
222
|
-
|
223
|
-
Your custom escape function must take the unescaped text as parameter and returns the escaped text.
|
224
|
-
The following default implementation comes with `hamlcoffee.js`:
|
225
|
-
|
226
|
-
```coffeescript
|
227
|
-
App.myEscape = (text) ->
|
228
|
-
('' + text)
|
229
|
-
.replace(/&/g, '&')
|
230
|
-
.replace(/</g, '<')
|
231
|
-
.replace(/>/g, '>')
|
232
|
-
.replace(/"/g, '"')
|
233
|
-
```
|
234
|
-
|
235
|
-
#### Custom clean value function
|
236
|
-
|
237
|
-
All your evaluated CoffeeScript code will go through the clean value function. By default this simply cleans `undefined`
|
238
|
-
and `null` values, so that they appear as empty string in your template.
|
239
|
-
|
240
|
-
You can set a custom clean value function in your `config/application.rb`:
|
241
|
-
|
242
|
-
```ruby
|
243
|
-
config.hamlcoffee.customCleanValue = 'App.myCleanValue'
|
244
|
-
```
|
245
|
-
|
246
|
-
Your custom clean value function must take the value as parameter and returns the cleaned value.
|
247
|
-
The following default implementation comes with `hamlcoffee.js`:
|
248
|
-
|
249
|
-
```coffeescript
|
250
|
-
App.myCleanValue = (value) -> if value is null or value is undefined then '' else value
|
218
|
+
config.hamlcoffee.uglify = true
|
251
219
|
```
|
252
220
|
|
253
221
|
### Global context
|
@@ -307,15 +275,151 @@ App.globalTemplateContext = (locals) -> _.extend({}, {
|
|
307
275
|
}, locals)
|
308
276
|
```
|
309
277
|
|
310
|
-
|
278
|
+
### Customize the tag lists
|
279
|
+
|
280
|
+
Haml Coffee contains two list of HTML tags that you can customize. In general you're fine with the defaults, but if
|
281
|
+
you need to extend the list, you can instruct Haml Coffee Assets to do so.
|
282
|
+
|
283
|
+
#### Whitespace sensitive tag list
|
284
|
+
|
285
|
+
* Tags: `textarea`, `pre`
|
286
|
+
|
287
|
+
Some HTML tags are whitespace sensitive, which means that whitespace used for proper indention results in a wrong
|
288
|
+
display of the tag. In order to avoid this, the content is preserved by converting the nerwlines to a HTML
|
289
|
+
entity. You can set your own list of whitespace sensitive tags in your `config/application.rb`:
|
290
|
+
|
291
|
+
```ruby
|
292
|
+
config.hamlcoffee.preserve = 'pre,textarea,abbr'
|
293
|
+
```
|
294
|
+
|
295
|
+
This list is also taken into account for the `HAML.preserveAndFind` helper function that is provided and its shortcut
|
296
|
+
notation `~`.
|
297
|
+
|
298
|
+
#### Auto-closing tag list
|
299
|
+
|
300
|
+
Tags: `meta`, `img`, `link`, `br`, `hr`, `input`, `area`, `param`, `col`, `base`
|
301
|
+
|
302
|
+
The auto-closing tag list will contains the tags that will be self-closes if they have no content. You can set the
|
303
|
+
list of self closing tags in your `config/application.rb`:
|
304
|
+
|
305
|
+
```ruby
|
306
|
+
config.hamlcoffee.autoclose = 'meta,img,link,br,hr,input,area,param,col,base'
|
307
|
+
```
|
308
|
+
|
309
|
+
### Custom helper functions
|
310
|
+
|
311
|
+
Haml Coffee Assets provides a set of custom functions for Haml Coffee, so that the templates doesn't have to be self
|
312
|
+
contained and can make use of the global functions. In general you don't have to customize them further, but if you need
|
313
|
+
to, you can.
|
314
|
+
|
315
|
+
#### Custom escape function
|
316
|
+
|
317
|
+
By default your code block in your Haml Coffee template will be escaped through the `HAML.escape` function that is
|
318
|
+
provided in the `hamlcoffee.js` script.
|
319
|
+
|
320
|
+
You can set a custom escaping function in your `config/application.rb`:
|
321
|
+
|
322
|
+
```ruby
|
323
|
+
config.hamlcoffee.customHtmlEscape = 'App.myEscape'
|
324
|
+
```
|
325
|
+
|
326
|
+
Your custom escape function must take the unescaped text as parameter and returns the escaped text.
|
327
|
+
The following default implementation comes with `hamlcoffee.js`:
|
328
|
+
|
329
|
+
```coffeescript
|
330
|
+
App.myEscape = (text) ->
|
331
|
+
('' + text)
|
332
|
+
.replace(/&/g, '&')
|
333
|
+
.replace(/</g, '<')
|
334
|
+
.replace(/>/g, '>')
|
335
|
+
.replace(/'/g, ''')
|
336
|
+
.replace(/"/g, '"')
|
337
|
+
```
|
338
|
+
|
339
|
+
#### Custom clean value function
|
311
340
|
|
312
|
-
|
341
|
+
All your evaluated CoffeeScript code will go through the clean value function. By default this simply cleans `undefined`
|
342
|
+
and `null` values, so that they appear as empty string in your template.
|
343
|
+
|
344
|
+
You can set a custom clean value function in your `config/application.rb`:
|
345
|
+
|
346
|
+
```ruby
|
347
|
+
config.hamlcoffee.customCleanValue = 'App.myCleanValue'
|
348
|
+
```
|
349
|
+
|
350
|
+
Your custom clean value function must take the value as parameter and returns the cleaned value.
|
351
|
+
The following default implementation comes with `hamlcoffee.js`:
|
352
|
+
|
353
|
+
```coffeescript
|
354
|
+
App.myCleanValue = (value) -> if value is null or value is undefined then '' else value
|
355
|
+
```
|
356
|
+
|
357
|
+
#### Custom preserve function
|
358
|
+
|
359
|
+
All the content from the HTML tags that are contained in the whitespace sensitive tag list are passed through the
|
360
|
+
preserve function.
|
361
|
+
|
362
|
+
You can set a custom preserve function in your `config/application.rb`:
|
363
|
+
|
364
|
+
```ruby
|
365
|
+
config.hamlcoffee.customPreserve = 'App.myPreserve'
|
366
|
+
```
|
367
|
+
|
368
|
+
Your custom preserve function must take the text to be preserved as parameter and returns the preserved content.
|
369
|
+
The following default implementation comes with `hamlcoffee.js`:
|
370
|
+
|
371
|
+
```coffeescript
|
372
|
+
App.myPreserve = (value) -> text.replace /\\n/g, '
'
|
373
|
+
```
|
374
|
+
|
375
|
+
#### Custom find and preserve function
|
376
|
+
|
377
|
+
The findAndPreserve function is a specialized preserve function, that you can pass a text containing HTML, and only the
|
378
|
+
newlines in between a whitespace sensitive tag are preserved. This function uses the previous preserve function to do
|
379
|
+
the final preservation.
|
380
|
+
|
381
|
+
You can set a custom find and preserve function in your `config/application.rb`:
|
382
|
+
|
383
|
+
```ruby
|
384
|
+
config.hamlcoffee.customFindAndPreserve = 'App.myFindAndPreserve'
|
385
|
+
```
|
386
|
+
|
387
|
+
Your custom find and preserve function must take the text to search for whitespace sensitive tags as parameter and
|
388
|
+
returns the preserved content.
|
389
|
+
|
390
|
+
The following default implementation comes with `hamlcoffee.js`:
|
391
|
+
|
392
|
+
```coffeescript
|
393
|
+
App.myPreserve = (value) ->
|
394
|
+
text.replace /<(textarea|pre)>([^]*?)<\/\1>/g, (str, tag, content) ->
|
395
|
+
"<#{ tag }>#{ HAML.preserve(content) }</#{ tag }>"
|
396
|
+
```
|
397
|
+
|
398
|
+
## Prepare your assets for production
|
399
|
+
|
400
|
+
Using haml_coffee_assets requires you to set
|
313
401
|
|
314
402
|
config.assets.initialize_on_precompile = true
|
315
403
|
|
316
404
|
in your `config/environments/production.rb`. Read more about the it at the
|
317
405
|
[Asset Pipeline Guide](http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets).
|
318
406
|
|
407
|
+
## Development
|
408
|
+
|
409
|
+
* Issues and feature request hosted at [GitHub Issues](https://github.com/netzpirat/haml_coffee_assets/issues).
|
410
|
+
* Documentation hosted at [RubyDoc](http://rubydoc.info/github/netzpirat/haml_coffee_assets/master/frames).
|
411
|
+
* Source hosted at [GitHub](https://github.com/netzpirat/haml_coffee_assets).
|
412
|
+
|
413
|
+
Pull requests are very welcome! Please try to follow these simple rules if applicable:
|
414
|
+
|
415
|
+
* Please create a topic branch for every separate change you make.
|
416
|
+
* Make sure your patches are well tested. All specs must pass.
|
417
|
+
* Update the [Yard](http://yardoc.org/) documentation.
|
418
|
+
* Update the README.
|
419
|
+
* Please **do not change** the version number.
|
420
|
+
|
421
|
+
For questions please join `#haml` on irc.freenode.net
|
422
|
+
|
319
423
|
## Acknowledgement
|
320
424
|
|
321
425
|
* [Jeremy Ashkenas](http://twitter.com/#!/jashkenas) for CoffeeScript, that little language that compiles into
|
@@ -9,13 +9,18 @@ module HamlCoffeeAssets
|
|
9
9
|
config.hamlcoffee = ActiveSupport::OrderedOptions.new
|
10
10
|
|
11
11
|
DEFAULT_CONFIG = {
|
12
|
-
:format
|
13
|
-
:namespace
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
12
|
+
:format => 'html5',
|
13
|
+
:namespace => 'window.JST',
|
14
|
+
:uglify => false,
|
15
|
+
:escapeHtml => true,
|
16
|
+
:escapeAttributes => true,
|
17
|
+
:customHtmlEscape => 'HAML.escape',
|
18
|
+
:customCleanValue => 'HAML.cleanValue',
|
19
|
+
:customPreserve => 'HAML.escape',
|
20
|
+
:customFindAndPreserve => 'HAML.findAndPreserve',
|
21
|
+
:preserve => 'textarea,pre',
|
22
|
+
:autoclose => 'meta,img,link,br,hr,input,area,param,col,base',
|
23
|
+
:context => 'HAML.context'
|
19
24
|
}
|
20
25
|
|
21
26
|
# Initialize Haml Coffee Assets after Sprockets
|
@@ -30,13 +35,18 @@ module HamlCoffeeAssets
|
|
30
35
|
options = DEFAULT_CONFIG.merge(app.config.hamlcoffee)
|
31
36
|
|
32
37
|
HamlCoffee.configure do |config|
|
33
|
-
config.namespace
|
34
|
-
config.format
|
35
|
-
config.
|
36
|
-
config.
|
37
|
-
config.
|
38
|
-
config.
|
39
|
-
config.
|
38
|
+
config.namespace = options[:namespace]
|
39
|
+
config.format = options[:format]
|
40
|
+
config.uglify = options[:uglify]
|
41
|
+
config.escapeHtml = options[:escapeHtml]
|
42
|
+
config.escapeAttributes = options[:escapeAttributes]
|
43
|
+
config.customHtmlEscape = options[:customHtmlEscape]
|
44
|
+
config.customCleanValue = options[:customCleanValue]
|
45
|
+
config.customPreserve = options[:customPreserve]
|
46
|
+
config.customFindAndPreserve = options[:customFindAndPreserve]
|
47
|
+
config.preserveTags = options[:preserve]
|
48
|
+
config.selfCloseTags = options[:autoclose]
|
49
|
+
config.context = options[:context]
|
40
50
|
end
|
41
51
|
end
|
42
52
|
|
@@ -16,6 +16,11 @@ module HamlCoffeeAssets
|
|
16
16
|
mattr_accessor :format
|
17
17
|
self.format = 'html5'
|
18
18
|
|
19
|
+
# Uglify HTML output by skip indention
|
20
|
+
#
|
21
|
+
mattr_accessor :uglify
|
22
|
+
self.uglify = false
|
23
|
+
|
19
24
|
# Escape template code output
|
20
25
|
#
|
21
26
|
mattr_accessor :escapeHtml
|
@@ -36,6 +41,26 @@ module HamlCoffeeAssets
|
|
36
41
|
mattr_accessor :customCleanValue
|
37
42
|
self.customCleanValue = 'window.HAML.cleanValue'
|
38
43
|
|
44
|
+
# Custom preserve function
|
45
|
+
#
|
46
|
+
mattr_accessor :customPreserve
|
47
|
+
self.customPreserve = 'window.HAML.preserve'
|
48
|
+
|
49
|
+
# Custom find and preserve function
|
50
|
+
#
|
51
|
+
mattr_accessor :customFindAndPreserve
|
52
|
+
self.customFindAndPreserve = 'window.HAML.findAndPreserve'
|
53
|
+
|
54
|
+
# List of tags to preserve
|
55
|
+
#
|
56
|
+
mattr_accessor :preserveTags
|
57
|
+
self.preserveTags = 'textarea,pre'
|
58
|
+
|
59
|
+
# List of self closing tags
|
60
|
+
#
|
61
|
+
mattr_accessor :selfCloseTags
|
62
|
+
self.selfCloseTags = 'meta,img,link,br,hr,input,area,param,col,base'
|
63
|
+
|
39
64
|
# Custom global context to merge
|
40
65
|
#
|
41
66
|
mattr_accessor :context
|
@@ -56,9 +81,12 @@ module HamlCoffeeAssets
|
|
56
81
|
# @return [String] the compiled template in JavaScript
|
57
82
|
#
|
58
83
|
def compile(name, source)
|
59
|
-
runtime.call('HamlCoffeeAssets.compile', name, source,
|
60
|
-
HamlCoffee.
|
61
|
-
HamlCoffee.customHtmlEscape, HamlCoffee.customCleanValue,
|
84
|
+
runtime.call('HamlCoffeeAssets.compile', name, source, HamlCoffee.namespace, HamlCoffee.format, HamlCoffee.uglify,
|
85
|
+
HamlCoffee.escapeHtml, HamlCoffee.escapeAttributes,
|
86
|
+
HamlCoffee.customHtmlEscape, HamlCoffee.customCleanValue,
|
87
|
+
HamlCoffee.customPreserve, HamlCoffee.customFindAndPreserve,
|
88
|
+
HamlCoffee.preserveTags, HamlCoffee.selfCloseTags,
|
89
|
+
HamlCoffee.context)
|
62
90
|
end
|
63
91
|
|
64
92
|
private
|
@@ -19,23 +19,36 @@ var HamlCoffeeAssets = (function(){
|
|
19
19
|
/**
|
20
20
|
* Compile the HAML Coffee template to JavaScript
|
21
21
|
*
|
22
|
-
* @param namespace [String] the template namespace
|
23
22
|
* @param name [String] the name of the template that is registered to the namespace
|
24
23
|
* @param source [String] the template source code to be compiled
|
24
|
+
* @param namespace [String] the template namespace
|
25
|
+
* @param format [String] output HTML format
|
26
|
+
* @param uglify [Boolean] skip HTML indention
|
25
27
|
* @param escapeHtml [Boolean] whether to escape HTML output by default or not
|
26
28
|
* @param escapeAttributes [Boolean] whether to escape HTML attributes output by default or not
|
27
29
|
* @param customHtmlEscape [String] the name of the function to escape the output
|
28
30
|
* @param customCleanValue [String] the name of the function to clean the code output
|
31
|
+
* @param preserveTags [String] comma separated list of tags to preserve whitespace
|
32
|
+
* @param selfCloseTags [String] comma separated list of tags to self-closing tags
|
29
33
|
* @param context [String] the name of the function to merge contexts
|
30
34
|
*/
|
31
|
-
compile: function(name, source, namespace, format,
|
35
|
+
compile: function(name, source, namespace, format, uglify,
|
36
|
+
escapeHtml, escapeAttributes,
|
37
|
+
customHtmlEscape, customCleanValue, customPreserve, customFindAndPreserve,
|
38
|
+
preserveTags, selfCloseTags,
|
39
|
+
context) {
|
32
40
|
|
33
41
|
var compiler = new Compiler({
|
34
42
|
format: format,
|
43
|
+
uglify: uglify,
|
35
44
|
escapeHtml: escapeHtml,
|
36
45
|
escapeAttributes: escapeAttributes,
|
37
46
|
customHtmlEscape: customHtmlEscape,
|
38
|
-
customCleanValue: customCleanValue
|
47
|
+
customCleanValue: customCleanValue,
|
48
|
+
customPreserve: customPreserve,
|
49
|
+
customFindAndPreserve: customFindAndPreserve,
|
50
|
+
preserveTags: preserveTags,
|
51
|
+
selfCloseTags: selfCloseTags
|
39
52
|
});
|
40
53
|
|
41
54
|
compiler.parse(source);
|
data/lib/js/haml-coffee.js
CHANGED
@@ -340,6 +340,7 @@ require.define("/nodes/node.js", function (require, module, exports, __dirname,
|
|
340
340
|
this.children = [];
|
341
341
|
this.opener = this.closer = null;
|
342
342
|
this.silent = false;
|
343
|
+
this.preserveTags = options.preserveTags.split(',');
|
343
344
|
this.preserve = false;
|
344
345
|
this.wsRemoval = {
|
345
346
|
around: false,
|
@@ -348,6 +349,8 @@ require.define("/nodes/node.js", function (require, module, exports, __dirname,
|
|
348
349
|
this.escapeHtml = options.escapeHtml;
|
349
350
|
this.escapeAttributes = options.escapeAttributes;
|
350
351
|
this.format = options.format;
|
352
|
+
this.selfCloseTags = options.selfCloseTags.split(',');
|
353
|
+
this.uglify = options.uglify;
|
351
354
|
this.codeBlockLevel = options.codeBlockLevel;
|
352
355
|
this.blockLevel = options.blockLevel;
|
353
356
|
}
|
@@ -391,7 +394,7 @@ require.define("/nodes/node.js", function (require, module, exports, __dirname,
|
|
391
394
|
return {
|
392
395
|
type: 'text',
|
393
396
|
cw: this.codeBlockLevel,
|
394
|
-
hw: this.blockLevel - this.codeBlockLevel + 2,
|
397
|
+
hw: this.uglify ? 0 : this.blockLevel - this.codeBlockLevel + 2,
|
395
398
|
text: escape ? e(text) : text
|
396
399
|
};
|
397
400
|
};
|
@@ -404,13 +407,17 @@ require.define("/nodes/node.js", function (require, module, exports, __dirname,
|
|
404
407
|
};
|
405
408
|
};
|
406
409
|
|
407
|
-
Node.prototype.markInsertingCode = function(code, escape) {
|
410
|
+
Node.prototype.markInsertingCode = function(code, escape, preserve, findAndPreserve) {
|
408
411
|
if (escape == null) escape = false;
|
412
|
+
if (preserve == null) preserve = false;
|
413
|
+
if (findAndPreserve == null) findAndPreserve = false;
|
409
414
|
return {
|
410
415
|
type: 'insert',
|
411
416
|
cw: this.codeBlockLevel,
|
412
|
-
hw: this.blockLevel,
|
417
|
+
hw: this.uglify ? 0 : this.blockLevel,
|
413
418
|
escape: escape,
|
419
|
+
preserve: preserve,
|
420
|
+
findAndPreserve: findAndPreserve,
|
414
421
|
code: code
|
415
422
|
};
|
416
423
|
};
|
@@ -418,7 +425,7 @@ require.define("/nodes/node.js", function (require, module, exports, __dirname,
|
|
418
425
|
Node.prototype.evaluate = function() {};
|
419
426
|
|
420
427
|
Node.prototype.render = function() {
|
421
|
-
var child, output,
|
428
|
+
var child, output, rendered, tag, _i, _j, _k, _l, _len, _len2, _len3, _len4, _len5, _m, _ref, _ref2, _ref3, _ref4, _ref5;
|
422
429
|
output = [];
|
423
430
|
if (this.silent) return output;
|
424
431
|
if (this.children.length === 0) {
|
@@ -436,35 +443,39 @@ require.define("/nodes/node.js", function (require, module, exports, __dirname,
|
|
436
443
|
} else {
|
437
444
|
if (this.opener && this.closer) {
|
438
445
|
if (this.preserve) {
|
439
|
-
|
446
|
+
this.wsRemoval.inside = true;
|
447
|
+
output.push(this.getOpener());
|
440
448
|
_ref = this.children;
|
441
449
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
442
450
|
child = _ref[_i];
|
443
|
-
|
451
|
+
_ref2 = child.render();
|
452
|
+
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
|
453
|
+
rendered = _ref2[_j];
|
454
|
+
rendered.hw = this.blockLevel;
|
455
|
+
output.push(rendered);
|
456
|
+
}
|
444
457
|
}
|
445
|
-
|
446
|
-
preserve += this.getCloser().text;
|
447
|
-
output.push(this.markText(preserve));
|
458
|
+
output.push(this.getCloser());
|
448
459
|
} else {
|
449
460
|
output.push(this.getOpener());
|
450
|
-
|
451
|
-
for (
|
452
|
-
child =
|
461
|
+
_ref3 = this.children;
|
462
|
+
for (_k = 0, _len3 = _ref3.length; _k < _len3; _k++) {
|
463
|
+
child = _ref3[_k];
|
453
464
|
output = output.concat(child.render());
|
454
465
|
}
|
455
466
|
output.push(this.getCloser());
|
456
467
|
}
|
457
468
|
} else if (this.opener) {
|
458
469
|
output.push(this.getOpener());
|
459
|
-
_ref3 = this.children;
|
460
|
-
for (_k = 0, _len3 = _ref3.length; _k < _len3; _k++) {
|
461
|
-
child = _ref3[_k];
|
462
|
-
output = output.concat(child.render());
|
463
|
-
}
|
464
|
-
} else {
|
465
470
|
_ref4 = this.children;
|
466
471
|
for (_l = 0, _len4 = _ref4.length; _l < _len4; _l++) {
|
467
472
|
child = _ref4[_l];
|
473
|
+
output = output.concat(child.render());
|
474
|
+
}
|
475
|
+
} else {
|
476
|
+
_ref5 = this.children;
|
477
|
+
for (_m = 0, _len5 = _ref5.length; _m < _len5; _m++) {
|
478
|
+
child = _ref5[_m];
|
468
479
|
output.push(this.markText(child.render().text));
|
469
480
|
}
|
470
481
|
}
|
@@ -559,10 +570,6 @@ require.define("/nodes/haml.js", function (require, module, exports, __dirname,
|
|
559
570
|
Haml.__super__.constructor.apply(this, arguments);
|
560
571
|
}
|
561
572
|
|
562
|
-
Haml.selfCloseTags = ['meta', 'img', 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base'];
|
563
|
-
|
564
|
-
Haml.preserveTags = ['pre', 'textarea'];
|
565
|
-
|
566
573
|
Haml.prototype.evaluate = function() {
|
567
574
|
var assignment, code, identifier, match, prefix, tokens;
|
568
575
|
tokens = this.parseExpression(this.expression);
|
@@ -576,11 +583,19 @@ require.define("/nodes/haml.js", function (require, module, exports, __dirname,
|
|
576
583
|
identifier = match[1];
|
577
584
|
assignment = match[2];
|
578
585
|
if (identifier === '~') {
|
579
|
-
code =
|
586
|
+
code = "\#{fp(" + assignment + ")}";
|
580
587
|
} else if (identifier === '&=' || (identifier === '=' && this.escapeHtml)) {
|
581
|
-
|
588
|
+
if (this.preserve) {
|
589
|
+
code = "\#{p(e(c(" + assignment + ")))}";
|
590
|
+
} else {
|
591
|
+
code = "\#{e(c(" + assignment + "))}";
|
592
|
+
}
|
582
593
|
} else if (identifier === '!=' || (identifier === '=' && !this.escapeHtml)) {
|
583
|
-
|
594
|
+
if (this.preserve) {
|
595
|
+
code = "\#{p(c(" + assignment + "))}";
|
596
|
+
} else {
|
597
|
+
code = "\#{c(" + assignment + ")}";
|
598
|
+
}
|
584
599
|
}
|
585
600
|
this.opener = this.markText("" + prefix + ">" + code);
|
586
601
|
return this.closer = this.markText("</" + tokens.tag + ">");
|
@@ -602,7 +617,7 @@ require.define("/nodes/haml.js", function (require, module, exports, __dirname,
|
|
602
617
|
Haml.prototype.parseExpression = function(exp) {
|
603
618
|
var attribute, attributes, classes, id, tag, _i, _len, _ref, _ref2;
|
604
619
|
tag = this.parseTag(exp);
|
605
|
-
if (
|
620
|
+
if (this.preserveTags.indexOf(tag.tag) !== -1) this.preserve = true;
|
606
621
|
id = (_ref = tag.ids) != null ? _ref.pop() : void 0;
|
607
622
|
classes = tag.classes;
|
608
623
|
attributes = [];
|
@@ -813,7 +828,7 @@ require.define("/nodes/haml.js", function (require, module, exports, __dirname,
|
|
813
828
|
};
|
814
829
|
|
815
830
|
Haml.prototype.isNotSelfClosing = function(tag) {
|
816
|
-
return
|
831
|
+
return this.selfCloseTags.indexOf(tag) === -1 && !tag.match(/\/$/);
|
817
832
|
};
|
818
833
|
|
819
834
|
return Haml;
|
@@ -852,7 +867,11 @@ require.define("/nodes/code.js", function (require, module, exports, __dirname,
|
|
852
867
|
return this.closer = this.markRunningCode(" ''");
|
853
868
|
}
|
854
869
|
} else if (identifier === '~') {
|
855
|
-
|
870
|
+
if (this.escapeHtml) {
|
871
|
+
return this.opener = this.markInsertingCode(code, true, false, true);
|
872
|
+
} else {
|
873
|
+
return this.opener = this.markInsertingCode(code, false, false, true);
|
874
|
+
}
|
856
875
|
} else if (identifier === '&=' || (identifier === '=' && this.escapeHtml)) {
|
857
876
|
return this.opener = this.markInsertingCode(code, true);
|
858
877
|
} else if (identifier === '!=' || (identifier === '=' && !this.escapeHtml)) {
|
@@ -1056,7 +1075,7 @@ require.define("/compiler.js", function (require, module, exports, __dirname, __
|
|
1056
1075
|
module.exports = Compiler = (function() {
|
1057
1076
|
|
1058
1077
|
function Compiler(options) {
|
1059
|
-
var _base, _base2, _base3, _ref, _ref2, _ref3;
|
1078
|
+
var _base, _base2, _base3, _base4, _base5, _base6, _ref, _ref2, _ref3, _ref4, _ref5, _ref6;
|
1060
1079
|
this.options = options != null ? options : {};
|
1061
1080
|
if ((_ref = (_base = this.options).escapeHtml) == null) {
|
1062
1081
|
_base.escapeHtml = true;
|
@@ -1064,8 +1083,15 @@ require.define("/compiler.js", function (require, module, exports, __dirname, __
|
|
1064
1083
|
if ((_ref2 = (_base2 = this.options).escapeAttributes) == null) {
|
1065
1084
|
_base2.escapeAttributes = true;
|
1066
1085
|
}
|
1067
|
-
if ((_ref3 = (_base3 = this.options).
|
1068
|
-
|
1086
|
+
if ((_ref3 = (_base3 = this.options).uglify) == null) _base3.uglify = false;
|
1087
|
+
if ((_ref4 = (_base4 = this.options).format) == null) {
|
1088
|
+
_base4.format = 'html5';
|
1089
|
+
}
|
1090
|
+
if ((_ref5 = (_base5 = this.options).preserveTags) == null) {
|
1091
|
+
_base5.preserveTags = 'pre,textarea';
|
1092
|
+
}
|
1093
|
+
if ((_ref6 = (_base6 = this.options).selfCloseTags) == null) {
|
1094
|
+
_base6.selfCloseTags = 'meta,img,link,br,hr,input,area,param,col,base';
|
1069
1095
|
}
|
1070
1096
|
}
|
1071
1097
|
|
@@ -1132,7 +1158,10 @@ require.define("/compiler.js", function (require, module, exports, __dirname, __
|
|
1132
1158
|
codeBlockLevel: override.codeBlockLevel || this.currentCodeBlockLevel,
|
1133
1159
|
escapeHtml: override.escapeHtml || this.options.escapeHtml,
|
1134
1160
|
escapeAttributes: override.escapeAttributes || this.options.escapeAttributes,
|
1135
|
-
format: override.format || this.options.format
|
1161
|
+
format: override.format || this.options.format,
|
1162
|
+
preserveTags: override.preserveTags || this.options.preserveTags,
|
1163
|
+
selfCloseTags: override.selfCloseTags || this.options.selfCloseTags,
|
1164
|
+
uglify: override.uglify || this.options.uglify
|
1136
1165
|
};
|
1137
1166
|
};
|
1138
1167
|
|
@@ -1230,7 +1259,7 @@ require.define("/compiler.js", function (require, module, exports, __dirname, __
|
|
1230
1259
|
};
|
1231
1260
|
|
1232
1261
|
Compiler.prototype.render = function(templateName, namespace) {
|
1233
|
-
var cleanFn, code, escapeFn, output, segment, segments, _i, _len;
|
1262
|
+
var cleanFn, code, escapeFn, findAndPreserveFn, output, preserveFn, segment, segments, _i, _len;
|
1234
1263
|
if (namespace == null) namespace = 'window.HAML';
|
1235
1264
|
output = '';
|
1236
1265
|
segments = ("" + namespace + "." + templateName).replace(/(\s|-)+/g, '_').split(/\./);
|
@@ -1257,11 +1286,25 @@ require.define("/compiler.js", function (require, module, exports, __dirname, __
|
|
1257
1286
|
cleanFn = "" + namespace + ".cleanValue";
|
1258
1287
|
output += cleanFn + '||= (text) -> if text is null or text is undefined then \'\' else text\n';
|
1259
1288
|
}
|
1289
|
+
if (this.options.customPreserve) {
|
1290
|
+
preserveFn = this.options.customPreserve;
|
1291
|
+
} else {
|
1292
|
+
preserveFn = "" + namespace + ".preserve";
|
1293
|
+
output += preserveFn + "||= (text) -> text.replace /\\n/g, '
'\n";
|
1294
|
+
}
|
1295
|
+
if (this.options.customFindAndPreserve) {
|
1296
|
+
findAndPreserveFn = this.options.customFindAndPreserve;
|
1297
|
+
} else {
|
1298
|
+
findAndPreserveFn = "" + namespace + ".findAndPreserve";
|
1299
|
+
output += findAndPreserveFn + ("||= (text) ->\n text.replace /<(" + (this.options.preserveTags.split(',').join('|')) + ")>([^]*?)<\\/\\1>/g, (str, tag, content) ->\n \"<\#{ tag }>\#{ " + preserveFn + "(content) }</\#{ tag }>\"\n");
|
1300
|
+
}
|
1260
1301
|
output += "" + namespace + "['" + templateName + "'] = (context) ->\n";
|
1261
1302
|
output += " fn = (context) ->\n";
|
1262
1303
|
output += " o = []\n";
|
1263
1304
|
output += " e = " + escapeFn + "\n";
|
1264
1305
|
output += " c = " + cleanFn + "\n";
|
1306
|
+
output += " p = " + preserveFn + "\n";
|
1307
|
+
output += " fp = findAndPreserve = " + findAndPreserveFn + "\n";
|
1265
1308
|
code = this.createCode();
|
1266
1309
|
output += "" + code + "\n";
|
1267
1310
|
output += " return o.join(\"\\n\")" + (this.cleanupWhitespace(code)) + "\n";
|
@@ -1291,9 +1334,9 @@ require.define("/compiler.js", function (require, module, exports, __dirname, __
|
|
1291
1334
|
break;
|
1292
1335
|
case 'insert':
|
1293
1336
|
if (line.hw === 0) {
|
1294
|
-
code.push("" + (w(line.cw)) + "o.push " + (w(line.escape) ? 'e ' : '') + "c
|
1337
|
+
code.push("" + (w(line.cw)) + "o.push " + (w(line.findAndPreserve) ? 'fp ' : '') + (w(line.preserve) ? 'p ' : '') + (w(line.escape) ? 'e ' : '') + "c " + line.code);
|
1295
1338
|
} else {
|
1296
|
-
code.push("" + (w(line.cw)) + "o.push " + (w(line.
|
1339
|
+
code.push("" + (w(line.cw)) + "o.push \"" + (w(line.hw - line.cw + 2)) + "\" + " + (w(line.findAndPreserve) ? 'fp ' : '') + (w(line.preserve) ? 'p ' : '') + (w(line.escape) ? 'e ' : '') + "c " + line.code);
|
1297
1340
|
}
|
1298
1341
|
}
|
1299
1342
|
}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# HAML Coffee namespace
|
2
|
+
#
|
3
|
+
window.HAML ||= {}
|
4
|
+
|
5
|
+
# HAML Coffee html escape function
|
6
|
+
#
|
7
|
+
# @param text [String] the text to escape
|
8
|
+
# @return [String] the escaped text
|
9
|
+
#
|
10
|
+
window.HAML.escape ||= (text) ->
|
11
|
+
("" + text)
|
12
|
+
.replace(/&/g, "&")
|
13
|
+
.replace(/</g, "<")
|
14
|
+
.replace(/>/g, ">")
|
15
|
+
.replace(/"/g, """)
|
16
|
+
|
17
|
+
# HAML Coffee clean value function
|
18
|
+
#
|
19
|
+
# @param text [String] the text to be cleaned
|
20
|
+
# @return [String] the cleaned text
|
21
|
+
#
|
22
|
+
window.HAML.cleanValue ||= (text) ->
|
23
|
+
if text is null or text is undefined then '' else text
|
24
|
+
|
25
|
+
# HAML Coffee extend function.
|
26
|
+
#
|
27
|
+
# This will reuse the extend function from either:
|
28
|
+
#
|
29
|
+
# - jQuery
|
30
|
+
# - Underscore.js
|
31
|
+
# - Prototype
|
32
|
+
# - MooTools
|
33
|
+
# - Zepto.js
|
34
|
+
#
|
35
|
+
# You can assign a custom extend function if your framework
|
36
|
+
# is not supported out of the box.
|
37
|
+
#
|
38
|
+
window.HAML.extend ||= (globals, locals) ->
|
39
|
+
if jQuery?.extend
|
40
|
+
jQuery.extend {}, globals, locals
|
41
|
+
|
42
|
+
else if _?.extend
|
43
|
+
_.extend {}, globals, locals
|
44
|
+
|
45
|
+
else if Zepto?.extend
|
46
|
+
Zepto.extend(Zepto.extend({}, globals), locals)
|
47
|
+
|
48
|
+
else if Object.extend
|
49
|
+
Object.extend(Object.extend({}, globals), locals)
|
50
|
+
|
51
|
+
else if Object.append
|
52
|
+
Object.append(Object.append({}, globals), locals)
|
53
|
+
|
54
|
+
else
|
55
|
+
locals
|
56
|
+
|
57
|
+
# HAML Coffee global template context.
|
58
|
+
#
|
59
|
+
# @return [Object] the global template context
|
60
|
+
#
|
61
|
+
window.HAML.globals ||= -> {}
|
62
|
+
|
63
|
+
# Get the HAML template context. This merges the local
|
64
|
+
# and the global template context into a new context.
|
65
|
+
#
|
66
|
+
# @param locals [Object] the local template context
|
67
|
+
# @return [Object] the merged context
|
68
|
+
#
|
69
|
+
window.HAML.context ||= (locals) ->
|
70
|
+
HAML.extend(HAML.globals(), locals)
|
71
|
+
|
72
|
+
# Preserve newlines in the text
|
73
|
+
#
|
74
|
+
# @param text [String] the text to preserve
|
75
|
+
# @return [String] the preserved text
|
76
|
+
#
|
77
|
+
window.HAML.preserve ||= (text) ->
|
78
|
+
text.replace /\\n/g, '
'
|
79
|
+
|
80
|
+
# Find and preserve newlines in the preserving tags
|
81
|
+
#
|
82
|
+
# @param text [String] the text to preserve
|
83
|
+
# @return [String] the preserved text
|
84
|
+
#
|
85
|
+
window.HAML.findAndPreserve ||= ->
|
86
|
+
tags = '<%= HamlCoffeeAssets::HamlCoffee.preserveTags %>'.split(',').join('|')
|
87
|
+
text.replace ///<(#{ tags })>([^]*?)<\/\1>///g, (str, tag, content) ->
|
88
|
+
"<#{ tag }>#{ <%= HamlCoffeeAssets::HamlCoffee.customPreserve %>(content) }</#{ tag }>"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml_coffee_assets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-12-08 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &70174079146660 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '3.1'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70174079146660
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: execjs
|
27
|
-
requirement: &
|
27
|
+
requirement: &70174079146160 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.2.9
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70174079146160
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bundler
|
38
|
-
requirement: &
|
38
|
+
requirement: &70174079145700 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70174079145700
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &70174079145120 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 2.7.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70174079145120
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: guard-rspec
|
60
|
-
requirement: &
|
60
|
+
requirement: &70174079144540 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 0.5.0
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70174079144540
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
|
-
requirement: &
|
71
|
+
requirement: &70174079144040 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: 0.7.3
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70174079144040
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: redcarpet
|
82
|
-
requirement: &
|
82
|
+
requirement: &70174079143520 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: 1.17.2
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70174079143520
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: pry
|
93
|
-
requirement: &
|
93
|
+
requirement: &70174079143000 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ~>
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: 0.9.6.2
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70174079143000
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rake
|
104
|
-
requirement: &
|
104
|
+
requirement: &70174079142540 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
version: 0.9.2.2
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70174079142540
|
113
113
|
description: Compile Haml CoffeeScript templates in the Rails asset pipeline.
|
114
114
|
email:
|
115
115
|
- michi@netzpiraten.ch
|
@@ -126,7 +126,7 @@ files:
|
|
126
126
|
- lib/js/coffee-script.js
|
127
127
|
- lib/js/haml-coffee.js
|
128
128
|
- lib/tasks/haml-coffee-rails_tasks.rake
|
129
|
-
- vendor/assets/javascripts/hamlcoffee.js
|
129
|
+
- vendor/assets/javascripts/hamlcoffee.js.coffee.erb
|
130
130
|
- LICENSE
|
131
131
|
- README.md
|
132
132
|
homepage: https://github.com/netzpirat/haml_coffee_assets
|
@@ -1,85 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* HAML Coffee namespace
|
3
|
-
*/
|
4
|
-
window.HAML || (window.HAML = {});
|
5
|
-
|
6
|
-
/**
|
7
|
-
* HAML Coffee html escape function
|
8
|
-
*
|
9
|
-
* @param text [String] the text to escape
|
10
|
-
* @return [String] the escaped text
|
11
|
-
*/
|
12
|
-
window.HAML.escape || (window.HAML.escape = function(text) {
|
13
|
-
return ("" + text)
|
14
|
-
.replace(/&/g, "&")
|
15
|
-
.replace(/</g, "<")
|
16
|
-
.replace(/>/g, ">")
|
17
|
-
.replace(/"/g, """);
|
18
|
-
});
|
19
|
-
|
20
|
-
/**
|
21
|
-
* HAML Coffee clean value function
|
22
|
-
*
|
23
|
-
* @param text [String] the text to be cleaned
|
24
|
-
* @return [String] the cleaned text
|
25
|
-
*/
|
26
|
-
window.HAML.cleanValue || (window.HAML.cleanValue = function(text) {
|
27
|
-
if (text === null || text === void 0) {
|
28
|
-
return '';
|
29
|
-
} else {
|
30
|
-
return text;
|
31
|
-
}
|
32
|
-
});
|
33
|
-
|
34
|
-
/**
|
35
|
-
* HAML Coffee extend function.
|
36
|
-
*
|
37
|
-
* This will reuse the extend function from either:
|
38
|
-
*
|
39
|
-
* - jQuery
|
40
|
-
* - Underscore.js
|
41
|
-
* - Prototype
|
42
|
-
* - MooTools
|
43
|
-
* - Zepto.js
|
44
|
-
*
|
45
|
-
* You can assign a custom extend function if your framework
|
46
|
-
* is not supported out of the box.
|
47
|
-
*/
|
48
|
-
window.HAML.extend || (window.HAML.extend = function(globals, locals) {
|
49
|
-
if (jQuery && jQuery.extend) {
|
50
|
-
return jQuery.extend({}, globals, locals);
|
51
|
-
}
|
52
|
-
else if (_ && _.extend) {
|
53
|
-
return _.extend({}, globals, locals);
|
54
|
-
}
|
55
|
-
else if (Zepto && Zepto.extend) {
|
56
|
-
return Zepto.extend(Zepto.extend({}, globals), locals);
|
57
|
-
}
|
58
|
-
else if (Object.extend) {
|
59
|
-
return Object.extend(Object.extend({}, globals), locals)
|
60
|
-
}
|
61
|
-
else if (Object.append) {
|
62
|
-
return Object.append(Object.append({}, globals), locals)
|
63
|
-
}
|
64
|
-
else { return locals }
|
65
|
-
});
|
66
|
-
|
67
|
-
/**
|
68
|
-
* HAML Coffee global template context.
|
69
|
-
*
|
70
|
-
* @return [Object] the global template context
|
71
|
-
*/
|
72
|
-
window.HAML.globals || (window.HAML.globals = function() {
|
73
|
-
return {}
|
74
|
-
});
|
75
|
-
|
76
|
-
/**
|
77
|
-
* Get the HAML template context. This merges the local
|
78
|
-
* and the global template context into a new context.
|
79
|
-
*
|
80
|
-
* @param locals [Object] the local template context
|
81
|
-
* @return [Object] the merged context
|
82
|
-
*/
|
83
|
-
window.HAML.context || (window.HAML.context = function(locals) {
|
84
|
-
return HAML.extend(HAML.globals(), locals)
|
85
|
-
});
|