hamlit 0.5.0 → 0.5.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f3c1078cb3f9e7ede4ba7c795b4e3efc2362741f
4
- data.tar.gz: 698a072f9a818ce45c49840474b3a195ce1eddaf
3
+ metadata.gz: 0bfb9ad9ffecfdff23622a518e793277666c95dc
4
+ data.tar.gz: 0ce26c8bf5d259d79af24b18d5c5fd4f83a4d862
5
5
  SHA512:
6
- metadata.gz: 87200444daaae8c0d02f191bd001bfee731e357087220926f8fb4c8659c2e9028af2996d1d819b7002cf1ad7582b80bcd83962ea24bd4ece1c04e3fcaa8f2d6a
7
- data.tar.gz: dce886340c509921c981afdcc7f83d1d9a5f8bd175c796dc285064a6f2f8e35e68e9929a8ce6158087919bde932f695e4db989d941f34b0384e4221d041d8b30
6
+ metadata.gz: 04fd200583dd12ef868addaddbd6d0e85d76ffd96bd6ca29010d853acb6ffd8844ace8888d8d2948aa38379349df76ee054b53014c7bd16417af4b61f4a63426
7
+ data.tar.gz: 73bfe1a5b717565904aac6e0dc1fc07bb27a44f8b1507624c607bc8a240989b8f80ebee8345c65648163f4cfe069cb4cd05d06458406805763fc23a864655cc7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## v0.5.1
2
+
3
+ - Bugfix about duplicated id and class
4
+ - https://github.com/k0kubun/hamlit/issues/4
5
+ - Thanks to @os0x
6
+
1
7
  ## v0.5.0
2
8
 
3
9
  - Escape special characters in attribute values
@@ -10,18 +10,18 @@ module Hamlit
10
10
  class Attribute
11
11
  include Concerns::AttributeBuilder
12
12
 
13
- def self.build(quote, attributes)
13
+ def self.build(quote, attributes, base = {})
14
14
  builder = self.new(quote)
15
- builder.build(attributes)
15
+ builder.build(attributes, base)
16
16
  end
17
17
 
18
18
  def initialize(quote)
19
19
  @quote = quote
20
20
  end
21
21
 
22
- def build(attributes)
22
+ def build(attributes, base)
23
23
  result = ''
24
- flatten_attributes(attributes).each do |key, value|
24
+ merge_attributes(base, attributes).each do |key, value|
25
25
  if value == true
26
26
  result += " #{key}"
27
27
  next
@@ -32,5 +32,27 @@ module Hamlit
32
32
  end
33
33
  result
34
34
  end
35
+
36
+ private
37
+
38
+ def merge_attributes(base, target)
39
+ result = {}
40
+ base = flatten_attributes(base)
41
+ target = flatten_attributes(target)
42
+
43
+ (base.keys | target.keys).each do |key|
44
+ if base[key] && target[key]
45
+ case key
46
+ when :id
47
+ result[key] = [base[key], target[key]].compact.join('_')
48
+ else
49
+ result[key] = [base[key], target[key]].compact.join(' ')
50
+ end
51
+ else
52
+ result[key] = base[key].nil? ? target[key] : base[key]
53
+ end
54
+ end
55
+ result
56
+ end
35
57
  end
36
58
  end
@@ -1,5 +1,6 @@
1
1
  require 'hamlit/compilers/new_attribute'
2
2
  require 'hamlit/compilers/old_attribute'
3
+ require 'hamlit/compilers/runtime_attribute'
3
4
  require 'hamlit/concerns/escapable'
4
5
  require 'hamlit/concerns/included'
5
6
 
@@ -9,6 +10,7 @@ module Hamlit
9
10
  extend Concerns::Included
10
11
  include Compilers::NewAttribute
11
12
  include Compilers::OldAttribute
13
+ include Compilers::RuntimeAttribute
12
14
 
13
15
  included do
14
16
  include Concerns::Escapable
@@ -21,6 +23,13 @@ module Hamlit
21
23
  attrs = join_ids(attrs)
22
24
  attrs = combine_classes(attrs)
23
25
  attrs = pull_class_first(attrs)
26
+
27
+ if has_runtime_attribute?(attrs) && has_attr?(attrs, 'class', 'id')
28
+ attrs = merge_runtime_attributes(attrs)
29
+ return [:html, :attrs, *escape_attribute_values(attrs)]
30
+ end
31
+ attrs = attrs.map { |a| compile(a) }
32
+
24
33
  [:html, :attrs, *escape_attribute_values(attrs)]
25
34
  end
