haml 6.1.2 → 6.2.3
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 +36 -1
- data/FAQ.md +1 -1
- data/README.md +5 -5
- data/REFERENCE.md +25 -29
- data/Rakefile +3 -37
- data/haml.gemspec +1 -7
- data/lib/haml/attribute_builder.rb +124 -136
- data/lib/haml/attribute_compiler.rb +10 -5
- data/lib/haml/compiler/doctype_compiler.rb +8 -2
- data/lib/haml/rails_template.rb +5 -0
- data/lib/haml/util.rb +5 -4
- data/lib/haml/version.rb +1 -1
- metadata +4 -23
- data/ext/haml/extconf.rb +0 -10
- data/ext/haml/haml.c +0 -537
- data/ext/haml/hescape.c +0 -108
- data/ext/haml/hescape.h +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0e28e40ec5137482caae5c2fb466d21976027139b3f39d428035dbd35914774
|
4
|
+
data.tar.gz: c906550bd147f7e6a2961ebd07bc59fcc69b3433c454141cb2ae29e1ccd64e2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0583d8a879f6c7eda656d6c956a9e5573eedd5f94d14b28d378af85bbab73f220499b9c8021af0bad5946c95073cd1201d2d2765556e138696462bf2d28a4304'
|
7
|
+
data.tar.gz: 2847f03720469d3eaabcc689f628198569f668b1c87c70f67422c70ed1af25103998cc004a86d9f430d57fb12f88078ef2fa27d544dad69ad9df95cc9241bfdd
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,34 @@
|
|
1
1
|
# Haml Changelog
|
2
2
|
|
3
|
+
## 6.2.3
|
4
|
+
|
5
|
+
* Resurrect RDFa doctype support [#1147](https://github.com/haml/haml/issues/1147)
|
6
|
+
|
7
|
+
## 6.2.2
|
8
|
+
|
9
|
+
* Allow adding custom attributes to `Haml::BOOLEAN_ATTRIBUTES` [#1148](https://github.com/haml/haml/issues/1148)
|
10
|
+
* Consider `aria-xxx: false` as a boolean attribute
|
11
|
+
|
12
|
+
## 6.2.1
|
13
|
+
|
14
|
+
* Fix v6.2.0's bug in rendering dynamic `aria` attributes [#1149](https://github.com/haml/haml/issues/1149)
|
15
|
+
|
16
|
+
## 6.2.0
|
17
|
+
|
18
|
+
* Drop the C extension [#1146](https://github.com/haml/haml/issues/1146)
|
19
|
+
|
20
|
+
## 6.1.4
|
21
|
+
|
22
|
+
* Let `Haml::Util.escape_html` use `ERB::Escape` if available [#1145](https://github.com/haml/haml/issues/1145)
|
23
|
+
|
24
|
+
## 6.1.3
|
25
|
+
|
26
|
+
* Add `Haml::RailsTemplate#default_format` for Turbo compatibility [#1144](https://github.com/haml/haml/issues/1144)
|
27
|
+
|
28
|
+
## 6.1.2
|
29
|
+
|
30
|
+
* Use the rails template path as `filename` [#1140](https://github.com/haml/haml/issues/1140)
|
31
|
+
|
3
32
|
## 6.1.1
|
4
33
|
|
5
34
|
* Fix an empty output of Ruby 3.1's Hash shorthand syntax [#1083](https://github.com/haml/haml/issues/1083)
|
@@ -102,6 +131,12 @@ Released on September 21, 2022
|
|
102
131
|
`list_of`, `non_haml`, `precede`, `succeed`, `surround`, `tab_down`, `tab_up`, `with_tabs`
|
103
132
|
* `:ruby` filter
|
104
133
|
* Removed: `haml_io`
|
134
|
+
* Alternatives to the removed helpers:
|
135
|
+
* Some simple ones could work by copying [the original definition](https://github.com/haml/haml/blob/v5.2.2/lib/haml/helpers.rb).
|
136
|
+
* For helpers generating general HTML tags, also consider using what your framework provides, e.g. Rails `content_tag`.
|
137
|
+
Same applies to `capture_haml`, e.g. Rails `capture`.
|
138
|
+
* Ones that rely on `Haml::Buffer` have no direct alternative by design. They existed at the cost of performance.
|
139
|
+
You need to define a helper, instantiate a String buffer in it, append stuff to it, and call it inside `=`.
|
105
140
|
* Only the following attributes and `aria`/`data` attributes are considered boolean attributes:
|
106
141
|
* `allowfullscreen`, `async`, `autobuffer`, `autofocus`, `autoplay`, `checked`, `controls`, `default`,
|
107
142
|
`defer`, `disabled`, `download`, `formnovalidate`, `hidden`, `inert`, `ismap`, `itemscope`, `loop`,
|
@@ -1426,7 +1461,7 @@ Haml 2.2 introduces a new syntax for attributes
|
|
1426
1461
|
based on the HTML syntax.
|
1427
1462
|
For example:
|
1428
1463
|
|
1429
|
-
%a(href="
|
1464
|
+
%a(href="https://haml.info" title="Haml's so cool!")
|
1430
1465
|
%img(src="/images/haml.png" alt="Haml")
|
1431
1466
|
|
1432
1467
|
There are two main reasons for this.
|
data/FAQ.md
CHANGED
@@ -141,7 +141,7 @@ For other plugins, a little searching will probably turn up a way to fix them as
|
|
141
141
|
|
142
142
|
## You still haven't answered my question!
|
143
143
|
|
144
|
-
Sorry! Try looking at the [Haml](
|
144
|
+
Sorry! Try looking at the [Haml](https://haml.info/docs/yardoc/file.REFERENCE.html) reference,
|
145
145
|
If you can't find an answer there,
|
146
146
|
feel free to ask in `#haml` on irc.freenode.net
|
147
147
|
or send an email to the [mailing list](http://groups.google.com/group/haml).
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Haml
|
2
2
|
|
3
|
-
[](
|
3
|
+
[](https://rubygems.org/gems/haml)
|
4
4
|
[](https://github.com/haml/haml/actions/workflows/test.yml)
|
5
5
|
[](https://codeclimate.com/github/haml/haml)
|
6
6
|
[](https://inch-ci.org/github/haml/haml)
|
@@ -31,7 +31,7 @@ to compile it to HTML. For more information on these commands, check out
|
|
31
31
|
haml --help
|
32
32
|
~~~
|
33
33
|
|
34
|
-
To use Haml programmatically, check out the [YARD documentation](
|
34
|
+
To use Haml programmatically, check out the [YARD documentation](https://haml.info/docs/yardoc/).
|
35
35
|
|
36
36
|
## Using Haml with Rails
|
37
37
|
|
@@ -120,7 +120,7 @@ output the result. You can even use control statements like `if` and `while`:
|
|
120
120
|
~~~
|
121
121
|
|
122
122
|
Haml provides far more tools than those presented here. Check out the [reference
|
123
|
-
documentation](
|
123
|
+
documentation](https://haml.info/docs/yardoc/file.REFERENCE.html)
|
124
124
|
for full details.
|
125
125
|
|
126
126
|
### Indentation
|
@@ -132,7 +132,7 @@ can't be mixed, and the same number of tabs or spaces must be used throughout.
|
|
132
132
|
## Contributing
|
133
133
|
|
134
134
|
Contributions are welcomed, but before you get started please read the
|
135
|
-
[guidelines](
|
135
|
+
[guidelines](https://haml.info/development.html#contributing).
|
136
136
|
|
137
137
|
After forking and then cloning the repo locally, install Bundler and then use it
|
138
138
|
to install the development gem dependencies:
|
@@ -182,7 +182,7 @@ but still consults on language issues.
|
|
182
182
|
[Natalie Weizenbaum](http://nex-3.com) was for many years the primary developer
|
183
183
|
and architect of the "modern" Ruby implementation of Haml.
|
184
184
|
|
185
|
-
[Norman Clarke](
|
185
|
+
[Norman Clarke](https://github.com/norman) was the primary maintainer of Haml from 2012 to 2016.
|
186
186
|
|
187
187
|
## License
|
188
188
|
|
data/REFERENCE.md
CHANGED
@@ -1200,40 +1200,36 @@ You can also define your own filters.
|
|
1200
1200
|
|
1201
1201
|
The simplest example of a filter might be something like:
|
1202
1202
|
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
Haml::Filters.registered[:hello] ||= HelloFilter
|
1211
|
-
```
|
1203
|
+
class HelloFilter < Haml::Filters::Base
|
1204
|
+
def compile(_node)
|
1205
|
+
[:static, "hello world"]
|
1206
|
+
end
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
Haml::Filters.registered[:hello] ||= HelloFilter
|
1212
1210
|
|
1213
1211
|
A more complex example:
|
1214
1212
|
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1213
|
+
class BetterFilter < Haml::Filters::Base
|
1214
|
+
def compile(node)
|
1215
|
+
temple = [:multi]
|
1216
|
+
temple << [:static, "hello "]
|
1217
|
+
temple << compile_text(node.value[:text])
|
1218
|
+
temple << [:static, " world"]
|
1219
|
+
temple
|
1220
|
+
end
|
1221
|
+
|
1222
|
+
private
|
1223
|
+
def compile_text(text)
|
1224
|
+
if ::Haml::Util.contains_interpolation?(text)
|
1225
|
+
[:dynamic, ::Haml::Util.unescape_interpolation(text)]
|
1226
|
+
else
|
1227
|
+
[:static, text]
|
1228
|
+
end
|
1229
|
+
end
|
1231
1230
|
end
|
1232
|
-
end
|
1233
|
-
end
|
1234
1231
|
|
1235
|
-
Haml::Filters.registered[:better] ||= BetterFilter
|
1236
|
-
```
|
1232
|
+
Haml::Filters.registered[:better] ||= BetterFilter
|
1237
1233
|
|
1238
1234
|
See {Haml::Filters} for examples.
|
1239
1235
|
|
data/Rakefile
CHANGED
@@ -1,39 +1,5 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
|
3
|
-
#
|
4
|
-
# Prepend DevKit into compilation phase
|
5
|
-
#
|
6
|
-
if Gem.win_platform?
|
7
|
-
desc 'Activates DevKit'
|
8
|
-
task :devkit do
|
9
|
-
begin
|
10
|
-
require 'devkit'
|
11
|
-
rescue LoadError
|
12
|
-
abort 'Failed to load DevKit required for compilation'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
task compile: :devkit
|
16
|
-
end
|
17
|
-
|
18
2
|
require 'rake/testtask'
|
19
|
-
if /java/ === RUBY_PLATFORM
|
20
|
-
# require 'rake/javaextensiontask'
|
21
|
-
# Rake::JavaExtensionTask.new(:haml) do |ext|
|
22
|
-
# ext.ext_dir = 'ext/java'
|
23
|
-
# ext.lib_dir = 'lib/haml'
|
24
|
-
# end
|
25
|
-
|
26
|
-
task :compile do
|
27
|
-
# dummy for now
|
28
|
-
end
|
29
|
-
else
|
30
|
-
require 'rake/extensiontask'
|
31
|
-
Rake::ExtensionTask.new(:haml) do |ext|
|
32
|
-
ext.lib_dir = 'lib/haml'
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
Dir['benchmark/*.rake'].each { |b| import(b) }
|
37
3
|
|
38
4
|
Rake::TestTask.new do |t|
|
39
5
|
t.libs << 'lib' << 'test'
|
@@ -42,10 +8,10 @@ Rake::TestTask.new do |t|
|
|
42
8
|
t.test_files = files
|
43
9
|
t.verbose = true
|
44
10
|
end
|
45
|
-
task test
|
11
|
+
task :test
|
46
12
|
|
47
13
|
desc 'bench task for CI'
|
48
|
-
task bench
|
14
|
+
task :bench do
|
49
15
|
if ENV['SLIM_BENCH'] == '1'
|
50
16
|
cmd = %w[bundle exec ruby benchmark/slim/run-benchmarks.rb]
|
51
17
|
else
|
@@ -79,4 +45,4 @@ task(:doc => 'doc:sass') {sh "yard"}
|
|
79
45
|
desc "Generate documentation incrementally"
|
80
46
|
task(:redoc) {sh "yard -c"}
|
81
47
|
|
82
|
-
task default:
|
48
|
+
task default: :test
|
data/haml.gemspec
CHANGED
@@ -21,12 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.metadata = { 'rubygems_mfa_required' => 'true' }
|
23
23
|
|
24
|
-
|
25
|
-
spec.platform = 'java'
|
26
|
-
else
|
27
|
-
spec.extensions = ['ext/haml/extconf.rb']
|
28
|
-
spec.required_ruby_version = '>= 2.1.0'
|
29
|
-
end
|
24
|
+
spec.required_ruby_version = '>= 2.1.0'
|
30
25
|
|
31
26
|
spec.add_dependency 'temple', '>= 0.8.2'
|
32
27
|
spec.add_dependency 'thor'
|
@@ -41,7 +36,6 @@ Gem::Specification.new do |spec|
|
|
41
36
|
spec.add_development_dependency 'minitest-reporters', '~> 1.1'
|
42
37
|
spec.add_development_dependency 'rails', '>= 4.0'
|
43
38
|
spec.add_development_dependency 'rake'
|
44
|
-
spec.add_development_dependency 'rake-compiler'
|
45
39
|
spec.add_development_dependency 'sass'
|
46
40
|
spec.add_development_dependency 'slim'
|
47
41
|
spec.add_development_dependency 'string_template'
|
@@ -2,173 +2,161 @@
|
|
2
2
|
require 'haml/object_ref'
|
3
3
|
|
4
4
|
module Haml::AttributeBuilder
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
buf << " class=#{quote}#{build_class(escape_attrs, *hash[key])}#{quote}"
|
27
|
-
when 'data'.freeze
|
28
|
-
buf << build_data(escape_attrs, quote, *hash[key])
|
29
|
-
when *boolean_attributes, /\Adata-/
|
30
|
-
build_boolean!(escape_attrs, quote, format, buf, key, hash[key])
|
31
|
-
else
|
32
|
-
buf << " #{key}=#{quote}#{escape_html(escape_attrs, hash[key].to_s)}#{quote}"
|
33
|
-
end
|
5
|
+
class << self
|
6
|
+
def build(escape_attrs, quote, format, object_ref, *hashes)
|
7
|
+
hashes << Haml::ObjectRef.parse(object_ref) if object_ref
|
8
|
+
buf = []
|
9
|
+
hash = merge_all_attrs(hashes)
|
10
|
+
|
11
|
+
keys = hash.keys.sort!
|
12
|
+
keys.each do |key|
|
13
|
+
case key
|
14
|
+
when 'id'
|
15
|
+
buf << " id=#{quote}#{build_id(escape_attrs, *hash[key])}#{quote}"
|
16
|
+
when 'class'
|
17
|
+
buf << " class=#{quote}#{build_class(escape_attrs, *hash[key])}#{quote}"
|
18
|
+
when 'data'
|
19
|
+
buf << build_data(escape_attrs, quote, *hash[key])
|
20
|
+
when 'aria'
|
21
|
+
buf << build_aria(escape_attrs, quote, *hash[key])
|
22
|
+
when *Haml::BOOLEAN_ATTRIBUTES, /\Adata-/, /\Aaria-/
|
23
|
+
build_boolean!(escape_attrs, quote, format, buf, key, hash[key])
|
24
|
+
else
|
25
|
+
buf << " #{key}=#{quote}#{escape_html(escape_attrs, hash[key].to_s)}#{quote}"
|
34
26
|
end
|
35
|
-
buf.join
|
36
|
-
end
|
37
|
-
|
38
|
-
def build_id(escape_attrs, *values)
|
39
|
-
escape_html(escape_attrs, values.flatten.select { |v| v }.join('_'))
|
40
27
|
end
|
28
|
+
buf.join
|
29
|
+
end
|
41
30
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
case
|
46
|
-
when value.is_a?(String)
|
47
|
-
# noop
|
48
|
-
when value.is_a?(Array)
|
49
|
-
value = value.flatten.select { |v| v }.map(&:to_s).uniq.join(' ')
|
50
|
-
when value
|
51
|
-
value = value.to_s
|
52
|
-
else
|
53
|
-
return ''
|
54
|
-
end
|
55
|
-
return escape_html(escape_attrs, value)
|
56
|
-
end
|
31
|
+
def build_id(escape_attrs, *values)
|
32
|
+
escape_html(escape_attrs, values.flatten.select { |v| v }.join('_'))
|
33
|
+
end
|
57
34
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
35
|
+
def build_class(escape_attrs, *values)
|
36
|
+
if values.size == 1
|
37
|
+
value = values.first
|
38
|
+
case
|
39
|
+
when value.is_a?(String)
|
40
|
+
# noop
|
41
|
+
when value.is_a?(Array)
|
42
|
+
value = value.flatten.select { |v| v }.map(&:to_s).uniq.join(' ')
|
43
|
+
when value
|
44
|
+
value = value.to_s
|
45
|
+
else
|
46
|
+
return ''
|
68
47
|
end
|
69
|
-
escape_html(escape_attrs,
|
48
|
+
return escape_html(escape_attrs, value)
|
70
49
|
end
|
71
50
|
|
72
|
-
|
73
|
-
|
51
|
+
classes = []
|
52
|
+
values.each do |value|
|
53
|
+
case
|
54
|
+
when value.is_a?(String)
|
55
|
+
classes += value.split(' ')
|
56
|
+
when value.is_a?(Array)
|
57
|
+
classes += value.select { |v| v }
|
58
|
+
when value
|
59
|
+
classes << value.to_s
|
60
|
+
end
|
74
61
|
end
|
62
|
+
escape_html(escape_attrs, classes.map(&:to_s).uniq.join(' '))
|
63
|
+
end
|
75
64
|
|
76
|
-
|
77
|
-
|
78
|
-
|
65
|
+
def build_data(escape_attrs, quote, *hashes)
|
66
|
+
build_data_attribute(:data, escape_attrs, quote, *hashes)
|
67
|
+
end
|
79
68
|
|
80
|
-
|
69
|
+
def build_aria(escape_attrs, quote, *hashes)
|
70
|
+
build_data_attribute(:aria, escape_attrs, quote, *hashes)
|
71
|
+
end
|
81
72
|
|
82
|
-
|
83
|
-
attrs = []
|
84
|
-
if hashes.size > 1 && hashes.all? { |h| h.is_a?(Hash) }
|
85
|
-
data_value = merge_all_attrs(hashes)
|
86
|
-
else
|
87
|
-
data_value = hashes.last
|
88
|
-
end
|
89
|
-
hash = flatten_attributes(key => data_value)
|
73
|
+
private
|
90
74
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
attrs << " #{key}=#{quote}#{escape_html(escape_attrs, value.to_s)}#{quote}"
|
99
|
-
end
|
100
|
-
end
|
101
|
-
attrs.join
|
75
|
+
def build_data_attribute(key, escape_attrs, quote, *hashes)
|
76
|
+
attrs = []
|
77
|
+
if hashes.size > 1 && hashes.all? { |h| h.is_a?(Hash) }
|
78
|
+
data_value = merge_all_attrs(hashes)
|
79
|
+
else
|
80
|
+
data_value = hashes.last
|
102
81
|
end
|
82
|
+
hash = flatten_attributes(key => data_value)
|
103
83
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
if k.nil?
|
113
|
-
flattened[key] = v
|
114
|
-
else
|
115
|
-
flattened["#{key}-#{k.to_s.gsub(/_/, '-')}"] = v
|
116
|
-
end
|
117
|
-
end
|
118
|
-
else
|
119
|
-
flattened[key] = value if value
|
120
|
-
end
|
84
|
+
hash.sort_by(&:first).each do |key, value|
|
85
|
+
case value
|
86
|
+
when true
|
87
|
+
attrs << " #{key}"
|
88
|
+
when nil, false
|
89
|
+
# noop
|
90
|
+
else
|
91
|
+
attrs << " #{key}=#{quote}#{escape_html(escape_attrs, value.to_s)}#{quote}"
|
121
92
|
end
|
122
|
-
flattened
|
123
93
|
end
|
94
|
+
attrs.join
|
95
|
+
end
|
96
|
+
|
97
|
+
def flatten_attributes(attributes)
|
98
|
+
flattened = {}
|
124
99
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
merged[key] ||= []
|
133
|
-
merged[key] << value
|
100
|
+
attributes.each do |key, value|
|
101
|
+
case value
|
102
|
+
when attributes
|
103
|
+
when Hash
|
104
|
+
flatten_attributes(value).each do |k, v|
|
105
|
+
if k.nil?
|
106
|
+
flattened[key] = v
|
134
107
|
else
|
135
|
-
|
108
|
+
flattened["#{key}-#{k.to_s.gsub(/_/, '-')}"] = v
|
136
109
|
end
|
137
110
|
end
|
111
|
+
else
|
112
|
+
flattened[key] = value if value
|
138
113
|
end
|
139
|
-
merged
|
140
114
|
end
|
115
|
+
flattened
|
116
|
+
end
|
141
117
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
118
|
+
def merge_all_attrs(hashes)
|
119
|
+
merged = {}
|
120
|
+
hashes.each do |hash|
|
121
|
+
unless hash.is_a?(Hash)
|
122
|
+
raise ArgumentError, "Non-hash object is given to attributes!"
|
123
|
+
end
|
124
|
+
hash.each do |key, value|
|
125
|
+
key = key.to_s
|
126
|
+
case key
|
127
|
+
when 'id', 'class', 'data', 'aria'
|
128
|
+
merged[key] ||= []
|
129
|
+
merged[key] << value
|
148
130
|
else
|
149
|
-
|
131
|
+
merged[key] = value
|
150
132
|
end
|
151
|
-
when false, nil
|
152
|
-
# omitted
|
153
|
-
else
|
154
|
-
buf << " #{key}=#{quote}#{escape_html(escape_attrs, value)}#{quote}"
|
155
133
|
end
|
156
134
|
end
|
135
|
+
merged
|
136
|
+
end
|
157
137
|
|
158
|
-
|
159
|
-
|
160
|
-
|
138
|
+
def build_boolean!(escape_attrs, quote, format, buf, key, value)
|
139
|
+
case value
|
140
|
+
when true
|
141
|
+
case format
|
142
|
+
when :xhtml
|
143
|
+
buf << " #{key}=#{quote}#{key}#{quote}"
|
161
144
|
else
|
162
|
-
|
145
|
+
buf << " #{key}"
|
163
146
|
end
|
147
|
+
when false, nil
|
148
|
+
# omitted
|
149
|
+
else
|
150
|
+
buf << " #{key}=#{quote}#{escape_html(escape_attrs, value)}#{quote}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def escape_html(escape_attrs, str)
|
155
|
+
if escape_attrs
|
156
|
+
Haml::Util.escape_html(str)
|
157
|
+
else
|
158
|
+
str
|
164
159
|
end
|
165
160
|
end
|
166
|
-
else
|
167
|
-
# Haml::AttributeBuilder.build
|
168
|
-
# Haml::AttributeBuilder.build_id
|
169
|
-
# Haml::AttributeBuilder.build_class
|
170
|
-
# Haml::AttributeBuilder.build_data
|
171
|
-
# Haml::AttributeBuilder.build_aria
|
172
|
-
require 'haml/haml'
|
173
161
|
end
|
174
162
|
end
|
@@ -4,6 +4,14 @@ require 'haml/attribute_parser'
|
|
4
4
|
require 'haml/ruby_expression'
|
5
5
|
|
6
6
|
module Haml
|
7
|
+
# The list of boolean attributes. You may add custom attributes to this constant.
|
8
|
+
BOOLEAN_ATTRIBUTES = %w[disabled readonly multiple checked autobuffer
|
9
|
+
autoplay controls loop selected hidden scoped async
|
10
|
+
defer reversed ismap seamless muted required
|
11
|
+
autofocus novalidate formnovalidate open pubdate
|
12
|
+
itemscope allowfullscreen default inert sortable
|
13
|
+
truespeed typemustmatch download]
|
14
|
+
|
7
15
|
class AttributeCompiler
|
8
16
|
def initialize(identity, options)
|
9
17
|
@identity = identity
|
@@ -31,10 +39,7 @@ module Haml
|
|
31
39
|
attrs = []
|
32
40
|
attrs.unshift(node.value[:attributes].inspect) if node.value[:attributes] != {}
|
33
41
|
|
34
|
-
args = [
|
35
|
-
@escape_attrs.inspect, "#{@quote.inspect}.freeze", @format.inspect,
|
36
|
-
'::Haml::AttributeBuilder::BOOLEAN_ATTRIBUTES', node.value[:object_ref],
|
37
|
-
] + attrs
|
42
|
+
args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", @format.inspect, node.value[:object_ref]] + attrs
|
38
43
|
[:html, :attrs, [:dynamic, "::Haml::AttributeBuilder.build(#{args.join(', ')}, #{node.value[:dynamic_attributes].to_literal})"]]
|
39
44
|
end
|
40
45
|
|
@@ -52,7 +57,7 @@ module Haml
|
|
52
57
|
compile_class!(temple, key, values)
|
53
58
|
when 'data', 'aria'
|
54
59
|
compile_data!(temple, key, values)
|
55
|
-
when *
|
60
|
+
when *BOOLEAN_ATTRIBUTES, /\Adata-/, /\Aaria-/
|
56
61
|
compile_boolean!(temple, key, values)
|
57
62
|
else
|
58
63
|
compile_common!(temple, key, values)
|
@@ -8,10 +8,12 @@ module Haml
|
|
8
8
|
|
9
9
|
def compile(node)
|
10
10
|
case node.value[:type]
|
11
|
-
when 'xml'
|
12
|
-
xml_doctype
|
13
11
|
when ''
|
14
12
|
html_doctype(node)
|
13
|
+
when 'xml'
|
14
|
+
xml_doctype
|
15
|
+
when 'rdfa'
|
16
|
+
rdfa_doctype
|
15
17
|
else
|
16
18
|
[:html, :doctype, node.value[:type]]
|
17
19
|
end
|
@@ -41,6 +43,10 @@ module Haml
|
|
41
43
|
[:multi]
|
42
44
|
end
|
43
45
|
end
|
46
|
+
|
47
|
+
def rdfa_doctype
|
48
|
+
[:static, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">']
|
49
|
+
end
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|
data/lib/haml/rails_template.rb
CHANGED
data/lib/haml/util.rb
CHANGED
@@ -14,15 +14,16 @@ module Haml
|
|
14
14
|
module Util
|
15
15
|
extend self
|
16
16
|
|
17
|
-
#
|
18
|
-
|
17
|
+
begin # Ruby 3.2+ or ERB 4+
|
18
|
+
require 'erb/escape'
|
19
|
+
|
20
|
+
define_singleton_method(:escape_html, ERB::Escape.instance_method(:html_escape))
|
21
|
+
rescue LoadError
|
19
22
|
require 'cgi/escape'
|
20
23
|
|
21
24
|
def self.escape_html(html)
|
22
25
|
CGI.escapeHTML(html.to_s)
|
23
26
|
end
|
24
|
-
else
|
25
|
-
require 'haml/haml' # Haml::Util.escape_html
|
26
27
|
end
|
27
28
|
|
28
29
|
# TODO: Remove unescape_interpolation's workaround and get rid of `respond_to?`.
|