better_html 1.0.5 → 1.0.6
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/lib/better_html/parser.rb +10 -8
- data/lib/better_html/test_helper/safe_erb/tag_interpolation.rb +3 -3
- data/lib/better_html/test_helper/safe_erb_tester.rb +4 -2
- data/lib/better_html/test_helper/safe_lodash_tester.rb +6 -4
- data/lib/better_html/tokenizer/base_erb.rb +7 -5
- data/lib/better_html/tokenizer/html_erb.rb +4 -4
- data/lib/better_html/tokenizer/html_lodash.rb +12 -12
- data/lib/better_html/tokenizer/location.rb +31 -48
- data/lib/better_html/version.rb +1 -1
- data/test/better_html/parser_test.rb +26 -26
- data/test/better_html/test_helper/safe_erb/allowed_script_type_test.rb +1 -1
- data/test/better_html/test_helper/safe_erb/no_javascript_tag_helper_test.rb +1 -1
- data/test/better_html/test_helper/safe_erb/no_statements_test.rb +1 -1
- data/test/better_html/test_helper/safe_erb/script_interpolation_test.rb +1 -1
- data/test/better_html/test_helper/safe_erb/tag_interpolation_test.rb +1 -1
- data/test/better_html/test_helper/safe_lodash_tester_test.rb +1 -1
- data/test/better_html/tokenizer/html_erb_test.rb +41 -41
- data/test/better_html/tokenizer/html_lodash_test.rb +25 -25
- data/test/better_html/tokenizer/location_test.rb +26 -10
- data/test/better_html/tokenizer/token_array_test.rb +4 -3
- data/test/better_html/tokenizer/token_test.rb +1 -1
- data/test/test_helper.rb +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbf85413b0af66cc73a928d1b37c0ba104c848ae
|
4
|
+
data.tar.gz: e934a9efa924f0647128517985f66d4dbd97f0de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb4ecf3184328d0388000db860f9126edad2e4a438c6c97623dbd29776d8f6a623fcbc5a24989c5fe47f0a92617eb0222738e28e5cae732d403a3bb805d3eb99
|
7
|
+
data.tar.gz: 5843b4928f2983d53e36e44053423b21286daf6b20cc1d7d5ddab3e3ceffe5f3c16f71a6849205732cd4c9e8776e4d86c299ca1603751da5a4056044eb653369
|
data/lib/better_html/parser.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative 'tokenizer/html_lodash'
|
|
4
4
|
require_relative 'tokenizer/location'
|
5
5
|
require_relative 'tokenizer/token_array'
|
6
6
|
require_relative 'ast/node'
|
7
|
+
require 'parser/source/buffer'
|
7
8
|
|
8
9
|
module BetterHtml
|
9
10
|
class Parser
|
@@ -19,16 +20,17 @@ module BetterHtml
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
|
-
def initialize(
|
23
|
-
|
23
|
+
def initialize(buffer, template_language: :html)
|
24
|
+
raise ArgumentError, 'first argument must be Parser::Source::Buffer' unless buffer.is_a?(::Parser::Source::Buffer)
|
25
|
+
@buffer = buffer
|
24
26
|
@template_language = template_language
|
25
27
|
@erb = case template_language
|
26
28
|
when :html
|
27
|
-
Tokenizer::HtmlErb.new(@
|
29
|
+
Tokenizer::HtmlErb.new(@buffer)
|
28
30
|
when :lodash
|
29
|
-
Tokenizer::HtmlLodash.new(@
|
31
|
+
Tokenizer::HtmlLodash.new(@buffer)
|
30
32
|
when :javascript
|
31
|
-
Tokenizer::JavascriptErb.new(@
|
33
|
+
Tokenizer::JavascriptErb.new(@buffer)
|
32
34
|
else
|
33
35
|
raise ArgumentError, "template_language can be :html or :javascript"
|
34
36
|
end
|
@@ -47,7 +49,7 @@ module BetterHtml
|
|
47
49
|
@erb.parser.errors.map do |error|
|
48
50
|
Error.new(
|
49
51
|
error.message,
|
50
|
-
location: Tokenizer::Location.new(@
|
52
|
+
location: Tokenizer::Location.new(@buffer, error.position, error.position + 1)
|
51
53
|
)
|
52
54
|
end
|
53
55
|
end
|
@@ -199,11 +201,11 @@ module BetterHtml
|
|
199
201
|
def build_location(enumerable)
|
200
202
|
enumerable = enumerable.compact
|
201
203
|
raise ArgumentError, "cannot build location for #{enumerable.inspect}" unless enumerable.first && enumerable.last
|
202
|
-
Tokenizer::Location.new(@
|
204
|
+
Tokenizer::Location.new(@buffer, enumerable.first.loc.begin_pos, enumerable.last.loc.end_pos)
|
203
205
|
end
|
204
206
|
|
205
207
|
def empty_location
|
206
|
-
Tokenizer::Location.new(@
|
208
|
+
Tokenizer::Location.new(@buffer, 0, 0)
|
207
209
|
end
|
208
210
|
|
209
211
|
def shift_all(tokens, *types)
|
@@ -158,9 +158,9 @@ module BetterHtml
|
|
158
158
|
|
159
159
|
def nested_location(parent_node, ruby_node)
|
160
160
|
Tokenizer::Location.new(
|
161
|
-
parent_node.loc.
|
162
|
-
parent_node.loc.
|
163
|
-
parent_node.loc.
|
161
|
+
parent_node.loc.source_buffer,
|
162
|
+
parent_node.loc.begin_pos + ruby_node.loc.expression.begin_pos,
|
163
|
+
parent_node.loc.begin_pos + ruby_node.loc.expression.end_pos
|
164
164
|
)
|
165
165
|
end
|
166
166
|
end
|
@@ -37,7 +37,9 @@ EOF
|
|
37
37
|
def assert_erb_safety(data, **options)
|
38
38
|
options = options.present? ? options.dup : {}
|
39
39
|
options[:template_language] ||= :html
|
40
|
-
|
40
|
+
buffer = ::Parser::Source::Buffer.new(options[:filename] || '(buffer)')
|
41
|
+
buffer.source = data
|
42
|
+
parser = BetterHtml::Parser.new(buffer, options)
|
41
43
|
|
42
44
|
tester_classes = [
|
43
45
|
SafeErb::NoStatements,
|
@@ -57,7 +59,7 @@ EOF
|
|
57
59
|
|
58
60
|
messages = errors.map do |error|
|
59
61
|
<<~EOL
|
60
|
-
|
62
|
+
In #{buffer.name}:#{error.location.line}
|
61
63
|
#{error.message}
|
62
64
|
#{error.location.line_source_with_underline}\n
|
63
65
|
EOL
|
@@ -28,7 +28,9 @@ Never use <script> tags inside lodash template.
|
|
28
28
|
EOF
|
29
29
|
|
30
30
|
def assert_lodash_safety(data, **options)
|
31
|
-
|
31
|
+
buffer = ::Parser::Source::Buffer.new(options[:filename] || '(buffer)')
|
32
|
+
buffer.source = data
|
33
|
+
tester = Tester.new(buffer, **options)
|
32
34
|
|
33
35
|
message = ""
|
34
36
|
tester.errors.each do |error|
|
@@ -49,11 +51,11 @@ EOF
|
|
49
51
|
class Tester
|
50
52
|
attr_reader :errors
|
51
53
|
|
52
|
-
def initialize(
|
53
|
-
@
|
54
|
+
def initialize(buffer, config: BetterHtml.config)
|
55
|
+
@buffer = buffer
|
54
56
|
@config = config
|
55
57
|
@errors = Errors.new
|
56
|
-
@parser = BetterHtml::Parser.new(
|
58
|
+
@parser = BetterHtml::Parser.new(buffer, template_language: :lodash)
|
57
59
|
validate!
|
58
60
|
end
|
59
61
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'erubi'
|
2
2
|
require_relative 'token'
|
3
3
|
require_relative 'location'
|
4
|
+
require 'parser/source/buffer'
|
4
5
|
|
5
6
|
module BetterHtml
|
6
7
|
module Tokenizer
|
@@ -12,11 +13,12 @@ module BetterHtml
|
|
12
13
|
attr_reader :tokens
|
13
14
|
attr_reader :current_position
|
14
15
|
|
15
|
-
def initialize(
|
16
|
-
|
16
|
+
def initialize(buffer)
|
17
|
+
raise ArgumentError, 'first argument must be Parser::Source::Buffer' unless buffer.is_a?(::Parser::Source::Buffer)
|
18
|
+
@buffer = buffer
|
17
19
|
@tokens = []
|
18
20
|
@current_position = 0
|
19
|
-
super(
|
21
|
+
super(buffer.source, regexp: REGEXP_WITHOUT_TRIM, trim: false)
|
20
22
|
end
|
21
23
|
|
22
24
|
private
|
@@ -66,10 +68,10 @@ module BetterHtml
|
|
66
68
|
token = add_token(:erb_end, pos, pos + 2)
|
67
69
|
end
|
68
70
|
|
69
|
-
def add_token(type,
|
71
|
+
def add_token(type, begin_pos, end_pos)
|
70
72
|
token = Token.new(
|
71
73
|
type: type,
|
72
|
-
loc: Location.new(@
|
74
|
+
loc: Location.new(@buffer, begin_pos, end_pos)
|
73
75
|
)
|
74
76
|
@tokens << token
|
75
77
|
token
|
@@ -6,9 +6,9 @@ module BetterHtml
|
|
6
6
|
class HtmlErb < BaseErb
|
7
7
|
attr_reader :parser
|
8
8
|
|
9
|
-
def initialize(
|
9
|
+
def initialize(buffer)
|
10
10
|
@parser = HtmlTokenizer::Parser.new
|
11
|
-
super(
|
11
|
+
super(buffer)
|
12
12
|
end
|
13
13
|
|
14
14
|
def current_position
|
@@ -22,8 +22,8 @@ module BetterHtml
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def add_text(text)
|
25
|
-
@parser.parse(text) do |type,
|
26
|
-
add_token(type,
|
25
|
+
@parser.parse(text) do |type, begin_pos, end_pos, _line, _column|
|
26
|
+
add_token(type, begin_pos, end_pos)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -13,9 +13,9 @@ module BetterHtml
|
|
13
13
|
self.lodash_evaluate = %r{(?:\[\%)(.+?)(?:\%\])}m
|
14
14
|
self.lodash_interpolate = %r{(?:\[\%)!(.+?)(?:\%\])}m
|
15
15
|
|
16
|
-
def initialize(
|
17
|
-
@
|
18
|
-
@scanner = StringScanner.new(
|
16
|
+
def initialize(buffer)
|
17
|
+
@buffer = buffer
|
18
|
+
@scanner = StringScanner.new(buffer.source)
|
19
19
|
@parser = HtmlTokenizer::Parser.new
|
20
20
|
@tokens = []
|
21
21
|
scan!
|
@@ -43,7 +43,7 @@ module BetterHtml
|
|
43
43
|
end
|
44
44
|
@parser.append_placeholder(match)
|
45
45
|
else
|
46
|
-
text = @
|
46
|
+
text = @buffer.source[(@scanner.pos)..(@buffer.source.size)]
|
47
47
|
add_text(text) unless text.blank?
|
48
48
|
break
|
49
49
|
end
|
@@ -62,32 +62,32 @@ module BetterHtml
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def add_text(text)
|
65
|
-
@parser.parse(text) do |type,
|
66
|
-
add_token(type,
|
65
|
+
@parser.parse(text) do |type, begin_pos, end_pos, _line, _column|
|
66
|
+
add_token(type, begin_pos: begin_pos, end_pos: end_pos)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
def add_lodash_tokens(indicator, code)
|
71
71
|
pos = @parser.document_length
|
72
72
|
|
73
|
-
add_token(:lodash_begin,
|
73
|
+
add_token(:lodash_begin, begin_pos: pos, end_pos: pos + 2)
|
74
74
|
pos += 2
|
75
75
|
|
76
76
|
if indicator
|
77
|
-
add_token(:indicator,
|
77
|
+
add_token(:indicator, begin_pos: pos, end_pos: pos + indicator.length)
|
78
78
|
pos += indicator.length
|
79
79
|
end
|
80
80
|
|
81
|
-
add_token(:code,
|
81
|
+
add_token(:code, begin_pos: pos, end_pos: pos + code.length)
|
82
82
|
pos += code.length
|
83
83
|
|
84
|
-
add_token(:lodash_end,
|
84
|
+
add_token(:lodash_end, begin_pos: pos, end_pos: pos + 2)
|
85
85
|
end
|
86
86
|
|
87
|
-
def add_token(type,
|
87
|
+
def add_token(type, begin_pos: nil, end_pos: nil)
|
88
88
|
token = Token.new(
|
89
89
|
type: type,
|
90
|
-
loc: Location.new(@
|
90
|
+
loc: Location.new(@buffer, begin_pos, end_pos)
|
91
91
|
)
|
92
92
|
@tokens << token
|
93
93
|
token
|
@@ -1,76 +1,59 @@
|
|
1
|
+
require 'parser/source/buffer'
|
2
|
+
require 'parser/source/range'
|
3
|
+
|
1
4
|
module BetterHtml
|
2
5
|
module Tokenizer
|
3
|
-
class Location
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
raise ArgumentError, "
|
8
|
-
raise ArgumentError, "stop location #{stop} is out of range for document of size #{document.size}" if stop > document.size
|
9
|
-
raise ArgumentError, "end of range must be greater than start of range (#{stop} < #{start})" if stop < start
|
6
|
+
class Location < ::Parser::Source::Range
|
7
|
+
def initialize(buffer, begin_pos, end_pos)
|
8
|
+
raise ArgumentError, 'first argument must be Parser::Source::Buffer' unless buffer.is_a?(::Parser::Source::Buffer)
|
9
|
+
raise ArgumentError, "begin_pos location #{begin_pos} is out of range for document of size #{buffer.source.size}" if begin_pos > buffer.source.size
|
10
|
+
raise ArgumentError, "end_pos location #{end_pos} is out of range for document of size #{buffer.source.size}" if (end_pos - 1) > buffer.source.size
|
10
11
|
|
11
|
-
|
12
|
-
@start = start
|
13
|
-
@stop = stop
|
12
|
+
super(buffer, begin_pos, end_pos)
|
14
13
|
end
|
15
14
|
|
16
15
|
def range
|
17
|
-
Range.new(
|
16
|
+
Range.new(begin_pos, end_pos, true)
|
18
17
|
end
|
19
18
|
|
20
19
|
def line_range
|
21
20
|
Range.new(start_line, stop_line)
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def start_line
|
29
|
-
@start_line ||= calculate_line(start)
|
30
|
-
end
|
31
|
-
|
32
|
-
def line
|
33
|
-
start_line
|
34
|
-
end
|
35
|
-
|
36
|
-
def stop_line
|
37
|
-
@stop_line ||= calculate_line(stop)
|
38
|
-
end
|
23
|
+
alias_method :start_line, :line
|
24
|
+
alias_method :stop_line, :last_line
|
25
|
+
alias_method :start_column, :column
|
26
|
+
alias_method :stop_column, :last_column
|
39
27
|
|
40
|
-
def
|
41
|
-
|
28
|
+
def line_source_with_underline
|
29
|
+
spaces = source_line.scan(/\A\s*/).first
|
30
|
+
column_without_spaces = [column - spaces.length, 0].max
|
31
|
+
underscore_length = [[end_pos - begin_pos, source_line.length - column_without_spaces].min, 1].max
|
32
|
+
"#{source_line.gsub(/\A\s*/, '')}\n#{' ' * column_without_spaces}#{'^' * underscore_length}"
|
42
33
|
end
|
43
34
|
|
44
|
-
def
|
45
|
-
|
35
|
+
def with(begin_pos: @begin_pos, end_pos: @end_pos)
|
36
|
+
self.class.new(@source_buffer, begin_pos, end_pos)
|
46
37
|
end
|
47
38
|
|
48
|
-
def
|
49
|
-
@
|
39
|
+
def adjust(begin_pos: 0, end_pos: 0)
|
40
|
+
self.class.new(@source_buffer, @begin_pos + begin_pos, @end_pos + end_pos)
|
50
41
|
end
|
51
42
|
|
52
|
-
def
|
53
|
-
|
54
|
-
spaces = line_content.scan(/\A\s*/).first
|
55
|
-
column_without_spaces = [column - spaces.length, 0].max
|
56
|
-
underscore_length = [[stop - start + 1, line_content.length - column_without_spaces].min, 1].max
|
57
|
-
"#{line_content.gsub(/\A\s*/, '')}\n#{' ' * column_without_spaces}#{'^' * underscore_length}"
|
43
|
+
def resize(new_size)
|
44
|
+
with(end_pos: @begin_pos + new_size)
|
58
45
|
end
|
59
46
|
|
60
|
-
|
61
|
-
|
62
|
-
def calculate_line(pos)
|
63
|
-
return 1 if pos == 0
|
64
|
-
@document[0..pos-1].scan("\n").count + 1
|
47
|
+
def offset(offset)
|
48
|
+
with(begin_pos: offset + @begin_pos, end_pos: offset + @end_pos)
|
65
49
|
end
|
66
50
|
|
67
|
-
def
|
68
|
-
|
69
|
-
@document[0..pos-1]&.split("\n", -1)&.last&.length || 0
|
51
|
+
def begin
|
52
|
+
with(end_pos: @begin_pos)
|
70
53
|
end
|
71
54
|
|
72
|
-
def
|
73
|
-
|
55
|
+
def end
|
56
|
+
with(begin_pos: @end_pos)
|
74
57
|
end
|
75
58
|
end
|
76
59
|
end
|
data/lib/better_html/version.rb
CHANGED
@@ -7,17 +7,17 @@ module BetterHtml
|
|
7
7
|
include ::AST::Sexp
|
8
8
|
|
9
9
|
test "parse empty document" do
|
10
|
-
tree = Parser.new('')
|
10
|
+
tree = Parser.new(buffer(''))
|
11
11
|
|
12
12
|
assert_equal s(:document), tree.ast
|
13
13
|
end
|
14
14
|
|
15
15
|
test "parser errors" do
|
16
|
-
tree = Parser.new('<>')
|
16
|
+
tree = Parser.new(buffer('<>'))
|
17
17
|
|
18
18
|
assert_equal 1, tree.parser_errors.size
|
19
19
|
assert_equal "expected '/' or tag name", tree.parser_errors[0].message
|
20
|
-
assert_equal 1
|
20
|
+
assert_equal 1...2, tree.parser_errors[0].location.range
|
21
21
|
assert_equal <<~EOF.strip, tree.parser_errors[0].location.line_source_with_underline
|
22
22
|
<>
|
23
23
|
^
|
@@ -26,7 +26,7 @@ module BetterHtml
|
|
26
26
|
|
27
27
|
test "consume cdata nodes" do
|
28
28
|
code = "<![CDATA[ foo ]]>"
|
29
|
-
tree = Parser.new(code)
|
29
|
+
tree = Parser.new(buffer(code))
|
30
30
|
|
31
31
|
assert_equal s(:document, s(:cdata, ' foo ')), tree.ast
|
32
32
|
assert_equal code, tree.ast.loc.source
|
@@ -34,7 +34,7 @@ module BetterHtml
|
|
34
34
|
|
35
35
|
test "unterminated cdata nodes are consumed until end" do
|
36
36
|
code = "<![CDATA[ foo"
|
37
|
-
tree = Parser.new(code)
|
37
|
+
tree = Parser.new(buffer(code))
|
38
38
|
|
39
39
|
assert_equal s(:document, s(:cdata, ' foo')), tree.ast
|
40
40
|
assert_equal code, tree.ast.loc.source
|
@@ -42,7 +42,7 @@ module BetterHtml
|
|
42
42
|
|
43
43
|
test "consume cdata with interpolation" do
|
44
44
|
code = "<![CDATA[ foo <%= bar %> baz ]]>"
|
45
|
-
tree = Parser.new(code)
|
45
|
+
tree = Parser.new(buffer(code))
|
46
46
|
|
47
47
|
assert_equal s(:document,
|
48
48
|
s(:cdata,
|
@@ -55,19 +55,19 @@ module BetterHtml
|
|
55
55
|
end
|
56
56
|
|
57
57
|
test "consume comment nodes" do
|
58
|
-
tree = Parser.new("<!-- foo -->")
|
58
|
+
tree = Parser.new(buffer("<!-- foo -->"))
|
59
59
|
|
60
60
|
assert_equal s(:document, s(:comment, ' foo ')), tree.ast
|
61
61
|
end
|
62
62
|
|
63
63
|
test "unterminated comment nodes are consumed until end" do
|
64
|
-
tree = Parser.new("<!-- foo")
|
64
|
+
tree = Parser.new(buffer("<!-- foo"))
|
65
65
|
|
66
66
|
assert_equal s(:document, s(:comment, ' foo')), tree.ast
|
67
67
|
end
|
68
68
|
|
69
69
|
test "consume comment with interpolation" do
|
70
|
-
tree = Parser.new("<!-- foo <%= bar %> baz -->")
|
70
|
+
tree = Parser.new(buffer("<!-- foo <%= bar %> baz -->"))
|
71
71
|
|
72
72
|
assert_equal s(:document,
|
73
73
|
s(:comment,
|
@@ -79,12 +79,12 @@ module BetterHtml
|
|
79
79
|
end
|
80
80
|
|
81
81
|
test "consume tag nodes" do
|
82
|
-
tree = Parser.new("<div>")
|
82
|
+
tree = Parser.new(buffer("<div>"))
|
83
83
|
assert_equal s(:document, s(:tag, nil, s(:tag_name, "div"), nil, nil)), tree.ast
|
84
84
|
end
|
85
85
|
|
86
86
|
test "tag without name" do
|
87
|
-
tree = Parser.new("foo < bar")
|
87
|
+
tree = Parser.new(buffer("foo < bar"))
|
88
88
|
assert_equal s(:document,
|
89
89
|
s(:text, "foo "),
|
90
90
|
s(:tag, nil, nil,
|
@@ -97,25 +97,25 @@ module BetterHtml
|
|
97
97
|
end
|
98
98
|
|
99
99
|
test "consume tag nodes with solidus" do
|
100
|
-
tree = Parser.new("</div>")
|
100
|
+
tree = Parser.new(buffer("</div>"))
|
101
101
|
assert_equal s(:document, s(:tag, s(:solidus), s(:tag_name, "div"), nil, nil)), tree.ast
|
102
102
|
end
|
103
103
|
|
104
104
|
test "sets self_closing when appropriate" do
|
105
|
-
tree = Parser.new("<div/>")
|
105
|
+
tree = Parser.new(buffer("<div/>"))
|
106
106
|
assert_equal s(:document, s(:tag, nil, s(:tag_name, "div"), nil, s(:solidus))), tree.ast
|
107
107
|
end
|
108
108
|
|
109
109
|
test "consume tag nodes until name ends" do
|
110
|
-
tree = Parser.new("<div/>")
|
110
|
+
tree = Parser.new(buffer("<div/>"))
|
111
111
|
assert_equal s(:document, s(:tag, nil, s(:tag_name, "div"), nil, s(:solidus))), tree.ast
|
112
112
|
|
113
|
-
tree = Parser.new("<div ")
|
113
|
+
tree = Parser.new(buffer("<div "))
|
114
114
|
assert_equal s(:document, s(:tag, nil, s(:tag_name, "div"), nil, nil)), tree.ast
|
115
115
|
end
|
116
116
|
|
117
117
|
test "consume tag nodes with interpolation" do
|
118
|
-
tree = Parser.new("<ns:<%= name %>-thing>")
|
118
|
+
tree = Parser.new(buffer("<ns:<%= name %>-thing>"))
|
119
119
|
assert_equal s(:document,
|
120
120
|
s(:tag,
|
121
121
|
nil,
|
@@ -126,7 +126,7 @@ module BetterHtml
|
|
126
126
|
end
|
127
127
|
|
128
128
|
test "consume tag attributes with erb" do
|
129
|
-
tree = Parser.new("<div class=foo <%= erb %> name=bar>")
|
129
|
+
tree = Parser.new(buffer("<div class=foo <%= erb %> name=bar>"))
|
130
130
|
assert_equal s(:document,
|
131
131
|
s(:tag, nil,
|
132
132
|
s(:tag_name, "div"),
|
@@ -149,7 +149,7 @@ module BetterHtml
|
|
149
149
|
end
|
150
150
|
|
151
151
|
test "consume tag attributes nodes unquoted value" do
|
152
|
-
tree = Parser.new("<div foo=bar>")
|
152
|
+
tree = Parser.new(buffer("<div foo=bar>"))
|
153
153
|
assert_equal s(:document,
|
154
154
|
s(:tag, nil,
|
155
155
|
s(:tag_name, "div"),
|
@@ -165,7 +165,7 @@ module BetterHtml
|
|
165
165
|
end
|
166
166
|
|
167
167
|
test "consume attributes without name" do
|
168
|
-
tree = Parser.new("<div 'thing'>")
|
168
|
+
tree = Parser.new(buffer("<div 'thing'>"))
|
169
169
|
assert_equal s(:document,
|
170
170
|
s(:tag, nil,
|
171
171
|
s(:tag_name, "div"),
|
@@ -181,7 +181,7 @@ module BetterHtml
|
|
181
181
|
end
|
182
182
|
|
183
183
|
test "consume tag attributes nodes quoted value" do
|
184
|
-
tree = Parser.new("<div foo=\"bar\">")
|
184
|
+
tree = Parser.new(buffer("<div foo=\"bar\">"))
|
185
185
|
assert_equal s(:document,
|
186
186
|
s(:tag, nil,
|
187
187
|
s(:tag_name, "div"),
|
@@ -197,7 +197,7 @@ module BetterHtml
|
|
197
197
|
end
|
198
198
|
|
199
199
|
test "consume tag attributes nodes interpolation in name and value" do
|
200
|
-
tree = Parser.new("<div data-<%= foo %>=\"some <%= value %> foo\">")
|
200
|
+
tree = Parser.new(buffer("<div data-<%= foo %>=\"some <%= value %> foo\">"))
|
201
201
|
assert_equal s(:document,
|
202
202
|
s(:tag, nil,
|
203
203
|
s(:tag_name, "div"),
|
@@ -219,7 +219,7 @@ module BetterHtml
|
|
219
219
|
end
|
220
220
|
|
221
221
|
test "consume text nodes" do
|
222
|
-
tree = Parser.new("here is <%= some %> text")
|
222
|
+
tree = Parser.new(buffer("here is <%= some %> text"))
|
223
223
|
|
224
224
|
assert_equal s(:document,
|
225
225
|
s(:text,
|
@@ -230,7 +230,7 @@ module BetterHtml
|
|
230
230
|
end
|
231
231
|
|
232
232
|
test "javascript template parsing works" do
|
233
|
-
tree = Parser.new("here is <%= some %> text", template_language: :javascript)
|
233
|
+
tree = Parser.new(buffer("here is <%= some %> text"), template_language: :javascript)
|
234
234
|
|
235
235
|
assert_equal s(:document,
|
236
236
|
s(:text,
|
@@ -241,7 +241,7 @@ module BetterHtml
|
|
241
241
|
end
|
242
242
|
|
243
243
|
test "javascript template does not consume html tags" do
|
244
|
-
tree = Parser.new("<div <%= some %> />", template_language: :javascript)
|
244
|
+
tree = Parser.new(buffer("<div <%= some %> />"), template_language: :javascript)
|
245
245
|
|
246
246
|
assert_equal s(:document,
|
247
247
|
s(:text,
|
@@ -252,7 +252,7 @@ module BetterHtml
|
|
252
252
|
end
|
253
253
|
|
254
254
|
test "lodash template parsing works" do
|
255
|
-
tree = Parser.new('<div class="[%= foo %]">', template_language: :lodash)
|
255
|
+
tree = Parser.new(buffer('<div class="[%= foo %]">'), template_language: :lodash)
|
256
256
|
|
257
257
|
assert_equal s(:document,
|
258
258
|
s(:tag,
|
@@ -275,7 +275,7 @@ module BetterHtml
|
|
275
275
|
end
|
276
276
|
|
277
277
|
test "nodes are all nested under document" do
|
278
|
-
tree = Parser.new(<<~HTML)
|
278
|
+
tree = Parser.new(buffer(<<~HTML))
|
279
279
|
some text
|
280
280
|
<!-- a comment -->
|
281
281
|
some more text
|
@@ -34,7 +34,7 @@ module BetterHtml
|
|
34
34
|
|
35
35
|
private
|
36
36
|
def validate(data, template_language: :html)
|
37
|
-
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
37
|
+
parser = BetterHtml::Parser.new(buffer(data), template_language: template_language)
|
38
38
|
tester = BetterHtml::TestHelper::SafeErb::AllowedScriptType.new(parser, config: @config)
|
39
39
|
tester.validate
|
40
40
|
tester
|
@@ -26,7 +26,7 @@ module BetterHtml
|
|
26
26
|
|
27
27
|
private
|
28
28
|
def validate(data, template_language: :html)
|
29
|
-
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
29
|
+
parser = BetterHtml::Parser.new(buffer(data), template_language: template_language)
|
30
30
|
tester = BetterHtml::TestHelper::SafeErb::NoJavascriptTagHelper.new(parser, config: @config)
|
31
31
|
tester.validate
|
32
32
|
tester
|
@@ -117,7 +117,7 @@ module BetterHtml
|
|
117
117
|
|
118
118
|
private
|
119
119
|
def validate(data, template_language: :html)
|
120
|
-
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
120
|
+
parser = BetterHtml::Parser.new(buffer(data), template_language: template_language)
|
121
121
|
tester = BetterHtml::TestHelper::SafeErb::NoStatements.new(parser, config: @config)
|
122
122
|
tester.validate
|
123
123
|
tester
|
@@ -138,7 +138,7 @@ module BetterHtml
|
|
138
138
|
|
139
139
|
private
|
140
140
|
def validate(data, template_language: :html)
|
141
|
-
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
141
|
+
parser = BetterHtml::Parser.new(buffer(data), template_language: template_language)
|
142
142
|
tester = BetterHtml::TestHelper::SafeErb::ScriptInterpolation.new(parser, config: @config)
|
143
143
|
tester.validate
|
144
144
|
tester
|
@@ -292,7 +292,7 @@ module BetterHtml
|
|
292
292
|
|
293
293
|
private
|
294
294
|
def validate(data, template_language: :html)
|
295
|
-
parser = BetterHtml::Parser.new(data, template_language: template_language)
|
295
|
+
parser = BetterHtml::Parser.new(buffer(data), template_language: template_language)
|
296
296
|
tester = BetterHtml::TestHelper::SafeErb::TagInterpolation.new(parser, config: @config)
|
297
297
|
tester.validate
|
298
298
|
tester
|
@@ -5,92 +5,92 @@ module BetterHtml
|
|
5
5
|
module Tokenizer
|
6
6
|
class HtmlErbTest < ActiveSupport::TestCase
|
7
7
|
test "text" do
|
8
|
-
scanner = HtmlErb.new("just some text")
|
8
|
+
scanner = HtmlErb.new(buffer("just some text"))
|
9
9
|
assert_equal 1, scanner.tokens.size
|
10
10
|
|
11
11
|
assert_attributes ({
|
12
12
|
type: :text,
|
13
|
-
loc: {
|
13
|
+
loc: { begin_pos: 0, end_pos: 14, source: 'just some text' }
|
14
14
|
}), scanner.tokens[0]
|
15
15
|
end
|
16
16
|
|
17
17
|
test "statement" do
|
18
|
-
scanner = HtmlErb.new("<% statement %>")
|
18
|
+
scanner = HtmlErb.new(buffer("<% statement %>"))
|
19
19
|
assert_equal 3, scanner.tokens.size
|
20
20
|
|
21
|
-
assert_attributes ({ type: :erb_begin, loc: {
|
22
|
-
assert_attributes ({ type: :code, loc: {
|
23
|
-
assert_attributes ({ type: :erb_end, loc: {
|
21
|
+
assert_attributes ({ type: :erb_begin, loc: { begin_pos: 0, end_pos: 2, source: '<%' } }), scanner.tokens[0]
|
22
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 2, end_pos: 13, source: ' statement ' } }), scanner.tokens[1]
|
23
|
+
assert_attributes ({ type: :erb_end, loc: { begin_pos: 13, end_pos: 15, source: '%>' } }), scanner.tokens[2]
|
24
24
|
end
|
25
25
|
|
26
26
|
test "debug statement" do
|
27
|
-
scanner = HtmlErb.new("<%# statement %>")
|
27
|
+
scanner = HtmlErb.new(buffer("<%# statement %>"))
|
28
28
|
assert_equal 4, scanner.tokens.size
|
29
29
|
|
30
|
-
assert_attributes ({ type: :erb_begin, loc: {
|
31
|
-
assert_attributes ({ type: :indicator, loc: {
|
32
|
-
assert_attributes ({ type: :code, loc: {
|
33
|
-
assert_attributes ({ type: :erb_end, loc: {
|
30
|
+
assert_attributes ({ type: :erb_begin, loc: { begin_pos: 0, end_pos: 2, source: '<%' } }), scanner.tokens[0]
|
31
|
+
assert_attributes ({ type: :indicator, loc: { begin_pos: 2, end_pos: 3, source: '#' } }), scanner.tokens[1]
|
32
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 3, end_pos: 14, source: ' statement ' } }), scanner.tokens[2]
|
33
|
+
assert_attributes ({ type: :erb_end, loc: { begin_pos: 14, end_pos: 16, source: '%>' } }), scanner.tokens[3]
|
34
34
|
end
|
35
35
|
|
36
36
|
test "when multi byte characters are present in erb" do
|
37
37
|
code = "<% ui_helper 'your store’s' %>"
|
38
|
-
scanner = HtmlErb.new(code)
|
38
|
+
scanner = HtmlErb.new(buffer(code))
|
39
39
|
assert_equal 3, scanner.tokens.size
|
40
40
|
|
41
|
-
assert_attributes ({ type: :erb_begin, loc: {
|
42
|
-
assert_attributes ({ type: :code, loc: {
|
43
|
-
assert_attributes ({ type: :erb_end, loc: {
|
41
|
+
assert_attributes ({ type: :erb_begin, loc: { begin_pos: 0, end_pos: 2, source: '<%' } }), scanner.tokens[0]
|
42
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 2, end_pos: 28, source: " ui_helper 'your store’s' " } }), scanner.tokens[1]
|
43
|
+
assert_attributes ({ type: :erb_end, loc: { begin_pos: 28, end_pos: 30, source: '%>' } }), scanner.tokens[2]
|
44
44
|
assert_equal code.length, scanner.current_position
|
45
45
|
end
|
46
46
|
|
47
47
|
test "when multi byte characters are present in text" do
|
48
48
|
code = "your store’s"
|
49
|
-
scanner = HtmlErb.new(code)
|
49
|
+
scanner = HtmlErb.new(buffer(code))
|
50
50
|
assert_equal 1, scanner.tokens.size
|
51
51
|
|
52
|
-
assert_attributes ({ type: :text, loc: {
|
52
|
+
assert_attributes ({ type: :text, loc: { begin_pos: 0, end_pos: 12, source: 'your store’s' } }), scanner.tokens[0]
|
53
53
|
assert_equal code.length, scanner.current_position
|
54
54
|
end
|
55
55
|
|
56
56
|
test "when multi byte characters are present in html" do
|
57
57
|
code = "<div title='your store’s'>foo</div>"
|
58
|
-
scanner = HtmlErb.new(code)
|
58
|
+
scanner = HtmlErb.new(buffer(code))
|
59
59
|
assert_equal 14, scanner.tokens.size
|
60
60
|
|
61
|
-
assert_attributes ({ type: :tag_start, loc: {
|
62
|
-
assert_attributes ({ type: :tag_name, loc: {
|
63
|
-
assert_attributes ({ type: :whitespace, loc: {
|
64
|
-
assert_attributes ({ type: :attribute_name, loc: {
|
65
|
-
assert_attributes ({ type: :equal, loc: {
|
66
|
-
assert_attributes ({ type: :attribute_quoted_value_start, loc: {
|
67
|
-
assert_attributes ({ type: :attribute_quoted_value, loc: {
|
68
|
-
assert_attributes ({ type: :attribute_quoted_value_end, loc: {
|
61
|
+
assert_attributes ({ type: :tag_start, loc: { begin_pos: 0, end_pos: 1, source: '<' } }), scanner.tokens[0]
|
62
|
+
assert_attributes ({ type: :tag_name, loc: { begin_pos: 1, end_pos: 4, source: "div" } }), scanner.tokens[1]
|
63
|
+
assert_attributes ({ type: :whitespace, loc: { begin_pos: 4, end_pos: 5, source: " " } }), scanner.tokens[2]
|
64
|
+
assert_attributes ({ type: :attribute_name, loc: { begin_pos: 5, end_pos: 10, source: "title" } }), scanner.tokens[3]
|
65
|
+
assert_attributes ({ type: :equal, loc: { begin_pos: 10, end_pos: 11, source: "=" } }), scanner.tokens[4]
|
66
|
+
assert_attributes ({ type: :attribute_quoted_value_start, loc: { begin_pos: 11, end_pos: 12, source: "'" } }), scanner.tokens[5]
|
67
|
+
assert_attributes ({ type: :attribute_quoted_value, loc: { begin_pos: 12, end_pos: 24, source: "your store’s" } }), scanner.tokens[6]
|
68
|
+
assert_attributes ({ type: :attribute_quoted_value_end, loc: { begin_pos: 24, end_pos: 25, source: "'" } }), scanner.tokens[7]
|
69
69
|
assert_equal code.length, scanner.current_position
|
70
70
|
end
|
71
71
|
|
72
72
|
test "expression literal" do
|
73
|
-
scanner = HtmlErb.new("<%= literal %>")
|
73
|
+
scanner = HtmlErb.new(buffer("<%= literal %>"))
|
74
74
|
assert_equal 4, scanner.tokens.size
|
75
75
|
|
76
|
-
assert_attributes ({ type: :erb_begin, loc: {
|
77
|
-
assert_attributes ({ type: :indicator, loc: {
|
78
|
-
assert_attributes ({ type: :code, loc: {
|
79
|
-
assert_attributes ({ type: :erb_end, loc: {
|
76
|
+
assert_attributes ({ type: :erb_begin, loc: { begin_pos: 0, end_pos: 2, source: '<%' } }), scanner.tokens[0]
|
77
|
+
assert_attributes ({ type: :indicator, loc: { begin_pos: 2, end_pos: 3, source: '=' } }), scanner.tokens[1]
|
78
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 3, end_pos: 12, source: ' literal ' } }), scanner.tokens[2]
|
79
|
+
assert_attributes ({ type: :erb_end, loc: { begin_pos: 12, end_pos: 14, source: '%>' } }), scanner.tokens[3]
|
80
80
|
end
|
81
81
|
|
82
82
|
test "expression escaped" do
|
83
|
-
scanner = HtmlErb.new("<%== escaped %>")
|
83
|
+
scanner = HtmlErb.new(buffer("<%== escaped %>"))
|
84
84
|
assert_equal 4, scanner.tokens.size
|
85
85
|
|
86
|
-
assert_attributes ({ type: :erb_begin, loc: {
|
87
|
-
assert_attributes ({ type: :indicator, loc: {
|
88
|
-
assert_attributes ({ type: :code, loc: {
|
89
|
-
assert_attributes ({ type: :erb_end, loc: {
|
86
|
+
assert_attributes ({ type: :erb_begin, loc: { begin_pos: 0, end_pos: 2, source: '<%' } }), scanner.tokens[0]
|
87
|
+
assert_attributes ({ type: :indicator, loc: { begin_pos: 2, end_pos: 4, source: '==' } }), scanner.tokens[1]
|
88
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 4, end_pos: 13, source: ' escaped ' } }), scanner.tokens[2]
|
89
|
+
assert_attributes ({ type: :erb_end, loc: { begin_pos: 13, end_pos: 15, source: '%>' } }), scanner.tokens[3]
|
90
90
|
end
|
91
91
|
|
92
92
|
test "line number for multi-line statements" do
|
93
|
-
scanner = HtmlErb.new("before <% multi\nline %> after")
|
93
|
+
scanner = HtmlErb.new(buffer("before <% multi\nline %> after"))
|
94
94
|
assert_equal 5, scanner.tokens.size
|
95
95
|
|
96
96
|
assert_attributes ({ type: :text, loc: { line: 1, source: 'before ' } }), scanner.tokens[0]
|
@@ -101,7 +101,7 @@ module BetterHtml
|
|
101
101
|
end
|
102
102
|
|
103
103
|
test "multi-line statements with trim" do
|
104
|
-
scanner = HtmlErb.new("before\n<% multi\nline -%>\nafter")
|
104
|
+
scanner = HtmlErb.new(buffer("before\n<% multi\nline -%>\nafter"))
|
105
105
|
assert_equal 7, scanner.tokens.size
|
106
106
|
|
107
107
|
assert_attributes ({ type: :text, loc: { line: 1, source: "before\n" } }), scanner.tokens[0]
|
@@ -114,7 +114,7 @@ module BetterHtml
|
|
114
114
|
end
|
115
115
|
|
116
116
|
test "right trim with =%>" do
|
117
|
-
scanner = HtmlErb.new("<% trim =%>")
|
117
|
+
scanner = HtmlErb.new(buffer("<% trim =%>"))
|
118
118
|
assert_equal 4, scanner.tokens.size
|
119
119
|
|
120
120
|
assert_attributes ({ type: :erb_begin, loc: { line: 1, source: '<%' } }), scanner.tokens[0]
|
@@ -124,7 +124,7 @@ module BetterHtml
|
|
124
124
|
end
|
125
125
|
|
126
126
|
test "multi-line expression with trim" do
|
127
|
-
scanner = HtmlErb.new("before\n<%= multi\nline -%>\nafter")
|
127
|
+
scanner = HtmlErb.new(buffer("before\n<%= multi\nline -%>\nafter"))
|
128
128
|
assert_equal 8, scanner.tokens.size
|
129
129
|
|
130
130
|
assert_attributes ({ type: :text, loc: { line: 1, source: "before\n" } }), scanner.tokens[0]
|
@@ -138,7 +138,7 @@ module BetterHtml
|
|
138
138
|
end
|
139
139
|
|
140
140
|
test "line counts with comments" do
|
141
|
-
scanner = HtmlErb.new("before\n<%# BO$$ Mode %>\nafter")
|
141
|
+
scanner = HtmlErb.new(buffer("before\n<%# BO$$ Mode %>\nafter"))
|
142
142
|
assert_equal 7, scanner.tokens.size
|
143
143
|
|
144
144
|
assert_attributes ({ type: :text, loc: { line: 1, source: "before\n" } }), scanner.tokens[0]
|
@@ -5,55 +5,55 @@ module BetterHtml
|
|
5
5
|
module Tokenizer
|
6
6
|
class HtmlLodashTest < ActiveSupport::TestCase
|
7
7
|
test "matches text" do
|
8
|
-
scanner = HtmlLodash.new("just some text")
|
8
|
+
scanner = HtmlLodash.new(buffer("just some text"))
|
9
9
|
assert_equal 1, scanner.tokens.size
|
10
10
|
|
11
|
-
assert_attributes ({ type: :text, loc: {
|
11
|
+
assert_attributes ({ type: :text, loc: { begin_pos: 0, end_pos: 14, source: "just some text" } }), scanner.tokens[0]
|
12
12
|
end
|
13
13
|
|
14
14
|
test "matches strings to be escaped" do
|
15
|
-
scanner = HtmlLodash.new("[%= foo %]")
|
15
|
+
scanner = HtmlLodash.new(buffer("[%= foo %]"))
|
16
16
|
assert_equal 4, scanner.tokens.size
|
17
17
|
|
18
|
-
assert_attributes ({ type: :lodash_begin, loc: {
|
19
|
-
assert_attributes ({ type: :indicator, loc: {
|
20
|
-
assert_attributes ({ type: :code, loc: {
|
21
|
-
assert_attributes ({ type: :lodash_end, loc: {
|
18
|
+
assert_attributes ({ type: :lodash_begin, loc: { begin_pos: 0, end_pos: 2, source: "[%" } }), scanner.tokens[0]
|
19
|
+
assert_attributes ({ type: :indicator, loc: { begin_pos: 2, end_pos: 3, source: "=" } }), scanner.tokens[1]
|
20
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 3, end_pos: 8, source: " foo " } }), scanner.tokens[2]
|
21
|
+
assert_attributes ({ type: :lodash_end, loc: { begin_pos: 8, end_pos: 10, source: "%]" } }), scanner.tokens[3]
|
22
22
|
end
|
23
23
|
|
24
24
|
test "matches interpolate" do
|
25
|
-
scanner = HtmlLodash.new("[%! foo %]")
|
25
|
+
scanner = HtmlLodash.new(buffer("[%! foo %]"))
|
26
26
|
assert_equal 4, scanner.tokens.size
|
27
27
|
|
28
|
-
assert_attributes ({ type: :lodash_begin, loc: {
|
29
|
-
assert_attributes ({ type: :indicator, loc: {
|
30
|
-
assert_attributes ({ type: :code, loc: {
|
31
|
-
assert_attributes ({ type: :lodash_end, loc: {
|
28
|
+
assert_attributes ({ type: :lodash_begin, loc: { begin_pos: 0, end_pos: 2, source: "[%" } }), scanner.tokens[0]
|
29
|
+
assert_attributes ({ type: :indicator, loc: { begin_pos: 2, end_pos: 3, source: "!" } }), scanner.tokens[1]
|
30
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 3, end_pos: 8, source: " foo " } }), scanner.tokens[2]
|
31
|
+
assert_attributes ({ type: :lodash_end, loc: { begin_pos: 8, end_pos: 10, source: "%]" } }), scanner.tokens[3]
|
32
32
|
end
|
33
33
|
|
34
34
|
test "matches statement" do
|
35
|
-
scanner = HtmlLodash.new("[% foo %]")
|
35
|
+
scanner = HtmlLodash.new(buffer("[% foo %]"))
|
36
36
|
assert_equal 3, scanner.tokens.size
|
37
37
|
|
38
|
-
assert_attributes ({ type: :lodash_begin, loc: {
|
39
|
-
assert_attributes ({ type: :code, loc: {
|
40
|
-
assert_attributes ({ type: :lodash_end, loc: {
|
38
|
+
assert_attributes ({ type: :lodash_begin, loc: { begin_pos: 0, end_pos: 2, source: "[%" } }), scanner.tokens[0]
|
39
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 2, end_pos: 7, source: " foo " } }), scanner.tokens[1]
|
40
|
+
assert_attributes ({ type: :lodash_end, loc: { begin_pos: 7, end_pos: 9, source: "%]" } }), scanner.tokens[2]
|
41
41
|
end
|
42
42
|
|
43
43
|
test "matches text before and after" do
|
44
|
-
scanner = HtmlLodash.new("before\n[%= foo %]\nafter")
|
44
|
+
scanner = HtmlLodash.new(buffer("before\n[%= foo %]\nafter"))
|
45
45
|
assert_equal 6, scanner.tokens.size
|
46
46
|
|
47
|
-
assert_attributes ({ type: :text, loc: {
|
48
|
-
assert_attributes ({ type: :lodash_begin, loc: {
|
49
|
-
assert_attributes ({ type: :indicator, loc: {
|
50
|
-
assert_attributes ({ type: :code, loc: {
|
51
|
-
assert_attributes ({ type: :lodash_end, loc: {
|
52
|
-
assert_attributes ({ type: :text, loc: {
|
47
|
+
assert_attributes ({ type: :text, loc: { begin_pos: 0, end_pos: 7, source: "before\n" } }), scanner.tokens[0]
|
48
|
+
assert_attributes ({ type: :lodash_begin, loc: { begin_pos: 7, end_pos: 9, source: "[%" } }), scanner.tokens[1]
|
49
|
+
assert_attributes ({ type: :indicator, loc: { begin_pos: 9, end_pos: 10, source: "=" } }), scanner.tokens[2]
|
50
|
+
assert_attributes ({ type: :code, loc: { begin_pos: 10, end_pos: 15, source: " foo " } }), scanner.tokens[3]
|
51
|
+
assert_attributes ({ type: :lodash_end, loc: { begin_pos: 15, end_pos: 17, source: "%]" } }), scanner.tokens[4]
|
52
|
+
assert_attributes ({ type: :text, loc: { begin_pos: 17, end_pos: 23, source: "\nafter" } }), scanner.tokens[5]
|
53
53
|
end
|
54
54
|
|
55
55
|
test "matches multiple" do
|
56
|
-
scanner = HtmlLodash.new("[% if() { %][%= foo %][% } %]")
|
56
|
+
scanner = HtmlLodash.new(buffer("[% if() { %][%= foo %][% } %]"))
|
57
57
|
assert_equal 10, scanner.tokens.size
|
58
58
|
|
59
59
|
assert_attributes ({ type: :lodash_begin, loc: { source: "[%" } }), scanner.tokens[0]
|
@@ -71,7 +71,7 @@ module BetterHtml
|
|
71
71
|
end
|
72
72
|
|
73
73
|
test "parses out html correctly" do
|
74
|
-
scanner = HtmlLodash.new('<div class="[%= foo %]">')
|
74
|
+
scanner = HtmlLodash.new(buffer('<div class="[%= foo %]">'))
|
75
75
|
assert_equal 12, scanner.tokens.size
|
76
76
|
assert_equal [:tag_start, :tag_name, :whitespace, :attribute_name,
|
77
77
|
:equal, :attribute_quoted_value_start,
|
@@ -6,37 +6,53 @@ module BetterHtml
|
|
6
6
|
class LocationTest < ActiveSupport::TestCase
|
7
7
|
test "location start out of bounds" do
|
8
8
|
e = assert_raises(ArgumentError) do
|
9
|
-
Location.new("foo", 5, 6)
|
9
|
+
Location.new(buffer("foo"), 5, 6)
|
10
10
|
end
|
11
|
-
assert_equal "
|
11
|
+
assert_equal "begin_pos location 5 is out of range for document of size 3", e.message
|
12
12
|
end
|
13
13
|
|
14
14
|
test "location stop out of bounds" do
|
15
15
|
e = assert_raises(ArgumentError) do
|
16
|
-
Location.new("foo", 2, 6)
|
16
|
+
Location.new(buffer("foo"), 2, 6)
|
17
17
|
end
|
18
|
-
assert_equal "
|
18
|
+
assert_equal "end_pos location 6 is out of range for document of size 3", e.message
|
19
19
|
end
|
20
20
|
|
21
21
|
test "location stop < start" do
|
22
22
|
e = assert_raises(ArgumentError) do
|
23
|
-
Location.new("aaaaaa", 5, 2)
|
23
|
+
Location.new(buffer("aaaaaa"), 5, 2)
|
24
24
|
end
|
25
|
-
assert_equal "
|
25
|
+
assert_equal "Parser::Source::Range: end_pos must not be less than begin_pos", e.message
|
26
|
+
end
|
27
|
+
|
28
|
+
test "location stop == start" do
|
29
|
+
loc = Location.new(buffer("aaaaaa"), 5, 5)
|
30
|
+
assert_equal "", loc.source
|
31
|
+
assert_equal 0, loc.size
|
32
|
+
end
|
33
|
+
|
34
|
+
test "end_pos is stop+1" do
|
35
|
+
loc = Location.new(buffer("aaaaaa"), 5, 5)
|
36
|
+
assert_equal 5, loc.end_pos
|
37
|
+
end
|
38
|
+
|
39
|
+
test "range is exclusive of last char" do
|
40
|
+
loc = Location.new(buffer("aaaaaa"), 5, 5)
|
41
|
+
assert_equal 5...5, loc.range
|
26
42
|
end
|
27
43
|
|
28
44
|
test "location calulates start and stop line and column" do
|
29
|
-
loc = Location.new("foo\nbar\nbaz", 5,
|
45
|
+
loc = Location.new(buffer("foo\nbar\nbaz"), 5, 10)
|
30
46
|
|
31
47
|
assert_equal "ar\nba", loc.source
|
32
48
|
assert_equal 2, loc.start_line
|
33
49
|
assert_equal 1, loc.start_column
|
34
50
|
assert_equal 3, loc.stop_line
|
35
|
-
assert_equal
|
51
|
+
assert_equal 2, loc.stop_column
|
36
52
|
end
|
37
53
|
|
38
54
|
test "line_source_with_underline" do
|
39
|
-
loc = Location.new("ui_helper(foo)", 10,
|
55
|
+
loc = Location.new(buffer("ui_helper(foo)"), 10, 13)
|
40
56
|
|
41
57
|
assert_equal "foo", loc.source
|
42
58
|
assert_equal <<~EOL.strip, loc.line_source_with_underline
|
@@ -46,7 +62,7 @@ module BetterHtml
|
|
46
62
|
end
|
47
63
|
|
48
64
|
test "line_source_with_underline removes empty spaces" do
|
49
|
-
loc = Location.new(" \t ui_helper(foo)", 17,
|
65
|
+
loc = Location.new(buffer(" \t ui_helper(foo)"), 17, 20)
|
50
66
|
|
51
67
|
assert_equal "foo", loc.source
|
52
68
|
assert_equal <<~EOL.strip, loc.line_source_with_underline
|
@@ -8,10 +8,11 @@ module BetterHtml
|
|
8
8
|
class TokenArrayTest < ActiveSupport::TestCase
|
9
9
|
setup do
|
10
10
|
@document = "<x>"
|
11
|
+
@buffer = buffer(@document)
|
11
12
|
@tokens = [
|
12
|
-
Token.new(type: :lquote, loc: Location.new(@
|
13
|
-
Token.new(type: :name, loc: Location.new(@
|
14
|
-
Token.new(type: :rquote, loc: Location.new(@
|
13
|
+
Token.new(type: :lquote, loc: Location.new(@buffer, 0, 0)),
|
14
|
+
Token.new(type: :name, loc: Location.new(@buffer, 1, 1)),
|
15
|
+
Token.new(type: :rquote, loc: Location.new(@buffer, 2, 2)),
|
15
16
|
]
|
16
17
|
@array = TokenArray.new(@tokens)
|
17
18
|
end
|
@@ -6,7 +6,7 @@ module BetterHtml
|
|
6
6
|
module Tokenizer
|
7
7
|
class TokenTest < ActiveSupport::TestCase
|
8
8
|
test "token inspect" do
|
9
|
-
loc = Location.new("foo", 0,
|
9
|
+
loc = Location.new(buffer("foo"), 0, 3)
|
10
10
|
token = Token.new(type: :foo, loc: loc)
|
11
11
|
assert_equal "t(:foo, \"foo\")", token.inspect
|
12
12
|
end
|
data/test/test_helper.rb
CHANGED
@@ -18,3 +18,13 @@ if ActiveSupport::TestCase.respond_to?(:fixture_path=)
|
|
18
18
|
end
|
19
19
|
|
20
20
|
require 'mocha/mini_test'
|
21
|
+
|
22
|
+
class ActiveSupport::TestCase
|
23
|
+
private
|
24
|
+
|
25
|
+
def buffer(string)
|
26
|
+
buffer = ::Parser::Source::Buffer.new('(test)')
|
27
|
+
buffer.source = string
|
28
|
+
buffer
|
29
|
+
end
|
30
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: better_html
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francois Chagnon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ast
|