slim 0.6.1 → 0.7.0.beta.2
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/.gitignore +8 -0
- data/Gemfile +1 -6
- data/Gemfile.lock +20 -16
- data/README.md +137 -90
- data/Rakefile +9 -37
- data/benchmarks/run.rb +63 -0
- data/benchmarks/src/complex.erb +23 -0
- data/benchmarks/src/complex.haml +18 -0
- data/benchmarks/src/complex.slim +18 -0
- data/benchmarks/src/complex_view.rb +17 -0
- data/lib/slim.rb +15 -11
- data/lib/slim/compiler.rb +71 -137
- data/lib/slim/embedded_engine.rb +108 -0
- data/lib/slim/end_inserter.rb +57 -0
- data/lib/slim/engine.rb +16 -14
- data/lib/slim/filter.rb +44 -0
- data/lib/slim/helpers.rb +37 -0
- data/lib/slim/parser.rb +355 -0
- data/lib/slim/rails.rb +2 -2
- data/lib/slim/template.rb +18 -0
- data/lib/slim/version.rb +3 -0
- data/slim.gemspec +26 -66
- data/test/helper.rb +32 -4
- data/test/slim/test_code_blocks.rb +33 -0
- data/test/slim/test_code_escaping.rb +69 -0
- data/test/slim/test_code_evaluation.rb +199 -0
- data/test/slim/test_code_helpers.rb +12 -0
- data/test/slim/test_code_output.rb +116 -0
- data/test/slim/test_code_structure.rb +84 -0
- data/test/slim/test_embedded_engines.rb +55 -0
- data/test/slim/test_html_escaping.rb +32 -0
- data/test/slim/test_html_structure.rb +181 -0
- data/test/slim/test_parser_errors.rb +98 -0
- data/test/slim/test_slim_template.rb +128 -0
- data/vim/slim.vim +33 -0
- data/vim/test.slim +27 -0
- metadata +127 -34
- data/lib/slim/optimizer.rb +0 -70
- data/readme.html +0 -159
- data/test/slim/test_compiler.rb +0 -389
- data/test/slim/test_engine.rb +0 -458
- data/test/test_slim.rb +0 -4
data/benchmarks/run.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib') << File.join(File.dirname(__FILE__), 'src')
|
4
|
+
|
5
|
+
require 'slim'
|
6
|
+
require 'complex_view'
|
7
|
+
|
8
|
+
require 'benchmark'
|
9
|
+
require 'ostruct'
|
10
|
+
require 'erubis'
|
11
|
+
require 'erb'
|
12
|
+
require 'haml'
|
13
|
+
|
14
|
+
class SlimBenchmarks
|
15
|
+
def initialize(iterations)
|
16
|
+
@iterations = (iterations || 1000).to_i
|
17
|
+
@benches = []
|
18
|
+
|
19
|
+
tpl_erb = File.read(File.dirname(__FILE__) + '/src/complex.erb')
|
20
|
+
tpl_haml = File.read(File.dirname(__FILE__) + '/src/complex.haml')
|
21
|
+
tpl_slim = File.read(File.dirname(__FILE__) + '/src/complex.slim')
|
22
|
+
|
23
|
+
view = ComplexView.new
|
24
|
+
eview = OpenStruct.new(:header => view.header, :item => view.item).instance_eval{ binding }
|
25
|
+
|
26
|
+
erb = ERB.new(tpl_erb)
|
27
|
+
erubis = Erubis::Eruby.new(tpl_erb)
|
28
|
+
fast_erubis = Erubis::FastEruby.new(tpl_erb)
|
29
|
+
haml = Haml::Engine.new(tpl_haml)
|
30
|
+
haml_ugly = Haml::Engine.new(tpl_haml, :ugly => true)
|
31
|
+
slim = Slim::Engine.new(tpl_slim)
|
32
|
+
|
33
|
+
bench('erb') { ERB.new(tpl_erb).result(eview) }
|
34
|
+
bench('erubis') { Erubis::Eruby.new(tpl_erb).result(eview) }
|
35
|
+
bench('fast erubis') { Erubis::Eruby.new(tpl_erb).result(eview) }
|
36
|
+
bench('slim') { Slim::Engine.new(tpl_slim).render(view) }
|
37
|
+
bench('haml') { Haml::Engine.new(tpl_haml).render(view) }
|
38
|
+
bench('haml ugly') { Haml::Engine.new(tpl_haml, :ugly => true).render(view) }
|
39
|
+
bench('erb (cached)') { erb.result(eview) }
|
40
|
+
bench('erubis (cached)') { erubis.result(eview) }
|
41
|
+
bench('fast erubis (cached)') { fast_erubis.result(eview) }
|
42
|
+
bench('slim (cached)') { slim.render(view) }
|
43
|
+
bench('haml (cached)') { haml.render(view) }
|
44
|
+
bench('haml ugly (cached)') { haml_ugly.render(view) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def run
|
48
|
+
puts "#{@iterations} Iterations"
|
49
|
+
Benchmark.bmbm do |x|
|
50
|
+
@benches.each do |name, block|
|
51
|
+
x.report name.to_s do
|
52
|
+
@iterations.to_i.times { block.call }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def bench(name, &block)
|
59
|
+
@benches.push([name, block])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
SlimBenchmarks.new(ARGV[0]).run
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!DOCTYPE HTML>
|
2
|
+
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<title>Simple Benchmark</title>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<h1><%= header %></h1>
|
9
|
+
<% unless item.empty? %>
|
10
|
+
<ul>
|
11
|
+
<% for i in item %>
|
12
|
+
<% if i[:current] %>
|
13
|
+
<li><strong><%= i[:name] %></strong></li>
|
14
|
+
<% else %>
|
15
|
+
<li><a href="<%= i[:url] %>"><%= i[:name] %></a></li>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
18
|
+
</ul>
|
19
|
+
<% else %>
|
20
|
+
<p>The list is empty.</p>
|
21
|
+
<% end %>
|
22
|
+
</body>
|
23
|
+
</html>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
!!! html
|
2
|
+
|
3
|
+
%body
|
4
|
+
%head
|
5
|
+
%title Simple Benchmark
|
6
|
+
%body
|
7
|
+
%h1= header
|
8
|
+
- unless item.empty?
|
9
|
+
%ul
|
10
|
+
- for i in item
|
11
|
+
- if i[:current]
|
12
|
+
%li
|
13
|
+
%strong= i[:name]
|
14
|
+
- else
|
15
|
+
%li
|
16
|
+
%a{:href => i[:url]}= i[:name]
|
17
|
+
- else
|
18
|
+
%p The list is empty.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
! doctype html
|
2
|
+
|
3
|
+
body
|
4
|
+
head
|
5
|
+
title Simple Benchmark
|
6
|
+
body
|
7
|
+
h1 == header
|
8
|
+
- unless item.empty?
|
9
|
+
ul
|
10
|
+
- for i in item
|
11
|
+
- if i[:current]
|
12
|
+
li
|
13
|
+
strong == i[:name]
|
14
|
+
- else
|
15
|
+
li
|
16
|
+
a href="#{i[:url]}" == i[:name]
|
17
|
+
- else
|
18
|
+
p The list is empty.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
|
3
|
+
class ComplexView
|
4
|
+
include Tilt::CompileSite
|
5
|
+
|
6
|
+
def header
|
7
|
+
"Colors"
|
8
|
+
end
|
9
|
+
|
10
|
+
def item
|
11
|
+
items = []
|
12
|
+
items << { :name => 'red', :current => true, :url => '#red' }
|
13
|
+
items << { :name => 'green', :current => false, :url => '#green' }
|
14
|
+
items << { :name => 'blue', :current => false, :url => '#blue' }
|
15
|
+
items
|
16
|
+
end
|
17
|
+
end
|
data/lib/slim.rb
CHANGED
@@ -1,20 +1,24 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
3
|
+
require 'temple'
|
4
|
+
require 'tilt'
|
4
5
|
|
5
|
-
require '
|
6
|
-
require '
|
6
|
+
require 'slim/helpers'
|
7
|
+
require 'slim/parser'
|
8
|
+
require 'slim/filter'
|
9
|
+
require 'slim/end_inserter'
|
10
|
+
require 'slim/embedded_engine'
|
7
11
|
require 'slim/compiler'
|
8
12
|
require 'slim/engine'
|
13
|
+
require 'slim/template'
|
9
14
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
+
begin
|
16
|
+
require 'escape_utils'
|
17
|
+
rescue LoadError
|
18
|
+
end
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
module Slim
|
21
|
+
def self.version
|
22
|
+
Slim::VERSION
|
19
23
|
end
|
20
24
|
end
|
data/lib/slim/compiler.rb
CHANGED
@@ -1,161 +1,95 @@
|
|
1
|
-
|
1
|
+
module Slim
|
2
|
+
# Compiles Slim expressions into Temple::HTML expressions.
|
3
|
+
class Compiler < Filter
|
4
|
+
def on_text(string)
|
5
|
+
if string.include?('#{')
|
6
|
+
[:dynamic, escape_interpolation(string)]
|
7
|
+
else
|
8
|
+
[:static, string]
|
9
|
+
end
|
10
|
+
end
|
2
11
|
|
3
|
-
|
12
|
+
def on_control(code, content)
|
13
|
+
[:multi,
|
14
|
+
[:block, code],
|
15
|
+
compile(content)]
|
16
|
+
end
|
4
17
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
AUTOCLOSED = %w{meta img link br hr input area param col base}
|
10
|
-
CONTROL_WORDS = %w{if unless do}
|
11
|
-
ELSE_CONTROL_WORDS = %w{else elsif}
|
12
|
-
|
13
|
-
REGEX_LINE_PARSER = /^(\s*)(!?`?\|?-?=?\/?\w*)\(?((\S*[#.]\S+)?(?:\s*(?:\w|-)*="[^=]+")*)?\)?(.*)/
|
14
|
-
|
15
|
-
REGEX_LINE_CONTAINS_OUTPUT_CODE = /^\s*=(.*)/
|
16
|
-
REGEX_LINE_CONTAINS_METHOD_DETECTED = /^((?:(?!#{CONTROL_WORDS * '\b|'}\b).)*)/
|
17
|
-
REGEX_METHOD_HAS_NO_PARENTHESES = /^\w+\s+\S+/
|
18
|
-
REGEX_CODE_BLOCK_DETECTED = / do ?.*$/
|
19
|
-
REGEX_CODE_CONTROL_WORD_DETECTED = /(?:\s|(\())(#{CONTROL_WORDS * '|'})\b\s?(.*)$/
|
20
|
-
REGEX_CODE_ELSE_CONTROL_WORD_DETECTED = /^#{ELSE_CONTROL_WORDS * '\b|'}\b/
|
21
|
-
REGEX_FIND_HTML_ATTR_ID = /#([^.\s]+)/
|
22
|
-
REGEX_FIND_HTML_ATTR_CLASSES = /\.([^#\s]+)/
|
23
|
-
|
24
|
-
def compile
|
25
|
-
@_buffer = ['_buf = [];']
|
26
|
-
in_text = false
|
27
|
-
enders = []
|
28
|
-
text_indent = last_indent = -1
|
29
|
-
|
30
|
-
@template.each_line do |line|
|
31
|
-
line.chomp!
|
32
|
-
line.rstrip!
|
33
|
-
|
34
|
-
if line.empty?
|
35
|
-
@_buffer << '_buf << "<br/>";' if in_text
|
36
|
-
next
|
37
|
-
end
|
18
|
+
def on_embedded(engine, *body)
|
19
|
+
EmbeddedEngine[engine].compile(body)
|
20
|
+
end
|
38
21
|
|
39
|
-
|
22
|
+
# why is escaping not handled by temple?
|
23
|
+
def on_output(escape, code, content)
|
24
|
+
if empty_exp?(content)
|
25
|
+
[:dynamic, escape ? escape_code(code) : code]
|
26
|
+
else
|
27
|
+
on_output_block(escape, code, content)
|
28
|
+
end
|
29
|
+
end
|
40
30
|
|
41
|
-
|
31
|
+
def on_output_block(escape, code, content)
|
32
|
+
tmp1, tmp2 = tmp_var, tmp_var
|
42
33
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
34
|
+
[:multi,
|
35
|
+
# Capture the result of the code in a variable. We can't do
|
36
|
+
# `[:dynamic, code]` because it's probably not a complete
|
37
|
+
# expression (which is a requirement for Temple).
|
38
|
+
[:block, "#{tmp1} = #{code}"],
|
48
39
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
# Remove the first space, but allow people to pad if they want.
|
55
|
-
string.slice!(0) if string =~ /^\s/
|
56
|
-
|
57
|
-
line_type = case marker
|
58
|
-
when '`', '|' then :text
|
59
|
-
when '-' then :control_code
|
60
|
-
when '=' then :output_code
|
61
|
-
when '!' then :declaration
|
62
|
-
when '/' then next # simply ignore any ruby code comments
|
63
|
-
else :markup
|
64
|
-
end
|
65
|
-
|
66
|
-
unless attrs.empty?
|
67
|
-
normalize_attributes!(attrs) if shortcut_attrs
|
68
|
-
attrs.gsub!('"', '\"')
|
69
|
-
attrs = " #{attrs}" unless attrs =~ /^\s/
|
70
|
-
end
|
40
|
+
# Capture the content of a block in a separate buffer. This means
|
41
|
+
# that `yield` will not output the content to the current buffer,
|
42
|
+
# but rather return the output.
|
43
|
+
[:capture, tmp2,
|
44
|
+
compile(content)],
|
71
45
|
|
72
|
-
|
73
|
-
|
74
|
-
break if enders.empty?
|
75
|
-
continue_closing = true
|
76
|
-
ender, ender_indent = enders.pop
|
77
|
-
|
78
|
-
unless ender_indent < indent || ender_indent == indent && string =~ REGEX_CODE_ELSE_CONTROL_WORD_DETECTED
|
79
|
-
@_buffer << ender
|
80
|
-
else
|
81
|
-
enders << [ender, ender_indent]
|
82
|
-
continue_closing = false
|
83
|
-
end
|
84
|
-
end while continue_closing == true
|
85
|
-
end
|
46
|
+
# Make sure that `yield` returns the output.
|
47
|
+
[:block, tmp2],
|
86
48
|
|
87
|
-
|
88
|
-
|
89
|
-
case line_type
|
90
|
-
when :markup
|
91
|
-
if AUTOCLOSED.include?(marker)
|
92
|
-
@_buffer << "_buf << \"<#{marker}#{attrs}/>\";"
|
93
|
-
else
|
94
|
-
# prepends "div" to the shortcut form of attrs if no marker is given
|
95
|
-
marker = 'div' if shortcut_attrs && marker.empty?
|
96
|
-
|
97
|
-
enders << ["_buf << \"</#{marker}>\";", indent]
|
98
|
-
@_buffer << "_buf << \"<#{marker}#{attrs}>\";"
|
99
|
-
end
|
100
|
-
|
101
|
-
if string =~ REGEX_LINE_CONTAINS_OUTPUT_CODE
|
102
|
-
@_buffer << "_buf << #{parse_string($1.strip)};"
|
103
|
-
else
|
104
|
-
@_buffer << "_buf << \"#{string}\";" unless string.empty?
|
105
|
-
end
|
106
|
-
when :text
|
107
|
-
in_text = true
|
108
|
-
text_indent = indent
|
109
|
-
@_buffer << "_buf << \"#{string}\";" unless string.empty?
|
110
|
-
when :control_code
|
111
|
-
enders << ['end;', indent] unless enders.detect{|e| e[0] == 'end;' && e[1] == indent}
|
112
|
-
@_buffer << "#{string};"
|
113
|
-
when :output_code
|
114
|
-
enders << ['end;', indent] if string =~ REGEX_CODE_BLOCK_DETECTED
|
115
|
-
@_buffer << "_buf << #{parse_string(string)};"
|
116
|
-
when :declaration
|
117
|
-
@_buffer << "_buf << \"<!#{string}>\";"
|
118
|
-
else
|
119
|
-
raise NotImplementedError.new("Don't know how to parse line: #{line}")
|
120
|
-
end
|
121
|
-
end # template iterator
|
49
|
+
# Close the block.
|
50
|
+
[:block, "end"],
|
122
51
|
|
123
|
-
|
124
|
-
|
52
|
+
# Output the content.
|
53
|
+
on_output(escape, tmp1, [:multi])]
|
54
|
+
end
|
55
|
+
|
56
|
+
def on_directive(type)
|
57
|
+
case type
|
58
|
+
when /^doctype/
|
59
|
+
[:html, :doctype, $'.strip]
|
60
|
+
else
|
125
61
|
end
|
62
|
+
end
|
126
63
|
|
127
|
-
|
64
|
+
def on_tag(name, attrs, content)
|
65
|
+
attrs = attrs.inject([:html, :attrs]) do |m, (key, value)|
|
66
|
+
if value.include?('#{')
|
67
|
+
value = [:dynamic, escape_interpolation(value)]
|
68
|
+
else
|
69
|
+
value = [:static, value]
|
70
|
+
end
|
71
|
+
m << [:html, :basicattr, [:static, key], value]
|
72
|
+
end
|
128
73
|
|
129
|
-
|
130
|
-
@optimized = optimize!
|
74
|
+
[:html, :tag, name, attrs, compile(content)]
|
131
75
|
end
|
132
76
|
|
133
77
|
private
|
134
78
|
|
135
|
-
def
|
136
|
-
|
137
|
-
$1
|
138
|
-
else
|
139
|
-
parenthesesify_method!(string) if string =~ REGEX_METHOD_HAS_NO_PARENTHESES
|
140
|
-
wraps_with_slim_escape!(string) unless string =~ REGEX_CODE_BLOCK_DETECTED
|
141
|
-
string.strip
|
79
|
+
def escape_interpolation(string)
|
80
|
+
string.gsub!(/(.?)\#\{(.*?)\}/) do
|
81
|
+
$1 == '\\' ? $& : "#{$1}#\{#{escape_code($2)}}"
|
142
82
|
end
|
83
|
+
'"%s"' % string
|
143
84
|
end
|
144
85
|
|
145
|
-
|
146
|
-
|
147
|
-
string.sub!(' ', '(') && string.sub!(REGEX_CODE_CONTROL_WORD_DETECTED, '\1) \2 \3') || string << ')'
|
148
|
-
end
|
149
|
-
|
150
|
-
# escapes the string
|
151
|
-
def wraps_with_slim_escape!(string)
|
152
|
-
string.sub!(REGEX_LINE_CONTAINS_METHOD_DETECTED, 'Slim.escape_html(\1)')
|
86
|
+
def escape_code(param)
|
87
|
+
"Slim::Helpers.escape_html#{@options[:use_html_safe] ? '_safe' : ''}((#{param}))"
|
153
88
|
end
|
154
89
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
string.sub!(REGEX_FIND_HTML_ATTR_CLASSES, ' class="\1"') && string.gsub!('.', ' ')
|
90
|
+
def tmp_var
|
91
|
+
@tmp_var ||= 0
|
92
|
+
"_slimtmp#{@tmp_var += 1}"
|
159
93
|
end
|
160
94
|
end
|
161
95
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Slim
|
2
|
+
class EmbeddedEngine
|
3
|
+
@engines = {}
|
4
|
+
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.[](name)
|
12
|
+
engine = @engines[name.to_s]
|
13
|
+
raise "Invalid embedded engine #{name}" if !engine
|
14
|
+
engine.dup
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.register(name, klass, options = {})
|
18
|
+
options.merge!(:name => name.to_s)
|
19
|
+
@engines[name.to_s] = klass.new(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def collect_text(body)
|
23
|
+
body.inject('') do |text, exp|
|
24
|
+
if exp[0] == :slim && exp[1] == :text
|
25
|
+
text << exp[2]
|
26
|
+
elsif exp[0] == :newline
|
27
|
+
text << "\n"
|
28
|
+
end
|
29
|
+
text
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class TiltEngine < EmbeddedEngine
|
34
|
+
# Code to collect local variables
|
35
|
+
COLLECT_LOCALS = %q{eval('{' + local_variables.select {|v| v[0] != ?_ }.map {|v| ":#{v}=>#{v}" }.join(',') + '}')}
|
36
|
+
|
37
|
+
def compile(body)
|
38
|
+
text = collect_text(body)
|
39
|
+
engine = Tilt[options[:name]]
|
40
|
+
if options[:precompiled]
|
41
|
+
# Wrap precompiled code in proc, local variables from out the proc are accessible
|
42
|
+
# WARNING: This is a bit of a hack. Tilt::Engine#precompiled is protected
|
43
|
+
precompiled = engine.new { text }.send(:precompiled, {}).first
|
44
|
+
[:dynamic, "proc { #{precompiled} }.call"]
|
45
|
+
elsif options[:dynamic]
|
46
|
+
# Fully dynamic evaluation of the template during runtime (Slow and uncached)
|
47
|
+
[:dynamic, "#{engine.name}.new { #{text.inspect} }.render(self, #{COLLECT_LOCALS})"]
|
48
|
+
elsif options[:interpolate]
|
49
|
+
# Static template with interpolated ruby code
|
50
|
+
[:dynamic, '"%s"' % engine.new { text }.render]
|
51
|
+
else
|
52
|
+
# Static template
|
53
|
+
[:static, engine.new { text }.render]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class TagEngine < EmbeddedEngine
|
59
|
+
def compile_text(body)
|
60
|
+
body.inject([:multi]) do |block, exp|
|
61
|
+
block << (exp[0] == :slim && exp[1] == :text ? [:static, exp[2]] : exp)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def compile(body)
|
66
|
+
attrs = [:html, :attrs]
|
67
|
+
options[:attributes].each do |key, value|
|
68
|
+
attrs << [:html, :basicattr, [:static, key.to_s], [:static, value.to_s]]
|
69
|
+
end
|
70
|
+
[:html, :tag, options[:tag], attrs, compile_text(body)]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class RubyEngine < EmbeddedEngine
|
75
|
+
def compile(body)
|
76
|
+
[:block, collect_text(body)]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# These engines are executed at compile time, embedded ruby is interpolated
|
81
|
+
register :markdown, TiltEngine, :interpolate => true
|
82
|
+
register :textile, TiltEngine, :interpolate => true
|
83
|
+
register :rdoc, TiltEngine, :interpolate => true
|
84
|
+
|
85
|
+
# These engines are executed at compile time
|
86
|
+
register :sass, TiltEngine
|
87
|
+
register :less, TiltEngine
|
88
|
+
register :coffee, TiltEngine
|
89
|
+
|
90
|
+
# These engines are precompiled, code is embedded
|
91
|
+
register :erb, TiltEngine, :precompiled => true
|
92
|
+
register :haml, TiltEngine, :precompiled => true
|
93
|
+
register :nokogiri, TiltEngine, :precompiled => true
|
94
|
+
register :builder, TiltEngine, :precompiled => true
|
95
|
+
|
96
|
+
# These engines are completely executed at runtime (Usage not recommended, no caching!)
|
97
|
+
register :liquid, TiltEngine, :dynamic => true
|
98
|
+
register :radius, TiltEngine, :dynamic => true
|
99
|
+
register :markaby, TiltEngine, :dynamic => true
|
100
|
+
|
101
|
+
# Embedded javascript/css
|
102
|
+
register :javascript, TagEngine, :tag => 'script', :attributes => { :type => 'text/javascript' }
|
103
|
+
register :css, TagEngine, :tag => 'style', :attributes => { :type => 'text/css' }
|
104
|
+
|
105
|
+
# Embedded ruby code
|
106
|
+
register :ruby, RubyEngine
|
107
|
+
end
|
108
|
+
end
|