opal-haml 0.4.3 → 0.4.4

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: 1419033dec6d3a72ed09a3011ecc454551406271
4
- data.tar.gz: '02064278322c4b072f766465870a035cc4724ad5'
3
+ metadata.gz: '09295c5a78ced0158a3b1fa7e80aa2048fca99ed'
4
+ data.tar.gz: 1549592bbd08fc4e9ddcaf743e4736413d2f05fd
5
5
  SHA512:
6
- metadata.gz: 5c66562091ba037ecbead72df0a925044e129c65a2d8d31965cd4a0293bdfa7935614630335b6f4c45577f949b3e903a4a532ff74efc139ad603cbe982866977
7
- data.tar.gz: 9c7de3fd306c703c012ee02992339cff80df33b18042aca33bc3ab535f2f43effd18cb38da334de2b1c00d68ec6f824942fdfa9129f4ef7e63690921f9669a76
6
+ metadata.gz: 3a1385061b8c9d8e9255cab355fbc84808e21b1545407ed5bb6c3f739805e20fea2d5ff0783299af9412841105b25d7973cdbaaa7f265af4714f22d8c39f854a
7
+ data.tar.gz: e58fc44ac5ebee247678509248157637c149892413a35d1716a7f13fb0773bf6dbd3d8f6cf7b7c26a71b3e2e6be9f0b741229f82cf4d8e21319c22c55f9253d2
@@ -1,37 +1,41 @@
1
+ ## 0.4.4 2017-05-13
2
+
3
+ - Improve support for the attribute builder
4
+
1
5
  ## 0.4.3 2017-05-02
2
6
 
3
- * Add support for Haml v5.0
7
+ - Add support for Haml v5.0
4
8
 
5
9
  ## 0.4.2 2016-10-06
6
10
 
7
- * Avoid Sprockets v3.7 deprecations
11
+ - Avoid Sprockets v3.7 deprecations
8
12
 
9
13
  ## 0.4.1 2015-11-02
10
14
 
11
- * Add support for nested attribute hashes: `%div{ data: { foo: 123 } }` now becomes `<div data-foo="123"></div>`.
15
+ - Add support for nested attribute hashes: `%div{ data: { foo: 123 } }` now becomes `<div data-foo="123"></div>`.
12
16
 
13
- * Attribute values are now properly escaped.
17
+ - Attribute values are now properly escaped.
14
18
 
15
19
  ## 0.4.0 2015-08-07
16
20
 
17
- * Add support for Opal 0.8.
21
+ - Add support for Opal 0.8.
18
22
 
19
- * Update the processor to reuse the good stuff from the Opal::Processor.
23
+ - Update the processor to reuse the good stuff from the Opal::Processor.
20
24
 
21
- * Now each compiled template automatically requires `opal-haml` with the new module system.
25
+ - Now each compiled template automatically requires `opal-haml` with the new module system.
22
26
 
23
27
  ## 0.3.0 2015-02-03
24
28
 
25
- * Add support for new opal Builder processors.
29
+ - Add support for new opal Builder processors.
26
30
 
27
- * Implicitly require `opal-haml` when any haml template is required
31
+ - Implicitly require `opal-haml` when any haml template is required
28
32
 
29
- * Cleanup generated code to be use Opal ERB runtime directly.
33
+ - Cleanup generated code to be use Opal ERB runtime directly.
30
34
 
31
35
  ## 0.2.0 2013-12-17
32
36
 
33
- * Remove opal-sprockets dependency
37
+ - Remove opal-sprockets dependency
34
38
 
35
39
  ## 0.1.0 2013-12-17
36
40
 
37
- * Initial release
41
+ - Initial release
@@ -1,5 +1,5 @@
1
1
  module Opal
2
2
  module Haml
3
- VERSION = '0.4.3'
3
+ VERSION = '0.4.4'
4
4
  end
5
5
  end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ module Haml
