haml 5.2.2 → 6.0.0.beta.1

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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/test.yml +13 -9
  4. data/.gitignore +16 -16
  5. data/CHANGELOG.md +13 -3
  6. data/Gemfile +18 -11
  7. data/MIT-LICENSE +1 -1
  8. data/README.md +13 -19
  9. data/Rakefile +95 -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 +135 -179
  24. data/lib/haml/attribute_compiler.rb +85 -194
  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 +3 -52
  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/haml_error.rb +66 -0
  57. data/lib/haml/helpers.rb +3 -697
  58. data/lib/haml/html.rb +22 -0
  59. data/lib/haml/identity.rb +13 -0
  60. data/lib/haml/object_ref.rb +30 -0
  61. data/lib/haml/parser.rb +179 -49
  62. data/lib/haml/rails_helpers.rb +51 -0
  63. data/lib/haml/rails_template.rb +55 -0
  64. data/lib/haml/railtie.rb +7 -45
  65. data/lib/haml/ruby_expression.rb +32 -0
  66. data/lib/haml/string_splitter.rb +20 -0
  67. data/lib/haml/template.rb +15 -34
  68. data/lib/haml/temple_line_counter.rb +2 -1
  69. data/lib/haml/util.rb +17 -15
  70. data/lib/haml/version.rb +1 -2
  71. data/lib/haml.rb +8 -20
  72. metadata +211 -57
  73. data/.gitmodules +0 -3
  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 -182
  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 -54
  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 -124
  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/TODO DELETED
@@ -1,24 +0,0 @@
1
- # -*- mode: org -*-
2
- #+STARTUP: nofold
3
-
4
- * Documentation
5
- Redo tutorial?
6
- Using helpers
7
- haml_concat and haml_tag in particular
8
- Syntax highlighting?
9
-
10
- * Code
11
- Keep track of error offsets everywhere
12
- Use this to show error location in messages
13
- ** Haml
14
- Support finer-grained HTML-escaping in filters
15
- Speed
16
- Make tags with dynamic attributes pre-render as much as possible
17
- Including the attribute name where doable
18
- :html improvements
19
- Ignore closing tags where we can
20
- http://code.google.com/speed/articles/optimizing-html.html
21
- Requires Haml parsing refactor
22
- Don't quote attributes that don't require it
23
- http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
24
- http://www.w3.org/TR/html5/syntax.html#attributes
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,182 +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
- # Remove the whitespace from the right side of the buffer string.
134
- # Doesn't do anything if we're at the beginning of a capture_haml block.
135
- def rstrip!
136
- if capture_position.nil?
137
- buffer.rstrip!
138
- return
139
- end
140
-
141
- buffer << buffer.slice!(capture_position..-1).rstrip
142
- end
143
-
144
- # Works like #{find_and_preserve}, but allows the first newline after a
145
- # preserved opening tag to remain unencoded, and then outdents the content.
146
- # This change was motivated primarily by the change in Rails 3.2.3 to emit
147
- # a newline after textarea helpers.
148
- #
149
- # @param input [String] The text to process
150
- # @since Haml 4.0.1
151
- # @private
152
- def fix_textareas!(input)
153
- return input unless input.include?('<textarea'.freeze)
154
-
155
- pattern = /<(textarea)([^>]*)>(\n|&#x000A;)(.*?)<\/textarea>/im
156
- input.gsub!(pattern) do |s|
157
- match = pattern.match(s)
158
- content = match[4]
159
- if match[3] == '&#x000A;'
160
- content.sub!(/\A /, '&#x0020;')
161
- else
162
- content.sub!(/\A[ ]*/, '')
163
- end
164
- "<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
165
- end
166
- input
167
- end
168
-
169
- private
170
-
171
- def new_encoded_string
172
- "".encode(options[:encoding])
173
- end
174
-
175
- @@tab_cache = {}
176
- # Gets `count` tabs. Mostly for internal use.
177
- def tabs(count = 0)
178
- tabs = [count + @tabulation, 0].max
179
- @@tab_cache[tabs] ||= ' ' * tabs
180
- end
181
- end
182
- 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