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 +4 -4
- data/CHANGELOG.md +16 -12
- data/lib/opal/haml/version.rb +1 -1
- data/opal/haml/attribute_builder.rb +184 -0
- data/opal/opal-haml.rb +1 -0
- data/spec/{advanced.haml → fixtures/advanced.haml} +0 -0
- data/spec/fixtures/attributes_helper.haml +7 -0
- data/spec/{html_content.haml → fixtures/html_content.haml} +0 -0
- data/spec/{simple.haml → fixtures/simple.haml} +0 -0
- data/spec/haml_spec.rb +31 -6
- metadata +11 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09295c5a78ced0158a3b1fa7e80aa2048fca99ed'
|
4
|
+
data.tar.gz: 1549592bbd08fc4e9ddcaf743e4736413d2f05fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a1385061b8c9d8e9255cab355fbc84808e21b1545407ed5bb6c3f739805e20fea2d5ff0783299af9412841105b25d7973cdbaaa7f265af4714f22d8c39f854a
|
7
|
+
data.tar.gz: e58fc44ac5ebee247678509248157637c149892413a35d1716a7f13fb0773bf6dbd3d8f6cf7b7c26a71b3e2e6be9f0b741229f82cf4d8e21319c22c55f9253d2
|
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
7
|
+
- Add support for Haml v5.0
|
4
8
|
|
5
9
|
## 0.4.2 2016-10-06
|
6
10
|
|
7
|
-
|
11
|
+
- Avoid Sprockets v3.7 deprecations
|
8
12
|
|
9
13
|
## 0.4.1 2015-11-02
|
10
14
|
|
11
|
-
|
15
|
+
- Add support for nested attribute hashes: `%div{ data: { foo: 123 } }` now becomes `<div data-foo="123"></div>`.
|
12
16
|
|
13
|
-
|
17
|
+
- Attribute values are now properly escaped.
|
14
18
|
|
15
19
|
## 0.4.0 2015-08-07
|
16
20
|
|
17
|
-
|
21
|
+
- Add support for Opal 0.8.
|
18
22
|
|
19
|
-
|
23
|
+
- Update the processor to reuse the good stuff from the Opal::Processor.
|
20
24
|
|
21
|
-
|
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
|
-
|
29
|
+
- Add support for new opal Builder processors.
|
26
30
|
|
27
|
-
|
31
|
+
- Implicitly require `opal-haml` when any haml template is required
|
28
32
|
|
29
|
-
|
33
|
+
- Cleanup generated code to be use Opal ERB runtime directly.
|
30
34
|
|
31
35
|
## 0.2.0 2013-12-17
|
32
36
|
|
33
|
-
|
37
|
+
- Remove opal-sprockets dependency
|
34
38
|
|
35
39
|
## 0.1.0 2013-12-17
|
36
40
|
|
37
|
-
|
41
|
+
- Initial release
|
data/lib/opal/haml/version.rb
CHANGED
@@ -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
|
data/opal/opal-haml.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
data/spec/haml_spec.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
|
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)
|
8
|
-
let(:advanced)
|
9
|
-
let(: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.
|
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-
|
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
|