haml 5.2.2 → 6.1.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 +4 -4
- data/.github/FUNDING.yml +3 -0
- data/.github/workflows/test.yml +13 -14
- data/.gitignore +16 -16
- data/.yardopts +0 -3
- data/CHANGELOG.md +116 -3
- data/Gemfile +18 -11
- data/MIT-LICENSE +1 -1
- data/README.md +17 -23
- data/REFERENCE.md +69 -145
- data/Rakefile +48 -81
- data/bin/bench +66 -0
- data/bin/console +11 -0
- data/bin/ruby +3 -0
- data/bin/setup +7 -0
- data/bin/stackprof +27 -0
- data/bin/test +24 -0
- data/exe/haml +6 -0
- data/ext/haml/extconf.rb +10 -0
- data/ext/haml/haml.c +537 -0
- data/ext/haml/hescape.c +108 -0
- data/ext/haml/hescape.h +20 -0
- data/haml.gemspec +39 -37
- data/lib/haml/ambles.rb +20 -0
- data/lib/haml/attribute_builder.rb +134 -179
- data/lib/haml/attribute_compiler.rb +85 -194
- data/lib/haml/attribute_parser.rb +92 -126
- data/lib/haml/cli.rb +154 -0
- data/lib/haml/compiler/children_compiler.rb +155 -0
- data/lib/haml/compiler/comment_compiler.rb +51 -0
- data/lib/haml/compiler/doctype_compiler.rb +46 -0
- data/lib/haml/compiler/script_compiler.rb +114 -0
- data/lib/haml/compiler/silent_script_compiler.rb +24 -0
- data/lib/haml/compiler/tag_compiler.rb +76 -0
- data/lib/haml/compiler.rb +63 -296
- data/lib/haml/dynamic_merger.rb +67 -0
- data/lib/haml/engine.rb +48 -227
- data/lib/haml/error.rb +5 -4
- data/lib/haml/escape.rb +13 -0
- data/lib/haml/escape_any.rb +21 -0
- data/lib/haml/filters/base.rb +12 -0
- data/lib/haml/filters/cdata.rb +20 -0
- data/lib/haml/filters/coffee.rb +17 -0
- data/lib/haml/filters/css.rb +33 -0
- data/lib/haml/filters/erb.rb +10 -0
- data/lib/haml/filters/escaped.rb +22 -0
- data/lib/haml/filters/javascript.rb +33 -0
- data/lib/haml/filters/less.rb +20 -0
- data/lib/haml/filters/markdown.rb +11 -0
- data/lib/haml/filters/plain.rb +29 -0
- data/lib/haml/filters/preserve.rb +22 -0
- data/lib/haml/filters/ruby.rb +10 -0
- data/lib/haml/filters/sass.rb +15 -0
- data/lib/haml/filters/scss.rb +15 -0
- data/lib/haml/filters/text_base.rb +25 -0
- data/lib/haml/filters/tilt_base.rb +59 -0
- data/lib/haml/filters.rb +54 -378
- data/lib/haml/force_escape.rb +29 -0
- data/lib/haml/helpers.rb +3 -697
- data/lib/haml/html.rb +22 -0
- data/lib/haml/identity.rb +13 -0
- data/lib/haml/object_ref.rb +35 -0
- data/lib/haml/parser.rb +157 -22
- data/lib/haml/rails_helpers.rb +53 -0
- data/lib/haml/rails_template.rb +57 -0
- data/lib/haml/railtie.rb +3 -46
- data/lib/haml/ruby_expression.rb +32 -0
- data/lib/haml/string_splitter.rb +140 -0
- data/lib/haml/template.rb +15 -34
- data/lib/haml/temple_line_counter.rb +2 -1
- data/lib/haml/util.rb +18 -15
- data/lib/haml/version.rb +1 -2
- data/lib/haml/whitespace.rb +8 -0
- data/lib/haml.rb +8 -20
- metadata +211 -55
- data/.gitmodules +0 -3
- data/TODO +0 -24
- data/benchmark.rb +0 -70
- data/bin/haml +0 -9
- data/lib/haml/.gitattributes +0 -1
- data/lib/haml/buffer.rb +0 -182
- data/lib/haml/escapable.rb +0 -77
- data/lib/haml/exec.rb +0 -347
- data/lib/haml/generator.rb +0 -42
- data/lib/haml/helpers/action_view_extensions.rb +0 -60
- data/lib/haml/helpers/action_view_mods.rb +0 -132
- data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
- data/lib/haml/helpers/safe_erubi_template.rb +0 -20
- data/lib/haml/helpers/safe_erubis_template.rb +0 -33
- data/lib/haml/helpers/xss_mods.rb +0 -114
- data/lib/haml/options.rb +0 -273
- data/lib/haml/plugin.rb +0 -54
- data/lib/haml/sass_rails_filter.rb +0 -47
- data/lib/haml/template/options.rb +0 -27
- data/lib/haml/temple_engine.rb +0 -124
- data/yard/default/.gitignore +0 -1
- data/yard/default/fulldoc/html/css/common.sass +0 -15
- data/yard/default/layout/html/footer.erb +0 -12
data/haml.gemspec
CHANGED
@@ -1,45 +1,47 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'haml/version'
|
3
5
|
|
4
6
|
Gem::Specification.new do |spec|
|
5
|
-
spec.name
|
6
|
-
spec.
|
7
|
-
spec.
|
8
|
-
spec.
|
9
|
-
spec.email = ['haml@googlegroups.com', 'ronnie@dio.jp']
|
7
|
+
spec.name = 'haml'
|
8
|
+
spec.version = Haml::VERSION
|
9
|
+
spec.authors = ['Natalie Weizenbaum', 'Hampton Catlin', 'Norman Clarke', 'Akira Matsuda', 'Takashi Kokubun']
|
10
|
+
spec.email = ['haml@googlegroups.com', 'ronnie@dio.jp']
|
10
11
|
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
|
14
|
-
|
15
|
-
spec.homepage = 'http://haml.info/'
|
16
|
-
spec.license = "MIT"
|
17
|
-
spec.metadata = {
|
18
|
-
"bug_tracker_uri" => "https://github.com/haml/haml/issues",
|
19
|
-
"changelog_uri" => "https://github.com/haml/haml/blob/main/CHANGELOG.md",
|
20
|
-
"documentation_uri" => "http://haml.info/docs.html",
|
21
|
-
"homepage_uri" => "http://haml.info",
|
22
|
-
"mailing_list_uri" => "https://groups.google.com/forum/?fromgroups#!forum/haml",
|
23
|
-
"source_code_uri" => "https://github.com/haml/haml"
|
24
|
-
}
|
25
|
-
|
26
|
-
spec.required_ruby_version = '>= 2.0.0'
|
12
|
+
spec.summary = %q{An elegant, structured (X)HTML/XML templating engine.}
|
13
|
+
spec.description = %q{An elegant, structured (X)HTML/XML templating engine.}
|
14
|
+
spec.homepage = 'https://haml.info'
|
15
|
+
spec.license = 'MIT'
|
27
16
|
|
28
|
-
spec.
|
29
|
-
spec.
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|sample|benchmark)/}) }
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
30
21
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
22
|
+
if /java/ === RUBY_PLATFORM
|
23
|
+
spec.platform = 'java'
|
24
|
+
else
|
25
|
+
spec.extensions = ['ext/haml/extconf.rb']
|
26
|
+
spec.required_ruby_version = '>= 2.1.0'
|
27
|
+
end
|
36
28
|
|
37
|
-
spec.
|
38
|
-
|
39
|
-
|
40
|
-
easy way by using indentation rather than closing tags and allowing Ruby to be
|
41
|
-
embedded with ease. It was originally envisioned as a plugin for Ruby on Rails,
|
42
|
-
but it can function as a stand-alone templating engine.
|
43
|
-
END
|
29
|
+
spec.add_dependency 'temple', '>= 0.8.2'
|
30
|
+
spec.add_dependency 'thor'
|
31
|
+
spec.add_dependency 'tilt'
|
44
32
|
|
33
|
+
spec.add_development_dependency 'benchmark_driver'
|
34
|
+
spec.add_development_dependency 'bundler'
|
35
|
+
spec.add_development_dependency 'coffee-script'
|
36
|
+
spec.add_development_dependency 'erubi'
|
37
|
+
spec.add_development_dependency 'haml', '>= 5'
|
38
|
+
spec.add_development_dependency 'less'
|
39
|
+
spec.add_development_dependency 'minitest-reporters', '~> 1.1'
|
40
|
+
spec.add_development_dependency 'rails', '>= 4.0'
|
41
|
+
spec.add_development_dependency 'rake'
|
42
|
+
spec.add_development_dependency 'rake-compiler'
|
43
|
+
spec.add_development_dependency 'sass'
|
44
|
+
spec.add_development_dependency 'slim'
|
45
|
+
spec.add_development_dependency 'string_template'
|
46
|
+
spec.add_development_dependency 'unindent'
|
45
47
|
end
|
data/lib/haml/ambles.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Haml
|
3
|
+
class Ambles < Temple::Filter
|
4
|
+
define_options :preamble, :postamble
|
5
|
+
|
6
|
+
def initialize(*)
|
7
|
+
super
|
8
|
+
@preamble = options[:preamble]
|
9
|
+
@postamble = options[:postamble]
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(ast)
|
13
|
+
ret = [:multi]
|
14
|
+
ret << [:static, @preamble] if @preamble
|
15
|
+
ret << ast
|
16
|
+
ret << [:static, @postamble] if @postamble
|
17
|
+
ret
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,219 +1,174 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
require 'haml/object_ref'
|
3
|
+
|
4
|
+
module Haml::AttributeBuilder
|
5
|
+
BOOLEAN_ATTRIBUTES = %w[disabled readonly multiple checked autobuffer
|
6
|
+
autoplay controls loop selected hidden scoped async
|
7
|
+
defer reversed ismap seamless muted required
|
8
|
+
autofocus novalidate formnovalidate open pubdate
|
9
|
+
itemscope allowfullscreen default inert sortable
|
10
|
+
truespeed typemustmatch download].freeze
|
11
|
+
|
12
|
+
# For JRuby, TruffleRuby, and Wasm, fallback to Ruby implementation.
|
13
|
+
if /java|wasm/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby'
|
8
14
|
class << self
|
9
|
-
def build(
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
+
def build(escape_attrs, quote, format, boolean_attributes, object_ref, *hashes)
|
16
|
+
hashes << Haml::ObjectRef.parse(object_ref) if object_ref
|
17
|
+
buf = []
|
18
|
+
hash = merge_all_attrs(hashes)
|
19
|
+
|
20
|
+
keys = hash.keys.sort!
|
21
|
+
keys.each do |key|
|
22
|
+
case key
|
23
|
+
when 'id'.freeze
|
24
|
+
buf << " id=#{quote}#{build_id(escape_attrs, *hash[key])}#{quote}"
|
25
|
+
when 'class'.freeze
|
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
|
15
34
|
end
|
16
|
-
|
17
|
-
build_attributes(is_html, attr_wrapper, escape_attrs, hyphenate_data_attrs, attributes)
|
35
|
+
buf.join
|
18
36
|
end
|
19
37
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
join_char = hyphenate_data_attrs ? '-' : '_'
|
38
|
+
def build_id(escape_attrs, *values)
|
39
|
+
escape_html(escape_attrs, values.flatten.select { |v| v }.join('_'))
|
40
|
+
end
|
24
41
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
42
|
+
def build_class(escape_attrs, *values)
|
43
|
+
if values.size == 1
|
44
|
+
value = values.first
|
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 ''
|
32
54
|
end
|
55
|
+
return escape_html(escape_attrs, value)
|
33
56
|
end
|
34
57
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
value
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
elsif value == false
|
45
|
-
next
|
58
|
+
classes = []
|
59
|
+
values.each do |value|
|
60
|
+
case
|
61
|
+
when value.is_a?(String)
|
62
|
+
classes += value.split(' ')
|
63
|
+
when value.is_a?(Array)
|
64
|
+
classes += value.select { |v| v }
|
65
|
+
when value
|
66
|
+
classes << value.to_s
|
46
67
|
end
|
47
|
-
|
48
|
-
value =
|
49
|
-
if escape_attrs == :once
|
50
|
-
Haml::Helpers.escape_once_without_haml_xss(value.to_s)
|
51
|
-
elsif escape_attrs
|
52
|
-
Haml::Helpers.html_escape_without_haml_xss(value.to_s)
|
53
|
-
else
|
54
|
-
value.to_s
|
55
|
-
end
|
56
|
-
" #{attr}=#{attr_wrapper}#{value}#{attr_wrapper}"
|
57
68
|
end
|
58
|
-
|
59
|
-
result.sort!
|
60
|
-
result.join
|
69
|
+
escape_html(escape_attrs, classes.map(&:to_s).uniq.join(' '))
|
61
70
|
end
|
62
71
|
|
63
|
-
|
64
|
-
|
65
|
-
return '' if (value.respond_to?(:empty?) && value.empty?)
|
66
|
-
|
67
|
-
if value.is_a?(Array)
|
68
|
-
value = value.flatten
|
69
|
-
value.map! {|item| item ? item.to_s : nil}
|
70
|
-
value.compact!
|
71
|
-
value = value.join(separator)
|
72
|
-
else
|
73
|
-
value = value ? value.to_s : nil
|
74
|
-
end
|
75
|
-
!value.nil? && !value.empty? && value
|
72
|
+
def build_data(escape_attrs, quote, *hashes)
|
73
|
+
build_data_attribute(:data, escape_attrs, quote, *hashes)
|
76
74
|
end
|
77
75
|
|
78
|
-
|
79
|
-
|
80
|
-
# except that it merges id, class, and data attributes.
|
81
|
-
#
|
82
|
-
# ids are concatenated with `"_"`,
|
83
|
-
# and classes are concatenated with `" "`.
|
84
|
-
# data hashes are simply merged.
|
85
|
-
#
|
86
|
-
# Destructively modifies `to`.
|
87
|
-
#
|
88
|
-
# @param to [{String => String,Hash}] The attribute hash to merge into
|
89
|
-
# @param from [{String => Object}] The attribute hash to merge from
|
90
|
-
# @return [{String => String,Hash}] `to`, after being merged
|
91
|
-
def merge_attributes!(to, from)
|
92
|
-
from.keys.each do |key|
|
93
|
-
to[key] = merge_value(key, to[key], from[key])
|
94
|
-
end
|
95
|
-
to
|
76
|
+
def build_aria(escape_attrs, quote, *hashes)
|
77
|
+
build_data_attribute(:aria, escape_attrs, quote, *hashes)
|
96
78
|
end
|
97
79
|
|
98
|
-
|
99
|
-
#
|
100
|
-
# @param key [String]
|
101
|
-
# @param values [Array<Object>]
|
102
|
-
# @return [String,Hash]
|
103
|
-
def merge_values(key, *values)
|
104
|
-
values.inject(nil) do |to, from|
|
105
|
-
merge_value(key, to, from)
|
106
|
-
end
|
107
|
-
end
|
80
|
+
private
|
108
81
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
82
|
+
def build_data_attribute(key, escape_attrs, quote, *hashes)
|
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)
|
90
|
+
|
91
|
+
hash.sort_by(&:first).each do |key, value|
|
92
|
+
case value
|
93
|
+
when true
|
94
|
+
attrs << " #{key}"
|
95
|
+
when nil, false
|
96
|
+
# noop
|
97
|
+
else
|
98
|
+
attrs << " #{key}=#{quote}#{escape_html(escape_attrs, value.to_s)}#{quote}"
|
113
99
|
end
|
114
100
|
end
|
101
|
+
attrs.join
|
115
102
|
end
|
116
103
|
|
117
|
-
|
104
|
+
def flatten_attributes(attributes)
|
105
|
+
flattened = {}
|
118
106
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
merged_id = "#{to}_#{merged_id}"
|
133
|
-
elsif to || merged_id
|
134
|
-
merged_id ||= to
|
135
|
-
end
|
136
|
-
merged_id
|
137
|
-
elsif key == 'class'
|
138
|
-
merged_class = filter_and_join(from, ' ')
|
139
|
-
if to && merged_class
|
140
|
-
merged_class = (to.split(' ') | merged_class.split(' ')).join(' ')
|
141
|
-
elsif to || merged_class
|
142
|
-
merged_class ||= to
|
107
|
+
attributes.each do |key, value|
|
108
|
+
case value
|
109
|
+
when attributes
|
110
|
+
when Hash
|
111
|
+
flatten_attributes(value).each do |k, v|
|
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
|
143
120
|
end
|
144
|
-
merged_class
|
145
|
-
else
|
146
|
-
from
|
147
121
|
end
|
122
|
+
flattened
|
148
123
|
end
|
149
124
|
|
150
|
-
def
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
125
|
+
def merge_all_attrs(hashes)
|
126
|
+
merged = {}
|
127
|
+
hashes.each do |hash|
|
128
|
+
hash.each do |key, value|
|
129
|
+
key = key.to_s
|
130
|
+
case key
|
131
|
+
when 'id'.freeze, 'class'.freeze, 'data'.freeze
|
132
|
+
merged[key] ||= []
|
133
|
+
merged[key] << value
|
134
|
+
else
|
135
|
+
merged[key] = value
|
136
|
+
end
|
158
137
|
end
|
159
|
-
end]
|
160
|
-
end
|
161
|
-
|
162
|
-
def flatten_data_attributes(data, key, join_char, seen = [])
|
163
|
-
return {key => data} unless data.is_a?(Hash)
|
164
|
-
|
165
|
-
return {key => nil} if seen.include? data.object_id
|
166
|
-
seen << data.object_id
|
167
|
-
|
168
|
-
data.sort {|x, y| x[0].to_s <=> y[0].to_s}.inject({}) do |hash, (k, v)|
|
169
|
-
joined = key == '' ? k : [key, k].join(join_char)
|
170
|
-
hash.merge! flatten_data_attributes(v, joined, join_char, seen)
|
171
138
|
end
|
139
|
+
merged
|
172
140
|
end
|
173
141
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
ref = ref[0]
|
181
|
-
# Let's make sure the value isn't nil. If it is, return the default Hash.
|
182
|
-
return {} if ref.nil?
|
183
|
-
class_name =
|
184
|
-
if ref.respond_to?(:haml_object_ref)
|
185
|
-
ref.haml_object_ref
|
186
|
-
else
|
187
|
-
underscore(ref.class)
|
188
|
-
end
|
189
|
-
ref_id =
|
190
|
-
if ref.respond_to?(:to_key)
|
191
|
-
key = ref.to_key
|
192
|
-
key.join('_') unless key.nil?
|
142
|
+
def build_boolean!(escape_attrs, quote, format, buf, key, value)
|
143
|
+
case value
|
144
|
+
when true
|
145
|
+
case format
|
146
|
+
when :xhtml
|
147
|
+
buf << " #{key}=#{quote}#{key}#{quote}"
|
193
148
|
else
|
194
|
-
|
149
|
+
buf << " #{key}"
|
195
150
|
end
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
151
|
+
when false, nil
|
152
|
+
# omitted
|
153
|
+
else
|
154
|
+
buf << " #{key}=#{quote}#{escape_html(escape_attrs, value)}#{quote}"
|
200
155
|
end
|
201
|
-
|
202
|
-
{ 'id'.freeze => id, 'class'.freeze => class_name }
|
203
156
|
end
|
204
157
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
212
|
-
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
213
|
-
word.tr!('-', '_')
|
214
|
-
word.downcase!
|
215
|
-
word
|
158
|
+
def escape_html(escape_attrs, str)
|
159
|
+
if escape_attrs
|
160
|
+
Haml::Util.escape_html(str)
|
161
|
+
else
|
162
|
+
str
|
163
|
+
end
|
216
164
|
end
|
217
165
|
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'
|
218
173
|
end
|
219
174
|
end
|