haml 5.2.1 → 6.0.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/test.yml +40 -0
  4. data/.gitignore +16 -16
  5. data/CHANGELOG.md +19 -0
  6. data/Gemfile +18 -11
  7. data/MIT-LICENSE +1 -1
  8. data/REFERENCE.md +10 -3
  9. data/Rakefile +94 -93
  10. data/bin/bench +66 -0
  11. data/bin/console +11 -0
  12. data/bin/ruby +3 -0
  13. data/bin/setup +7 -0
  14. data/bin/stackprof +27 -0
  15. data/bin/test +24 -0
  16. data/exe/haml +6 -0
  17. data/ext/haml/extconf.rb +10 -0
  18. data/ext/haml/haml.c +537 -0
  19. data/ext/haml/hescape.c +108 -0
  20. data/ext/haml/hescape.h +20 -0
  21. data/haml.gemspec +39 -37
  22. data/lib/haml/ambles.rb +20 -0
  23. data/lib/haml/attribute_builder.rb +140 -129
  24. data/lib/haml/attribute_compiler.rb +85 -192
  25. data/lib/haml/attribute_parser.rb +86 -126
  26. data/lib/haml/cli.rb +154 -0
  27. data/lib/haml/compiler/children_compiler.rb +126 -0
  28. data/lib/haml/compiler/comment_compiler.rb +39 -0
  29. data/lib/haml/compiler/doctype_compiler.rb +46 -0
  30. data/lib/haml/compiler/script_compiler.rb +116 -0
  31. data/lib/haml/compiler/silent_script_compiler.rb +24 -0
  32. data/lib/haml/compiler/tag_compiler.rb +76 -0
  33. data/lib/haml/compiler.rb +63 -296
  34. data/lib/haml/dynamic_merger.rb +67 -0
  35. data/lib/haml/engine.rb +42 -227
  36. data/lib/haml/error.rb +5 -4
  37. data/lib/haml/escapable.rb +6 -70
  38. data/lib/haml/filters/base.rb +12 -0
  39. data/lib/haml/filters/cdata.rb +20 -0
  40. data/lib/haml/filters/coffee.rb +17 -0
  41. data/lib/haml/filters/css.rb +33 -0
  42. data/lib/haml/filters/erb.rb +10 -0
  43. data/lib/haml/filters/escaped.rb +22 -0
  44. data/lib/haml/filters/javascript.rb +33 -0
  45. data/lib/haml/filters/less.rb +20 -0
  46. data/lib/haml/filters/markdown.rb +11 -0
  47. data/lib/haml/filters/plain.rb +29 -0
  48. data/lib/haml/filters/preserve.rb +22 -0
  49. data/lib/haml/filters/ruby.rb +10 -0
  50. data/lib/haml/filters/sass.rb +15 -0
  51. data/lib/haml/filters/scss.rb +15 -0
  52. data/lib/haml/filters/text_base.rb +25 -0
  53. data/lib/haml/filters/tilt_base.rb +49 -0
  54. data/lib/haml/filters.rb +54 -378
  55. data/lib/haml/force_escapable.rb +29 -0
  56. data/lib/haml/helpers.rb +3 -697
  57. data/lib/haml/html.rb +22 -0
  58. data/lib/haml/identity.rb +13 -0
  59. data/lib/haml/object_ref.rb +30 -0
  60. data/lib/haml/parser.rb +157 -22
  61. data/lib/haml/rails_helpers.rb +51 -0
  62. data/lib/haml/rails_template.rb +55 -0
  63. data/lib/haml/railtie.rb +7 -40
  64. data/lib/haml/ruby_expression.rb +32 -0
  65. data/lib/haml/string_splitter.rb +20 -0
  66. data/lib/haml/template.rb +15 -34
  67. data/lib/haml/temple_line_counter.rb +2 -1
  68. data/lib/haml/util.rb +17 -15
  69. data/lib/haml/version.rb +1 -2
  70. data/lib/haml.rb +8 -20
  71. metadata +211 -58
  72. data/.gitmodules +0 -3
  73. data/.travis.yml +0 -111
  74. data/.yardopts +0 -22
  75. data/TODO +0 -24
  76. data/benchmark.rb +0 -70
  77. data/bin/haml +0 -9
  78. data/lib/haml/.gitattributes +0 -1
  79. data/lib/haml/buffer.rb +0 -238
  80. data/lib/haml/exec.rb +0 -347
  81. data/lib/haml/generator.rb +0 -42
  82. data/lib/haml/helpers/action_view_extensions.rb +0 -60
  83. data/lib/haml/helpers/action_view_mods.rb +0 -132
  84. data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
  85. data/lib/haml/helpers/safe_erubi_template.rb +0 -20
  86. data/lib/haml/helpers/safe_erubis_template.rb +0 -33
  87. data/lib/haml/helpers/xss_mods.rb +0 -114
  88. data/lib/haml/options.rb +0 -273
  89. data/lib/haml/plugin.rb +0 -37
  90. data/lib/haml/sass_rails_filter.rb +0 -47
  91. data/lib/haml/template/options.rb +0 -27
  92. data/lib/haml/temple_engine.rb +0 -123
  93. data/yard/default/.gitignore +0 -1
  94. data/yard/default/fulldoc/html/css/common.sass +0 -15
  95. data/yard/default/layout/html/footer.erb +0 -12
