better_html 0.0.12 → 1.0.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/better_html.rb +0 -2
  3. data/lib/better_html/ast/iterator.rb +32 -0
  4. data/lib/better_html/ast/node.rb +14 -0
  5. data/lib/better_html/better_erb/runtime_checks.rb +3 -3
  6. data/lib/better_html/config.rb +12 -0
  7. data/lib/better_html/parser.rb +286 -0
  8. data/lib/better_html/test_helper/ruby_expr.rb +8 -5
  9. data/lib/better_html/test_helper/safe_erb_tester.rb +121 -108
  10. data/lib/better_html/test_helper/safe_lodash_tester.rb +44 -42
  11. data/lib/better_html/tokenizer/base_erb.rb +79 -0
  12. data/lib/better_html/tokenizer/html_erb.rb +31 -0
  13. data/lib/better_html/{node_iterator → tokenizer}/html_lodash.rb +30 -34
  14. data/lib/better_html/tokenizer/javascript_erb.rb +15 -0
  15. data/lib/better_html/{node_iterator → tokenizer}/location.rb +9 -3
  16. data/lib/better_html/tokenizer/token.rb +16 -0
  17. data/lib/better_html/tokenizer/token_array.rb +54 -0
  18. data/lib/better_html/tree/attribute.rb +31 -0
  19. data/lib/better_html/tree/attributes_list.rb +25 -0
  20. data/lib/better_html/tree/tag.rb +39 -0
  21. data/lib/better_html/version.rb +1 -1
  22. data/test/better_html/parser_test.rb +279 -0
  23. data/test/better_html/test_helper/safe_erb_tester_test.rb +11 -0
  24. data/test/better_html/test_helper/safe_lodash_tester_test.rb +11 -1
  25. data/test/better_html/tokenizer/html_erb_test.rb +158 -0
  26. data/test/better_html/tokenizer/html_lodash_test.rb +98 -0
  27. data/test/better_html/tokenizer/location_test.rb +57 -0
  28. data/test/better_html/tokenizer/token_array_test.rb +144 -0
  29. data/test/better_html/tokenizer/token_test.rb +15 -0
  30. metadata +45 -30
  31. data/lib/better_html/node_iterator.rb +0 -144
  32. data/lib/better_html/node_iterator/attribute.rb +0 -34
  33. data/lib/better_html/node_iterator/base.rb +0 -27
  34. data/lib/better_html/node_iterator/cdata.rb +0 -8
  35. data/lib/better_html/node_iterator/comment.rb +0 -8
  36. data/lib/better_html/node_iterator/content_node.rb +0 -13
  37. data/lib/better_html/node_iterator/element.rb +0 -26
  38. data/lib/better_html/node_iterator/html_erb.rb +0 -70
  39. data/lib/better_html/node_iterator/javascript_erb.rb +0 -55
  40. data/lib/better_html/node_iterator/text.rb +0 -8
  41. data/lib/better_html/node_iterator/token.rb +0 -8
  42. data/lib/better_html/tree.rb +0 -113
  43. data/test/better_html/node_iterator/html_erb_test.rb +0 -116
  44. data/test/better_html/node_iterator/html_lodash_test.rb +0 -132
  45. data/test/better_html/node_iterator/location_test.rb +0 -36
  46. data/test/better_html/node_iterator_test.rb +0 -221
  47. data/test/better_html/tree_test.rb +0 -110