26
35
 
@@ -72,9 +81,13 @@ module Hamlit
72
81
  [[:html, :attr, 'id', [:multi, *insert_static(values, '_')]]] + (attrs - id_attrs)
73
82
  end
74
83
 
75
- def filter_attrs(attrs, target)
76
- class_attrs = attrs.select do |html, attr, name, content|
77
- name == target
84
+ def has_attr?(attrs, *targets)
85
+ filter_attrs(attrs, *targets).any?
86
+ end
87
+
88
+ def filter_attrs(attrs, *targets)
89
+ attrs.select do |html, attr, name, content|
90
+ targets.include?(name)
78
91
  end
79
92
  end
80
93
 
@@ -1,4 +1,3 @@
1
- require 'hamlit/attribute'
2
1
  require 'hamlit/concerns/attribute_builder'
3
2
  require 'hamlit/concerns/balanceable'
4
3
  require 'hamlit/concerns/ripperable'
@@ -31,7 +30,8 @@ module Hamlit
31
30
  [:html, :attr, key, [:dynamic, value]]
32
31
  end
33
32
  rescue RuntimeBuild
34
- return runtime_build(str)
33
+ # Give up static compilation when given string is invalid as ruby hash
34
+ [[:runtime, str]]
35
35
  end
36
36
 
37
37
  private
@@ -48,7 +48,7 @@ module Hamlit
48
48
  end
49
49
  end
50
50
 
51
- # Give up static copmile when variables are detected.
51
+ # Give up static compilation when variables are detected.
52
52
  def assert_static_value!(value)
53
53
  tokens = Ripper.lex(value)
54
54
  tokens.each do |(row, col), type, str|
@@ -114,13 +114,6 @@ module Hamlit
114
114
  raise SyntaxError unless type == :on_op && str == '=>'
115
115
  end
116
116
 
117
- def runtime_build(str)
118
- str = str.gsub(/(\A\{|\}\Z)/, '')
119
- quote = options[:attr_quote].inspect
120
- code = "::Hamlit::Attribute.build(#{quote}, #{str})"
121
- [[:dynamic, code]]
122
- end
123
-
124
117
  def split_hash(str)
125
118
  columns = HashParser.assoc_columns(str)
126
119
  columns = reject_nested_columns(str, columns)
@@ -0,0 +1,58 @@
1
+ require 'hamlit/attribute'
2
+ require 'hamlit/concerns/string_interpolation'
3
+
4
+ # This module compiles :runtime sexp. It is a special version of
5
+ # old-style attribute which is built on runtime.
6
+ module Hamlit
7
+ module Compilers
8
+ module RuntimeAttribute
9
+ include Concerns::StringInterpolation
10
+
11
+ # This is used for compiling only runtime attribute in Compilers::Attribute.
12
+ def on_runtime(str)
13
+ compile_runtime_attribute(str)
14
+ end
15
+
16
+ # Given html attrs, merge classes and ids to :dynamic_attribute.
17
+ def merge_runtime_attributes(attrs)
18
+ merge_targets = filter_attrs(attrs, 'id', 'class')
19
+ dynamic_attr = attrs.find { |exp, *args| exp == :runtime }
20
+
21
+ attrs -= merge_targets
22
+ attrs.delete(dynamic_attr)
23
+
24
+ base = decompile_temple_attrs(merge_targets)
25
+ [compile_runtime_attribute(dynamic_attr.last, base), *attrs]
26
+ end
27
+
28
+ private
29
+
30
+ def compile_runtime_attribute(str, base = nil)
31
+ str = str.gsub(/(\A\{|\}\Z)/, '')
32
+ quote = options[:attr_quote].inspect
33
+ code = "::Hamlit::Attribute.build(#{[quote, str, base].compact.join(', ')})"
34
+ [:dynamic, code]
35
+ end
36
+
37
+ def has_runtime_attribute?(attrs)
38
+ attrs.any? do |exp, *args|
39
+ exp == :runtime
40
+ end
41
+ end
42
+
43
+ # Given attrs in temple ast, return an attribute as hash literal.
44
+ def decompile_temple_attrs(attrs)
45
+ literal = '{'
46
+ attrs.each do |html, attr, name, (type, value)|
47
+ case type
48
+ when :static
49
+ literal += ":#{name}=>#{string_literal(value)},"
50
+ when :dynamic
51
+ literal += ":#{name}=>#{value},"
52
+ end
53
+ end
54
+ literal.gsub(/,\Z/, '') + '}'
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,3 @@
1
1
  module Hamlit
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
@@ -41,5 +41,43 @@ describe Hamlit::Engine do
41
41
  HTML
