fast_haml 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +18 -0
- data/lib/fast_haml/ast.rb +0 -6
- data/lib/fast_haml/compiler.rb +32 -30
- data/lib/fast_haml/engine.rb +2 -0
- data/lib/fast_haml/newline.rb +30 -0
- data/lib/fast_haml/version.rb +1 -1
- data/spec/compiler_newline_spec.rb +19 -0
- data/spec/render/attribute_spec.rb +4 -0
- data/spec/render/element_spec.rb +0 -39
- data/spec/render/newline_spec.rb +83 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec965b362a4b85f320d2144ebc3117d16476505a
|
4
|
+
data.tar.gz: 4cdd71b4c7664e6fe6e9bf74f225be290b02456e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e8e90941f16081fba0ffc531cdcbc84fba4cf65ff629ebfcee51b50ad65660c78b4b92fbe965afa7798e3407567cdddc2064317fd996cec82c140a015831f71
|
7
|
+
data.tar.gz: f461f513f3e2d5249156e5dcc399216c777057431ebb5027bedcc372bd25e15d1374b961267d0d62af159250747a175ab66f27d3c4ccdc380bdae797ec44007b
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -88,6 +88,24 @@ I introduced incompatibility to expand the chance: all attribute values are conv
|
|
88
88
|
This will enable us to avoid runtime expensive hash merging and rendering.
|
89
89
|
The runtime hash merging is implemented by C extension in fast_haml.
|
90
90
|
|
91
|
+
Internally, attributes are categolized into three types.
|
92
|
+
|
93
|
+
1. Static attributes
|
94
|
+
- Both the key and the value are literal.
|
95
|
+
- Compiled into string literals.
|
96
|
+
- Fastest.
|
97
|
+
- e.g. `%input{checked: false}`
|
98
|
+
2. Dynamic attributes
|
99
|
+
- The key is literal but the value isn't.
|
100
|
+
- The key is compiled into string literal. The value is interpolated at run-time.
|
101
|
+
- Relatively fast.
|
102
|
+
- e.g. `%input{checked: helper_method(@record)}`
|
103
|
+
3. Ruby attributes
|
104
|
+
- Both the key and the value are non-literal expression.
|
105
|
+
- The attributes are stringified at run-time.
|
106
|
+
- Slow.
|
107
|
+
- e.g. `%input{helper_method(@record)}`
|
108
|
+
|
91
109
|
## Contributing
|
92
110
|
|
93
111
|
1. Fork it ( https://github.com/eagletmt/fast_haml/fork )
|
data/lib/fast_haml/ast.rb
CHANGED
data/lib/fast_haml/compiler.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'parser/current'
|
1
2
|
require 'temple'
|
2
3
|
require 'fast_haml/ast'
|
3
4
|
require 'fast_haml/filter_compilers'
|
@@ -6,6 +7,9 @@ require 'fast_haml/text_compiler'
|
|
6
7
|
|
7
8
|
module FastHaml
|
8
9
|
class Compiler < Temple::Parser
|
10
|
+
class UnparsableRubyCode < StandardError
|
11
|
+
end
|
12
|
+
|
9
13
|
DEFAULT_AUTO_CLOSE_TAGS = %w[
|
10
14
|
area base basefont br col command embed frame hr img input isindex keygen
|
11
15
|
link menuitem meta param source track wbr
|
@@ -72,34 +76,15 @@ module FastHaml
|
|
72
76
|
|
73
77
|
def compile_root(ast)
|
74
78
|
[:multi].tap do |temple|
|
75
|
-
temple.concat([[:newline]] * ast.leading_empty_lines)
|
76
79
|
compile_children(ast, temple)
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
80
83
|
def compile_children(ast, temple)
|
81
|
-
was_newline = false
|
82
84
|
ast.children.each do |c|
|
83
|
-
if c.is_a?(Ast::Element) && c.nuke_outer_whitespace && was_newline
|
84
|
-
# pop newline
|
85
|
-
x = temple.pop
|
86
|
-
if x == [:newline]
|
87
|
-
x = temple.pop
|
88
|
-
if x != [:static, "\n"]
|
89
|
-
raise "InternalError: Unexpected pop (expected [:static, \\n]): #{x}"
|
90
|
-
end
|
91
|
-
elsif x == [:static, "\n"]
|
92
|
-
# nothing
|
93
|
-
else
|
94
|
-
raise "InternalError: Unexpected pop (expected [:newline] or [:static, \\n]): #{x}"
|
95
|
-
end
|
96
|
-
unless suppress_code_newline?(c.oneline_child)
|
97
|
-
temple << [:newline]
|
98
|
-
end
|
99
|
-
end
|
100
85
|
temple << compile(c)
|
101
|
-
if
|
102
|
-
temple << [:
|
86
|
+
if need_newline?(c)
|
87
|
+
temple << [:mknl]
|
103
88
|
end
|
104
89
|
unless suppress_code_newline?(c)
|
105
90
|
temple << [:newline]
|
@@ -107,10 +92,7 @@ module FastHaml
|
|
107
92
|
end
|
108
93
|
end
|
109
94
|
|
110
|
-
def need_newline?(
|
111
|
-
if parent.is_a?(Ast::Element) && nuke_inner_whitespace?(parent) && parent.children.last.equal?(child)
|
112
|
-
return false
|
113
|
-
end
|
95
|
+
def need_newline?(child)
|
114
96
|
case child
|
115
97
|
when Ast::Script
|
116
98
|
child.children.empty?
|
@@ -127,7 +109,8 @@ module FastHaml
|
|
127
109
|
ast.is_a?(Ast::Script) ||
|
128
110
|
ast.is_a?(Ast::SilentScript) ||
|
129
111
|
(ast.is_a?(Ast::Element) && suppress_code_newline?(ast.oneline_child)) ||
|
130
|
-
(ast.is_a?(Ast::Element) && !ast.children.empty?)
|
112
|
+
(ast.is_a?(Ast::Element) && !ast.children.empty?) ||
|
113
|
+
(ast.is_a?(Ast::HtmlComment) && !ast.conditional.empty?)
|
131
114
|
end
|
132
115
|
|
133
116
|
def compile_text(ast)
|
@@ -160,9 +143,9 @@ module FastHaml
|
|
160
143
|
else
|
161
144
|
temple = [:multi]
|
162
145
|
if ast.conditional.empty?
|
163
|
-
temple << [:
|
146
|
+
temple << [:mknl]
|
164
147
|
else
|
165
|
-
temple << [:static, "[#{ast.conditional}]
|
148
|
+
temple << [:static, "[#{ast.conditional}]>"] << [:mknl] << [:newline]
|
166
149
|
end
|
167
150
|
compile_children(ast, temple)
|
168
151
|
unless ast.conditional.empty?
|
@@ -189,14 +172,21 @@ module FastHaml
|
|
189
172
|
elsif !ast.children.empty?
|
190
173
|
children = [:multi]
|
191
174
|
unless nuke_inner_whitespace?(ast)
|
192
|
-
children << [:
|
175
|
+
children << [:mknl]
|
193
176
|
end
|
194
177
|
children << [:newline]
|
195
178
|
compile_children(ast, children)
|
179
|
+
if nuke_inner_whitespace?(ast)
|
180
|
+
children << [:rmnl]
|
181
|
+
end
|
196
182
|
temple << children
|
197
183
|
end
|
198
184
|
|
199
|
-
|
185
|
+
if ast.nuke_outer_whitespace
|
186
|
+
[:multi, [:rmnl], temple]
|
187
|
+
else
|
188
|
+
temple
|
189
|
+
end
|
200
190
|
end
|
201
191
|
|
202
192
|
def self_closing?(ast)
|
@@ -249,6 +239,7 @@ module FastHaml
|
|
249
239
|
def try_optimize_attributes(text, static_id, static_class)
|
250
240
|
parser = StaticHashParser.new
|
251
241
|
unless parser.parse("{#{text}}")
|
242
|
+
assert_valid_ruby_code!(text)
|
252
243
|
return nil
|
253
244
|
end
|
254
245
|
|
@@ -271,6 +262,17 @@ module FastHaml
|
|
271
262
|
end
|
272
263
|
end
|
273
264
|
|
265
|
+
def assert_valid_ruby_code!(text)
|
266
|
+
parser = ::Parser::CurrentRuby.new
|
267
|
+
parser.diagnostics.consumer = nil
|
268
|
+
buffer = ::Parser::Source::Buffer.new('(fast_haml)')
|
269
|
+
buffer.source = "call(#{text})"
|
270
|
+
parser.parse(buffer)
|
271
|
+
true
|
272
|
+
rescue ::Parser::SyntaxError
|
273
|
+
raise UnparsableRubyCode.new("Unparsable Ruby code is given to attributes: #{text}")
|
274
|
+
end
|
275
|
+
|
274
276
|
def build_optimized_attributes(parser, static_id, static_class)
|
275
277
|
static_attributes = {}
|
276
278
|
parser.static_attributes.each do |k, v|
|
data/lib/fast_haml/engine.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'temple'
|
2
2
|
require 'fast_haml/compiler'
|
3
3
|
require 'fast_haml/html'
|
4
|
+
require 'fast_haml/newline'
|
4
5
|
require 'fast_haml/parser'
|
5
6
|
|
6
7
|
module FastHaml
|
@@ -24,6 +25,7 @@ module FastHaml
|
|
24
25
|
filter :Escapable
|
25
26
|
filter :ControlFlow
|
26
27
|
filter :MultiFlattener
|
28
|
+
use Newline
|
27
29
|
filter :StaticMerger
|
28
30
|
use :Generator do
|
29
31
|
options[:generator].new(options.to_hash.reject {|k,v| !options[:generator].options.valid_key?(k) })
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'temple'
|
2
|
+
|
3
|
+
module FastHaml
|
4
|
+
class Newline < Temple::Filter
|
5
|
+
def on_multi(*exprs)
|
6
|
+
i = exprs.size-1
|
7
|
+
marker = false
|
8
|
+
while i >= 0
|
9
|
+
case exprs[i]
|
10
|
+
when [:rmnl]
|
11
|
+
if marker
|
12
|
+
raise "InternalError: double rmnl error"
|
13
|
+
else
|
14
|
+
marker = true
|
15
|
+
exprs.delete_at(i)
|
16
|
+
end
|
17
|
+
when [:mknl]
|
18
|
+
if marker
|
19
|
+
marker = false
|
20
|
+
exprs.delete_at(i)
|
21
|
+
else
|
22
|
+
exprs[i] = [:static, "\n"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
i -= 1
|
26
|
+
end
|
27
|
+
[:multi, *exprs]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/fast_haml/version.rb
CHANGED
@@ -75,4 +75,23 @@ HAML
|
|
75
75
|
%span= raise LineVerifier
|
76
76
|
HAML
|
77
77
|
end
|
78
|
+
|
79
|
+
context 'with conditional comment' do
|
80
|
+
it do
|
81
|
+
expect { render_string(<<HAML) }.to raise_error(LineVerifier, raised_at(3))
|
82
|
+
%div
|
83
|
+
/ [if IE]
|
84
|
+
%span= raise LineVerifier
|
85
|
+
HAML
|
86
|
+
end
|
87
|
+
|
88
|
+
it do
|
89
|
+
expect { render_string(<<HAML) }.to raise_error(LineVerifier, raised_at(4))
|
90
|
+
%div
|
91
|
+
/ [if IE]
|
92
|
+
%span hello
|
93
|
+
%span= raise LineVerifier
|
94
|
+
HAML
|
95
|
+
end
|
96
|
+
end
|
78
97
|
end
|
@@ -63,6 +63,10 @@ HAML
|
|
63
63
|
expect(render_string(%q|%span{foo: true, bar: 1} hello|)).to eq(%Q{<span bar='1' foo>hello</span>\n})
|
64
64
|
end
|
65
65
|
|
66
|
+
it 'raises error when unparsable Ruby code is given' do
|
67
|
+
expect { render_string('%span{x ==== 2}') }.to raise_error(FastHaml::Compiler::UnparsableRubyCode)
|
68
|
+
end
|
69
|
+
|
66
70
|
context 'with xhtml format' do
|
67
71
|
it 'renders name="name" if value is true' do
|
68
72
|
expect(render_string(%q|%span{foo: true, bar: 1} hello|, format: :xhtml)).to eq(%Q{<span bar='1' foo='foo'>hello</span>\n})
|
data/spec/render/element_spec.rb
CHANGED
@@ -119,45 +119,6 @@ HAML
|
|
119
119
|
expect(render_string('%meta{"http-equiv" => "Content-Type", :content => "text/html"}')).to eq("<meta content='text/html' http-equiv='Content-Type'>\n")
|
120
120
|
end
|
121
121
|
|
122
|
-
it 'parses nuke-inner-whitespace (<)' do
|
123
|
-
expect(render_string(<<HAML)).to eq("<blockquote><div>\nFoo!\n</div></blockquote>\n")
|
124
|
-
%blockquote<
|
125
|
-
%div
|
126
|
-
Foo!
|
127
|
-
HAML
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'renders pre tag as nuke-inner-whitespace by default' do
|
131
|
-
expect(render_string(<<HAML)).to eq("<pre>hello\nworld</pre>\n")
|
132
|
-
%pre
|
133
|
-
hello
|
134
|
-
world
|
135
|
-
HAML
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'parses nuke-outer-whitespace (>)' do
|
139
|
-
expect(render_string(<<HAML)).to eq("<img><span>hello</span><img>\n")
|
140
|
-
%img
|
141
|
-
%span> hello
|
142
|
-
%img
|
143
|
-
HAML
|
144
|
-
expect(render_string(<<HAML)).to eq("<div>\n<span>1</span><span>hoge</span></div>\n")
|
145
|
-
%div
|
146
|
-
%span= 1
|
147
|
-
%span> hoge
|
148
|
-
HAML
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'parses nuke-whitespaces' do
|
152
|
-
expect(render_string(<<HAML)).to eq("<img><pre>foo\nbar</pre><img>\n")
|
153
|
-
%img
|
154
|
-
%pre><
|
155
|
-
foo
|
156
|
-
bar
|
157
|
-
%img
|
158
|
-
HAML
|
159
|
-
end
|
160
|
-
|
161
122
|
it 'parses == syntax' do
|
162
123
|
expect(render_string('%p== =#{1+2}hello')).to eq("<p>=3hello</p>\n")
|
163
124
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'Newline with > and <', type: :render do
|
4
|
+
describe '>' do
|
5
|
+
it 'parses nuke-outer-whitespace (>)' do
|
6
|
+
expect(render_string(<<HAML)).to eq("<img><span>hello</span><img>\n")
|
7
|
+
%img
|
8
|
+
%span> hello
|
9
|
+
%img
|
10
|
+
HAML
|
11
|
+
|
12
|
+
expect(render_string(<<HAML)).to eq("<div>\n<span>1</span><span>hoge</span></div>\n")
|
13
|
+
%div
|
14
|
+
%span= 1
|
15
|
+
%span> hoge
|
16
|
+
HAML
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'handles silent script' do
|
20
|
+
expect(render_string(<<HAML)).to eq("<div><span>0</span><span>1</span></div>\n")
|
21
|
+
%div
|
22
|
+
- 2.times do |i|
|
23
|
+
%span>= i
|
24
|
+
HAML
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'handles comment' do
|
28
|
+
expect(render_string(<<HAML)).to eq("<div>\n<!--<span>0</span><span>1</span>-->\n</div>\n")
|
29
|
+
%div
|
30
|
+
/
|
31
|
+
- 2.times do |i|
|
32
|
+
%span>= i
|
33
|
+
HAML
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'handles conditional comment' do
|
37
|
+
expect(render_string(<<HAML)).to eq("<div>\n<!--[if IE]><span>0</span><span>1</span><![endif]-->\n</div>\n")
|
38
|
+
%div
|
39
|
+
/ [if IE]
|
40
|
+
- 2.times do |i|
|
41
|
+
%span>= i
|
42
|
+
HAML
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '>' do
|
47
|
+
it 'parses nuke-inner-whitespace (<)' do
|
48
|
+
expect(render_string(<<HAML)).to eq("<blockquote><div>\nFoo!\n</div></blockquote>\n")
|
49
|
+
%blockquote<
|
50
|
+
%div
|
51
|
+
Foo!
|
52
|
+
HAML
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'renders pre tag as nuke-inner-whitespace by default' do
|
56
|
+
expect(render_string(<<HAML)).to eq("<pre>hello\nworld</pre>\n")
|
57
|
+
%pre
|
58
|
+
hello
|
59
|
+
world
|
60
|
+
HAML
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'handles silent script' do
|
64
|
+
expect(render_string(<<HAML)).to eq("<div>012</div>\n")
|
65
|
+
%div<
|
66
|
+
- 3.times do |i|
|
67
|
+
= i
|
68
|
+
HAML
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '><' do
|
73
|
+
it 'parses nuke-whitespaces' do
|
74
|
+
expect(render_string(<<HAML)).to eq("<img><pre>foo\nbar</pre><img>\n")
|
75
|
+
%img
|
76
|
+
%pre><
|
77
|
+
foo
|
78
|
+
bar
|
79
|
+
%img
|
80
|
+
HAML
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast_haml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kohei Suzuki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: escape_utils
|
@@ -241,6 +241,7 @@ files:
|
|
241
241
|
- lib/fast_haml/html.rb
|
242
242
|
- lib/fast_haml/indent_tracker.rb
|
243
243
|
- lib/fast_haml/line_parser.rb
|
244
|
+
- lib/fast_haml/newline.rb
|
244
245
|
- lib/fast_haml/parser.rb
|
245
246
|
- lib/fast_haml/parser_utils.rb
|
246
247
|
- lib/fast_haml/rails_handler.rb
|
@@ -319,6 +320,7 @@ files:
|
|
319
320
|
- spec/render/filters_spec.rb
|
320
321
|
- spec/render/haml_comment_spec.rb
|
321
322
|
- spec/render/multiline_spec.rb
|
323
|
+
- spec/render/newline_spec.rb
|
322
324
|
- spec/render/plain_spec.rb
|
323
325
|
- spec/render/preserve_spec.rb
|
324
326
|
- spec/render/sanitize_spec.rb
|
@@ -420,6 +422,7 @@ test_files:
|
|
420
422
|
- spec/render/filters_spec.rb
|
421
423
|
- spec/render/haml_comment_spec.rb
|
422
424
|
- spec/render/multiline_spec.rb
|
425
|
+
- spec/render/newline_spec.rb
|
423
426
|
- spec/render/plain_spec.rb
|
424
427
|
- spec/render/preserve_spec.rb
|
425
428
|
- spec/render/sanitize_spec.rb
|