@@ -0,0 +1,98 @@
1
+ require 'test_helper'
2
+ require 'better_html/tokenizer/html_lodash'
3
+
4
+ module BetterHtml
5
+ module Tokenizer
6
+ class HtmlLodashTest < ActiveSupport::TestCase
7
+ test "matches text" do
8
+ scanner = HtmlLodash.new("just some text")
9
+ assert_equal 1, scanner.tokens.size
10
+
11
+ assert_attributes ({ type: :text, loc: { start: 0, stop: 13, source: "just some text" } }), scanner.tokens[0]
12
+ end
13
+
14
+ test "matches strings to be escaped" do
15
+ scanner = HtmlLodash.new("[%= foo %]")
16
+ assert_equal 4, scanner.tokens.size
17
+
18
+ assert_attributes ({ type: :lodash_begin, loc: { start: 0, stop: 1, source: "[%" } }), scanner.tokens[0]
19
+ assert_attributes ({ type: :indicator, loc: { start: 2, stop: 2, source: "=" } }), scanner.tokens[1]
20
+ assert_attributes ({ type: :code, loc: { start: 3, stop: 7, source: " foo " } }), scanner.tokens[2]
21
+ assert_attributes ({ type: :lodash_end, loc: { start: 8, stop: 9, source: "%]" } }), scanner.tokens[3]
22
+ end
23
+
24
+ test "matches interpolate" do
25
+ scanner = HtmlLodash.new("[%! foo %]")
26
+ assert_equal 4, scanner.tokens.size
27
+
28
+ assert_attributes ({ type: :lodash_begin, loc: { start: 0, stop: 1, source: "[%" } }), scanner.tokens[0]
29
+ assert_attributes ({ type: :indicator, loc: { start: 2, stop: 2, source: "!" } }), scanner.tokens[1]
30
+ assert_attributes ({ type: :code, loc: { start: 3, stop: 7, source: " foo " } }), scanner.tokens[2]
31
+ assert_attributes ({ type: :lodash_end, loc: { start: 8, stop: 9, source: "%]" } }), scanner.tokens[3]
32
+ end
33
+
34
+ test "matches statement" do
35
+ scanner = HtmlLodash.new("[% foo %]")
36
+ assert_equal 3, scanner.tokens.size
37
+
38
+ assert_attributes ({ type: :lodash_begin, loc: { start: 0, stop: 1, source: "[%" } }), scanner.tokens[0]
39
+ assert_attributes ({ type: :code, loc: { start: 2, stop: 6, source: " foo " } }), scanner.tokens[1]
40
+ assert_attributes ({ type: :lodash_end, loc: { start: 7, stop: 8, source: "%]" } }), scanner.tokens[2]
41
+ end
42
+
43
+ test "matches text before and after" do
44
+ scanner = HtmlLodash.new("before\n[%= foo %]\nafter")
45
+ assert_equal 6, scanner.tokens.size
46
+
47
+ assert_attributes ({ type: :text, loc: { start: 0, stop: 6, source: "before\n" } }), scanner.tokens[0]
48
+ assert_attributes ({ type: :lodash_begin, loc: { start: 7, stop: 8, source: "[%" } }), scanner.tokens[1]
49
+ assert_attributes ({ type: :indicator, loc: { start: 9, stop: 9, source: "=" } }), scanner.tokens[2]
50
+ assert_attributes ({ type: :code, loc: { start: 10, stop: 14, source: " foo " } }), scanner.tokens[3]
51
+ assert_attributes ({ type: :lodash_end, loc: { start: 15, stop: 16, source: "%]" } }), scanner.tokens[4]
52
+ assert_attributes ({ type: :text, loc: { start: 17, stop: 22, source: "\nafter" } }), scanner.tokens[5]
53
+ end
54
+
55
+ test "matches multiple" do
56
+ scanner = HtmlLodash.new("[% if() { %][%= foo %][% } %]")
57
+ assert_equal 10, scanner.tokens.size
58
+
59
+ assert_attributes ({ type: :lodash_begin, loc: { source: "[%" } }), scanner.tokens[0]
60
+ assert_attributes ({ type: :code, loc: { source: " if() { " } }), scanner.tokens[1]
61
+ assert_attributes ({ type: :lodash_end, loc: { source: "%]" } }), scanner.tokens[2]
62
+
63
+ assert_attributes ({ type: :lodash_begin, loc: { source: "[%" } }), scanner.tokens[3]
64
+ assert_attributes ({ type: :indicator, loc: { source: "=" } }), scanner.tokens[4]
65
+ assert_attributes ({ type: :code, loc: { source: " foo " } }), scanner.tokens[5]
66
+ assert_attributes ({ type: :lodash_end, loc: { source: "%]" } }), scanner.tokens[6]
67
+
68
+ assert_attributes ({ type: :lodash_begin, loc: { source: "[%" } }), scanner.tokens[7]
69
+ assert_attributes ({ type: :code, loc: { source: " } " } }), scanner.tokens[8]
70
+ assert_attributes ({ type: :lodash_end, loc: { source: "%]" } }), scanner.tokens[9]
71
+ end
72
+
73
+ test "parses out html correctly" do
74
+ scanner = HtmlLodash.new('<div class="[%= foo %]">')
75
+ assert_equal 12, scanner.tokens.size
76
+ assert_equal [:tag_start, :tag_name, :whitespace, :attribute_name,
77
+ :equal, :attribute_quoted_value_start,
78
+ :lodash_begin, :indicator, :code, :lodash_end,
79
+ :attribute_quoted_value_end, :tag_end], scanner.tokens.map(&:type)
80
+ assert_equal ["<", "div", " ", "class", "=", "\"", "[%", "=", " foo ", "%]", "\"", ">"], scanner.tokens.map(&:loc).map(&:source)
81
+ end
82
+
83
+ private
84
+
85
+ def assert_attributes(attributes, token)
86
+ attributes.each do |key, value|
87
+ if value.nil?
88
+ assert_nil token.send(key)
89
+ elsif value.is_a?(Hash)
90
+ assert_attributes(value, token.send(key))
91
+ else
92
+ assert_equal value, token.send(key)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+ require 'better_html/tokenizer/location'
3
+
4
+ module BetterHtml
5
+ module Tokenizer
6
+ class LocationTest < ActiveSupport::TestCase
7
+ test "location start out of bounds" do
8
+ e = assert_raises(ArgumentError) do
9
+ Location.new("foo", 5, 6)
10
+ end
11
+ assert_equal "start location 5 is out of range for document of size 3", e.message
12
+ end
13
+
14
+ test "location stop out of bounds" do
15
+ e = assert_raises(ArgumentError) do
16
+ Location.new("foo", 2, 6)
17
+ end
18
+ assert_equal "stop location 6 is out of range for document of size 3", e.message
19
+ end
20
+
21
+ test "location stop < start" do
22
+ e = assert_raises(ArgumentError) do
23
+ Location.new("aaaaaa", 5, 2)
24
+ end
25
+ assert_equal "end of range must be greater than start of range (2 < 5)", e.message
26
+ end
27
+
28
+ test "location without line and column" do
29
+ loc = Location.new("foo\nbar\nbaz", 9, 9)
30
+
31
+ assert_equal "a", loc.source
32
+ assert_equal 3, loc.line
33
+ assert_equal 1, loc.column
34
+ end
35
+
36
+ test "line_source_with_underline" do
37
+ loc = Location.new("ui_helper(foo)", 10, 12)
38
+
39
+ assert_equal "foo", loc.source
40
+ assert_equal <<~EOL.strip, loc.line_source_with_underline
41
+ ui_helper(foo)
42
+ ^^^
43
+ EOL
44
+ end
45
+
46
+ test "line_source_with_underline removes empty spaces" do
47
+ loc = Location.new(" \t ui_helper(foo)", 17, 19)
48
+
49
+ assert_equal "foo", loc.source
50
+ assert_equal <<~EOL.strip, loc.line_source_with_underline
51
+ ui_helper(foo)
52
+ ^^^
53
+ EOL
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,144 @@
1
+ require 'test_helper'
2
+ require 'better_html/tokenizer/token'
3
+ require 'better_html/tokenizer/location'
4
+ require 'better_html/tokenizer/token_array'
5
+
6
+ module BetterHtml
7
+ module Tokenizer
8
+ class TokenArrayTest < ActiveSupport::TestCase
9
+ setup do
10
+ @document = "<x>"
11
+ @tokens = [
12
+ Token.new(type: :lquote, loc: Location.new(@document, 0, 0)),
13
+ Token.new(type: :name, loc: Location.new(@document, 1, 1)),
14
+ Token.new(type: :rquote, loc: Location.new(@document, 2, 2)),
15
+ ]
16
+ @array = TokenArray.new(@tokens)
17
+ end
18
+
19
+ test "size" do
20
+ assert_equal 3, @array.size
21
+ end
22
+
23
+ test "size for empty array" do
24
+ @array = TokenArray.new([])
25
+ assert_equal 0, @array.size
26
+ end
27
+
28
+ test "shift returns element from beginning of array" do
29
+ assert_equal @tokens.first, @array.shift
30
+ end
31
+
32
+ test "shift decreases the size by 1" do
33
+ assert_difference(-> { @array.size }, -1) do
34
+ @array.shift
35
+ end
36
+ end
37
+
38
+ test "after shift, current element is changed" do
39
+ assert_equal @tokens.first, @array.current
40
+ assert_equal @tokens.first, @array.shift
41
+ assert_equal @tokens.second, @array.current
42
+ end
43
+
44
+ test "pop returns element from the end of array" do
45
+ assert_equal @tokens.last, @array.pop
46
+ end
47
+
48
+ test "pop decreases the size by 1" do
49
+ assert_difference(-> { @array.size }, -1) do
50
+ @array.pop
51
+ end
52
+ end
53
+
54
+ test "after pop, last element is changed" do
55
+ assert_equal @tokens.last, @array.last
56
+ assert_equal @tokens.last, @array.pop
57
+ assert_equal @tokens.second, @array.last
58
+ end
59
+
60
+ test "current returns element from beginning of array" do
61
+ assert_equal @tokens.first, @array.current
62
+ end
63
+
64
+ test "current does not change size" do
65
+ assert_no_difference(-> { @array.size }) do
66
+ @array.current
67
+ end
68
+ end
69
+
70
+ test "last returns element from the end of array" do
71
+ assert_equal @tokens.last, @array.last
72
+ end
73
+
74
+ test "last does not change size" do
75
+ assert_no_difference(-> { @array.size }) do
76
+ @array.last
77
+ end
78
+ end
79
+
80
+ test "empty?" do
81
+ refute_predicate @array, :empty?
82
+ 3.times { @array.shift }
83
+ assert_predicate @array, :empty?
84
+ end
85
+
86
+ test "any?" do
87
+ assert_predicate @array, :any?
88
+ 3.times { @array.shift }
89
+ refute_predicate @array, :any?
90
+ end
91
+
92
+ test "current is nil when array is empty" do
93
+ @array = TokenArray.new([])
94
+ assert_nil @array.current
95
+ end
96
+
97
+ test "last is nil when array is empty" do
98
+ @array = TokenArray.new([])
99
+ assert_nil @array.last
100
+ end
101
+
102
+ test "shift raises for empty array" do
103
+ @array = TokenArray.new([])
104
+ e = assert_raises(RuntimeError) do
105
+ @array.shift
106
+ end
107
+ assert_equal 'no tokens left to shift', e.message
108
+ end
109
+
110
+ test "pop raises for empty array" do
111
+ @array = TokenArray.new([])
112
+ e = assert_raises(RuntimeError) do
113
+ @array.pop
114
+ end
115
+ assert_equal 'no tokens left to pop', e.message
116
+ end
117
+
118
+ test "trim takes elements from the beginning of array" do
119
+ assert_difference(-> { @array.size }, -1) do
120
+ @array.trim(:lquote)
121
+ end
122
+
123
+ assert_equal @tokens.second, @array.current
124
+ end
125
+
126
+ test "trim takes elements from the end of array" do
127
+ assert_difference(-> { @array.size }, -1) do
128
+ @array.trim(:rquote)
129
+ end
130
+
131
+ assert_equal @tokens.second, @array.last
132
+ end
133
+
134
+ test "trim does not change array when element types are not at front nor back of array" do
135
+ assert_no_difference(-> { @array.size }) do
136
+ @array.trim(:name)
137
+ end
138
+
139
+ assert_equal @tokens.first, @array.current
140
+ assert_equal @tokens.last, @array.last
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+ require 'better_html/tokenizer/location'
3
+ require 'better_html/tokenizer/token'
4
+
5
+ module BetterHtml
6
+ module Tokenizer
7
+ class TokenTest < ActiveSupport::TestCase
8
+ test "token inspect" do
9
+ loc = Location.new("foo", 0, 2)
10
+ token = Token.new(type: :foo, loc: loc)
11
+ assert_equal "t(:foo, \"foo\")", token.inspect
12
+ end
13
+ end
14
+ end
15
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_html
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francois Chagnon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-15 00:00:00.000000000 Z
11
+ date: 2017-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ast
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: erubi
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +98,16 @@ dependencies:
84
98
  name: html_tokenizer
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - ">="
101
+ - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: '0'
103
+ version: 0.0.5
90
104
  type: :runtime
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - ">="
108
+ - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: '0'
110
+ version: 0.0.5
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rake
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +133,8 @@ files:
119
133
  - MIT-LICENSE
