slim 0.6.1 → 0.7.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|