haml 4.0.0 → 5.0.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 +7 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +117 -5
- data/FAQ.md +7 -17
- data/MIT-LICENSE +1 -1
- data/README.md +85 -42
- data/REFERENCE.md +181 -86
- data/Rakefile +47 -51
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +215 -0
- data/lib/haml/attribute_parser.rb +144 -0
- data/lib/haml/buffer.rb +38 -128
- data/lib/haml/compiler.rb +88 -295
- data/lib/haml/engine.rb +25 -41
- data/lib/haml/error.rb +3 -0
- data/lib/haml/escapable.rb +49 -0
- data/lib/haml/exec.rb +33 -19
- data/lib/haml/filters.rb +20 -24
- data/lib/haml/generator.rb +41 -0
- data/lib/haml/helpers/action_view_extensions.rb +3 -2
- data/lib/haml/helpers/action_view_mods.rb +44 -66
- data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
- data/lib/haml/helpers/safe_erubi_template.rb +27 -0
- data/lib/haml/helpers/safe_erubis_template.rb +16 -4
- data/lib/haml/helpers/xss_mods.rb +18 -12
- data/lib/haml/helpers.rb +122 -58
- data/lib/haml/options.rb +39 -46
- data/lib/haml/parser.rb +278 -217
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +21 -11
- data/lib/haml/sass_rails_filter.rb +17 -4
- data/lib/haml/template/options.rb +12 -2
- data/lib/haml/template.rb +12 -6
- data/lib/haml/temple_engine.rb +120 -0
- data/lib/haml/temple_line_counter.rb +29 -0
- data/lib/haml/util.rb +80 -199
- data/lib/haml/version.rb +2 -1
- data/lib/haml.rb +2 -1
- data/test/attribute_parser_test.rb +101 -0
- data/test/engine_test.rb +306 -176
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +11 -0
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +87 -0
- data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
- data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
- data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
- data/test/helper_test.rb +282 -96
- data/test/options_test.rb +22 -0
- data/test/parser_test.rb +71 -4
- data/test/results/bemit.xhtml +4 -0
- data/test/results/eval_suppressed.xhtml +4 -4
- data/test/results/helpers.xhtml +43 -41
- data/test/results/helpful.xhtml +6 -3
- data/test/results/just_stuff.xhtml +21 -20
- data/test/results/list.xhtml +9 -9
- data/test/results/nuke_inner_whitespace.xhtml +22 -22
- data/test/results/nuke_outer_whitespace.xhtml +84 -92
- data/test/results/original_engine.xhtml +17 -17
- data/test/results/partial_layout.xhtml +4 -3
- data/test/results/partial_layout_erb.xhtml +4 -3
- data/test/results/partials.xhtml +11 -10
- data/test/results/silent_script.xhtml +63 -63
- data/test/results/standard.xhtml +156 -159
- data/test/results/tag_parsing.xhtml +19 -19
- data/test/results/very_basic.xhtml +2 -2
- data/test/results/whitespace_handling.xhtml +56 -50
- data/test/template_test.rb +44 -53
- data/test/template_test_helper.rb +38 -0
- data/test/templates/_text_area_helper.html.haml +4 -0
- data/test/templates/bemit.haml +3 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/partial_layout_erb.erb +1 -1
- data/test/templates/standard_ugly.haml +1 -0
- data/test/templates/with_bom.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +26 -12
- data/test/util_test.rb +6 -47
- metadata +88 -106
- data/lib/haml/helpers/rails_323_textarea_fix.rb +0 -24
- data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
- data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
- data/test/gemfiles/Gemfile.rails-master +0 -4
- data/test/templates/_av_partial_1_ugly.haml +0 -9
- data/test/templates/_av_partial_2_ugly.haml +0 -5
- data/test/templates/action_view_ugly.haml +0 -47
- data/test/templates/standard_ugly.haml +0 -43
@@ -1,31 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Haml
|
2
3
|
|
3
4
|
# This module makes Haml work with Rails using the template handler API.
|
4
|
-
class Plugin
|
5
|
-
|
6
|
-
# Rails 3.1+, template handlers don't inherit from anything. In <= 3.0, they
|
7
|
-
# do. To avoid messy logic figuring this out, we just inherit from whatever
|
8
|
-
# the ERB handler does.
|
9
|
-
|
10
|
-
# In Rails 3.1+, we don't need to include Compilable.
|
11
|
-
if (ActionPack::VERSION::MAJOR == 3) && (ActionPack::VERSION::MINOR < 1)
|
12
|
-
include ActionView::Template::Handlers::Compilable
|
13
|
-
end
|
14
|
-
|
5
|
+
class Plugin
|
15
6
|
def handles_encoding?; true; end
|
16
7
|
|
17
8
|
def compile(template)
|
18
9
|
options = Haml::Template.options.dup
|
19
|
-
if
|
10
|
+
if template.respond_to?(:type)
|
20
11
|
options[:mime_type] = template.type
|
21
12
|
elsif template.respond_to? :mime_type
|
22
13
|
options[:mime_type] = template.mime_type
|
23
14
|
end
|
24
15
|
options[:filename] = template.identifier
|
25
|
-
Haml::Engine.new(template.source, options).compiler.precompiled_with_ambles(
|
16
|
+
Haml::Engine.new(template.source, options).compiler.precompiled_with_ambles(
|
17
|
+
[],
|
18
|
+
after_preamble: '@output_buffer = output_buffer ||= ActionView::OutputBuffer.new if defined?(ActionView::OutputBuffer)',
|
19
|
+
)
|
26
20
|
end
|
27
21
|
|
28
|
-
# In Rails 3.1+, #call takes the place of #compile
|
29
22
|
def self.call(template)
|
30
23
|
new.compile(template)
|
31
24
|
end
|
@@ -38,4 +31,4 @@ module Haml
|
|
38
31
|
end
|
39
32
|
end
|
40
33
|
|
41
|
-
ActionView::Template.register_template_handler(:haml, Haml::Plugin)
|
34
|
+
ActionView::Template.register_template_handler(:haml, Haml::Plugin)
|
data/lib/haml/railtie.rb
CHANGED
@@ -1,21 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'haml/template/options'
|
3
|
+
|
4
|
+
# check for a compatible Rails version when Haml is loaded
|
5
|
+
if (activesupport_spec = Gem.loaded_specs['activesupport'])
|
6
|
+
if activesupport_spec.version.to_s < '3.2'
|
7
|
+
raise Exception.new("\n\n** Haml now requires Rails 3.2 and later. Use Haml version 4.0.4\n\n")
|
7
8
|
end
|
8
9
|
end
|
9
10
|
|
10
11
|
module Haml
|
11
12
|
class Railtie < ::Rails::Railtie
|
12
13
|
initializer :haml do |app|
|
13
|
-
|
14
|
-
require "haml/
|
14
|
+
ActiveSupport.on_load(:action_view) do
|
15
|
+
require "haml/template"
|
16
|
+
|
17
|
+
if defined?(::Sass::Rails::SassTemplate) && app.config.assets.enabled
|
18
|
+
require "haml/sass_rails_filter"
|
19
|
+
end
|
20
|
+
|
21
|
+
if defined? Erubi
|
22
|
+
require "haml/helpers/safe_erubi_template"
|
23
|
+
Haml::Filters::Erb.template_class = Haml::SafeErubiTemplate
|
24
|
+
else
|
25
|
+
require "haml/helpers/safe_erubis_template"
|
26
|
+
Haml::Filters::Erb.template_class = Haml::SafeErubisTemplate
|
27
|
+
end
|
15
28
|
end
|
16
29
|
end
|
17
30
|
end
|
18
31
|
end
|
19
|
-
|
20
|
-
require "haml/helpers/safe_erubis_template"
|
21
|
-
Haml::Filters::Erb.template_class = Haml::SafeErubisTemplate
|
@@ -1,11 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Haml
|
2
3
|
module Filters
|
3
4
|
# This is an extension of Sass::Rails's SassTemplate class that allows
|
4
5
|
# Rails's asset helpers to be used inside Haml Sass filter.
|
5
6
|
class SassRailsTemplate < ::Sass::Rails::SassTemplate
|
6
|
-
|
7
|
-
scope
|
8
|
-
|
7
|
+
if Gem::Version.new(Sprockets::VERSION) >= Gem::Version.new('3.0.0')
|
8
|
+
def render(scope=Object.new, locals={}, &block)
|
9
|
+
environment = ::Sprockets::Railtie.build_environment(Rails.application)
|
10
|
+
scope = environment.context_class.new(
|
11
|
+
environment: environment,
|
12
|
+
filename: "/",
|
13
|
+
metadata: {}
|
14
|
+
)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
else
|
18
|
+
def render(scope=Object.new, locals={}, &block)
|
19
|
+
scope = ::Rails.application.assets.context_class.new(::Rails.application.assets, "/", "/")
|
20
|
+
super
|
21
|
+
end
|
9
22
|
end
|
10
23
|
|
11
24
|
def sass_options(scope)
|
@@ -30,4 +43,4 @@ module Haml
|
|
30
43
|
register_tilt_filter "Sass", :extend => "Css", :template_class => SassRailsTemplate
|
31
44
|
register_tilt_filter "Scss", :extend => "Css", :template_class => ScssRailsTemplate
|
32
45
|
end
|
33
|
-
end
|
46
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# We keep options in its own self-contained file
|
2
3
|
# so that we can load it independently in Rails 3,
|
3
4
|
# where the full template stuff is lazy-loaded.
|
@@ -6,11 +7,20 @@ module Haml
|
|
6
7
|
module Template
|
7
8
|
extend self
|
8
9
|
|
9
|
-
|
10
|
+
class Options < Hash
|
11
|
+
def []=(key, value)
|
12
|
+
super
|
13
|
+
if Haml::Options.buffer_defaults.key?(key)
|
14
|
+
Haml::Options.buffer_defaults[key] = value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
@options = ::Haml::Template::Options.new
|
10
20
|
# The options hash for Haml when used within Rails.
|
11
21
|
# See {file:REFERENCE.md#options the Haml options documentation}.
|
12
22
|
#
|
13
|
-
# @return [
|
23
|
+
# @return [Haml::Template::Options<Symbol => Object>]
|
14
24
|
attr_accessor :options
|
15
25
|
end
|
16
26
|
end
|
data/lib/haml/template.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'haml/template/options'
|
2
|
-
|
3
|
-
|
4
|
-
require 'haml/helpers/
|
3
|
+
if defined?(ActiveSupport)
|
4
|
+
ActiveSupport.on_load(:action_view) do
|
5
|
+
require 'haml/helpers/action_view_mods'
|
6
|
+
require 'haml/helpers/action_view_extensions'
|
7
|
+
end
|
8
|
+
else
|
9
|
+
require 'haml/helpers/action_view_mods'
|
10
|
+
require 'haml/helpers/action_view_extensions'
|
11
|
+
end
|
5
12
|
require 'haml/helpers/xss_mods'
|
6
13
|
require 'haml/helpers/action_view_xss_mods'
|
7
14
|
|
8
15
|
module Haml
|
9
|
-
class
|
16
|
+
class TempleEngine
|
10
17
|
def precompiled_method_return_value_with_haml_xss
|
11
18
|
"::Haml::Util.html_safe(#{precompiled_method_return_value_without_haml_xss})"
|
12
19
|
end
|
@@ -26,7 +33,6 @@ module Haml
|
|
26
33
|
end
|
27
34
|
|
28
35
|
|
29
|
-
Haml::Template.options[:ugly] = !Rails.env.development?
|
30
36
|
Haml::Template.options[:escape_html] = true
|
31
37
|
|
32
|
-
require 'haml/
|
38
|
+
require 'haml/plugin'
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require 'temple'
|
3
|
+
require 'haml/escapable'
|
4
|
+
require 'haml/generator'
|
5
|
+
|
6
|
+
module Haml
|
7
|
+
class TempleEngine < Temple::Engine
|
8
|
+
define_options(
|
9
|
+
attr_wrapper: "'",
|
10
|
+
autoclose: %w(area base basefont br col command embed frame
|
11
|
+
hr img input isindex keygen link menuitem meta
|
12
|
+
param source track wbr),
|
13
|
+
encoding: nil,
|
14
|
+
escape_attrs: true,
|
15
|
+
escape_html: false,
|
16
|
+
filename: '(haml)',
|
17
|
+
format: :html5,
|
18
|
+
hyphenate_data_attrs: true,
|
19
|
+
line: 1,
|
20
|
+
mime_type: 'text/html',
|
21
|
+
preserve: %w(textarea pre code),
|
22
|
+
remove_whitespace: false,
|
23
|
+
suppress_eval: false,
|
24
|
+
cdata: false,
|
25
|
+
parser_class: ::Haml::Parser,
|
26
|
+
compiler_class: ::Haml::Compiler,
|
27
|
+
trace: false,
|
28
|
+
)
|
29
|
+
|
30
|
+
use :Parser, -> { options[:parser_class] }
|
31
|
+
use :Compiler, -> { options[:compiler_class] }
|
32
|
+
use Escapable
|
33
|
+
filter :ControlFlow
|
34
|
+
filter :MultiFlattener
|
35
|
+
filter :StaticMerger
|
36
|
+
use Generator
|
37
|
+
|
38
|
+
def compile(template)
|
39
|
+
initialize_encoding(template, options[:encoding])
|
40
|
+
@precompiled = call(template)
|
41
|
+
end
|
42
|
+
|
43
|
+
# The source code that is evaluated to produce the Haml document.
|
44
|
+
#
|
45
|
+
# This is automatically converted to the correct encoding
|
46
|
+
# (see {file:REFERENCE.md#encodings the `:encoding` option}).
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
def precompiled
|
50
|
+
encoding = Encoding.find(@encoding || '')
|
51
|
+
return @precompiled.force_encoding(encoding) if encoding == Encoding::ASCII_8BIT
|
52
|
+
return @precompiled.encode(encoding)
|
53
|
+
end
|
54
|
+
|
55
|
+
def precompiled_with_return_value
|
56
|
+
"#{precompiled};#{precompiled_method_return_value}"
|
57
|
+
end
|
58
|
+
|
59
|
+
# The source code that is evaluated to produce the Haml document.
|
60
|
+
#
|
61
|
+
# This is automatically converted to the correct encoding
|
62
|
+
# (see {file:REFERENCE.md#encodings the `:encoding` option}).
|
63
|
+
#
|
64
|
+
# @return [String]
|
65
|
+
def precompiled_with_ambles(local_names, after_preamble: '')
|
66
|
+
preamble = <<END.tr!("\n", ';')
|
67
|
+
begin
|
68
|
+
extend Haml::Helpers
|
69
|
+
_hamlout = @haml_buffer = Haml::Buffer.new(haml_buffer, #{Options.new(options).for_buffer.inspect})
|
70
|
+
_erbout = _hamlout.buffer
|
71
|
+
#{after_preamble}
|
72
|
+
END
|
73
|
+
postamble = <<END.tr!("\n", ';')
|
74
|
+
#{precompiled_method_return_value}
|
75
|
+
ensure
|
76
|
+
@haml_buffer = @haml_buffer.upper if @haml_buffer
|
77
|
+
end
|
78
|
+
END
|
79
|
+
"#{preamble}#{locals_code(local_names)}#{precompiled}#{postamble}"
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def initialize_encoding(template, given_value)
|
85
|
+
if given_value
|
86
|
+
@encoding = given_value
|
87
|
+
else
|
88
|
+
@encoding = Encoding.default_internal || template.encoding
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the string used as the return value of the precompiled method.
|
93
|
+
# This method exists so it can be monkeypatched to return modified values.
|
94
|
+
def precompiled_method_return_value
|
95
|
+
"_erbout"
|
96
|
+
end
|
97
|
+
|
98
|
+
def locals_code(names)
|
99
|
+
names = names.keys if Hash === names
|
100
|
+
|
101
|
+
names.each_with_object('') do |name, code|
|
102
|
+
# Can't use || because someone might explicitly pass in false with a symbol
|
103
|
+
sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]"
|
104
|
+
str_local = "_haml_locals[#{inspect_obj(name.to_s)}]"
|
105
|
+
code << "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local};"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def inspect_obj(obj)
|
110
|
+
case obj
|
111
|
+
when String
|
112
|
+
%Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"!
|
113
|
+
when Symbol
|
114
|
+
":#{inspect_obj(obj.to_s)}"
|
115
|
+
else
|
116
|
+
obj.inspect
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Haml
|
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
|
+
else
|
25
|
+
raise UnexpectedExpression.new("[HAML BUG] Unexpected Temple expression '#{type}' is given!")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|