120
134
  - Rakefile
121
135
  - lib/better_html.rb
136
+ - lib/better_html/ast/iterator.rb
137
+ - lib/better_html/ast/node.rb
122
138
  - lib/better_html/better_erb.rb
123
139
  - lib/better_html/better_erb/erubi_implementation.rb
124
140
  - lib/better_html/better_erb/erubis_implementation.rb
@@ -128,37 +144,35 @@ files:
128
144
  - lib/better_html/errors.rb
129
145
  - lib/better_html/helpers.rb
130
146
  - lib/better_html/html_attributes.rb
131
- - lib/better_html/node_iterator.rb
132
- - lib/better_html/node_iterator/attribute.rb
133
- - lib/better_html/node_iterator/base.rb
134
- - lib/better_html/node_iterator/cdata.rb
135
- - lib/better_html/node_iterator/comment.rb
136
- - lib/better_html/node_iterator/content_node.rb
137
- - lib/better_html/node_iterator/element.rb
138
- - lib/better_html/node_iterator/html_erb.rb
139
- - lib/better_html/node_iterator/html_lodash.rb
140
- - lib/better_html/node_iterator/javascript_erb.rb
141
- - lib/better_html/node_iterator/location.rb
142
- - lib/better_html/node_iterator/text.rb
143
- - lib/better_html/node_iterator/token.rb
147
+ - lib/better_html/parser.rb
144
148
  - lib/better_html/railtie.rb
