hamlit 2.9.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 +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +45 -0
- data/CHANGELOG.md +676 -0
- data/Gemfile +28 -0
- data/LICENSE.txt +44 -0
- data/README.md +150 -0
- data/REFERENCE.md +266 -0
- data/Rakefile +117 -0
- data/benchmark/boolean_attribute.haml +6 -0
- data/benchmark/class_attribute.haml +5 -0
- data/benchmark/common_attribute.haml +3 -0
- data/benchmark/data_attribute.haml +4 -0
- data/benchmark/dynamic_attributes/boolean_attribute.haml +4 -0
- data/benchmark/dynamic_attributes/class_attribute.haml +4 -0
- data/benchmark/dynamic_attributes/common_attribute.haml +2 -0
- data/benchmark/dynamic_attributes/data_attribute.haml +2 -0
- data/benchmark/dynamic_attributes/id_attribute.haml +2 -0
- data/benchmark/dynamic_boolean_attribute.haml +4 -0
- data/benchmark/etc/attribute_builder.haml +5 -0
- data/benchmark/etc/real_sample.haml +888 -0
- data/benchmark/etc/real_sample.rb +11 -0
- data/benchmark/etc/static_analyzer.haml +1 -0
- data/benchmark/etc/string_interpolation.haml +2 -0
- data/benchmark/etc/tags.haml +3 -0
- data/benchmark/etc/tags_loop.haml +2 -0
- data/benchmark/ext/build_data.rb +17 -0
- data/benchmark/ext/build_id.rb +13 -0
- data/benchmark/id_attribute.haml +3 -0
- data/benchmark/plain.haml +4 -0
- data/benchmark/script.haml +4 -0
- data/benchmark/slim/LICENSE +21 -0
- data/benchmark/slim/context.rb +11 -0
- data/benchmark/slim/run-benchmarks.rb +94 -0
- data/benchmark/slim/view.erb +23 -0
- data/benchmark/slim/view.haml +18 -0
- data/benchmark/slim/view.slim +17 -0
- data/benchmark/utils/benchmark_ips_extension.rb +43 -0
- data/bin/bench +77 -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/hamlit +6 -0
- data/ext/hamlit/extconf.rb +10 -0
- data/ext/hamlit/hamlit.c +553 -0
- data/ext/hamlit/hescape.c +108 -0
- data/ext/hamlit/hescape.h +20 -0
- data/hamlit.gemspec +45 -0
- data/lib/hamlit.rb +11 -0
- data/lib/hamlit/attribute_builder.rb +173 -0
- data/lib/hamlit/attribute_compiler.rb +123 -0
- data/lib/hamlit/attribute_parser.rb +110 -0
- data/lib/hamlit/cli.rb +130 -0
- data/lib/hamlit/compiler.rb +97 -0
- data/lib/hamlit/compiler/children_compiler.rb +112 -0
- data/lib/hamlit/compiler/comment_compiler.rb +36 -0
- data/lib/hamlit/compiler/doctype_compiler.rb +46 -0
- data/lib/hamlit/compiler/script_compiler.rb +102 -0
- data/lib/hamlit/compiler/silent_script_compiler.rb +24 -0
- data/lib/hamlit/compiler/tag_compiler.rb +74 -0
- data/lib/hamlit/engine.rb +37 -0
- data/lib/hamlit/error.rb +15 -0
- data/lib/hamlit/escapable.rb +13 -0
- data/lib/hamlit/filters.rb +75 -0
- data/lib/hamlit/filters/base.rb +12 -0
- data/lib/hamlit/filters/cdata.rb +20 -0
- data/lib/hamlit/filters/coffee.rb +17 -0
- data/lib/hamlit/filters/css.rb +33 -0
- data/lib/hamlit/filters/erb.rb +10 -0
- data/lib/hamlit/filters/escaped.rb +22 -0
- data/lib/hamlit/filters/javascript.rb +33 -0
- data/lib/hamlit/filters/less.rb +20 -0
- data/lib/hamlit/filters/markdown.rb +10 -0
- data/lib/hamlit/filters/plain.rb +29 -0
- data/lib/hamlit/filters/preserve.rb +22 -0
- data/lib/hamlit/filters/ruby.rb +10 -0
- data/lib/hamlit/filters/sass.rb +15 -0
- data/lib/hamlit/filters/scss.rb +15 -0
- data/lib/hamlit/filters/text_base.rb +25 -0
- data/lib/hamlit/filters/tilt_base.rb +49 -0
- data/lib/hamlit/force_escapable.rb +29 -0
- data/lib/hamlit/helpers.rb +15 -0
- data/lib/hamlit/html.rb +14 -0
- data/lib/hamlit/identity.rb +13 -0
- data/lib/hamlit/object_ref.rb +30 -0
- data/lib/hamlit/parser.rb +49 -0
- data/lib/hamlit/parser/MIT-LICENSE +20 -0
- data/lib/hamlit/parser/README.md +30 -0
- data/lib/hamlit/parser/haml_buffer.rb +348 -0
- data/lib/hamlit/parser/haml_compiler.rb +553 -0
- data/lib/hamlit/parser/haml_error.rb +61 -0
- data/lib/hamlit/parser/haml_helpers.rb +727 -0
- data/lib/hamlit/parser/haml_options.rb +286 -0
- data/lib/hamlit/parser/haml_parser.rb +800 -0
- data/lib/hamlit/parser/haml_util.rb +288 -0
- data/lib/hamlit/parser/haml_xss_mods.rb +109 -0
- data/lib/hamlit/rails_helpers.rb +51 -0
- data/lib/hamlit/rails_template.rb +59 -0
- data/lib/hamlit/railtie.rb +10 -0
- data/lib/hamlit/ruby_expression.rb +32 -0
- data/lib/hamlit/string_splitter.rb +88 -0
- data/lib/hamlit/template.rb +28 -0
- data/lib/hamlit/utils.rb +18 -0
- data/lib/hamlit/version.rb +4 -0
- metadata +361 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Hamlit::Parser uses original Haml::Parser to generate Haml AST.
|
3
|
+
# hamlit/parser/haml_* are modules originally in haml gem.
|
4
|
+
|
5
|
+
require 'hamlit/parser/haml_error'
|
6
|
+
require 'hamlit/parser/haml_util'
|
7
|
+
require 'hamlit/parser/haml_buffer'
|
8
|
+
require 'hamlit/parser/haml_compiler'
|
9
|
+
require 'hamlit/parser/haml_parser'
|
10
|
+
require 'hamlit/parser/haml_helpers'
|
11
|
+
require 'hamlit/parser/haml_options'
|
12
|
+
|
13
|
+
module Hamlit
|
14
|
+
class Parser
|
15
|
+
AVAILABLE_OPTIONS = %i[
|
16
|
+
autoclose
|
17
|
+
escape_html
|
18
|
+
escape_attrs
|
19
|
+
].freeze
|
20
|
+
|
21
|
+
def initialize(options = {})
|
22
|
+
@options = HamlOptions.defaults.dup
|
23
|
+
AVAILABLE_OPTIONS.each do |key|
|
24
|
+
@options[key] = options[key]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(template)
|
29
|
+
template = Hamlit::HamlUtil.check_haml_encoding(template) do |msg, line|
|
30
|
+
raise Hamlit::Error.new(msg, line)
|
31
|
+
end
|
32
|
+
HamlParser.new(template, HamlOptions.new(@options)).parse
|
33
|
+
rescue ::Hamlit::HamlError => e
|
34
|
+
error_with_lineno(e)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def error_with_lineno(error)
|
40
|
+
return error if error.line
|
41
|
+
|
42
|
+
trace = error.backtrace.first
|
43
|
+
return error unless trace
|
44
|
+
|
45
|
+
line = trace.match(/\d+\z/).to_s.to_i
|
46
|
+
HamlSyntaxError.new(error.message, line)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# lib/hamlit/parser/haml\_\*.rb
|
2
|
+
|
3
|
+
Hamlit::HamlFoo is originally Haml::Foo in haml gem.
|
4
|
+
|
5
|
+
This directory is NOT intended to be updated other than following Haml's changes.
|
6
|
+
|
7
|
+
## License
|
8
|
+
|
9
|
+
lib/hamlit/parser/haml\_\*.rb is:
|
10
|
+
|
11
|
+
Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum
|
12
|
+
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
14
|
+
a copy of this software and associated documentation files (the
|
15
|
+
"Software"), to deal in the Software without restriction, including
|
16
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
17
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
18
|
+
permit persons to whom the Software is furnished to do so, subject to
|
19
|
+
the following conditions:
|
20
|
+
|
21
|
+
The above copyright notice and this permission notice shall be
|
22
|
+
included in all copies or substantial portions of the Software.
|
23
|
+
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
25
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
26
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
27
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
28
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
29
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
30
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,348 @@
|
|
1
|
+
require 'hamlit/parser/haml_helpers'
|
2
|
+
require 'hamlit/parser/haml_util'
|
3
|
+
require 'hamlit/parser/haml_compiler'
|
4
|
+
|
5
|
+
module Hamlit
|
6
|
+
# This class is used only internally. It holds the buffer of HTML that
|
7
|
+
# is eventually output as the resulting document.
|
8
|
+
# It's called from within the precompiled code,
|
9
|
+
# and helps reduce the amount of processing done within `instance_eval`ed code.
|
10
|
+
class HamlBuffer
|
11
|
+
ID_KEY = 'id'.freeze
|
12
|
+
CLASS_KEY = 'class'.freeze
|
13
|
+
DATA_KEY = 'data'.freeze
|
14
|
+
|
15
|
+
include ::Hamlit::HamlHelpers
|
16
|
+
include ::Hamlit::HamlUtil
|
17
|
+
|
18
|
+
# The string that holds the compiled HTML. This is aliased as
|
19
|
+
# `_erbout` for compatibility with ERB-specific code.
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
attr_accessor :buffer
|
23
|
+
|
24
|
+
# The options hash passed in from {Haml::Engine}.
|
25
|
+
#
|
26
|
+
# @return [{String => Object}]
|
27
|
+
# @see Haml::Options#for_buffer
|
28
|
+
attr_accessor :options
|
29
|
+
|
30
|
+
# The {Buffer} for the enclosing Haml document.
|
31
|
+
# This is set for partials and similar sorts of nested templates.
|
32
|
+
# It's `nil` at the top level (see \{#toplevel?}).
|
33
|
+
#
|
34
|
+
# @return [Buffer]
|
35
|
+
attr_accessor :upper
|
36
|
+
|
37
|
+
# nil if there's no capture_haml block running,
|
38
|
+
# and the position at which it's beginning the capture if there is one.
|
39
|
+
#
|
40
|
+
# @return [Fixnum, nil]
|
41
|
+
attr_accessor :capture_position
|
42
|
+
|
43
|
+
# @return [Boolean]
|
44
|
+
# @see #active?
|
45
|
+
attr_writer :active
|
46
|
+
|
47
|
+
# @return [Boolean] Whether or not the format is XHTML
|
48
|
+
def xhtml?
|
49
|
+
not html?
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Boolean] Whether or not the format is any flavor of HTML
|
53
|
+
def html?
|
54
|
+
html4? or html5?
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Boolean] Whether or not the format is HTML4
|
58
|
+
def html4?
|
59
|
+
@options[:format] == :html4
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Boolean] Whether or not the format is HTML5.
|
63
|
+
def html5?
|
64
|
+
@options[:format] == :html5
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Boolean] Whether or not this buffer is a top-level template,
|
68
|
+
# as opposed to a nested partial
|
69
|
+
def toplevel?
|
70
|
+
upper.nil?
|
71
|
+
end
|
72
|
+
|
73
|
+
# Whether or not this buffer is currently being used to render a Haml template.
|
74
|
+
# Returns `false` if a subtemplate is being rendered,
|
75
|
+
# even if it's a subtemplate of this buffer's template.
|
76
|
+
#
|
77
|
+
# @return [Boolean]
|
78
|
+
def active?
|
79
|
+
@active
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Fixnum] The current indentation level of the document
|
83
|
+
def tabulation
|
84
|
+
@real_tabs + @tabulation
|
85
|
+
end
|
86
|
+
|
87
|
+
# Sets the current tabulation of the document.
|
88
|
+
#
|
89
|
+
# @param val [Fixnum] The new tabulation
|
90
|
+
def tabulation=(val)
|
91
|
+
val = val - @real_tabs
|
92
|
+
@tabulation = val > -1 ? val : 0
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param upper [Buffer] The parent buffer
|
96
|
+
# @param options [{Symbol => Object}] An options hash.
|
97
|
+
# See {Haml::Engine#options\_for\_buffer}
|
98
|
+
def initialize(upper = nil, options = {})
|
99
|
+
@active = true
|
100
|
+
@upper = upper
|
101
|
+
@options = options
|
102
|
+
@buffer = new_encoded_string
|
103
|
+
@tabulation = 0
|
104
|
+
|
105
|
+
# The number of tabs that Engine thinks we should have
|
106
|
+
# @real_tabs + @tabulation is the number of tabs actually output
|
107
|
+
@real_tabs = 0
|
108
|
+
end
|
109
|
+
|
110
|
+
# Appends text to the buffer, properly tabulated.
|
111
|
+
# Also modifies the document's indentation.
|
112
|
+
#
|
113
|
+
# @param text [String] The text to append
|
114
|
+
# @param tab_change [Fixnum] The number of tabs by which to increase
|
115
|
+
# or decrease the document's indentation
|
116
|
+
# @param dont_tab_up [Boolean] If true, don't indent the first line of `text`
|
117
|
+
def push_text(text, tab_change, dont_tab_up)
|
118
|
+
if @tabulation > 0
|
119
|
+
# Have to push every line in by the extra user set tabulation.
|
120
|
+
# Don't push lines with just whitespace, though,
|
121
|
+
# because that screws up precompiled indentation.
|
122
|
+
text.gsub!(/^(?!\s+$)/m, tabs)
|
123
|
+
text.sub!(tabs, '') if dont_tab_up
|
124
|
+
end
|
125
|
+
|
126
|
+
@real_tabs += tab_change
|
127
|
+
@buffer << text
|
128
|
+
end
|
129
|
+
|
130
|
+
# Modifies the indentation of the document.
|
131
|
+
#
|
132
|
+
# @param tab_change [Fixnum] The number of tabs by which to increase
|
133
|
+
# or decrease the document's indentation
|
134
|
+
def adjust_tabs(tab_change)
|
135
|
+
@real_tabs += tab_change
|
136
|
+
end
|
137
|
+
|
138
|
+
# the number of arguments here is insane, but passing in an options hash instead of named arguments
|
139
|
+
# causes a significant performance regression
|
140
|
+
def format_script(result, preserve_script, in_tag, preserve_tag, escape_html, nuke_inner_whitespace, interpolated, ugly)
|
141
|
+
result_name = escape_html ? html_escape(result.to_s) : result.to_s
|
142
|
+
|
143
|
+
if ugly
|
144
|
+
result = nuke_inner_whitespace ? result_name.strip : result_name
|
145
|
+
result = preserve(result, preserve_script, preserve_tag)
|
146
|
+
fix_textareas!(result) if toplevel? && result.include?('<textarea')
|
147
|
+
return result
|
148
|
+
end
|
149
|
+
|
150
|
+
# If we're interpolated,
|
151
|
+
# then the custom tabulation is handled in #push_text.
|
152
|
+
# The easiest way to avoid it here is to reset @tabulation.
|
153
|
+
if interpolated
|
154
|
+
old_tabulation = @tabulation
|
155
|
+
@tabulation = 0
|
156
|
+
end
|
157
|
+
|
158
|
+
in_tag_no_nuke = in_tag && !nuke_inner_whitespace
|
159
|
+
preserved_no_nuke = in_tag_no_nuke && preserve_tag
|
160
|
+
tabulation = !preserved_no_nuke && @real_tabs
|
161
|
+
|
162
|
+
result = nuke_inner_whitespace ? result_name.strip : result_name.rstrip
|
163
|
+
result = preserve(result, preserve_script, preserve_tag)
|
164
|
+
|
165
|
+
has_newline = !preserved_no_nuke && result.include?("\n")
|
166
|
+
|
167
|
+
if in_tag_no_nuke && (preserve_tag || !has_newline)
|
168
|
+
@real_tabs -= 1
|
169
|
+
@tabulation = old_tabulation if interpolated
|
170
|
+
return result
|
171
|
+
end
|
172
|
+
|
173
|
+
unless preserved_no_nuke
|
174
|
+
# Precompiled tabulation may be wrong
|
175
|
+
result = "#{tabs}#{result}" if !interpolated && !in_tag && @tabulation > 0
|
176
|
+
|
177
|
+
if has_newline
|
178
|
+
result.gsub! "\n", "\n#{tabs(tabulation)}"
|
179
|
+
|
180
|
+
# Add tabulation if it wasn't precompiled
|
181
|
+
result = "#{tabs(tabulation)}#{result}" if in_tag_no_nuke
|
182
|
+
end
|
183
|
+
|
184
|
+
fix_textareas!(result) if toplevel? && result.include?('<textarea')
|
185
|
+
|
186
|
+
if in_tag_no_nuke
|
187
|
+
result = "\n#{result}\n#{tabs(tabulation-1)}"
|
188
|
+
@real_tabs -= 1
|
189
|
+
end
|
190
|
+
@tabulation = old_tabulation if interpolated
|
191
|
+
result
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def attributes(class_id, obj_ref, *attributes_hashes)
|
196
|
+
attributes = class_id
|
197
|
+
attributes_hashes.each do |old|
|
198
|
+
self.class.merge_attrs(attributes, Hash[old.map {|k, v| [k.to_s, v]}])
|
199
|
+
end
|
200
|
+
self.class.merge_attrs(attributes, parse_object_ref(obj_ref)) if obj_ref
|
201
|
+
::Hamlit::HamlCompiler.build_attributes(
|
202
|
+
html?, @options[:attr_wrapper], @options[:escape_attrs], @options[:hyphenate_data_attrs], attributes)
|
203
|
+
end
|
204
|
+
|
205
|
+
# Remove the whitespace from the right side of the buffer string.
|
206
|
+
# Doesn't do anything if we're at the beginning of a capture_haml block.
|
207
|
+
def rstrip!
|
208
|
+
if capture_position.nil?
|
209
|
+
buffer.rstrip!
|
210
|
+
return
|
211
|
+
end
|
212
|
+
|
213
|
+
buffer << buffer.slice!(capture_position..-1).rstrip
|
214
|
+
end
|
215
|
+
|
216
|
+
# Merges two attribute hashes.
|
217
|
+
# This is the same as `to.merge!(from)`,
|
218
|
+
# except that it merges id, class, and data attributes.
|
219
|
+
#
|
220
|
+
# ids are concatenated with `"_"`,
|
221
|
+
# and classes are concatenated with `" "`.
|
222
|
+
# data hashes are simply merged.
|
223
|
+
#
|
224
|
+
# Destructively modifies both `to` and `from`.
|
225
|
+
#
|
226
|
+
# @param to [{String => String}] The attribute hash to merge into
|
227
|
+
# @param from [{String => #to_s}] The attribute hash to merge from
|
228
|
+
# @return [{String => String}] `to`, after being merged
|
229
|
+
def self.merge_attrs(to, from)
|
230
|
+
from[ID_KEY] = ::Hamlit::HamlCompiler.filter_and_join(from[ID_KEY], '_') if from[ID_KEY]
|
231
|
+
if to[ID_KEY] && from[ID_KEY]
|
232
|
+
to[ID_KEY] << "_#{from.delete(ID_KEY)}"
|
233
|
+
elsif to[ID_KEY] || from[ID_KEY]
|
234
|
+
from[ID_KEY] ||= to[ID_KEY]
|
235
|
+
end
|
236
|
+
|
237
|
+
from[CLASS_KEY] = ::Hamlit::HamlCompiler.filter_and_join(from[CLASS_KEY], ' ') if from[CLASS_KEY]
|
238
|
+
if to[CLASS_KEY] && from[CLASS_KEY]
|
239
|
+
# Make sure we don't duplicate class names
|
240
|
+
from[CLASS_KEY] = (from[CLASS_KEY].to_s.split(' ') | to[CLASS_KEY].split(' ')).sort.join(' ')
|
241
|
+
elsif to[CLASS_KEY] || from[CLASS_KEY]
|
242
|
+
from[CLASS_KEY] ||= to[CLASS_KEY]
|
243
|
+
end
|
244
|
+
|
245
|
+
from.keys.each do |key|
|
246
|
+
next unless from[key].kind_of?(Hash) || to[key].kind_of?(Hash)
|
247
|
+
|
248
|
+
from_data = from.delete(key)
|
249
|
+
# forces to_data & from_data into a hash
|
250
|
+
from_data = { nil => from_data } if from_data && !from_data.is_a?(Hash)
|
251
|
+
to[key] = { nil => to[key] } if to[key] && !to[key].is_a?(Hash)
|
252
|
+
|
253
|
+
if from_data && !to[key]
|
254
|
+
to[key] = from_data
|
255
|
+
elsif from_data && to[key]
|
256
|
+
to[key].merge! from_data
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
to.merge!(from)
|
261
|
+
end
|
262
|
+
|
263
|
+
private
|
264
|
+
|
265
|
+
def preserve(result, preserve_script, preserve_tag)
|
266
|
+
return ::Hamlit::HamlHelpers.preserve(result) if preserve_tag
|
267
|
+
return ::Hamlit::HamlHelpers.find_and_preserve(result, options[:preserve]) if preserve_script
|
268
|
+
result
|
269
|
+
end
|
270
|
+
|
271
|
+
# Works like #{find_and_preserve}, but allows the first newline after a
|
272
|
+
# preserved opening tag to remain unencoded, and then outdents the content.
|
273
|
+
# This change was motivated primarily by the change in Rails 3.2.3 to emit
|
274
|
+
# a newline after textarea helpers.
|
275
|
+
#
|
276
|
+
# @param input [String] The text to process
|
277
|
+
# @since Haml 4.0.1
|
278
|
+
# @private
|
279
|
+
def fix_textareas!(input)
|
280
|
+
pattern = /<(textarea)([^>]*)>(\n|
)(.*?)<\/textarea>/im
|
281
|
+
input.gsub!(pattern) do |s|
|
282
|
+
match = pattern.match(s)
|
283
|
+
content = match[4]
|
284
|
+
if match[3] == '
'
|
285
|
+
content.sub!(/\A /, ' ')
|
286
|
+
else
|
287
|
+
content.sub!(/\A[ ]*/, '')
|
288
|
+
end
|
289
|
+
"<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def new_encoded_string
|
294
|
+
"".encode(Encoding.find(options[:encoding]))
|
295
|
+
end
|
296
|
+
|
297
|
+
@@tab_cache = {}
|
298
|
+
# Gets `count` tabs. Mostly for internal use.
|
299
|
+
def tabs(count = 0)
|
300
|
+
tabs = [count + @tabulation, 0].max
|
301
|
+
@@tab_cache[tabs] ||= ' ' * tabs
|
302
|
+
end
|
303
|
+
|
304
|
+
# Takes an array of objects and uses the class and id of the first
|
305
|
+
# one to create an attributes hash.
|
306
|
+
# The second object, if present, is used as a prefix,
|
307
|
+
# just like you can do with `dom_id()` and `dom_class()` in Rails
|
308
|
+
def parse_object_ref(ref)
|
309
|
+
prefix = ref[1]
|
310
|
+
ref = ref[0]
|
311
|
+
# Let's make sure the value isn't nil. If it is, return the default Hash.
|
312
|
+
return {} if ref.nil?
|
313
|
+
class_name =
|
314
|
+
if ref.respond_to?(:haml_object_ref)
|
315
|
+
ref.haml_object_ref
|
316
|
+
else
|
317
|
+
underscore(ref.class)
|
318
|
+
end
|
319
|
+
ref_id =
|
320
|
+
if ref.respond_to?(:to_key)
|
321
|
+
key = ref.to_key
|
322
|
+
key.join('_') unless key.nil?
|
323
|
+
else
|
324
|
+
ref.id
|
325
|
+
end
|
326
|
+
id = "#{class_name}_#{ref_id || 'new'}"
|
327
|
+
if prefix
|
328
|
+
class_name = "#{ prefix }_#{ class_name}"
|
329
|
+
id = "#{ prefix }_#{ id }"
|
330
|
+
end
|
331
|
+
|
332
|
+
{ID_KEY => id, CLASS_KEY => class_name}
|
333
|
+
end
|
334
|
+
|
335
|
+
# Changes a word from camel case to underscores.
|
336
|
+
# Based on the method of the same name in Rails' Inflector,
|
337
|
+
# but copied here so it'll run properly without Rails.
|
338
|
+
def underscore(camel_cased_word)
|
339
|
+
word = camel_cased_word.to_s.dup
|
340
|
+
word.gsub!(/::/, '_')
|
341
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
342
|
+
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
343
|
+
word.tr!('-', '_')
|
344
|
+
word.downcase!
|
345
|
+
word
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|