haml 5.2.2 → 6.0.0.beta.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 +1 -0
- data/.github/workflows/test.yml +13 -9
- data/.gitignore +16 -16
- data/CHANGELOG.md +13 -3
- data/Gemfile +18 -11
- data/MIT-LICENSE +1 -1
- data/README.md +13 -19
- data/Rakefile +95 -93
- 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 +135 -179
- data/lib/haml/attribute_compiler.rb +85 -194
- data/lib/haml/attribute_parser.rb +86 -126
- data/lib/haml/cli.rb +154 -0
- data/lib/haml/compiler/children_compiler.rb +126 -0
- data/lib/haml/compiler/comment_compiler.rb +39 -0
- data/lib/haml/compiler/doctype_compiler.rb +46 -0
- data/lib/haml/compiler/script_compiler.rb +116 -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 +42 -227
- data/lib/haml/error.rb +3 -52
- data/lib/haml/escapable.rb +6 -70
- 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 +49 -0
- data/lib/haml/filters.rb +54 -378
- data/lib/haml/force_escapable.rb +29 -0
- data/lib/haml/haml_error.rb +66 -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 +30 -0
- data/lib/haml/parser.rb +179 -49
- data/lib/haml/rails_helpers.rb +51 -0
- data/lib/haml/rails_template.rb +55 -0
- data/lib/haml/railtie.rb +7 -45
- data/lib/haml/ruby_expression.rb +32 -0
- data/lib/haml/string_splitter.rb +20 -0
- data/lib/haml/template.rb +15 -34
- data/lib/haml/temple_line_counter.rb +2 -1
- data/lib/haml/util.rb +17 -15
- data/lib/haml/version.rb +1 -2
- data/lib/haml.rb +8 -20
- metadata +211 -57
- data/.gitmodules +0 -3
- data/.yardopts +0 -22
- 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/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,175 @@
|
|
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
|
+
# Java extension is not implemented for JRuby yet.
|
13
|
+
# TruffleRuby does not implement `rb_ary_sort_bang`, etc.
|
14
|
+
if /java/ === RUBY_PLATFORM || RUBY_ENGINE == 'truffleruby'
|
8
15
|
class << self
|
9
|
-
def build(
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
def build(escape_attrs, quote, format, boolean_attributes, object_ref, *hashes)
|
17
|
+
hashes << Haml::ObjectRef.parse(object_ref) if object_ref
|
18
|
+
buf = []
|
19
|
+
hash = merge_all_attrs(hashes)
|
20
|
+
|
21
|
+
keys = hash.keys.sort!
|
22
|
+
keys.each do |key|
|
23
|
+
case key
|
24
|
+
when 'id'.freeze
|
25
|
+
buf << " id=#{quote}#{build_id(escape_attrs, *hash[key])}#{quote}"
|
26
|
+
when 'class'.freeze
|
27
|
+
buf << " class=#{quote}#{build_class(escape_attrs, *hash[key])}#{quote}"
|
28
|
+
when 'data'.freeze
|
29
|
+
buf << build_data(escape_attrs, quote, *hash[key])
|
30
|
+
when *boolean_attributes, /\Adata-/
|
31
|
+
build_boolean!(escape_attrs, quote, format, buf, key, hash[key])
|
32
|
+
else
|
33
|
+
buf << " #{key}=#{quote}#{escape_html(escape_attrs, hash[key].to_s)}#{quote}"
|
34
|
+
end
|
15
35
|
end
|
16
|
-
|
17
|
-
build_attributes(is_html, attr_wrapper, escape_attrs, hyphenate_data_attrs, attributes)
|
36
|
+
buf.join
|
18
37
|
end
|
19
38
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
join_char = hyphenate_data_attrs ? '-' : '_'
|
39
|
+
def build_id(escape_attrs, *values)
|
40
|
+
escape_html(escape_attrs, values.flatten.select { |v| v }.join('_'))
|
41
|
+
end
|
24
42
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
43
|
+
def build_class(escape_attrs, *values)
|
44
|
+
if values.size == 1
|
45
|
+
value = values.first
|
46
|
+
case
|
47
|
+
when value.is_a?(String)
|
48
|
+
# noop
|
49
|
+
when value.is_a?(Array)
|
50
|
+
value = value.flatten.select { |v| v }.map(&:to_s).uniq.join(' ')
|
51
|
+
when value
|
52
|
+
value = value.to_s
|
53
|
+
else
|
54
|
+
return ''
|
32
55
|
end
|
56
|
+
return escape_html(escape_attrs, value)
|
33
57
|
end
|
34
58
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
value
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
elsif value == false
|
45
|
-
next
|
59
|
+
classes = []
|
60
|
+
values.each do |value|
|
61
|
+
case
|
62
|
+
when value.is_a?(String)
|
63
|
+
classes += value.split(' ')
|
64
|
+
when value.is_a?(Array)
|
65
|
+
classes += value.select { |v| v }
|
66
|
+
when value
|
67
|
+
classes << value.to_s
|
46
68
|
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
69
|
end
|
58
|
-
|
59
|
-
result.sort!
|
60
|
-
result.join
|
70
|
+
escape_html(escape_attrs, classes.map(&:to_s).uniq.join(' '))
|
61
71
|
end
|
62
72
|
|
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
|
73
|
+
def build_data(escape_attrs, quote, *hashes)
|
74
|
+
build_data_attribute(:data, escape_attrs, quote, *hashes)
|
76
75
|
end
|
77
76
|
|
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
|
77
|
+
def build_aria(escape_attrs, quote, *hashes)
|
78
|
+
build_data_attribute(:aria, escape_attrs, quote, *hashes)
|
96
79
|
end
|
97
80
|
|
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
|
81
|
+
private
|
108
82
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
83
|
+
def build_data_attribute(key, escape_attrs, quote, *hashes)
|
84
|
+
attrs = []
|
85
|
+
if hashes.size > 1 && hashes.all? { |h| h.is_a?(Hash) }
|
86
|
+
data_value = merge_all_attrs(hashes)
|
87
|
+
else
|
88
|
+
data_value = hashes.last
|
89
|
+
end
|
90
|
+
hash = flatten_attributes(key => data_value)
|
91
|
+
|
92
|
+
hash.sort_by(&:first).each do |key, value|
|
93
|
+
case value
|
94
|
+
when true
|
95
|
+
attrs << " #{key}"
|
96
|
+
when nil, false
|
97
|
+
# noop
|
98
|
+
else
|
99
|
+
attrs << " #{key}=#{quote}#{escape_html(escape_attrs, value.to_s)}#{quote}"
|
113
100
|
end
|
114
101
|
end
|
102
|
+
attrs.join
|
115
103
|
end
|
116
104
|
|
117
|
-
|
105
|
+
def flatten_attributes(attributes)
|
106
|
+
flattened = {}
|
118
107
|
|
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
|
108
|
+
attributes.each do |key, value|
|
109
|
+
case value
|
110
|
+
when attributes
|
111
|
+
when Hash
|
112
|
+
flatten_attributes(value).each do |k, v|
|
113
|
+
if k.nil?
|
114
|
+
flattened[key] = v
|
115
|
+
else
|
116
|
+
flattened["#{key}-#{k.to_s.gsub(/_/, '-')}"] = v
|
117
|
+
end
|
118
|
+
end
|
119
|
+
else
|
120
|
+
flattened[key] = value if value
|
143
121
|
end
|
144
|
-
merged_class
|
145
|
-
else
|
146
|
-
from
|
147
122
|
end
|
123
|
+
flattened
|
148
124
|
end
|
149
125
|
|
150
|
-
def
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
126
|
+
def merge_all_attrs(hashes)
|
127
|
+
merged = {}
|
128
|
+
hashes.each do |hash|
|
129
|
+
hash.each do |key, value|
|
130
|
+
key = key.to_s
|
131
|
+
case key
|
132
|
+
when 'id'.freeze, 'class'.freeze, 'data'.freeze
|
133
|
+
merged[key] ||= []
|
134
|
+
merged[key] << value
|
135
|
+
else
|
136
|
+
merged[key] = value
|
137
|
+
end
|
158
138
|
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
139
|
end
|
140
|
+
merged
|
172
141
|
end
|
173
142
|
|
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?
|
143
|
+
def build_boolean!(escape_attrs, quote, format, buf, key, value)
|
144
|
+
case value
|
145
|
+
when true
|
146
|
+
case format
|
147
|
+
when :xhtml
|
148
|
+
buf << " #{key}=#{quote}#{key}#{quote}"
|
193
149
|
else
|
194
|
-
|
150
|
+
buf << " #{key}"
|
195
151
|
end
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
152
|
+
when false, nil
|
153
|
+
# omitted
|
154
|
+
else
|
155
|
+
buf << " #{key}=#{quote}#{escape_html(escape_attrs, value)}#{quote}"
|
200
156
|
end
|
201
|
-
|
202
|
-
{ 'id'.freeze => id, 'class'.freeze => class_name }
|
203
157
|
end
|
204
158
|
|
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
|
159
|
+
def escape_html(escape_attrs, str)
|
160
|
+
if escape_attrs
|
161
|
+
Haml::Util.escape_html(str)
|
162
|
+
else
|
163
|
+
str
|
164
|
+
end
|
216
165
|
end
|
217
166
|
end
|
167
|
+
else
|
168
|
+
# Haml::AttributeBuilder.build
|
169
|
+
# Haml::AttributeBuilder.build_id
|
170
|
+
# Haml::AttributeBuilder.build_class
|
171
|
+
# Haml::AttributeBuilder.build_data
|
172
|
+
# Haml::AttributeBuilder.build_aria
|
173
|
+
require 'haml/haml'
|
218
174
|
end
|
219
175
|
end
|