fast_haml 0.1.7 → 0.1.8
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.
- 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
|