145
149
  - lib/better_html/test_helper/ruby_expr.rb
146
150
  - lib/better_html/test_helper/safe_erb_tester.rb
147
151
  - lib/better_html/test_helper/safe_lodash_tester.rb
148
152
  - lib/better_html/test_helper/safety_error.rb
149
- - lib/better_html/tree.rb
153
+ - lib/better_html/tokenizer/base_erb.rb
154
+ - lib/better_html/tokenizer/html_erb.rb
155
+ - lib/better_html/tokenizer/html_lodash.rb
156
+ - lib/better_html/tokenizer/javascript_erb.rb
157
+ - lib/better_html/tokenizer/location.rb
158
+ - lib/better_html/tokenizer/token.rb
159
+ - lib/better_html/tokenizer/token_array.rb
160
+ - lib/better_html/tree/attribute.rb
161
+ - lib/better_html/tree/attributes_list.rb
162
+ - lib/better_html/tree/tag.rb
150
163
  - lib/better_html/version.rb
151
164
  - lib/tasks/better_html_tasks.rake
152
165
  - test/better_html/better_erb/implementation_test.rb
153
166
  - test/better_html/helpers_test.rb
154
- - test/better_html/node_iterator/html_erb_test.rb
155
- - test/better_html/node_iterator/html_lodash_test.rb
156
- - test/better_html/node_iterator/location_test.rb
157
- - test/better_html/node_iterator_test.rb
167
+ - test/better_html/parser_test.rb
158
168
  - test/better_html/test_helper/ruby_expr_test.rb
