fast_haml 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.travis.yml +25 -0
- data/Appraisals +26 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +96 -0
- data/Rakefile +11 -0
- data/benchmark/rendering.rb +29 -0
- data/bin/fast_haml +4 -0
- data/ext/attribute_builder/attribute_builder.c +259 -0
- data/ext/attribute_builder/extconf.rb +3 -0
- data/fast_haml.gemspec +35 -0
- data/gemfiles/rails_4.0.gemfile +9 -0
- data/gemfiles/rails_4.1.gemfile +9 -0
- data/gemfiles/rails_4.2.gemfile +9 -0
- data/gemfiles/rails_edge.gemfile +10 -0
- data/haml_spec_test.rb +22 -0
- data/lib/fast_haml/ast.rb +112 -0
- data/lib/fast_haml/cli.rb +38 -0
- data/lib/fast_haml/compiler.rb +325 -0
- data/lib/fast_haml/element_parser.rb +288 -0
- data/lib/fast_haml/engine.rb +32 -0
- data/lib/fast_haml/filter_compilers/base.rb +29 -0
- data/lib/fast_haml/filter_compilers/cdata.rb +15 -0
- data/lib/fast_haml/filter_compilers/css.rb +15 -0
- data/lib/fast_haml/filter_compilers/escaped.rb +22 -0
- data/lib/fast_haml/filter_compilers/javascript.rb +15 -0
- data/lib/fast_haml/filter_compilers/plain.rb +17 -0
- data/lib/fast_haml/filter_compilers/preserve.rb +30 -0
- data/lib/fast_haml/filter_compilers/ruby.rb +13 -0
- data/lib/fast_haml/filter_compilers.rb +37 -0
- data/lib/fast_haml/filter_parser.rb +54 -0
- data/lib/fast_haml/html.rb +44 -0
- data/lib/fast_haml/indent_tracker.rb +84 -0
- data/lib/fast_haml/line_parser.rb +66 -0
- data/lib/fast_haml/parser.rb +251 -0
- data/lib/fast_haml/parser_utils.rb +17 -0
- data/lib/fast_haml/rails_handler.rb +10 -0
- data/lib/fast_haml/railtie.rb +8 -0
- data/lib/fast_haml/ruby_multiline.rb +23 -0
- data/lib/fast_haml/static_hash_parser.rb +113 -0
- data/lib/fast_haml/syntax_error.rb +10 -0
- data/lib/fast_haml/text_compiler.rb +69 -0
- data/lib/fast_haml/tilt.rb +16 -0
- data/lib/fast_haml/version.rb +3 -0
- data/lib/fast_haml.rb +10 -0
- data/spec/rails/Rakefile +6 -0
- data/spec/rails/app/assets/images/.keep +0 -0
- data/spec/rails/app/assets/javascripts/application.js +13 -0
- data/spec/rails/app/assets/stylesheets/application.css +15 -0
- data/spec/rails/app/controllers/application_controller.rb +5 -0
- data/spec/rails/app/controllers/books_controller.rb +8 -0
- data/spec/rails/app/controllers/concerns/.keep +0 -0
- data/spec/rails/app/helpers/application_helper.rb +2 -0
- data/spec/rails/app/mailers/.keep +0 -0
- data/spec/rails/app/models/.keep +0 -0
- data/spec/rails/app/models/book.rb +9 -0
- data/spec/rails/app/models/concerns/.keep +0 -0
- data/spec/rails/app/views/books/hello.html.haml +2 -0
- data/spec/rails/app/views/books/with_capture.html.haml +4 -0
- data/spec/rails/app/views/books/with_variables.html.haml +4 -0
- data/spec/rails/app/views/layouts/application.html.haml +9 -0
- data/spec/rails/bin/bundle +3 -0
- data/spec/rails/bin/rails +4 -0
- data/spec/rails/bin/rake +4 -0
- data/spec/rails/bin/setup +29 -0
- data/spec/rails/config/application.rb +12 -0
- data/spec/rails/config/boot.rb +3 -0
- data/spec/rails/config/database.yml +25 -0
- data/spec/rails/config/environment.rb +5 -0
- data/spec/rails/config/environments/development.rb +41 -0
- data/spec/rails/config/environments/production.rb +79 -0
- data/spec/rails/config/environments/test.rb +42 -0
- data/spec/rails/config/initializers/assets.rb +11 -0
- data/spec/rails/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails/config/initializers/cookies_serializer.rb +3 -0
- data/spec/rails/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/rails/config/initializers/inflections.rb +16 -0
- data/spec/rails/config/initializers/mime_types.rb +4 -0
- data/spec/rails/config/initializers/secret_key_base.rb +6 -0
- data/spec/rails/config/initializers/session_store.rb +3 -0
- data/spec/rails/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails/config/locales/en.yml +23 -0
- data/spec/rails/config/routes.rb +7 -0
- data/spec/rails/config/secrets.yml +22 -0
- data/spec/rails/config.ru +4 -0
- data/spec/rails/db/seeds.rb +7 -0
- data/spec/rails/lib/assets/.keep +0 -0
- data/spec/rails/lib/tasks/.keep +0 -0
- data/spec/rails/log/.keep +0 -0
- data/spec/rails/public/404.html +67 -0
- data/spec/rails/public/422.html +67 -0
- data/spec/rails/public/500.html +66 -0
- data/spec/rails/public/favicon.ico +0 -0
- data/spec/rails/public/robots.txt +5 -0
- data/spec/rails/spec/requests/fast_haml_spec.rb +41 -0
- data/spec/rails/vendor/assets/javascripts/.keep +0 -0
- data/spec/rails/vendor/assets/stylesheets/.keep +0 -0
- data/spec/rails_helper.rb +4 -0
- data/spec/render/attribute_spec.rb +209 -0
- data/spec/render/comment_spec.rb +61 -0
- data/spec/render/doctype_spec.rb +62 -0
- data/spec/render/element_spec.rb +165 -0
- data/spec/render/filters/cdata_spec.rb +12 -0
- data/spec/render/filters/css_spec.rb +45 -0
- data/spec/render/filters/escaped_spec.rb +14 -0
- data/spec/render/filters/javascript_spec.rb +44 -0
- data/spec/render/filters/plain_spec.rb +24 -0
- data/spec/render/filters/preserve_spec.rb +25 -0
- data/spec/render/filters/ruby_spec.rb +13 -0
- data/spec/render/filters_spec.rb +11 -0
- data/spec/render/haml_comment_spec.rb +24 -0
- data/spec/render/multiline_spec.rb +39 -0
- data/spec/render/plain_spec.rb +20 -0
- data/spec/render/preserve_spec.rb +8 -0
- data/spec/render/sanitize_spec.rb +36 -0
- data/spec/render/script_spec.rb +74 -0
- data/spec/render/silent_script_spec.rb +97 -0
- data/spec/render/unescape_spec.rb +40 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/tilt_spec.rb +33 -0
- metadata +427 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
module FastHaml
|
2
|
+
module Ast
|
3
|
+
module Construct
|
4
|
+
end
|
5
|
+
|
6
|
+
module HasChildren
|
7
|
+
def initialize(*)
|
8
|
+
super
|
9
|
+
self.children ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(ast)
|
13
|
+
self.children << ast
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Root < Struct.new(:children)
|
18
|
+
include HasChildren
|
19
|
+
end
|
20
|
+
|
21
|
+
class Doctype < Struct.new(:doctype)
|
22
|
+
end
|
23
|
+
|
24
|
+
class Element < Struct.new(
|
25
|
+
:children,
|
26
|
+
:tag_name,
|
27
|
+
:static_class,
|
28
|
+
:static_id,
|
29
|
+
:attributes,
|
30
|
+
:oneline_child,
|
31
|
+
:self_closing,
|
32
|
+
:nuke_inner_whitespace,
|
33
|
+
:nuke_outer_whitespace,
|
34
|
+
)
|
35
|
+
include HasChildren
|
36
|
+
|
37
|
+
def initialize(*)
|
38
|
+
super
|
39
|
+
self.static_class ||= ''
|
40
|
+
self.static_id ||= ''
|
41
|
+
self.attributes ||= ''
|
42
|
+
self.self_closing ||= false
|
43
|
+
self.nuke_inner_whitespace ||= false
|
44
|
+
self.nuke_outer_whitespace ||= false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Script < Struct.new(
|
49
|
+
:children,
|
50
|
+
:script,
|
51
|
+
:escape_html,
|
52
|
+
:preserve,
|
53
|
+
:mid_block_keyword,
|
54
|
+
)
|
55
|
+
include HasChildren
|
56
|
+
|
57
|
+
def initialize(*)
|
58
|
+
super
|
59
|
+
if self.escape_html.nil?
|
60
|
+
self.escape_html = true
|
61
|
+
end
|
62
|
+
if self.preserve.nil?
|
63
|
+
self.preserve = false
|
64
|
+
end
|
65
|
+
if self.mid_block_keyword.nil?
|
66
|
+
self.mid_block_keyword = false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class SilentScript < Struct.new(:children, :script, :mid_block_keyword)
|
72
|
+
include HasChildren
|
73
|
+
|
74
|
+
def initialize(*)
|
75
|
+
super
|
76
|
+
if self.mid_block_keyword.nil?
|
77
|
+
self.mid_block_keyword = false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class HtmlComment < Struct.new(:children, :comment, :conditional)
|
83
|
+
include HasChildren
|
84
|
+
|
85
|
+
def initialize(*)
|
86
|
+
super
|
87
|
+
self.comment ||= ''
|
88
|
+
self.conditional ||= ''
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class HamlComment < Struct.new(:children)
|
93
|
+
include HasChildren
|
94
|
+
end
|
95
|
+
|
96
|
+
class Text < Struct.new(:text, :escape_html)
|
97
|
+
def initialize(*)
|
98
|
+
super
|
99
|
+
if self.escape_html.nil?
|
100
|
+
self.escape_html = true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Filter < Struct.new(:name, :texts)
|
106
|
+
def initialize(*)
|
107
|
+
super
|
108
|
+
self.texts ||= []
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'fast_haml'
|
2
|
+
require 'thor'
|
3
|
+
|
4
|
+
module FastHaml
|
5
|
+
class CLI < Thor
|
6
|
+
desc 'render FILE', 'Render haml template'
|
7
|
+
def render(file)
|
8
|
+
puts eval(compile_file(file))
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'compile FILE', 'Compile haml template'
|
12
|
+
def compile(file)
|
13
|
+
puts compile_file(file)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'parse FILE', 'Render fast_haml AST'
|
17
|
+
def parse(file)
|
18
|
+
require 'pp'
|
19
|
+
pp parse_file(file)
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'temple FILE', 'Render temple AST'
|
23
|
+
def temple(file)
|
24
|
+
require 'pp'
|
25
|
+
pp FastHaml::Compiler.new.call(parse_file(file))
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def compile_file(file)
|
31
|
+
FastHaml::Engine.new.call(File.read(file))
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_file(file)
|
35
|
+
FastHaml::Parser.new.call(File.read(file))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,325 @@
|
|
1
|
+
require 'temple'
|
2
|
+
require 'fast_haml/ast'
|
3
|
+
require 'fast_haml/filter_compilers'
|
4
|
+
require 'fast_haml/static_hash_parser'
|
5
|
+
require 'fast_haml/text_compiler'
|
6
|
+
|
7
|
+
module FastHaml
|
8
|
+
class Compiler < Temple::Parser
|
9
|
+
DEFAULT_AUTO_CLOSE_TAGS = %w[
|
10
|
+
area base basefont br col command embed frame hr img input isindex keygen
|
11
|
+
link menuitem meta param source track wbr
|
12
|
+
]
|
13
|
+
DEFAULT_PRESERVE_TAGS = %w[pre textarea code]
|
14
|
+
|
15
|
+
define_options(
|
16
|
+
autoclose: DEFAULT_AUTO_CLOSE_TAGS,
|
17
|
+
format: :html,
|
18
|
+
preserve: DEFAULT_PRESERVE_TAGS,
|
19
|
+
)
|
20
|
+
|
21
|
+
def initialize(*)
|
22
|
+
super
|
23
|
+
@text_compiler = TextCompiler.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(ast)
|
27
|
+
compile(ast)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.find_and_preserve(input)
|
31
|
+
# Taken from the original haml code
|
32
|
+
re = /<(#{options[:preserve].map(&Regexp.method(:escape)).join('|')})([^>]*)>(.*?)(<\/\1>)/im
|
33
|
+
input.to_s.gsub(re) do |s|
|
34
|
+
s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible
|
35
|
+
"<#{$1}#{$2}>#{preserve($3)}</#{$1}>"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.preserve(input)
|
40
|
+
# Taken from the original haml code
|
41
|
+
input.to_s.chomp("\n").gsub(/\n/, '
').gsub(/\r/, '')
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def compile(ast)
|
47
|
+
case ast
|
48
|
+
when Ast::Root
|
49
|
+
compile_root(ast)
|
50
|
+
when Ast::Doctype
|
51
|
+
compile_doctype(ast)
|
52
|
+
when Ast::HtmlComment
|
53
|
+
compile_html_comment(ast)
|
54
|
+
when Ast::HamlComment
|
55
|
+
[:multi]
|
56
|
+
when Ast::Element
|
57
|
+
compile_element(ast)
|
58
|
+
when Ast::Script
|
59
|
+
compile_script(ast)
|
60
|
+
when Ast::SilentScript
|
61
|
+
compile_silent_script(ast)
|
62
|
+
when Ast::Text
|
63
|
+
compile_text(ast)
|
64
|
+
when Ast::Filter
|
65
|
+
compile_filter(ast)
|
66
|
+
else
|
67
|
+
raise "InternalError: Unknown AST node #{ast.class}: #{ast.inspect}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def compile_root(ast)
|
72
|
+
[:multi, [:newline]].tap do |temple|
|
73
|
+
compile_children(ast, temple)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def compile_children(ast, temple)
|
78
|
+
was_newline = false
|
79
|
+
ast.children.each do |c|
|
80
|
+
if c.is_a?(Ast::Element) && c.nuke_outer_whitespace && was_newline
|
81
|
+
# pop newline
|
82
|
+
x = temple.pop
|
83
|
+
if x != [:newline]
|
84
|
+
raise "InternalError: Unexpected pop (expected [:newline]): #{x}"
|
85
|
+
end
|
86
|
+
x = temple.pop
|
87
|
+
if x != [:static, "\n"]
|
88
|
+
raise "InternalError: Unexpected pop (expected [:static, newline]): #{x}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
temple << compile(c)
|
92
|
+
if was_newline = need_newline?(ast, c)
|
93
|
+
temple << [:static, "\n"]
|
94
|
+
temple << [:newline]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def need_newline?(parent, child)
|
100
|
+
if parent.is_a?(Ast::Element) && nuke_inner_whitespace?(parent) && parent.children.last.equal?(child)
|
101
|
+
return false
|
102
|
+
end
|
103
|
+
case child
|
104
|
+
when Ast::Script
|
105
|
+
child.children.empty?
|
106
|
+
when Ast::SilentScript, Ast::HamlComment
|
107
|
+
false
|
108
|
+
when Ast::Element
|
109
|
+
!child.nuke_outer_whitespace
|
110
|
+
else
|
111
|
+
true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def compile_text(ast)
|
116
|
+
@text_compiler.compile(ast.text, escape_html: ast.escape_html)
|
117
|
+
end
|
118
|
+
|
119
|
+
# html5 and html4 is deprecated in temple.
|
120
|
+
DEFAULT_DOCTYPE = {
|
121
|
+
html: 'html',
|
122
|
+
html5: 'html',
|
123
|
+
html4: 'transitional',
|
124
|
+
xhtml: 'transitional',
|
125
|
+
}.freeze
|
126
|
+
|
127
|
+
def compile_doctype(ast)
|
128
|
+
doctype = ast.doctype.downcase
|
129
|
+
if doctype.empty?
|
130
|
+
doctype = DEFAULT_DOCTYPE[options[:format]]
|
131
|
+
end
|
132
|
+
[:haml, :doctype, doctype]
|
133
|
+
end
|
134
|
+
|
135
|
+
def compile_html_comment(ast)
|
136
|
+
if ast.children.empty?
|
137
|
+
if ast.conditional.empty?
|
138
|
+
[:html, :comment, [:static, " #{ast.comment} "]]
|
139
|
+
else
|
140
|
+
[:html, :comment, [:static, "[#{ast.conditional}]> #{ast.comment} <![endif]"]]
|
141
|
+
end
|
142
|
+
else
|
143
|
+
temple = [:multi]
|
144
|
+
if ast.conditional.empty?
|
145
|
+
temple << [:static, "\n"]
|
146
|
+
else
|
147
|
+
temple << [:static, "[#{ast.conditional}]>\n"]
|
148
|
+
end
|
149
|
+
compile_children(ast, temple)
|
150
|
+
unless ast.conditional.empty?
|
151
|
+
temple << [:static, "<![endif]"]
|
152
|
+
end
|
153
|
+
[:multi, [:html, :comment, temple]]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def compile_element(ast)
|
158
|
+
temple = [
|
159
|
+
:haml, :tag,
|
160
|
+
ast.tag_name,
|
161
|
+
self_closing?(ast),
|
162
|
+
compile_attributes(ast.attributes, ast.static_id, ast.static_class),
|
163
|
+
]
|
164
|
+
|
165
|
+
if ast.oneline_child
|
166
|
+
temple << compile(ast.oneline_child)
|
167
|
+
elsif !ast.children.empty?
|
168
|
+
children = [:multi]
|
169
|
+
unless nuke_inner_whitespace?(ast)
|
170
|
+
children << [:static, "\n"]
|
171
|
+
end
|
172
|
+
children << [:newline]
|
173
|
+
compile_children(ast, children)
|
174
|
+
temple << children
|
175
|
+
end
|
176
|
+
|
177
|
+
temple
|
178
|
+
end
|
179
|
+
|
180
|
+
def self_closing?(ast)
|
181
|
+
ast.self_closing || options[:autoclose].include?(ast.tag_name)
|
182
|
+
end
|
183
|
+
|
184
|
+
def nuke_inner_whitespace?(ast)
|
185
|
+
ast.nuke_inner_whitespace || options[:preserve].include?(ast.tag_name)
|
186
|
+
end
|
187
|
+
|
188
|
+
def compile_attributes(text, static_id, static_class)
|
189
|
+
if text.empty?
|
190
|
+
return compile_static_id_and_class(static_id, static_class)
|
191
|
+
end
|
192
|
+
|
193
|
+
if attrs = try_optimize_attributes(text, static_id, static_class)
|
194
|
+
return [:html, :attrs, *attrs]
|
195
|
+
end
|
196
|
+
|
197
|
+
# Slow version
|
198
|
+
|
199
|
+
h = {}
|
200
|
+
unless static_class.empty?
|
201
|
+
h[:class] = static_class.split(/ +/)
|
202
|
+
end
|
203
|
+
unless static_id.empty?
|
204
|
+
h[:id] = static_id
|
205
|
+
end
|
206
|
+
|
207
|
+
t =
|
208
|
+
if h.empty?
|
209
|
+
text
|
210
|
+
else
|
211
|
+
"#{h.inspect}, #{text}"
|
212
|
+
end
|
213
|
+
[:haml, :attrs, t]
|
214
|
+
end
|
215
|
+
|
216
|
+
def compile_static_id_and_class(static_id, static_class)
|
217
|
+
[:html, :attrs].tap do |html_attrs|
|
218
|
+
unless static_class.empty?
|
219
|
+
html_attrs << [:haml, :attr, 'class', [:static, static_class]]
|
220
|
+
end
|
221
|
+
unless static_id.empty?
|
222
|
+
html_attrs << [:haml, :attr, 'id', [:static, static_id]]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def try_optimize_attributes(text, static_id, static_class)
|
228
|
+
parser = StaticHashParser.new
|
229
|
+
unless parser.parse("{#{text}}")
|
230
|
+
return nil
|
231
|
+
end
|
232
|
+
|
233
|
+
static_attributes, dynamic_attributes = build_optimized_attributes(parser, static_id, static_class)
|
234
|
+
if static_attributes.nil?
|
235
|
+
return nil
|
236
|
+
end
|
237
|
+
|
238
|
+
if dynamic_attributes.has_key?('data')
|
239
|
+
# XXX: Quit optimization...
|
240
|
+
return nil
|
241
|
+
end
|
242
|
+
|
243
|
+
(static_attributes.keys + dynamic_attributes.keys).sort.flat_map do |k|
|
244
|
+
if static_attributes.has_key?(k)
|
245
|
+
compile_static_attribute(k, static_attributes[k])
|
246
|
+
else
|
247
|
+
compile_dynamic_attribute(k, dynamic_attributes[k])
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def build_optimized_attributes(parser, static_id, static_class)
|
253
|
+
static_attributes = {}
|
254
|
+
parser.static_attributes.each do |k, v|
|
255
|
+
static_attributes[k.to_s] = v;
|
256
|
+
end
|
257
|
+
unless static_class.empty?
|
258
|
+
static_attributes['class'] = [static_class.split(/ +/), static_attributes['class']].compact.flatten.sort.join(' ')
|
259
|
+
end
|
260
|
+
unless static_id.empty?
|
261
|
+
static_attributes['id'] = [static_id, static_attributes['id']].compact.join('_')
|
262
|
+
end
|
263
|
+
|
264
|
+
dynamic_attributes = {}
|
265
|
+
parser.dynamic_attributes.each do |k, v|
|
266
|
+
k = k.to_s
|
267
|
+
if static_attributes.has_key?(k)
|
268
|
+
if StaticHashParser::SPECIAL_ATTRIBUTES.include?(k)
|
269
|
+
# XXX: Quit optimization
|
270
|
+
return [nil, nil]
|
271
|
+
end
|
272
|
+
end
|
273
|
+
dynamic_attributes[k] = v
|
274
|
+
end
|
275
|
+
|
276
|
+
[static_attributes, dynamic_attributes]
|
277
|
+
end
|
278
|
+
|
279
|
+
def compile_static_attribute(key, value)
|
280
|
+
case
|
281
|
+
when value == true
|
282
|
+
[[:haml, :attr, key, [:multi]]]
|
283
|
+
when value.is_a?(Hash) && key == 'data'
|
284
|
+
data = AttributeBuilder.normalize_data(value)
|
285
|
+
data.keys.sort.map do |k|
|
286
|
+
[:haml, :attr, "data-#{k}", [:static, Temple::Utils.escape_html(data[k])]]
|
287
|
+
end
|
288
|
+
else
|
289
|
+
[[:haml, :attr, key, [:static, Temple::Utils.escape_html(value)]]]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def compile_dynamic_attribute(key, value)
|
294
|
+
[[:haml, :attr, key, [:escape, true, [:dynamic, value]]]]
|
295
|
+
end
|
296
|
+
|
297
|
+
def compile_script(ast)
|
298
|
+
sym = unique_name
|
299
|
+
temple = [:multi, [:code, "#{sym} = #{ast.script}"], [:newline]]
|
300
|
+
compile_children(ast, temple)
|
301
|
+
if !ast.children.empty? && !ast.mid_block_keyword
|
302
|
+
temple << [:code, 'end']
|
303
|
+
end
|
304
|
+
if !ast.escape_html && ast.preserve
|
305
|
+
temple << [:haml, :preserve, sym]
|
306
|
+
else
|
307
|
+
temple << [:escape, ast.escape_html, [:dynamic, "#{sym}.to_s"]]
|
308
|
+
end
|
309
|
+
temple
|
310
|
+
end
|
311
|
+
|
312
|
+
def compile_silent_script(ast)
|
313
|
+
temple = [:multi, [:code, ast.script], [:newline]]
|
314
|
+
compile_children(ast, temple)
|
315
|
+
if !ast.children.empty? && !ast.mid_block_keyword
|
316
|
+
temple << [:code, 'end']
|
317
|
+
end
|
318
|
+
temple
|
319
|
+
end
|
320
|
+
|
321
|
+
def compile_filter(ast)
|
322
|
+
FilterCompilers.find(ast.name).compile(ast.texts)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|