24
+ module AttributeBuilder
25
+ # https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
26
+ INVALID_ATTRIBUTE_NAME_REGEX = /[ \0"'>\/=]/
27
+
28
+ class << self
29
+ def build_attributes(is_html, attr_wrapper, escape_attrs, hyphenate_data_attrs, attributes = {})
30
+ # @TODO this is an absolutely ridiculous amount of arguments. At least
31
+ # some of this needs to be moved into an instance method.
32
+ join_char = hyphenate_data_attrs ? '-' : '_'
33
+
34
+ attributes.each do |key, value|
35
+ if value.is_a?(Hash)
36
+ data_attributes = attributes.delete(key)
37
+ data_attributes = flatten_data_attributes(data_attributes, '', join_char)
38
+ data_attributes = build_data_keys(data_attributes, hyphenate_data_attrs, key)
39
+ verify_attribute_names!(data_attributes.keys)
40
+ attributes = data_attributes.merge(attributes)
41
+ end
42
+ end
43
+
44
+ result = attributes.collect do |attr, value|
45
+ next if value.nil?
46
+
47
+ value = filter_and_join(value, ' ') if attr == 'class'
48
+ value = filter_and_join(value, '_') if attr == 'id'
49
+
50
+ if value == true
51
+ next " #{attr}" if is_html
52
+ next " #{attr}=#{attr_wrapper}#{attr}#{attr_wrapper}"
53
+ elsif value == false
54
+ next
55
+ end
56
+
57
+ value =
58
+ if escape_attrs == :once
59
+ Haml::Helpers.escape_once(value.to_s)
60
+ elsif escape_attrs
61
+ Haml::Helpers.html_escape(value.to_s)
62
+ else
63
+ value.to_s
64
+ end
65
+ " #{attr}=#{attr_wrapper}#{value}#{attr_wrapper}"
66
+ end
67
+ result.compact!
68
+ result.sort!
69
+ result.join
70
+ end
71
+
72
+ # @return [String, nil]
73
+ def filter_and_join(value, separator)
74
+ return '' if (value.respond_to?(:empty?) && value.empty?)
75
+
76
+ if value.is_a?(Array)
77
+ value = value.flatten
78
+ value.map! {|item| item ? item.to_s : nil}
79
+ value.compact!
80
+ value = value.join(separator)
81
+ else
82
+ value = value ? value.to_s : nil
83
+ end
84
+ !value.nil? && !value.empty? && value
85
+ end
86
+
87
+ # Merges two attribute hashes.
88
+ # This is the same as `to.merge!(from)`,
89
+ # except that it merges id, class, and data attributes.
90
+ #
91
+ # ids are concatenated with `"_"`,
92
+ # and classes are concatenated with `" "`.
93
+ # data hashes are simply merged.
94
+ #
95
+ # Destructively modifies `to`.
96
+ #
97
+ # @param to [{String => String,Hash}] The attribute hash to merge into
98
+ # @param from [{String => Object}] The attribute hash to merge from
99
+ # @return [{String => String,Hash}] `to`, after being merged
100
+ def merge_attributes!(to, from)
101
+ from.keys.each do |key|
102
+ to[key] = merge_value(key, to[key], from[key])
103
+ end
104
+ to
105
+ end
106
+
107
+ # Merge multiple values to one attribute value. No destructive operation.
108
+ #
109
+ # @param key [String]
110
+ # @param values [Array<Object>]
111
+ # @return [String,Hash]
112
+ def merge_values(key, *values)
113
+ values.inject(nil) do |to, from|
114
+ merge_value(key, to, from)
115
+ end
116
+ end
117
+
118
+ def verify_attribute_names!(attribute_names)
119
+ attribute_names.each do |attribute_name|
120
+ if attribute_name =~ INVALID_ATTRIBUTE_NAME_REGEX
121
+ raise InvalidAttributeNameError.new("Invalid attribute name '#{attribute_name}' was rendered")
122
+ end
123
+ end
124
+ end
125
+
126
+ private
127
+
128
+ # Merge a couple of values to one attribute value. No destructive operation.
129
+ #
130
+ # @param to [String,Hash,nil]
131
+ # @param from [Object]
132
+ # @return [String,Hash]
133
+ def merge_value(key, to, from)
134
+ if from.kind_of?(Hash) || to.kind_of?(Hash)
135
+ from = { nil => from } if !from.is_a?(Hash)
136
+ to = { nil => to } if !to.is_a?(Hash)
137
+ to.merge(from)
138
+ elsif key == 'id'
139
+ merged_id = filter_and_join(from, '_')
140
+ if to && merged_id
141
+ merged_id = "#{to}_#{merged_id}"
142
+ elsif to || merged_id
143
+ merged_id ||= to
144
+ end
145
+ merged_id
146
+ elsif key == 'class'
147
+ merged_class = filter_and_join(from, ' ')
148
+ if to && merged_class
149
+ merged_class = (merged_class.split(' ') | to.split(' ')).sort.join(' ')
150
+ elsif to || merged_class
151
+ merged_class ||= to
152
+ end
153
+ merged_class
154
+ else
155
+ from
156
+ end
157
+ end
158
+
159
+ def build_data_keys(data_hash, hyphenate, attr_name="data")
160
+ Hash[data_hash.map do |name, value|
161
+ if name == nil
162
+ [attr_name, value]
163
+ elsif hyphenate
164
+ ["#{attr_name}-#{name.to_s.tr('_', '-')}", value]
165
+ else
166
+ ["#{attr_name}-#{name}", value]
167
+ end
168
+ end]
169
+ end
170
+
171
+ def flatten_data_attributes(data, key, join_char, seen = [])
172
+ return {key => data} unless data.is_a?(Hash)
173
+
174
+ return {key => nil} if seen.include? data.object_id
175
+ seen << data.object_id
176
+
177
+ data.sort {|x, y| x[0].to_s <=> y[0].to_s}.inject({}) do |hash, (k, v)|
178
+ joined = key == '' ? k : [key, k].join(join_char)
179
+ hash.merge! flatten_data_attributes(v, joined, join_char, seen)
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
@@ -1,4 +1,5 @@
1
1
  require 'template'
2
+ require 'haml/attribute_builder'
2
3
 
3
4
  module Haml
4
5
  module Buffer
@@ -0,0 +1,7 @@
1
+ .keyboard
2
+ -2.times do
3
+ .octave
4
+ -@keyboard.notes.each do |note|
5
+ %a.key(class="#{2+2}")
6
+ .key{class: "#{note.note_class}"}
7
+ .name= note.name
@@ -1,12 +1,11 @@
1
1
  require 'spec_helper'
2
- require File.expand_path('../simple', __FILE__)
3
- require File.expand_path('../advanced', __FILE__)
4
- require File.expand_path('../html_content', __FILE__)
2
+ require_tree './fixtures'
5
3
 
6
4
  describe "Haml files" do
7
- let(:simple) { Template['simple'] }
8
- let(:advanced) { Template['advanced'] }
9
- let(:html_content) { Template['html_content'] }
5
+ let(:simple) { Template['fixtures/simple'] }
6
+ let(:advanced) { Template['fixtures/advanced'] }
7
+ let(:html_content) { Template['fixtures/html_content'] }
8
+ let(:attributes_helper) { Template['fixtures/attributes_helper'] }
10
9
 
11
10
  it "should be defined by filename on Template namespace" do
12
11
  expect(simple).to be_kind_of(Template)
@@ -29,4 +28,30 @@ describe "Haml files" do
29
28
  @h1_content = 'Ford Perfect'
30
29
  expect(html_content.render(self)).to include('<h1>Ford Perfect</h1>')
31
30
  end
31
+
32
+ it 'can generates attributes' do
33
+ require 'ostruct'
34
+ note = Struct.new(:name, :note_class)
35
+ @keyboard = OpenStruct.new(notes: [note.new(:C, :sharp), note.new(:F, :sharp)])
36
+ expect([
37
+ "<div class='keyboard'>"+
38
+ "<div class='octave'>"+
39
+ "<a class='4 key'></a><div class='key sharp'><div class='name'>C</div></div>"+
40
+ "<a class='4 key'></a><div class='key sharp'><div class='name'>F</div></div>"+
41
+ "</div><div class='octave'>"+
42
+ "<a class='4 key'></a><div class='key sharp'><div class='name'>C</div></div>"+
43
+ "<a class='4 key'></a><div class='key sharp'><div class='name'>F</div></div>"+
44
+ "</div>"+
45
+ "</div>",
46
+ "<div class='keyboard'>"+
47
+ "<div class='octave'>"+
48
+ "<a class='key 4'></a><div class='key sharp'><div class='name'>C</div></div>"+
49
+ "<a class='key 4'></a><div class='key sharp'><div class='name'>F</div></div>"+
50
+ "</div><div class='octave'>"+
51
+ "<a class='key 4'></a><div class='key sharp'><div class='name'>C</div></div>"+
52
+ "<a class='key 4'></a><div class='key sharp'><div class='name'>F</div></div>"+
53
+ "</div>"+
54
+ "</div>"
55
+ ]).to include(attributes_helper.render(self))
56
+ end
32
57
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opal-haml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Beynon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-02 00:00:00.000000000 Z
11
+ date: 2017-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -86,12 +86,14 @@ files:
86
86
  - lib/opal/haml/processor.rb
87
87
  - lib/opal/haml/version.rb
88
88
  - opal-haml.gemspec
89
+ - opal/haml/attribute_builder.rb
89
90
  - opal/opal-haml.rb
90
- - spec/advanced.haml
91
+ - spec/fixtures/advanced.haml
92
+ - spec/fixtures/attributes_helper.haml
93
+ - spec/fixtures/html_content.haml
94
+ - spec/fixtures/simple.haml
91
95
  - spec/haml_spec.rb
92
- - spec/html_content.haml
93
96
  - spec/output_buffer_spec.rb
94
- - spec/simple.haml
95
97
  - spec/spec_helper.rb
96
98
  homepage: http://opalrb.org
97
99
  licenses:
@@ -118,9 +120,10 @@ signing_key:
118
120
  specification_version: 4
119
121
  summary: Run Haml templates client-side with Opal
120
122
  test_files:
121
- - spec/advanced.haml
123
+ - spec/fixtures/advanced.haml
124
+ - spec/fixtures/attributes_helper.haml
125
+ - spec/fixtures/html_content.haml
126
+ - spec/fixtures/simple.haml
122
127
  - spec/haml_spec.rb
123
- - spec/html_content.haml
124
128
  - spec/output_buffer_spec.rb
125
- - spec/simple.haml
126
129
  - spec/spec_helper.rb