159
169
  - test/better_html/test_helper/safe_erb_tester_test.rb
160
170
  - test/better_html/test_helper/safe_lodash_tester_test.rb
161
- - test/better_html/tree_test.rb
171
+ - test/better_html/tokenizer/html_erb_test.rb
172
+ - test/better_html/tokenizer/html_lodash_test.rb
173
+ - test/better_html/tokenizer/location_test.rb
174
+ - test/better_html/tokenizer/token_array_test.rb
175
+ - test/better_html/tokenizer/token_test.rb
162
176
  - test/dummy/README.rdoc
163
177
  - test/dummy/Rakefile
164
178
  - test/dummy/app/assets/javascripts/application.js
@@ -255,12 +269,13 @@ test_files:
255
269
  - test/dummy/Rakefile
256
270
  - test/test_helper.rb
257
271
  - test/better_html/helpers_test.rb
258
- - test/better_html/node_iterator_test.rb
259
- - test/better_html/node_iterator/location_test.rb
260
- - test/better_html/node_iterator/html_lodash_test.rb
261
- - test/better_html/node_iterator/html_erb_test.rb
272
+ - test/better_html/parser_test.rb
262
273
  - test/better_html/better_erb/implementation_test.rb
263
274
  - test/better_html/test_helper/safe_erb_tester_test.rb
264
275
  - test/better_html/test_helper/safe_lodash_tester_test.rb
265
276
  - test/better_html/test_helper/ruby_expr_test.rb
266
- - test/better_html/tree_test.rb
277
+ - test/better_html/tokenizer/location_test.rb
278
+ - test/better_html/tokenizer/html_lodash_test.rb
279
+ - test/better_html/tokenizer/html_erb_test.rb
280
+ - test/better_html/tokenizer/token_array_test.rb
281
+ - test/better_html/tokenizer/token_test.rb