hamlit 2.11.0-java → 2.12.0-java
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/.travis.yml +12 -10
- data/CHANGELOG.md +16 -1
- data/Gemfile +1 -7
- data/REFERENCE.md +4 -4
- data/ext/hamlit/hamlit.c +0 -1
- data/lib/hamlit/attribute_builder.rb +2 -2
- data/lib/hamlit/attribute_compiler.rb +3 -3
- data/lib/hamlit/compiler/children_compiler.rb +18 -4
- data/lib/hamlit/parser/haml_attribute_builder.rb +164 -0
- data/lib/hamlit/parser/haml_helpers.rb +6 -0
- data/lib/hamlit/parser/haml_parser.rb +32 -9
- data/lib/hamlit/parser/haml_xss_mods.rb +6 -3
- data/lib/hamlit/temple_line_counter.rb +31 -0
- data/lib/hamlit/version.rb +1 -1
- metadata +22 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9730ad24ae51f479f990d08aaa054adc41541e02f058889d085c437b7fce3772
|
|
4
|
+
data.tar.gz: 96956fc4d9e69332956936769d0843548d769179f31c2499706befc566dab02b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7d12567ab91773b31fbb8431362c821261b5ad47e678f75465df51e52a48bb101da829dd9e93b7aea75925a77b179f09f92ab08c0c0042b46478f0497bed7c6e
|
|
7
|
+
data.tar.gz: fa594a116affab20ea90313253bc5308a9e0d47a369b07d4b971e97728ac8fcbb6bbaa4ee1509ffede4b9f546e47d1abd6810d0c545377357748805416bfd34f
|
data/.travis.yml
CHANGED
|
@@ -9,11 +9,13 @@ matrix:
|
|
|
9
9
|
include:
|
|
10
10
|
- rvm: 2.3.8
|
|
11
11
|
env: TASK=test
|
|
12
|
-
- rvm: 2.4.
|
|
12
|
+
- rvm: 2.4.9
|
|
13
13
|
env: TASK=test
|
|
14
|
-
- rvm: 2.5.
|
|
14
|
+
- rvm: 2.5.7
|
|
15
15
|
env: TASK=test
|
|
16
|
-
- rvm: 2.6.
|
|
16
|
+
- rvm: 2.6.5
|
|
17
|
+
env: TASK=test
|
|
18
|
+
- rvm: 2.7.0
|
|
17
19
|
env: TASK=test
|
|
18
20
|
- rvm: ruby-head
|
|
19
21
|
env: TASK=test
|
|
@@ -21,19 +23,19 @@ matrix:
|
|
|
21
23
|
env: TASK=test
|
|
22
24
|
- rvm: truffleruby
|
|
23
25
|
env: TASK=test
|
|
24
|
-
- rvm: 2.
|
|
26
|
+
- rvm: 2.7.0
|
|
25
27
|
env: TASK=bench TEMPLATE=benchmark/boolean_attribute.haml,benchmark/class_attribute.haml,benchmark/id_attribute.haml,benchmark/data_attribute.haml,benchmark/common_attribute.haml
|
|
26
|
-
- rvm: 2.
|
|
28
|
+
- rvm: 2.7.0
|
|
27
29
|
env: TASK=bench TEMPLATE=benchmark/dynamic_attributes/boolean_attribute.haml,benchmark/dynamic_attributes/class_attribute.haml,benchmark/dynamic_attributes/id_attribute.haml,benchmark/dynamic_attributes/data_attribute.haml,benchmark/dynamic_attributes/common_attribute.haml
|
|
28
|
-
- rvm: 2.
|
|
30
|
+
- rvm: 2.7.0
|
|
29
31
|
env: TASK=bench SLIM_BENCH=1
|
|
30
|
-
- rvm: 2.
|
|
32
|
+
- rvm: 2.7.0
|
|
31
33
|
env: TASK=bench TEMPLATE=benchmark/etc/attribute_builder.haml
|
|
32
|
-
- rvm: 2.
|
|
34
|
+
- rvm: 2.7.0
|
|
33
35
|
env: TASK=bench TEMPLATE=benchmark/etc/static_analyzer.haml
|
|
34
|
-
- rvm: 2.
|
|
36
|
+
- rvm: 2.7.0
|
|
35
37
|
env: TASK=bench TEMPLATE=benchmark/etc/string_interpolation.haml
|
|
36
|
-
- rvm: 2.
|
|
38
|
+
- rvm: 2.7.0
|
|
37
39
|
env: TASK=bench TEMPLATE=test/haml/templates/standard.haml COMPILE=1
|
|
38
40
|
allow_failures:
|
|
39
41
|
- rvm: ruby-head
|
data/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,22 @@ All notable changes to this project will be documented in this file. This
|
|
|
4
4
|
project adheres to [Semantic Versioning](http://semver.org/). This change log is based upon
|
|
5
5
|
[keep-a-changelog](https://github.com/olivierlacan/keep-a-changelog).
|
|
6
6
|
|
|
7
|
-
## [2.
|
|
7
|
+
## [2.12.0](https://github.com/k0kubun/hamlit/compare/v2.11.1...v2.12.0) - 2020-09-30
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Class names are no longer ordered alphabetically
|
|
12
|
+
*Thanks to @aliismayilov*
|
|
13
|
+
- This is compatible with [Haml 5.2](https://github.com/haml/haml/blob/v5.2.0/CHANGELOG.md#52)
|
|
14
|
+
|
|
15
|
+
## [2.11.1](https://github.com/k0kubun/hamlit/compare/v2.11.0...v2.11.1) - 2020-08-25
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Fix a line number on an error after filters like preserve, plain, and ruby.
|
|
20
|
+
*Thanks to @rgisiger*
|
|
21
|
+
|
|
22
|
+
## [2.11.0](https://github.com/k0kubun/hamlit/compare/v2.10.1...v2.11.0) - 2019-12-12
|
|
8
23
|
|
|
9
24
|
### Added
|
|
10
25
|
|
data/Gemfile
CHANGED
|
@@ -8,10 +8,6 @@ end
|
|
|
8
8
|
# Specify your gem's dependencies in hamlit.gemspec
|
|
9
9
|
gemspec
|
|
10
10
|
|
|
11
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.2')
|
|
12
|
-
gem 'rack', '< 2'
|
|
13
|
-
end
|
|
14
|
-
|
|
15
11
|
gem 'benchmark-ips', '2.3.0'
|
|
16
12
|
gem 'maxitest'
|
|
17
13
|
gem 'pry'
|
|
@@ -22,9 +18,7 @@ else
|
|
|
22
18
|
gem 'redcarpet'
|
|
23
19
|
|
|
24
20
|
if RUBY_PLATFORM !~ /mswin|mingw/ && RUBY_ENGINE != 'truffleruby'
|
|
25
|
-
|
|
26
|
-
gem 'faml'
|
|
27
|
-
end
|
|
21
|
+
gem 'faml'
|
|
28
22
|
gem 'stackprof'
|
|
29
23
|
end
|
|
30
24
|
end
|
data/REFERENCE.md
CHANGED
|
@@ -122,10 +122,10 @@ and merging multiple ids results in concatenation by "\_".
|
|
|
122
122
|
%div{ id: false }
|
|
123
123
|
|
|
124
124
|
# Output
|
|
125
|
-
<div id='foo_bar'></
|
|
126
|
-
<div id='foo_bar'></
|
|
127
|
-
<div id='foo_bar'></
|
|
128
|
-
<div id=''></
|
|
125
|
+
<div id='foo_bar'></div>
|
|
126
|
+
<div id='foo_bar'></div>
|
|
127
|
+
<div id='foo_bar'></div>
|
|
128
|
+
<div id=''></div>
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
### class attribute
|
data/ext/hamlit/hamlit.c
CHANGED
|
@@ -47,7 +47,7 @@ module Hamlit::AttributeBuilder
|
|
|
47
47
|
when value.is_a?(String)
|
|
48
48
|
# noop
|
|
49
49
|
when value.is_a?(Array)
|
|
50
|
-
value = value.flatten.select { |v| v }.map(&:to_s).
|
|
50
|
+
value = value.flatten.select { |v| v }.map(&:to_s).uniq.join(' ')
|
|
51
51
|
when value
|
|
52
52
|
value = value.to_s
|
|
53
53
|
else
|
|
@@ -67,7 +67,7 @@ module Hamlit::AttributeBuilder
|
|
|
67
67
|
classes << value.to_s
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
|
-
escape_html(escape_attrs, classes.map(&:to_s).
|
|
70
|
+
escape_html(escape_attrs, classes.map(&:to_s).uniq.join(' '))
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def build_data(escape_attrs, quote, *hashes)
|
|
@@ -17,7 +17,7 @@ module Hamlit
|
|
|
17
17
|
if node.value[:object_ref] != :nil || !Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby
|
|
18
18
|
return runtime_compile(node)
|
|
19
19
|
end
|
|
20
|
-
node.value[:
|
|
20
|
+
[node.value[:dynamic_attributes].new, node.value[:dynamic_attributes].old].compact.each do |attribute_str|
|
|
21
21
|
hash = AttributeParser.parse(attribute_str)
|
|
22
22
|
return runtime_compile(node) unless hash
|
|
23
23
|
hashes << hash
|
|
@@ -28,11 +28,11 @@ module Hamlit
|
|
|
28
28
|
private
|
|
29
29
|
|
|
30
30
|
def runtime_compile(node)
|
|
31
|
-
attrs =
|
|
31
|
+
attrs = []
|
|
32
32
|
attrs.unshift(node.value[:attributes].inspect) if node.value[:attributes] != {}
|
|
33
33
|
|
|
34
34
|
args = [@escape_attrs.inspect, "#{@quote.inspect}.freeze", @format.inspect].push(node.value[:object_ref]) + attrs
|
|
35
|
-
[:html, :attrs, [:dynamic, "::Hamlit::AttributeBuilder.build(#{args.join(', ')})"]]
|
|
35
|
+
[:html, :attrs, [:dynamic, "::Hamlit::AttributeBuilder.build(#{args.join(', ')}, #{node.value[:dynamic_attributes].to_literal})"]]
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def static_compile(static_hash, dynamic_hashes)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
require 'hamlit/temple_line_counter'
|
|
3
|
+
|
|
2
4
|
module Hamlit
|
|
3
5
|
class Compiler
|
|
4
6
|
class ChildrenCompiler
|
|
@@ -14,7 +16,7 @@ module Hamlit
|
|
|
14
16
|
node.children.each do |n|
|
|
15
17
|
rstrip_whitespace!(temple) if nuke_prev_whitespace?(n)
|
|
16
18
|
insert_newlines!(temple, n)
|
|
17
|
-
temple <<
|
|
19
|
+
temple << moving_lineno(n) { block.call(n) }
|
|
18
20
|
temple << :whitespace if insert_whitespace?(n)
|
|
19
21
|
end
|
|
20
22
|
rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
|
|
@@ -27,19 +29,31 @@ module Hamlit
|
|
|
27
29
|
(node.line - @lineno).times do
|
|
28
30
|
temple << [:newline]
|
|
29
31
|
end
|
|
32
|
+
|
|
30
33
|
@lineno = node.line
|
|
34
|
+
end
|
|
31
35
|
|
|
36
|
+
def moving_lineno(node, &block)
|
|
37
|
+
# before: As they may have children, we need to increment lineno before compilation.
|
|
32
38
|
case node.type
|
|
33
39
|
when :script, :silent_script
|
|
34
40
|
@lineno += 1
|
|
35
|
-
when :filter
|
|
36
|
-
@lineno += (node.value[:text] || '').split("\n").size
|
|
37
41
|
when :tag
|
|
38
|
-
node.value[:
|
|
42
|
+
[node.value[:dynamic_attributes].new, node.value[:dynamic_attributes].old].compact.each do |attribute_hash|
|
|
39
43
|
@lineno += attribute_hash.count("\n")
|
|
40
44
|
end
|
|
41
45
|
@lineno += 1 if node.children.empty? && node.value[:parse]
|
|
42
46
|
end
|
|
47
|
+
|
|
48
|
+
temple = block.call # compile
|
|
49
|
+
|
|
50
|
+
# after: filter may not have children, and for some dynamic filters we can't predict the number of lines.
|
|
51
|
+
case node.type
|
|
52
|
+
when :filter
|
|
53
|
+
@lineno += TempleLineCounter.count_lines(temple)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
temple
|
|
43
57
|
end
|
|
44
58
|
|
|
45
59
|
def confirm_whitespace(temple)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hamlit
|
|
4
|
+
module HamlAttributeBuilder
|
|
5
|
+
# https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
|
|
6
|
+
INVALID_ATTRIBUTE_NAME_REGEX = /[ \0"'>\/=]/
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def build_attributes(is_html, attr_wrapper, escape_attrs, hyphenate_data_attrs, attributes = {})
|
|
10
|
+
# @TODO this is an absolutely ridiculous amount of arguments. At least
|
|
11
|
+
# some of this needs to be moved into an instance method.
|
|
12
|
+
join_char = hyphenate_data_attrs ? '-' : '_'
|
|
13
|
+
|
|
14
|
+
attributes.each do |key, value|
|
|
15
|
+
if value.is_a?(Hash)
|
|
16
|
+
data_attributes = attributes.delete(key)
|
|
17
|
+
data_attributes = flatten_data_attributes(data_attributes, '', join_char)
|
|
18
|
+
data_attributes = build_data_keys(data_attributes, hyphenate_data_attrs, key)
|
|
19
|
+
verify_attribute_names!(data_attributes.keys)
|
|
20
|
+
attributes = data_attributes.merge(attributes)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
result = attributes.collect do |attr, value|
|
|
25
|
+
next if value.nil?
|
|
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
|
+
Hamlit::HamlHelpers.escape_once_without_haml_xss(value.to_s)
|
|
40
|
+
elsif escape_attrs
|
|
41
|
+
Hamlit::HamlHelpers.html_escape_without_haml_xss(value.to_s)
|
|
42
|
+
else
|
|
43
|
+
value.to_s
|
|
44
|
+
end
|
|
45
|
+
" #{attr}=#{attr_wrapper}#{value}#{attr_wrapper}"
|
|
46
|
+
end
|
|
47
|
+
result.compact!
|
|
48
|
+
result.sort!
|
|
49
|
+
result.join
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @return [String, nil]
|
|
53
|
+
def filter_and_join(value, separator)
|
|
54
|
+
return '' if (value.respond_to?(:empty?) && value.empty?)
|
|
55
|
+
|
|
56
|
+
if value.is_a?(Array)
|
|
57
|
+
value = value.flatten
|
|
58
|
+
value.map! {|item| item ? item.to_s : nil}
|
|
59
|
+
value.compact!
|
|
60
|
+
value = value.join(separator)
|
|
61
|
+
else
|
|
62
|
+
value = value ? value.to_s : nil
|
|
63
|
+
end
|
|
64
|
+
!value.nil? && !value.empty? && value
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Merges two attribute hashes.
|
|
68
|
+
# This is the same as `to.merge!(from)`,
|
|
69
|
+
# except that it merges id, class, and data attributes.
|
|
70
|
+
#
|
|
71
|
+
# ids are concatenated with `"_"`,
|
|
72
|
+
# and classes are concatenated with `" "`.
|
|
73
|
+
# data hashes are simply merged.
|
|
74
|
+
#
|
|
75
|
+
# Destructively modifies `to`.
|
|
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])
|
|
83
|
+
end
|
|
84
|
+
to
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Merge multiple values to one attribute value. No destructive operation.
|
|
88
|
+
#
|
|
89
|
+
# @param key [String]
|
|
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
|
|
97
|
+
|
|
98
|
+
def verify_attribute_names!(attribute_names)
|
|
99
|
+
attribute_names.each do |attribute_name|
|
|
100
|
+
if attribute_name =~ INVALID_ATTRIBUTE_NAME_REGEX
|
|
101
|
+
raise InvalidAttributeNameError.new("Invalid attribute name '#{attribute_name}' was rendered")
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# Merge a couple of values to one attribute value. No destructive operation.
|
|
109
|
+
#
|
|
110
|
+
# @param to [String,Hash,nil]
|
|
111
|
+
# @param from [Object]
|
|
112
|
+
# @return [String,Hash]
|
|
113
|
+
def merge_value(key, to, from)
|
|
114
|
+
if from.kind_of?(Hash) || to.kind_of?(Hash)
|
|
115
|
+
from = { nil => from } if !from.is_a?(Hash)
|
|
116
|
+
to = { nil => to } if !to.is_a?(Hash)
|
|
117
|
+
to.merge(from)
|
|
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 = (to.split(' ') | merged_class.split(' ')).join(' ')
|
|
130
|
+
elsif to || merged_class
|
|
131
|
+
merged_class ||= to
|
|
132
|
+
end
|
|
133
|
+
merged_class
|
|
134
|
+
else
|
|
135
|
+
from
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def build_data_keys(data_hash, hyphenate, attr_name="data")
|
|
140
|
+
Hash[data_hash.map do |name, value|
|
|
141
|
+
if name == nil
|
|
142
|
+
[attr_name, value]
|
|
143
|
+
elsif hyphenate
|
|
144
|
+
["#{attr_name}-#{name.to_s.tr('_', '-')}", value]
|
|
145
|
+
else
|
|
146
|
+
["#{attr_name}-#{name}", value]
|
|
147
|
+
end
|
|
148
|
+
end]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def flatten_data_attributes(data, key, join_char, seen = [])
|
|
152
|
+
return {key => data} unless data.is_a?(Hash)
|
|
153
|
+
|
|
154
|
+
return {key => nil} if seen.include? data.object_id
|
|
155
|
+
seen << data.object_id
|
|
156
|
+
|
|
157
|
+
data.sort {|x, y| x[0].to_s <=> y[0].to_s}.inject({}) do |hash, (k, v)|
|
|
158
|
+
joined = key == '' ? k : [key, k].join(join_char)
|
|
159
|
+
hash.merge! flatten_data_attributes(v, joined, join_char, seen)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -617,6 +617,9 @@ MESSAGE
|
|
|
617
617
|
text.gsub(HTML_ESCAPE_REGEX, HTML_ESCAPE)
|
|
618
618
|
end
|
|
619
619
|
|
|
620
|
+
# Always escape text regardless of html_safe?
|
|
621
|
+
alias_method :html_escape_without_haml_xss, :html_escape
|
|
622
|
+
|
|
620
623
|
HTML_ESCAPE_ONCE_REGEX = /[\"><]|&(?!(?:[a-zA-Z]+|#(?:\d+|[xX][0-9a-fA-F]+));)/
|
|
621
624
|
|
|
622
625
|
# Escapes HTML entities in `text`, but without escaping an ampersand
|
|
@@ -629,6 +632,9 @@ MESSAGE
|
|
|
629
632
|
text.gsub(HTML_ESCAPE_ONCE_REGEX, HTML_ESCAPE)
|
|
630
633
|
end
|
|
631
634
|
|
|
635
|
+
# Always escape text once regardless of html_safe?
|
|
636
|
+
alias_method :escape_once_without_haml_xss, :escape_once
|
|
637
|
+
|
|
632
638
|
# Returns whether or not the current template is a Haml template.
|
|
633
639
|
#
|
|
634
640
|
# This function, unlike other {Haml::Helpers} functions,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'strscan'
|
|
2
2
|
require 'hamlit/parser/haml_util'
|
|
3
3
|
require 'hamlit/parser/haml_error'
|
|
4
|
+
require 'hamlit/parser/haml_attribute_builder'
|
|
4
5
|
|
|
5
6
|
module Hamlit
|
|
6
7
|
class HamlParser
|
|
@@ -206,6 +207,31 @@ module Hamlit
|
|
|
206
207
|
end
|
|
207
208
|
end
|
|
208
209
|
|
|
210
|
+
# @param [String] new - Hash literal including dynamic values.
|
|
211
|
+
# @param [String] old - Hash literal including dynamic values or Ruby literal of multiple Hashes which MUST be interpreted as method's last arguments.
|
|
212
|
+
DynamicAttributes = Struct.new(:new, :old) do
|
|
213
|
+
undef :old=
|
|
214
|
+
def old=(value)
|
|
215
|
+
unless value =~ /\A{.*}\z/m
|
|
216
|
+
raise ArgumentError.new('Old attributes must start with "{" and end with "}"')
|
|
217
|
+
end
|
|
218
|
+
self[:old] = value
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# This will be a literal for Haml::Buffer#attributes's last argument, `attributes_hashes`.
|
|
222
|
+
def to_literal
|
|
223
|
+
[new, stripped_old].compact.join(', ')
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
private
|
|
227
|
+
|
|
228
|
+
# For `%foo{ { foo: 1 }, bar: 2 }`, :old is "{ { foo: 1 }, bar: 2 }" and this method returns " { foo: 1 }, bar: 2 " for last argument.
|
|
229
|
+
def stripped_old
|
|
230
|
+
return nil if old.nil?
|
|
231
|
+
old.sub!(/\A{/, '').sub!(/}\z/m, '')
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
209
235
|
# Processes and deals with lowering indentation.
|
|
210
236
|
def process_indent(line)
|
|
211
237
|
return unless line.tabs <= @template_tabs && @template_tabs > 0
|
|
@@ -403,22 +429,20 @@ module Hamlit
|
|
|
403
429
|
end
|
|
404
430
|
|
|
405
431
|
attributes = ::Hamlit::HamlParser.parse_class_and_id(attributes)
|
|
406
|
-
|
|
432
|
+
dynamic_attributes = DynamicAttributes.new
|
|
407
433
|
|
|
408
434
|
if attributes_hashes[:new]
|
|
409
435
|
static_attributes, attributes_hash = attributes_hashes[:new]
|
|
410
|
-
|
|
411
|
-
|
|
436
|
+
HamlAttributeBuilder.merge_attributes!(attributes, static_attributes) if static_attributes
|
|
437
|
+
dynamic_attributes.new = attributes_hash
|
|
412
438
|
end
|
|
413
439
|
|
|
414
440
|
if attributes_hashes[:old]
|
|
415
441
|
static_attributes = parse_static_hash(attributes_hashes[:old])
|
|
416
|
-
|
|
417
|
-
|
|
442
|
+
HamlAttributeBuilder.merge_attributes!(attributes, static_attributes) if static_attributes
|
|
443
|
+
dynamic_attributes.old = attributes_hashes[:old] unless static_attributes || @options.suppress_eval
|
|
418
444
|
end
|
|
419
445
|
|
|
420
|
-
attributes_list.compact!
|
|
421
|
-
|
|
422
446
|
raise ::Hamlit::HamlSyntaxError.new(::Hamlit::HamlError.message(:illegal_nesting_self_closing), @next_line.index) if block_opened? && self_closing
|
|
423
447
|
raise ::Hamlit::HamlSyntaxError.new(::Hamlit::HamlError.message(:no_ruby_code, action), last_line - 1) if parse && value.empty?
|
|
424
448
|
raise ::Hamlit::HamlSyntaxError.new(::Hamlit::HamlError.message(:self_closing_content), last_line - 1) if self_closing && !value.empty?
|
|
@@ -433,7 +457,7 @@ module Hamlit
|
|
|
433
457
|
line = handle_ruby_multiline(line) if parse
|
|
434
458
|
|
|
435
459
|
ParseNode.new(:tag, line.index + 1, :name => tag_name, :attributes => attributes,
|
|
436
|
-
:
|
|
460
|
+
:dynamic_attributes => dynamic_attributes, :self_closing => self_closing,
|
|
437
461
|
:nuke_inner_whitespace => nuke_inner_whitespace,
|
|
438
462
|
:nuke_outer_whitespace => nuke_outer_whitespace, :object_ref => object_ref,
|
|
439
463
|
:escape_html => escape_html, :preserve_tag => preserve_tag,
|
|
@@ -641,7 +665,6 @@ module Hamlit
|
|
|
641
665
|
raise e
|
|
642
666
|
end
|
|
643
667
|
|
|
644
|
-
attributes_hash = attributes_hash[1...-1] if attributes_hash
|
|
645
668
|
return attributes_hash, rest, last_line
|
|
646
669
|
end
|
|
647
670
|
|
|
@@ -6,12 +6,15 @@ module Hamlit
|
|
|
6
6
|
# to work with Rails' XSS protection methods.
|
|
7
7
|
module XssMods
|
|
8
8
|
def self.included(base)
|
|
9
|
-
%w[
|
|
10
|
-
precede succeed capture_haml haml_concat haml_internal_concat haml_indent
|
|
11
|
-
escape_once].each do |name|
|
|
9
|
+
%w[find_and_preserve preserve list_of surround
|
|
10
|
+
precede succeed capture_haml haml_concat haml_internal_concat haml_indent].each do |name|
|
|
12
11
|
base.send(:alias_method, "#{name}_without_haml_xss", name)
|
|
13
12
|
base.send(:alias_method, name, "#{name}_with_haml_xss")
|
|
14
13
|
end
|
|
14
|
+
# Those two always have _without_haml_xss
|
|
15
|
+
%w[html_escape escape_once].each do |name|
|
|
16
|
+
base.send(:alias_method, name, "#{name}_with_haml_xss")
|
|
17
|
+
end
|
|
15
18
|
end
|
|
16
19
|
|
|
17
20
|
# Don't escape text that's already safe,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hamlit
|
|
3
|
+
# A module to count lines of expected code. This would be faster than actual code generation
|
|
4
|
+
# and counting newlines in it.
|
|
5
|
+
module TempleLineCounter
|
|
6
|
+
class UnexpectedExpression < StandardError; end
|
|
7
|
+
|
|
8
|
+
def self.count_lines(exp)
|
|
9
|
+
type, *args = exp
|
|
10
|
+
case type
|
|
11
|
+
when :multi
|
|
12
|
+
args.map { |a| count_lines(a) }.reduce(:+) || 0
|
|
13
|
+
when :dynamic, :code
|
|
14
|
+
args.first.count("\n")
|
|
15
|
+
when :static
|
|
16
|
+
0 # It has not real newline "\n" but escaped "\\n".
|
|
17
|
+
when :case
|
|
18
|
+
arg, *cases = args
|
|
19
|
+
arg.count("\n") + cases.map do |cond, e|
|
|
20
|
+
(cond == :else ? 0 : cond.count("\n")) + count_lines(e)
|
|
21
|
+
end.reduce(:+)
|
|
22
|
+
when :escape
|
|
23
|
+
count_lines(args[1])
|
|
24
|
+
when :newline
|
|
25
|
+
1
|
|
26
|
+
else
|
|
27
|
+
raise UnexpectedExpression.new("[HAML BUG] Unexpected Temple expression '#{type}' is given!")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/hamlit/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hamlit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.12.0
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Takashi Kokubun
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-10-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -17,8 +17,8 @@ dependencies:
|
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: 0.8.2
|
|
19
19
|
name: temple
|
|
20
|
-
prerelease: false
|
|
21
20
|
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
@@ -31,8 +31,8 @@ dependencies:
|
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: '0'
|
|
33
33
|
name: thor
|
|
34
|
-
prerelease: false
|
|
35
34
|
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - ">="
|
|
@@ -45,8 +45,8 @@ dependencies:
|
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
46
|
version: '0'
|
|
47
47
|
name: tilt
|
|
48
|
-
prerelease: false
|
|
49
48
|
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - ">="
|
|
@@ -59,8 +59,8 @@ dependencies:
|
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
60
|
version: '0'
|
|
61
61
|
name: benchmark_driver
|
|
62
|
-
prerelease: false
|
|
63
62
|
type: :development
|
|
63
|
+
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - ">="
|
|
@@ -73,8 +73,8 @@ dependencies:
|
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
74
|
version: '0'
|
|
75
75
|
name: bundler
|
|
76
|
-
prerelease: false
|
|
77
76
|
type: :development
|
|
77
|
+
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
80
|
- - ">="
|
|
@@ -87,8 +87,8 @@ dependencies:
|
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
88
|
version: '0'
|
|
89
89
|
name: coffee-script
|
|
90
|
-
prerelease: false
|
|
91
90
|
type: :development
|
|
91
|
+
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - ">="
|
|
@@ -101,8 +101,8 @@ dependencies:
|
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
102
|
version: '0'
|
|
103
103
|
name: erubi
|
|
104
|
-
prerelease: false
|
|
105
104
|
type: :development
|
|
105
|
+
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - ">="
|
|
@@ -115,8 +115,8 @@ dependencies:
|
|
|
115
115
|
- !ruby/object:Gem::Version
|
|
116
116
|
version: '5'
|
|
117
117
|
name: haml
|
|
118
|
-
prerelease: false
|
|
119
118
|
type: :development
|
|
119
|
+
prerelease: false
|
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
121
|
requirements:
|
|
122
122
|
- - ">="
|
|
@@ -129,8 +129,8 @@ dependencies:
|
|
|
129
129
|
- !ruby/object:Gem::Version
|
|
130
130
|
version: '0'
|
|
131
131
|
name: less
|
|
132
|
-
prerelease: false
|
|
133
132
|
type: :development
|
|
133
|
+
prerelease: false
|
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
136
|
- - ">="
|
|
@@ -143,8 +143,8 @@ dependencies:
|
|
|
143
143
|
- !ruby/object:Gem::Version
|
|
144
144
|
version: '1.1'
|
|
145
145
|
name: minitest-reporters
|
|
146
|
-
prerelease: false
|
|
147
146
|
type: :development
|
|
147
|
+
prerelease: false
|
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
149
|
requirements:
|
|
150
150
|
- - "~>"
|
|
@@ -157,8 +157,8 @@ dependencies:
|
|
|
157
157
|
- !ruby/object:Gem::Version
|
|
158
158
|
version: 4.0.0
|
|
159
159
|
name: rails
|
|
160
|
-
prerelease: false
|
|
161
160
|
type: :development
|
|
161
|
+
prerelease: false
|
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
|
163
163
|
requirements:
|
|
164
164
|
- - ">="
|
|
@@ -171,8 +171,8 @@ dependencies:
|
|
|
171
171
|
- !ruby/object:Gem::Version
|
|
172
172
|
version: '0'
|
|
173
173
|
name: rake
|
|
174
|
-
prerelease: false
|
|
175
174
|
type: :development
|
|
175
|
+
prerelease: false
|
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
|
177
177
|
requirements:
|
|
178
178
|
- - ">="
|
|
@@ -185,8 +185,8 @@ dependencies:
|
|
|
185
185
|
- !ruby/object:Gem::Version
|
|
186
186
|
version: '0'
|
|
187
187
|
name: rake-compiler
|
|
188
|
-
prerelease: false
|
|
189
188
|
type: :development
|
|
189
|
+
prerelease: false
|
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
|
191
191
|
requirements:
|
|
192
192
|
- - ">="
|
|
@@ -199,8 +199,8 @@ dependencies:
|
|
|
199
199
|
- !ruby/object:Gem::Version
|
|
200
200
|
version: '0'
|
|
201
201
|
name: sass
|
|
202
|
-
prerelease: false
|
|
203
202
|
type: :development
|
|
203
|
+
prerelease: false
|
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
|
205
205
|
requirements:
|
|
206
206
|
- - ">="
|
|
@@ -213,8 +213,8 @@ dependencies:
|
|
|
213
213
|
- !ruby/object:Gem::Version
|
|
214
214
|
version: '0'
|
|
215
215
|
name: slim
|
|
216
|
-
prerelease: false
|
|
217
216
|
type: :development
|
|
217
|
+
prerelease: false
|
|
218
218
|
version_requirements: !ruby/object:Gem::Requirement
|
|
219
219
|
requirements:
|
|
220
220
|
- - ">="
|
|
@@ -227,8 +227,8 @@ dependencies:
|
|
|
227
227
|
- !ruby/object:Gem::Version
|
|
228
228
|
version: '0'
|
|
229
229
|
name: string_template
|
|
230
|
-
prerelease: false
|
|
231
230
|
type: :development
|
|
231
|
+
prerelease: false
|
|
232
232
|
version_requirements: !ruby/object:Gem::Requirement
|
|
233
233
|
requirements:
|
|
234
234
|
- - ">="
|
|
@@ -241,8 +241,8 @@ dependencies:
|
|
|
241
241
|
- !ruby/object:Gem::Version
|
|
242
242
|
version: '0'
|
|
243
243
|
name: unindent
|
|
244
|
-
prerelease: false
|
|
245
244
|
type: :development
|
|
245
|
+
prerelease: false
|
|
246
246
|
version_requirements: !ruby/object:Gem::Requirement
|
|
247
247
|
requirements:
|
|
248
248
|
- - ">="
|
|
@@ -349,6 +349,7 @@ files:
|
|
|
349
349
|
- lib/hamlit/parser.rb
|
|
350
350
|
- lib/hamlit/parser/MIT-LICENSE
|
|
351
351
|
- lib/hamlit/parser/README.md
|
|
352
|
+
- lib/hamlit/parser/haml_attribute_builder.rb
|
|
352
353
|
- lib/hamlit/parser/haml_buffer.rb
|
|
353
354
|
- lib/hamlit/parser/haml_compiler.rb
|
|
354
355
|
- lib/hamlit/parser/haml_error.rb
|
|
@@ -363,6 +364,7 @@ files:
|
|
|
363
364
|
- lib/hamlit/ruby_expression.rb
|
|
364
365
|
- lib/hamlit/string_splitter.rb
|
|
365
366
|
- lib/hamlit/template.rb
|
|
367
|
+
- lib/hamlit/temple_line_counter.rb
|
|
366
368
|
- lib/hamlit/utils.rb
|
|
367
369
|
- lib/hamlit/version.rb
|
|
368
370
|
homepage: https://github.com/k0kubun/hamlit
|
|
@@ -384,8 +386,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
384
386
|
- !ruby/object:Gem::Version
|
|
385
387
|
version: '0'
|
|
386
388
|
requirements: []
|
|
387
|
-
|
|
388
|
-
rubygems_version: 2.7.9
|
|
389
|
+
rubygems_version: 3.0.6
|
|
389
390
|
signing_key:
|
|
390
391
|
specification_version: 4
|
|
391
392
|
summary: High Performance Haml Implementation
|