data/benchmark.rb DELETED
@@ -1,70 +0,0 @@
1
- require "bundler/setup"
2
- require "haml"
3
- require "rbench"
4
-
5
- times = (ARGV.first || 1000).to_i
6
-
7
- if times == 0 # Invalid parameter
8
- puts <<END
9
- ruby #$0 [times=1000]
10
- Benchmark Haml against various other templating languages.
11
- END
12
- exit 1
13
- end
14
-
15
- %w[erb erubi rails active_support action_controller
16
- action_view action_pack haml/template rbench].each {|dep| require(dep)}
17
-
18
- def view
19
- base = ActionView::Base.new
20
- base.view_paths << File.join(File.dirname(__FILE__), '/test')
21
- base
22
- end
23
-
24
- def render(view, file)
25
- view.render :file => file
26
- end
27
-
28
- RBench.run(times) do
29
- column :haml, :title => "Haml"
30
- column :erb, :title => "ERB"
31
- column :erubi, :title => "Erubi"
32
-
33
- template_name = 'standard'
34
- haml_template = File.read("#{File.dirname(__FILE__)}/test/templates/#{template_name}.haml")
35
- erb_template = File.read("#{File.dirname(__FILE__)}/test/erb/#{template_name}.erb")
36
-
37
- report "Cached" do
38
- obj = Object.new
39
-
40
- Haml::Engine.new(haml_template).def_method(obj, :haml)
41
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
42
- obj.instance_eval("def erb; #{ERB.new(erb_template, trim_mode: '-').src}; end")
43
- else
44
- obj.instance_eval("def erb; #{ERB.new(erb_template, nil, '-').src}; end")
45
- end
46
- obj.instance_eval("def erubi; #{Erubi::Engine.new(erb_template).src}; end")
47
-
48
- haml { obj.haml }
49
- erb { obj.erb }
50
- erubi { obj.erubi }
51
- end
52
-
53
- report "ActionView" do
54
- # To cache the template
55
- render view, 'templates/standard'
56
- render view, 'erb/standard'
57
-
58
- haml { render view, 'templates/standard' }
59
- erubi { render view, 'erb/standard' }
60
- end
61
-
62
- report "ActionView with deep partials" do
63
- # To cache the template
64
- render view, 'templates/action_view'
65
- render view, 'erb/action_view'
66
-
67
- haml { render view, 'templates/action_view' }
68
- erubi { render view, 'erb/action_view' }
69
- end
70
- end
data/bin/haml DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # The command line Haml parser.
3
-
4
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
5
- require 'haml'
6
- require 'haml/exec'
7
-
8
- opts = Haml::Exec::Haml.new(ARGV)
9
- opts.parse!
@@ -1 +0,0 @@
1
- version.rb merge=ours
data/lib/haml/buffer.rb DELETED
@@ -1,238 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Haml
4
- # This class is used only internally. It holds the buffer of HTML that
5
- # is eventually output as the resulting document.
6
- # It's called from within the precompiled code,
7
- # and helps reduce the amount of processing done within `instance_eval`ed code.
8
- class Buffer
9
- include Haml::Helpers
10
- include Haml::Util
11
-
12
- # The string that holds the compiled HTML. This is aliased as
13
- # `_erbout` for compatibility with ERB-specific code.
14
- #
15
- # @return [String]
16
- attr_accessor :buffer
17
-
18
- # The options hash passed in from {Haml::Engine}.
19
- #
20
- # @return [{String => Object}]
21
- # @see Haml::Options#for_buffer
22
- attr_accessor :options
23
-
24
- # The {Buffer} for the enclosing Haml document.
25
- # This is set for partials and similar sorts of nested templates.
26
- # It's `nil` at the top level (see \{#toplevel?}).
27
- #
28
- # @return [Buffer]
29
- attr_accessor :upper
30
-
31
- # nil if there's no capture_haml block running,
32
- # and the position at which it's beginning the capture if there is one.
33
- #
34
- # @return [Fixnum, nil]
35
- attr_accessor :capture_position
36
-
37
- # @return [Boolean]
38
- # @see #active?
39
- attr_writer :active
40
-
41
- # @return [Boolean] Whether or not the format is XHTML
42
- def xhtml?
43
- not html?
44
- end
45
-
46
- # @return [Boolean] Whether or not the format is any flavor of HTML
47
- def html?
48
- html4? or html5?
49
- end
50
-
51
- # @return [Boolean] Whether or not the format is HTML4
52
- def html4?
53
- @options[:format] == :html4
54
- end
55
-
56
- # @return [Boolean] Whether or not the format is HTML5.
57
- def html5?
58
- @options[:format] == :html5
59
- end
60
-
61
- # @return [Boolean] Whether or not this buffer is a top-level template,
62
- # as opposed to a nested partial
63
- def toplevel?
64
- upper.nil?
65
- end
66
-
67
- # Whether or not this buffer is currently being used to render a Haml template.
68
- # Returns `false` if a subtemplate is being rendered,
69
- # even if it's a subtemplate of this buffer's template.
70
- #
71
- # @return [Boolean]
72
- def active?
73
- @active
74
- end
75
-
76
- # @return [Fixnum] The current indentation level of the document
77
- def tabulation
78
- @real_tabs + @tabulation
79
- end
80
-
81
- # Sets the current tabulation of the document.
82
- #
83
- # @param val [Fixnum] The new tabulation
84
- def tabulation=(val)
85
- val = val - @real_tabs
86
- @tabulation = val > -1 ? val : 0
87
- end
88
-
89
- # @param upper [Buffer] The parent buffer
90
- # @param options [{Symbol => Object}] An options hash.
91
- # See {Haml::Engine#options\_for\_buffer}
92
- def initialize(upper = nil, options = {})
93
- @active = true
94
- @upper = upper
95
- @options = Options.buffer_defaults
96
- @options = @options.merge(options) unless options.empty?
97
- @buffer = new_encoded_string
98
- @tabulation = 0
99
-
100
- # The number of tabs that Engine thinks we should have
101
- # @real_tabs + @tabulation is the number of tabs actually output
102
- @real_tabs = 0
103
- end
104
-
105
- # Appends text to the buffer, properly tabulated.
106
- # Also modifies the document's indentation.
107
- #
108
- # @param text [String] The text to append
109
- # @param tab_change [Fixnum] The number of tabs by which to increase
110
- # or decrease the document's indentation
111
- # @param dont_tab_up [Boolean] If true, don't indent the first line of `text`
112
- def push_text(text, tab_change, dont_tab_up)
113
- if @tabulation > 0
114
- # Have to push every line in by the extra user set tabulation.
115
- # Don't push lines with just whitespace, though,
116
- # because that screws up precompiled indentation.
117
- text.gsub!(/^(?!\s+$)/m, tabs)
118
- text.sub!(tabs, '') if dont_tab_up
119
- end
120
-
121
- @real_tabs += tab_change
122
- @buffer << text
123
- end
124
-
125
- # Modifies the indentation of the document.
126
- #
127
- # @param tab_change [Fixnum] The number of tabs by which to increase
128
- # or decrease the document's indentation
129
- def adjust_tabs(tab_change)
130
- @real_tabs += tab_change
131
- end
132
-
133
- def attributes(class_id, obj_ref, *attributes_hashes)
134
- attributes = class_id
135
- attributes_hashes.each do |old|
136
- result = {}
137
- old.each { |k, v| result[k.to_s] = v }
138
- AttributeBuilder.merge_attributes!(attributes, result)
139
- end
140
- AttributeBuilder.merge_attributes!(attributes, parse_object_ref(obj_ref)) if obj_ref
141
- AttributeBuilder.build_attributes(
142
- html?, @options[:attr_wrapper], @options[:escape_attrs], @options[:hyphenate_data_attrs], attributes)
143
- end
144
-
145
- # Remove the whitespace from the right side of the buffer string.
146
- # Doesn't do anything if we're at the beginning of a capture_haml block.
147
- def rstrip!
148
- if capture_position.nil?
149
- buffer.rstrip!
150
- return
151
- end
152
-
153
- buffer << buffer.slice!(capture_position..-1).rstrip
154
- end
155
-
156
- # Works like #{find_and_preserve}, but allows the first newline after a
157
- # preserved opening tag to remain unencoded, and then outdents the content.
158
- # This change was motivated primarily by the change in Rails 3.2.3 to emit
159
- # a newline after textarea helpers.
160
- #
161
- # @param input [String] The text to process
162
- # @since Haml 4.0.1
163
- # @private
164
- def fix_textareas!(input)
165
- return input unless input.include?('<textarea'.freeze)
166
-
167
- pattern = /<(textarea)([^>]*)>(\n|&#x000A;)(.*?)<\/textarea>/im
168
- input.gsub!(pattern) do |s|
169
- match = pattern.match(s)
170
- content = match[4]
171
- if match[3] == '&#x000A;'
172
- content.sub!(/\A /, '&#x0020;')
173
- else
174
- content.sub!(/\A[ ]*/, '')
175
- end
176
- "<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
177
- end
178
- input
179
- end
180
-
181
- private
182
-
183
- def new_encoded_string
184
- "".encode(options[:encoding])
185
- end
186
-
187
- @@tab_cache = {}
188
- # Gets `count` tabs. Mostly for internal use.
189
- def tabs(count = 0)
190
- tabs = [count + @tabulation, 0].max
191
- @@tab_cache[tabs] ||= ' ' * tabs
192
- end
193
-
194
- # Takes an array of objects and uses the class and id of the first
195
- # one to create an attributes hash.
196
- # The second object, if present, is used as a prefix,
197
- # just like you can do with `dom_id()` and `dom_class()` in Rails
198
- def parse_object_ref(ref)
199
- prefix = ref[1]
200
- ref = ref[0]
201
- # Let's make sure the value isn't nil. If it is, return the default Hash.
202
- return {} if ref.nil?
203
- class_name =
204
- if ref.respond_to?(:haml_object_ref)
205
- ref.haml_object_ref
206
- else
207
- underscore(ref.class)
208
- end
209
- ref_id =
210
- if ref.respond_to?(:to_key)
211
- key = ref.to_key
212
- key.join('_') unless key.nil?
213
- else
214
- ref.id
215
- end
216
- id = "#{class_name}_#{ref_id || 'new'}"
217
- if prefix
218
- class_name = "#{ prefix }_#{ class_name}"
219
- id = "#{ prefix }_#{ id }"
220
- end
221
-
222
- { 'id'.freeze => id, 'class'.freeze => class_name }
223
- end
224
-
225
- # Changes a word from camel case to underscores.
226
- # Based on the method of the same name in Rails' Inflector,
227
- # but copied here so it'll run properly without Rails.
228
- def underscore(camel_cased_word)
229
- word = camel_cased_word.to_s.dup
230
- word.gsub!(/::/, '_')
231
- word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
232
- word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
233
- word.tr!('-', '_')
234
- word.downcase!
235
- word
236
- end
237
- end
238
- end
data/lib/haml/exec.rb DELETED
@@ -1,347 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'optparse'
4
- require 'rbconfig'
5
- require 'pp'
6
-
7
- module Haml
8
- # This module handles the various Haml executables (`haml` and `haml-convert`).
9
- module Exec
10
- # An abstract class that encapsulates the executable code for all three executables.
11
- class Generic
12
- # @param args [Array<String>] The command-line arguments
13
- def initialize(args)
14
- @args = args
15
- @options = {:for_engine => {}}
16
- end
17
-
18
- # Parses the command-line arguments and runs the executable.
19
- # Calls `Kernel#exit` at the end, so it never returns.
20
- #
21
- # @see #parse
22
- def parse!
23
- begin
24
- parse
25
- rescue Exception => e
26
- raise e if @options[:trace] || e.is_a?(SystemExit)
27
-
28
- $stderr.print "#{e.class}: " unless e.class == RuntimeError
29
- $stderr.puts "#{e.message}"
30
- $stderr.puts " Use --trace for backtrace."
31
- exit 1
32
- end
33
- exit 0
34
- end
35
-
36
- # Parses the command-line arguments and runs the executable.
37
- # This does not handle exceptions or exit the program.
38
- #
39
- # @see #parse!
40
- def parse
41
- @opts = OptionParser.new(&method(:set_opts))
42
- @opts.parse!(@args)
43
-
44
- process_result
45
-
46
- @options
47
- end
48
-
49
- # @return [String] A description of the executable
50
- def to_s
51
- @opts.to_s
52
- end
53
-
54
- protected
55
-
56
- # Finds the line of the source template
57
- # on which an exception was raised.
58
- #
59
- # @param exception [Exception] The exception
60
- # @return [String] The line number
61
- def get_line(exception)
62
- # SyntaxErrors have weird line reporting
63
- # when there's trailing whitespace,
64
- # which there is for Haml documents.
65
- return (exception.message.scan(/:(\d+)/).first || ["??"]).first if exception.is_a?(::SyntaxError)
66
- (exception.backtrace[0].scan(/:(\d+)/).first || ["??"]).first
67
- end
68
-
69
- # Tells optparse how to parse the arguments
70
- # available for all executables.
71
- #
72
- # This is meant to be overridden by subclasses
73
- # so they can add their own options.
74
- #
75
- # @param opts [OptionParser]
76
- def set_opts(opts)
77
- opts.on('-s', '--stdin', :NONE, 'Read input from standard input instead of an input file') do
78
- @options[:input] = $stdin
79
- end
80
-
81
- opts.on('--trace', :NONE, 'Show a full traceback on error') do
82
- @options[:trace] = true
83
- end
84
-
85
- opts.on('--unix-newlines', 'Use Unix-style newlines in written files.') do
86
- # Note that this is the preferred way to check for Windows, since
87
- # JRuby and Rubinius also run there.
88
- if RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
89
- @options[:unix_newlines] = true
90
- end
91
- end
92
-
93
- opts.on_tail("-?", "-h", "--help", "Show this message") do
94
- puts opts
95
- exit
96
- end
97
-
98
- opts.on_tail("-v", "--version", "Print version") do
99
- puts("Haml #{::Haml::VERSION}")
100
- exit
101
- end
102
- end
103
-
104
- # Processes the options set by the command-line arguments.
105
- # In particular, sets `@options[:input]` and `@options[:output]`
106
- # to appropriate IO streams.
107
- #
108
- # This is meant to be overridden by subclasses
109
- # so they can run their respective programs.
110
- def process_result
111
- input, output = @options[:input], @options[:output]
112
- args = @args.dup
113
- input ||=
114
- begin
115
- filename = args.shift
116
- @options[:filename] = filename
117
- open_file(filename) || $stdin
118
- end
119
- output ||= open_file(args.shift, 'w') || $stdout
120
-
121
- @options[:input], @options[:output] = input, output
122
- end
123
-
124
- COLORS = {red: 31, green: 32, yellow: 33}.freeze
125
-
126
- # Prints a status message about performing the given action,
127
- # colored using the given color (via terminal escapes) if possible.
128
- #
129
- # @param name [#to_s] A short name for the action being performed.
130
- # Shouldn't be longer than 11 characters.
131
- # @param color [Symbol] The name of the color to use for this action.
132
- # Can be `:red`, `:green`, or `:yellow`.
133
- def puts_action(name, color, arg)
134
- return if @options[:for_engine][:quiet]
135
- printf color(color, "%11s %s\n"), name, arg
136
- end
137
-
138
- # Same as `Kernel.puts`, but doesn't print anything if the `--quiet` option is set.
139
- #
140
- # @param args [Array] Passed on to `Kernel.puts`
141
- def puts(*args)
142
- return if @options[:for_engine][:quiet]
143
- Kernel.puts(*args)
144
- end
145
-
146
- # Wraps the given string in terminal escapes
147
- # causing it to have the given color.
148
- # If terminal esapes aren't supported on this platform,
149
- # just returns the string instead.
150
- #
151
- # @param color [Symbol] The name of the color to use.
152
- # Can be `:red`, `:green`, or `:yellow`.
153
- # @param str [String] The string to wrap in the given color.
154
- # @return [String] The wrapped string.
155
- def color(color, str)
156
- raise "[BUG] Unrecognized color #{color}" unless COLORS[color]
157
-
158
- # Almost any real Unix terminal will support color,
159
- # so we just filter for Windows terms (which don't set TERM)
160
- # and not-real terminals, which aren't ttys.
161
- return str if ENV["TERM"].nil? || ENV["TERM"].empty? || !STDOUT.tty?
162
- return "\e[#{COLORS[color]}m#{str}\e[0m"
163
- end
164
-
165
- private
166
-
167
- def open_file(filename, flag = 'r')
168
- return if filename.nil?
169
- flag = 'wb' if @options[:unix_newlines] && flag == 'w'
170
- File.open(filename, flag)
171
- end
172
-
173
- def handle_load_error(err)
174
- dep = err.message[/^no such file to load -- (.*)/, 1]
175
- raise err if @options[:trace] || dep.nil? || dep.empty?
176
- $stderr.puts <<MESSAGE
177
- Required dependency #{dep} not found!
178
- Run "gem install #{dep}" to get it.
179
- Use --trace for backtrace.
180
- MESSAGE
181
- exit 1
182
- end
183
- end
184
-
185
- # The `haml` executable.
186
- class Haml < Generic
187
- # @param args [Array<String>] The command-line arguments
188
- def initialize(args)
189
- super
190
- @options[:for_engine] = {}
191
- @options[:requires] = []
192
- @options[:load_paths] = []
193
- end
194
-
195
- # Tells optparse how to parse the arguments.
196
- #
197
- # @param opts [OptionParser]
198
- def set_opts(opts)
199
- super
200
-
201
- opts.banner = <<END
202
- Usage: haml [options] [INPUT] [OUTPUT]
203
-
204
- Description:
205
- Converts Haml files to HTML.
206
-
207
- Options:
208
- END
209
-
210
- opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
211
- require 'stringio'
212
- @options[:check_syntax] = true
213
- @options[:output] = StringIO.new
214
- end
215
-
216
- opts.on('-f', '--format NAME',
217
- 'Output format. Can be html5 (default), xhtml, or html4.') do |name|
218
- @options[:for_engine][:format] = name.to_sym
219
- end
220
-
221
- opts.on('-e', '--escape-html',
222
- 'Escape HTML characters (like ampersands and angle brackets) by default.') do
223
- @options[:for_engine][:escape_html] = true
224
- end
225
-
226
- opts.on('--no-escape-attrs',
227
- "Don't escape HTML characters (like ampersands and angle brackets) in attributes.") do
228
- @options[:for_engine][:escape_attrs] = false
229
- end
230
-
231
- opts.on('-q', '--double-quote-attributes',
232
- 'Set attribute wrapper to double-quotes (default is single).') do
233
- @options[:for_engine][:attr_wrapper] = '"'
234
- end
235
-
236
- opts.on('--remove-whitespace',
237
- 'Remove whitespace surrounding and within tags') do
238
- @options[:for_engine][:remove_whitespace] = true
239
- end
240
-
241
- opts.on('--cdata',
242
- 'Always add CDATA sections to javascript and css blocks.') do
243
- @options[:for_engine][:cdata] = true
244
- end
245
-
246
- opts.on('--autoclose LIST',
247
- 'Comma separated list of elements to be automatically self-closed.') do |list|
248
- @options[:for_engine][:autoclose] = list.split(',')
249
- end
250
-
251
- opts.on('--suppress-eval',
252
- 'Don\'t evaluate Ruby scripts.') do
253
- @options[:for_engine][:suppress_eval] = true
254
- end
255
-
256
- opts.on('-r', '--require FILE', "Same as 'ruby -r'.") do |file|
257
- @options[:requires] << file
258
- end
259
-
260
- opts.on('-I', '--load-path PATH', "Same as 'ruby -I'.") do |path|
261
- @options[:load_paths] << path
262
- end
263
-
264
- opts.on('-E ex[:in]', 'Specify the default external and internal character encodings.') do |encoding|
265
- external, internal = encoding.split(':')
266
- Encoding.default_external = external if external && !external.empty?
267
- Encoding.default_internal = internal if internal && !internal.empty?
268
- end
269
-
270
- opts.on('-d', '--debug', "Print out the precompiled Ruby source, and show syntax errors in the Ruby code.") do
271
- @options[:debug] = true
272
- end
273
-
274
- opts.on('-p', '--parse', "Print out Haml parse tree.") do
275
- @options[:parse] = true
276
- end
277
-
278
- end
279
-
280
- # Processes the options set by the command-line arguments,
281
- # and runs the Haml compiler appropriately.
282
- def process_result
283
- super
284
- @options[:for_engine][:filename] = @options[:filename]
285
- input = @options[:input]
286
- output = @options[:output]
287
-
288
- template = input.read()
289
- input.close() if input.is_a? File
290
-
291
- @options[:load_paths].each {|p| $LOAD_PATH << p}
292
- @options[:requires].each {|f| require f}
293
-
294
- begin
295
-
296
- if @options[:parse]
297
- parser = ::Haml::Parser.new(::Haml::Options.new(@options))
298
- pp parser.call(template)
299
- return
300
- end
301
-
302
- engine = ::Haml::Engine.new(template, @options[:for_engine])
303
-
304
- if @options[:check_syntax]
305
- error = validate_ruby(engine.precompiled)
306
- if error
307
- puts error.message.split("\n").first
308
- exit 1
309
- end
310
- puts "Syntax OK"
311
- return
312
- end
313
-
314
- if @options[:debug]
315
- puts engine.precompiled
316
- error = validate_ruby(engine.precompiled)
317
- if error
318
- puts '=' * 100
319
- puts error.message.split("\n")[0]
320
- exit 1
321
- end
322
- return
323
- end
324
-
325
- result = engine.to_html
326
- rescue Exception => e
327
- raise e if @options[:trace]
328
-
329
- case e
330
- when ::Haml::SyntaxError; raise "Syntax error on line #{get_line e}: #{e.message}"
331
- when ::Haml::Error; raise "Haml error on line #{get_line e}: #{e.message}"
332
- else raise "Exception on line #{get_line e}: #{e.message}"
333
- end
334
- end
335
-
336
- output.write(result)
337
- output.close() if output.is_a? File
338
- end
339
-
340
- def validate_ruby(code)
341
- eval("BEGIN {return nil}; #{code}", binding, @options[:filename] || "")
342
- rescue ::SyntaxError # Not to be confused with Haml::SyntaxError
343
- $!
344
- end
345
- end
346
- end
347
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Haml
4
- # Ruby code generator, which is a limited version of Temple::Generator.
5
- # Limit methods since Haml doesn't need most of them.
6
- class Generator
7
- include Temple::Mixins::CompiledDispatcher
8
- include Temple::Mixins::Options
9
-
10
- define_options freeze_static: RUBY_VERSION >= '2.1'
11
-
12
- def call(exp)
13
- compile(exp)
14
- end
15
-
16
- def on_multi(*exp)
17
- exp.map { |e| compile(e) }.join('; ')
18
- end
19
-
20
- def on_static(text)
21
- concat(options[:freeze_static] ? "#{Util.inspect_obj(text)}.freeze" : Util.inspect_obj(text))
22
- end
23
-
24
- def on_dynamic(code)
25
- concat(code)
26
- end
27
-
28
- def on_code(exp)
29
- exp
30
- end
31
-
32
- def on_newline
33
- "\n"
34
- end
35
-
36
- private
37
-
38
- def concat(str)
39
- "_hamlout.buffer << (#{str});"
40
- end
41
- end
42
- end