42
42
  end
43
43
  end
44
+
45
+ describe 'element class with attribute class' do
46
+ it 'does not generate double classes' do
47
+ assert_render(<<-HAML, <<-HTML)
48
+ .item(class='first')
49
+ HAML
50
+ <div class='first item'></div>
51
+ HTML
52
+ end
53
+
54
+ it 'does not generate double classes for a variable' do
55
+ assert_render(<<-HAML, <<-HTML)
56
+ - val = 'val'
57
+ .element(class=val)
58
+ HAML
59
+ <div class='element val'></div>
60
+ HTML
61
+ end
62
+ end
63
+
64
+ describe 'element id with attribute id' do
65
+ it 'concatenates ids with underscore' do
66
+ assert_render(<<-HAML, <<-HTML)
67
+ #item(id='first')
68
+ HAML
69
+ <div id='item_first'></div>
70
+ HTML
71
+ end
72
+
73
+ it 'concatenates ids with underscore for a variable' do
74
+ assert_render(<<-HAML, <<-HTML)
75
+ - val = 'first'
76
+ #item(id=val)
77
+ HAML
78
+ <div id='item_first'></div>
79
+ HTML
80
+ end
81
+ end
44
82
  end
45
83
  end
@@ -160,7 +160,7 @@ describe Hamlit::Engine do
160
160
  end
161
161
  end
162
162
 
163
- describe 'element class with attributes class' do
163
+ describe 'element class with attribute class' do
164
164
  it 'does not generate double classes' do
165
165
  assert_render(<<-HAML, <<-HTML)
166
166
  .item{ class: 'first' }
@@ -177,6 +177,52 @@ describe Hamlit::Engine do
177
177
  <div class='element val'></div>
178
178
  HTML
179
179
  end
180
+
181
+ it 'does not generate double classes for hash attributes' do
182
+ assert_render(<<-HAML, <<-HTML)
183
+ - hash = { class: 'val' }
184
+ .element{ hash }
185
+ HAML
186
+ <div class='element val'></div>
187
+ HTML
188
+ end
189
+ end
190
+
191
+ describe 'element id with attribute id' do
192
+ it 'does not generate double ids' do
193
+ assert_render(<<-HAML, <<-HTML)
194
+ #item{ id: 'first' }
195
+ HAML
196
+ <div id='item_first'></div>
197
+ HTML
198
+ end
199
+
200
+ it 'does not generate double ids for a variable' do
201
+ assert_render(<<-HAML, <<-HTML)
202
+ - val = 'first'
203
+ #item{ id: val }
204
+ HAML
205
+ <div id='item_first'></div>
206
+ HTML
207
+ end
208
+
209
+ it 'does not generate double ids for hash attributes' do
210
+ assert_render(<<-HAML, <<-HTML)
211
+ - hash = { id: 'first' }
212
+ #item{ hash }
213
+ HAML
214
+ <div id='item_first'></div>
215
+ HTML
216
+ end
217
+
218
+ it 'does not generate double ids and classes for hash attributes' do
219
+ assert_render(<<-HAML, <<-HTML)
220
+ - hash = { id: 'first', class: 'foo' }
221
+ #item.bar{ hash }
222
+ HAML
223
+ <div class='bar foo' id='item_first'></div>
224
+ HTML
225
+ end
180
226
  end
181
227
  end
182
228
  end
@@ -30,7 +30,7 @@ describe 'Hamlit rails integration', type: :request do
30
30
  expect(response.body).to include("<span data-value='foo 2'></span>")
31
31
  expect(response.body).to include("<div class='foo' data-value='foo 3'></div>")
32
32
  expect(response.body).to include("<a data-value='foo 4'></a>")
33
- expect(response.body).to include("<a data-value='[{:count=>1}]'></a>")
33
+ expect(response.body).to include("<a data-value='[{:count=&gt;1}]'></a>")
34
34
  end
35
35
 
36
36
  describe 'escaping' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hamlit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takashi Kokubun
@@ -312,6 +312,7 @@ files:
312
312
  - lib/hamlit/compilers/new_attribute.rb
313
313
  - lib/hamlit/compilers/old_attribute.rb
314
314
  - lib/hamlit/compilers/preserve.rb
315
+ - lib/hamlit/compilers/runtime_attribute.rb
315
316
  - lib/hamlit/compilers/script.rb
316
317
  - lib/hamlit/compilers/strip.rb
317
318
  - lib/hamlit/compilers/text.rb