haml 5.1.2 → 6.3.0
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 +36 -0
- data/.gitignore +16 -15
- data/.yardopts +0 -3
- data/CHANGELOG.md +189 -1
- data/FAQ.md +1 -1
- data/Gemfile +20 -12
- data/MIT-LICENSE +1 -1
- data/README.md +10 -17
- data/REFERENCE.md +129 -164
- data/Rakefile +15 -89
- 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/haml.gemspec +34 -35
- data/lib/haml/ambles.rb +20 -0
- data/lib/haml/attribute_builder.rb +131 -133
- data/lib/haml/attribute_compiler.rb +91 -182
- 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 +52 -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 -691
- 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 +190 -27
- data/lib/haml/rails_helpers.rb +53 -0
- data/lib/haml/rails_template.rb +62 -0
- data/lib/haml/railtie.rb +3 -41
- 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 +20 -16
- data/lib/haml/version.rb +1 -2
- data/lib/haml/whitespace.rb +8 -0
- data/lib/haml.rb +8 -20
- metadata +205 -53
- data/.gitmodules +0 -3
- data/.travis.yml +0 -97
- 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 -238
- data/lib/haml/escapable.rb +0 -50
- 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 -111
- data/lib/haml/options.rb +0 -273
- data/lib/haml/plugin.rb +0 -37
- data/lib/haml/sass_rails_filter.rb +0 -47
- data/lib/haml/template/options.rb +0 -27
- data/lib/haml/temple_engine.rb +0 -123
- 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/bin/stackprof
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'hamlit'
|
5
|
+
require 'stackprof'
|
6
|
+
|
7
|
+
def open_flamegraph(report)
|
8
|
+
temp = `mktemp /tmp/stackflame-XXXXXXXX`.strip
|
9
|
+
data_path = "#{temp}.js"
|
10
|
+
system("mv #{temp} #{data_path}")
|
11
|
+
|
12
|
+
File.open(data_path, 'w') do |f|
|
13
|
+
report.print_flamegraph(f)
|
14
|
+
end
|
15
|
+
|
16
|
+
viewer_path = File.join(`bundle show stackprof`.strip, 'lib/stackprof/flamegraph/viewer.html')
|
17
|
+
url = "file://#{viewer_path}?data=#{data_path}"
|
18
|
+
system(%Q[osascript -e 'open location "#{url}"'])
|
19
|
+
end
|
20
|
+
|
21
|
+
haml = File.read(ARGV.first)
|
22
|
+
StackProf.start(mode: :wall, interval: 1, raw: false)
|
23
|
+
Hamlit::Engine.new.call(haml)
|
24
|
+
StackProf.stop
|
25
|
+
|
26
|
+
report = StackProf::Report.new(StackProf.results)
|
27
|
+
report.print_text(false)
|
data/bin/test
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
VERSIONS=(
|
4
|
+
2.1.10
|
5
|
+
2.2.5
|
6
|
+
2.3.1
|
7
|
+
)
|
8
|
+
|
9
|
+
set -e
|
10
|
+
trap 'echo "${VERSIONS[2]}" > .ruby-version' 0
|
11
|
+
|
12
|
+
function test_with() {
|
13
|
+
version=$1
|
14
|
+
rbenv local $version
|
15
|
+
if ! bundle check > /dev/null; then
|
16
|
+
bundle install
|
17
|
+
fi
|
18
|
+
ruby -v
|
19
|
+
bundle exec rake test
|
20
|
+
}
|
21
|
+
|
22
|
+
for version in ${VERSIONS[@]}; do
|
23
|
+
test_with $version
|
24
|
+
done
|
data/exe/haml
ADDED
data/haml.gemspec
CHANGED
@@ -1,44 +1,43 @@
|
|
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/master/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
|
-
}
|
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'
|
25
16
|
|
26
|
-
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']
|
27
21
|
|
28
|
-
spec.
|
29
|
-
spec.add_dependency 'tilt'
|
22
|
+
spec.metadata = { 'rubygems_mfa_required' => 'true' }
|
30
23
|
|
31
|
-
spec.
|
32
|
-
spec.add_development_dependency 'rbench'
|
33
|
-
spec.add_development_dependency 'minitest', '>= 4.0'
|
34
|
-
spec.add_development_dependency 'nokogiri'
|
24
|
+
spec.required_ruby_version = '>= 2.1.0'
|
35
25
|
|
36
|
-
spec.
|
37
|
-
|
38
|
-
|
39
|
-
easy way by using indentation rather than closing tags and allowing Ruby to be
|
40
|
-
embedded with ease. It was originally envisioned as a plugin for Ruby on Rails,
|
41
|
-
but it can function as a stand-alone templating engine.
|
42
|
-
END
|
26
|
+
spec.add_dependency 'temple', '>= 0.8.2'
|
27
|
+
spec.add_dependency 'thor'
|
28
|
+
spec.add_dependency 'tilt'
|
43
29
|
|
30
|
+
spec.add_development_dependency 'benchmark_driver'
|
31
|
+
spec.add_development_dependency 'bundler'
|
32
|
+
spec.add_development_dependency 'coffee-script'
|
33
|
+
spec.add_development_dependency 'erubi'
|
34
|
+
spec.add_development_dependency 'haml', '>= 5'
|
35
|
+
spec.add_development_dependency 'less'
|
36
|
+
spec.add_development_dependency 'minitest-reporters', '~> 1.1'
|
37
|
+
spec.add_development_dependency 'rails', '>= 4.0'
|
38
|
+
spec.add_development_dependency 'rake'
|
39
|
+
spec.add_development_dependency 'sass'
|
40
|
+
spec.add_development_dependency 'slim'
|
41
|
+
spec.add_development_dependency 'string_template'
|
42
|
+
spec.add_development_dependency 'unindent'
|
44
43
|
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,163 +1,161 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
value = filter_and_join(value, ' ') if attr == 'class'
|
28
|
-
value = filter_and_join(value, '_') if attr == 'id'
|
29
|
-
|
30
|
-
if value == true
|
31
|
-
next " #{attr}" if is_html
|
32
|
-
next " #{attr}=#{attr_wrapper}#{attr}#{attr_wrapper}"
|
33
|
-
elsif value == false
|
34
|
-
next
|
35
|
-
end
|
36
|
-
|
37
|
-
value =
|
38
|
-
if escape_attrs == :once
|
39
|
-
Haml::Helpers.escape_once(value.to_s)
|
40
|
-
elsif escape_attrs
|
41
|
-
Haml::Helpers.html_escape(value.to_s)
|
42
|
-
else
|
43
|
-
value.to_s
|
44
|
-
end
|
45
|
-
" #{attr}=#{attr_wrapper}#{value}#{attr_wrapper}"
|
2
|
+
require 'haml/object_ref'
|
3
|
+
|
4
|
+
module Haml::AttributeBuilder
|
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}"
|
46
26
|
end
|
47
|
-
result.compact!
|
48
|
-
result.sort!
|
49
|
-
result.join
|
50
27
|
end
|
28
|
+
buf.join
|
29
|
+
end
|
51
30
|
|
52
|
-
|
53
|
-
|
54
|
-
|
31
|
+
def build_id(escape_attrs, *values)
|
32
|
+
escape_html(escape_attrs, values.flatten.select { |v| v }.join('_'))
|
33
|
+
end
|
55
34
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
61
45
|
else
|
62
|
-
|
46
|
+
return ''
|
63
47
|
end
|
64
|
-
|
48
|
+
return escape_html(escape_attrs, value)
|
65
49
|
end
|
66
50
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
#
|
77
|
-
# @param to [{String => String,Hash}] The attribute hash to merge into
|
78
|
-
# @param from [{String => Object}] The attribute hash to merge from
|
79
|
-
# @return [{String => String,Hash}] `to`, after being merged
|
80
|
-
def merge_attributes!(to, from)
|
81
|
-
from.keys.each do |key|
|
82
|
-
to[key] = merge_value(key, to[key], from[key])
|
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
|
83
60
|
end
|
84
|
-
to
|
85
61
|
end
|
62
|
+
escape_html(escape_attrs, classes.map(&:to_s).uniq.join(' '))
|
63
|
+
end
|
86
64
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
# @param values [Array<Object>]
|
91
|
-
# @return [String,Hash]
|
92
|
-
def merge_values(key, *values)
|
93
|
-
values.inject(nil) do |to, from|
|
94
|
-
merge_value(key, to, from)
|
95
|
-
end
|
96
|
-
end
|
65
|
+
def build_data(escape_attrs, quote, *hashes)
|
66
|
+
build_data_attribute(:data, escape_attrs, quote, *hashes)
|
67
|
+
end
|
97
68
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
69
|
+
def build_aria(escape_attrs, quote, *hashes)
|
70
|
+
build_data_attribute(:aria, escape_attrs, quote, *hashes)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
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
|
81
|
+
end
|
82
|
+
hash = flatten_attributes(key => data_value)
|
83
|
+
|
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}"
|
103
92
|
end
|
104
93
|
end
|
94
|
+
attrs.join
|
95
|
+
end
|
105
96
|
|
106
|
-
|
97
|
+
def flatten_attributes(attributes)
|
98
|
+
flattened = {}
|
107
99
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
elsif key == 'id'
|
119
|
-
merged_id = filter_and_join(from, '_')
|
120
|
-
if to && merged_id
|
121
|
-
merged_id = "#{to}_#{merged_id}"
|
122
|
-
elsif to || merged_id
|
123
|
-
merged_id ||= to
|
124
|
-
end
|
125
|
-
merged_id
|
126
|
-
elsif key == 'class'
|
127
|
-
merged_class = filter_and_join(from, ' ')
|
128
|
-
if to && merged_class
|
129
|
-
merged_class = (merged_class.split(' ') | to.split(' ')).sort.join(' ')
|
130
|
-
elsif to || merged_class
|
131
|
-
merged_class ||= to
|
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
|
107
|
+
else
|
108
|
+
flattened["#{key}-#{k.to_s.gsub(/_/, '-')}"] = v
|
109
|
+
end
|
132
110
|
end
|
133
|
-
merged_class
|
134
111
|
else
|
135
|
-
|
112
|
+
flattened[key] = value if value
|
136
113
|
end
|
137
114
|
end
|
115
|
+
flattened
|
116
|
+
end
|
138
117
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
145
130
|
else
|
146
|
-
[
|
131
|
+
merged[key] = value
|
147
132
|
end
|
148
|
-
end
|
133
|
+
end
|
149
134
|
end
|
135
|
+
merged
|
136
|
+
end
|
150
137
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
hash.merge! flatten_data_attributes(v, joined, join_char, seen)
|
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}"
|
144
|
+
else
|
145
|
+
buf << " #{key}"
|
160
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
|
161
159
|
end
|
162
160
|
end
|
163
161
|
end
|