merbjedi-haml 2.1.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.
- data/FAQ +138 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +332 -0
- data/REVISION +1 -0
- data/Rakefile +184 -0
- data/VERSION +1 -0
- data/bin/css2sass +7 -0
- data/bin/haml +9 -0
- data/bin/html2haml +7 -0
- data/bin/sass +8 -0
- data/extra/haml-mode.el +434 -0
- data/extra/sass-mode.el +98 -0
- data/init.rb +8 -0
- data/lib/haml.rb +1025 -0
- data/lib/haml/buffer.rb +255 -0
- data/lib/haml/engine.rb +268 -0
- data/lib/haml/error.rb +22 -0
- data/lib/haml/exec.rb +395 -0
- data/lib/haml/filters.rb +276 -0
- data/lib/haml/helpers.rb +465 -0
- data/lib/haml/helpers/action_view_extensions.rb +45 -0
- data/lib/haml/helpers/action_view_mods.rb +181 -0
- data/lib/haml/html.rb +218 -0
- data/lib/haml/precompiler.rb +896 -0
- data/lib/haml/shared.rb +45 -0
- data/lib/haml/template.rb +51 -0
- data/lib/haml/template/patch.rb +58 -0
- data/lib/haml/template/plugin.rb +72 -0
- data/lib/haml/util.rb +77 -0
- data/lib/haml/version.rb +47 -0
- data/lib/sass.rb +1062 -0
- data/lib/sass/css.rb +388 -0
- data/lib/sass/engine.rb +501 -0
- data/lib/sass/environment.rb +33 -0
- data/lib/sass/error.rb +35 -0
- data/lib/sass/plugin.rb +203 -0
- data/lib/sass/plugin/merb.rb +56 -0
- data/lib/sass/plugin/rails.rb +24 -0
- data/lib/sass/repl.rb +44 -0
- data/lib/sass/script.rb +38 -0
- data/lib/sass/script/bool.rb +13 -0
- data/lib/sass/script/color.rb +97 -0
- data/lib/sass/script/funcall.rb +28 -0
- data/lib/sass/script/functions.rb +122 -0
- data/lib/sass/script/lexer.rb +144 -0
- data/lib/sass/script/literal.rb +60 -0
- data/lib/sass/script/number.rb +231 -0
- data/lib/sass/script/operation.rb +30 -0
- data/lib/sass/script/parser.rb +142 -0
- data/lib/sass/script/string.rb +42 -0
- data/lib/sass/script/unary_operation.rb +21 -0
- data/lib/sass/script/variable.rb +20 -0
- data/lib/sass/tree/attr_node.rb +64 -0
- data/lib/sass/tree/comment_node.rb +30 -0
- data/lib/sass/tree/debug_node.rb +22 -0
- data/lib/sass/tree/directive_node.rb +50 -0
- data/lib/sass/tree/file_node.rb +27 -0
- data/lib/sass/tree/for_node.rb +29 -0
- data/lib/sass/tree/if_node.rb +27 -0
- data/lib/sass/tree/mixin_def_node.rb +18 -0
- data/lib/sass/tree/mixin_node.rb +34 -0
- data/lib/sass/tree/node.rb +97 -0
- data/lib/sass/tree/rule_node.rb +120 -0
- data/lib/sass/tree/variable_node.rb +24 -0
- data/lib/sass/tree/while_node.rb +20 -0
- data/rails/init.rb +1 -0
- data/test/benchmark.rb +99 -0
- data/test/haml/engine_test.rb +852 -0
- data/test/haml/helper_test.rb +224 -0
- data/test/haml/html2haml_test.rb +92 -0
- data/test/haml/markaby/standard.mab +52 -0
- data/test/haml/mocks/article.rb +6 -0
- data/test/haml/results/content_for_layout.xhtml +15 -0
- data/test/haml/results/eval_suppressed.xhtml +9 -0
- data/test/haml/results/filters.xhtml +62 -0
- data/test/haml/results/helpers.xhtml +93 -0
- data/test/haml/results/helpful.xhtml +10 -0
- data/test/haml/results/just_stuff.xhtml +68 -0
- data/test/haml/results/list.xhtml +12 -0
- data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
- data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
- data/test/haml/results/original_engine.xhtml +20 -0
- data/test/haml/results/partial_layout.xhtml +5 -0
- data/test/haml/results/partials.xhtml +21 -0
- data/test/haml/results/render_layout.xhtml +3 -0
- data/test/haml/results/silent_script.xhtml +74 -0
- data/test/haml/results/standard.xhtml +42 -0
- data/test/haml/results/tag_parsing.xhtml +23 -0
- data/test/haml/results/very_basic.xhtml +5 -0
- data/test/haml/results/whitespace_handling.xhtml +89 -0
- data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
- data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
- data/test/haml/rhtml/action_view.rhtml +62 -0
- data/test/haml/rhtml/standard.rhtml +54 -0
- data/test/haml/template_test.rb +204 -0
- data/test/haml/templates/_av_partial_1.haml +9 -0
- data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
- data/test/haml/templates/_av_partial_2.haml +5 -0
- data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
- data/test/haml/templates/_layout.erb +3 -0
- data/test/haml/templates/_layout_for_partial.haml +3 -0
- data/test/haml/templates/_partial.haml +8 -0
- data/test/haml/templates/_text_area.haml +3 -0
- data/test/haml/templates/action_view.haml +47 -0
- data/test/haml/templates/action_view_ugly.haml +47 -0
- data/test/haml/templates/breakage.haml +8 -0
- data/test/haml/templates/content_for_layout.haml +10 -0
- data/test/haml/templates/eval_suppressed.haml +11 -0
- data/test/haml/templates/filters.haml +66 -0
- data/test/haml/templates/helpers.haml +95 -0
- data/test/haml/templates/helpful.haml +11 -0
- data/test/haml/templates/just_stuff.haml +83 -0
- data/test/haml/templates/list.haml +12 -0
- data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
- data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
- data/test/haml/templates/original_engine.haml +17 -0
- data/test/haml/templates/partial_layout.haml +3 -0
- data/test/haml/templates/partialize.haml +1 -0
- data/test/haml/templates/partials.haml +12 -0
- data/test/haml/templates/render_layout.haml +2 -0
- data/test/haml/templates/silent_script.haml +40 -0
- data/test/haml/templates/standard.haml +42 -0
- data/test/haml/templates/standard_ugly.haml +42 -0
- data/test/haml/templates/tag_parsing.haml +21 -0
- data/test/haml/templates/very_basic.haml +4 -0
- data/test/haml/templates/whitespace_handling.haml +87 -0
- data/test/linked_rails.rb +12 -0
- data/test/sass/css2sass_test.rb +193 -0
- data/test/sass/engine_test.rb +752 -0
- data/test/sass/functions_test.rb +96 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +208 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +87 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/import.css +29 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/script_test.rb +152 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +309 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/import.sass +11 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/parent_ref.sass +25 -0
- data/test/sass/templates/script.sass +101 -0
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/test_helper.rb +21 -0
- metadata +273 -0
data/lib/haml/error.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Haml
|
2
|
+
# An exception raised by Haml code.
|
3
|
+
class Error < StandardError
|
4
|
+
# :stopdoc:
|
5
|
+
|
6
|
+
# By default, an error is taken to refer to the line of the template
|
7
|
+
# that was being processed when the exception was raised.
|
8
|
+
# However, if line is non-nil, it + 1 is used instead.
|
9
|
+
attr_reader :line
|
10
|
+
|
11
|
+
def initialize(message = nil, line = nil)
|
12
|
+
super(message)
|
13
|
+
@line = line
|
14
|
+
end
|
15
|
+
# :startdoc:
|
16
|
+
end
|
17
|
+
|
18
|
+
# SyntaxError is the type of exception raised when Haml encounters an
|
19
|
+
# ill-formatted document.
|
20
|
+
# It's not particularly interesting, except in that it includes Haml::Error.
|
21
|
+
class SyntaxError < Haml::Error; end
|
22
|
+
end
|
data/lib/haml/exec.rb
ADDED
@@ -0,0 +1,395 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Haml
|
5
|
+
# This module contains code for working with the
|
6
|
+
# haml, sass, and haml2html executables,
|
7
|
+
# such as command-line parsing stuff.
|
8
|
+
# It shouldn't need to be invoked by client code.
|
9
|
+
module Exec # :nodoc:
|
10
|
+
# A class that encapsulates the executable code
|
11
|
+
# for all three executables.
|
12
|
+
class Generic # :nodoc:
|
13
|
+
def initialize(args)
|
14
|
+
@args = args
|
15
|
+
@options = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse!
|
19
|
+
begin
|
20
|
+
@opts = OptionParser.new(&method(:set_opts))
|
21
|
+
@opts.parse!(@args)
|
22
|
+
|
23
|
+
process_result
|
24
|
+
|
25
|
+
@options
|
26
|
+
rescue Exception => e
|
27
|
+
raise e if @options[:trace] || e.is_a?(SystemExit)
|
28
|
+
|
29
|
+
$stderr.puts e.message
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
exit 0
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
@opts.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def get_line(exception)
|
42
|
+
# SyntaxErrors have weird line reporting
|
43
|
+
# when there's trailing whitespace,
|
44
|
+
# which there is for Haml documents.
|
45
|
+
return exception.message.scan(/:(\d+)/).first.first if exception.is_a?(::SyntaxError)
|
46
|
+
exception.backtrace[0].scan(/:(\d+)/).first.first
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def set_opts(opts)
|
52
|
+
opts.on('-s', '--stdin', :NONE, 'Read input from standard input instead of an input file') do
|
53
|
+
@options[:input] = $stdin
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on('--trace', :NONE, 'Show a full traceback on error') do
|
57
|
+
@options[:trace] = true
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on_tail("-?", "-h", "--help", "Show this message") do
|
61
|
+
puts opts
|
62
|
+
exit
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on_tail("-v", "--version", "Print version") do
|
66
|
+
puts("Haml #{::Haml.version[:string]}")
|
67
|
+
exit
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def process_result
|
72
|
+
input, output = @options[:input], @options[:output]
|
73
|
+
input_file, output_file = if input
|
74
|
+
[nil, open_file(ARGV[0], 'w')]
|
75
|
+
else
|
76
|
+
@options[:filename] = ARGV[0]
|
77
|
+
[open_file(ARGV[0]), open_file(ARGV[1], 'w')]
|
78
|
+
end
|
79
|
+
|
80
|
+
input ||= input_file
|
81
|
+
output ||= output_file
|
82
|
+
input ||= $stdin
|
83
|
+
output ||= $stdout
|
84
|
+
|
85
|
+
@options[:input], @options[:output] = input, output
|
86
|
+
end
|
87
|
+
|
88
|
+
def open_file(filename, flag = 'r')
|
89
|
+
return if filename.nil?
|
90
|
+
File.open(filename, flag)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# A class encapsulating the executable functionality
|
95
|
+
# specific to Haml and Sass.
|
96
|
+
class HamlSass < Generic # :nodoc:
|
97
|
+
def initialize(args)
|
98
|
+
super
|
99
|
+
@options[:for_engine] = {}
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def set_opts(opts)
|
105
|
+
opts.banner = <<END
|
106
|
+
Usage: #{@name.downcase} [options] [INPUT] [OUTPUT]
|
107
|
+
|
108
|
+
Description:
|
109
|
+
Uses the #{@name} engine to parse the specified template
|
110
|
+
and outputs the result to the specified file.
|
111
|
+
|
112
|
+
Options:
|
113
|
+
END
|
114
|
+
|
115
|
+
opts.on('--rails RAILS_DIR', "Install Haml and Sass from the Gem to a Rails project") do |dir|
|
116
|
+
original_dir = dir
|
117
|
+
|
118
|
+
dir = File.join(dir, 'vendor', 'plugins')
|
119
|
+
|
120
|
+
unless File.exists?(dir)
|
121
|
+
puts "Directory #{dir} doesn't exist"
|
122
|
+
exit
|
123
|
+
end
|
124
|
+
|
125
|
+
dir = File.join(dir, 'haml')
|
126
|
+
|
127
|
+
if File.exists?(dir)
|
128
|
+
print "Directory #{dir} already exists, overwrite [y/N]? "
|
129
|
+
exit if gets !~ /y/i
|
130
|
+
FileUtils.rm_rf(dir)
|
131
|
+
end
|
132
|
+
|
133
|
+
begin
|
134
|
+
Dir.mkdir(dir)
|
135
|
+
rescue SystemCallError
|
136
|
+
puts "Cannot create #{dir}"
|
137
|
+
exit
|
138
|
+
end
|
139
|
+
|
140
|
+
File.open(File.join(dir, 'init.rb'), 'w') do |file|
|
141
|
+
file.puts "require 'rubygems'"
|
142
|
+
file << File.read(File.dirname(__FILE__) + "/../../init.rb")
|
143
|
+
end
|
144
|
+
|
145
|
+
puts "Haml plugin added to #{original_dir}"
|
146
|
+
exit
|
147
|
+
end
|
148
|
+
|
149
|
+
opts.on('-c', '--check', "Just check syntax, don't evaluate.") do
|
150
|
+
require 'stringio'
|
151
|
+
@options[:check_syntax] = true
|
152
|
+
@options[:output] = StringIO.new
|
153
|
+
end
|
154
|
+
|
155
|
+
super
|
156
|
+
end
|
157
|
+
|
158
|
+
def process_result
|
159
|
+
super
|
160
|
+
@options[:for_engine][:filename] = @options[:filename] if @options[:filename]
|
161
|
+
require File.dirname(__FILE__) + "/../#{@name.downcase}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# A class encapsulating executable functionality
|
166
|
+
# specific to Sass.
|
167
|
+
class Sass < HamlSass # :nodoc:
|
168
|
+
def initialize(args)
|
169
|
+
super
|
170
|
+
@name = "Sass"
|
171
|
+
@options[:for_engine][:load_paths] = ['.'] + (ENV['SASSPATH'] || '').split(File::PATH_SEPARATOR)
|
172
|
+
end
|
173
|
+
|
174
|
+
def set_opts(opts)
|
175
|
+
super
|
176
|
+
|
177
|
+
opts.on('-t', '--style NAME',
|
178
|
+
'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
|
179
|
+
@options[:for_engine][:style] = name.to_sym
|
180
|
+
end
|
181
|
+
opts.on('-l', '--line-comments',
|
182
|
+
'Line Comments. Emit comments in the generated CSS indicating the corresponding sass line.') do
|
183
|
+
@options[:for_engine][:line_comments] = true
|
184
|
+
end
|
185
|
+
opts.on('-i', '--interactive',
|
186
|
+
'Run an interactive SassScript shell.') do
|
187
|
+
@options[:interactive] = true
|
188
|
+
end
|
189
|
+
opts.on('-I', '--load-path PATH', 'Add a sass import path.') do |path|
|
190
|
+
@options[:for_engine][:load_paths] << path
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def process_result
|
195
|
+
if @options[:interactive]
|
196
|
+
require 'sass'
|
197
|
+
require 'sass/repl'
|
198
|
+
::Sass::Repl.run
|
199
|
+
return
|
200
|
+
end
|
201
|
+
|
202
|
+
super
|
203
|
+
input = @options[:input]
|
204
|
+
output = @options[:output]
|
205
|
+
|
206
|
+
template = input.read()
|
207
|
+
input.close() if input.is_a? File
|
208
|
+
|
209
|
+
begin
|
210
|
+
# We don't need to do any special handling of @options[:check_syntax] here,
|
211
|
+
# because the Sass syntax checking happens alongside evaluation
|
212
|
+
# and evaluation doesn't actually evaluate any code anyway.
|
213
|
+
result = ::Sass::Engine.new(template, @options[:for_engine]).render
|
214
|
+
rescue ::Sass::SyntaxError => e
|
215
|
+
raise e if @options[:trace]
|
216
|
+
raise "Syntax error on line #{get_line e}: #{e.message}"
|
217
|
+
end
|
218
|
+
|
219
|
+
output.write(result)
|
220
|
+
output.close() if output.is_a? File
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# A class encapsulating executable functionality
|
225
|
+
# specific to Haml.
|
226
|
+
class Haml < HamlSass # :nodoc:
|
227
|
+
def initialize(args)
|
228
|
+
super
|
229
|
+
@name = "Haml"
|
230
|
+
@options[:requires] = []
|
231
|
+
@options[:load_paths] = []
|
232
|
+
end
|
233
|
+
|
234
|
+
def set_opts(opts)
|
235
|
+
super
|
236
|
+
|
237
|
+
opts.on('-t', '--style NAME',
|
238
|
+
'Output style. Can be indented (default) or ugly.') do |name|
|
239
|
+
@options[:for_engine][:ugly] = true if name.to_sym == :ugly
|
240
|
+
end
|
241
|
+
|
242
|
+
opts.on('-f', '--format NAME',
|
243
|
+
'Output format. Can be xhtml (default), html4, or html5.') do |name|
|
244
|
+
@options[:for_engine][:format] = name.to_sym
|
245
|
+
end
|
246
|
+
|
247
|
+
opts.on('-e', '--escape-html',
|
248
|
+
'Escape HTML characters (like ampersands and angle brackets) by default.') do
|
249
|
+
@options[:for_engine][:escape_html] = true
|
250
|
+
end
|
251
|
+
|
252
|
+
opts.on('-r', '--require FILE', "Same as 'ruby -r'.") do |file|
|
253
|
+
@options[:requires] << file
|
254
|
+
end
|
255
|
+
|
256
|
+
opts.on('-I', '--load-path PATH', "Same as 'ruby -I'.") do |path|
|
257
|
+
@options[:load_paths] << path
|
258
|
+
end
|
259
|
+
|
260
|
+
opts.on('--debug', "Print out the precompiled Ruby source.") do
|
261
|
+
@options[:debug] = true
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def process_result
|
266
|
+
super
|
267
|
+
input = @options[:input]
|
268
|
+
output = @options[:output]
|
269
|
+
|
270
|
+
template = input.read()
|
271
|
+
input.close() if input.is_a? File
|
272
|
+
|
273
|
+
begin
|
274
|
+
engine = ::Haml::Engine.new(template, @options[:for_engine])
|
275
|
+
if @options[:check_syntax]
|
276
|
+
puts "Syntax OK"
|
277
|
+
return
|
278
|
+
end
|
279
|
+
|
280
|
+
@options[:load_paths].each {|p| $LOAD_PATH << p}
|
281
|
+
@options[:requires].each {|f| require f}
|
282
|
+
|
283
|
+
if @options[:debug]
|
284
|
+
puts engine.precompiled
|
285
|
+
puts '=' * 100
|
286
|
+
end
|
287
|
+
|
288
|
+
result = engine.to_html
|
289
|
+
rescue Exception => e
|
290
|
+
raise e if @options[:trace]
|
291
|
+
|
292
|
+
case e
|
293
|
+
when ::Haml::SyntaxError; raise "Syntax error on line #{get_line e}: #{e.message}"
|
294
|
+
when ::Haml::Error; raise "Haml error on line #{get_line e}: #{e.message}"
|
295
|
+
else raise "Exception on line #{get_line e}: #{e.message}\n Use --trace for backtrace."
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
output.write(result)
|
300
|
+
output.close() if output.is_a? File
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# A class encapsulating executable functionality
|
305
|
+
# specific to the html2haml executable.
|
306
|
+
class HTML2Haml < Generic # :nodoc:
|
307
|
+
def initialize(args)
|
308
|
+
super
|
309
|
+
|
310
|
+
@module_opts = {}
|
311
|
+
|
312
|
+
begin
|
313
|
+
require 'haml/html'
|
314
|
+
rescue LoadError => err
|
315
|
+
dep = err.message.scan(/^no such file to load -- (.*)/)[0]
|
316
|
+
puts "Required dependency #{dep} not found!"
|
317
|
+
exit 1
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def set_opts(opts)
|
322
|
+
opts.banner = <<END
|
323
|
+
Usage: html2haml [options] [INPUT] [OUTPUT]
|
324
|
+
|
325
|
+
Description: Transforms an HTML file into corresponding Haml code.
|
326
|
+
|
327
|
+
Options:
|
328
|
+
END
|
329
|
+
|
330
|
+
opts.on('-r', '--rhtml', 'Parse RHTML tags.') do
|
331
|
+
@module_opts[:rhtml] = true
|
332
|
+
end
|
333
|
+
|
334
|
+
opts.on('--no-rhtml', "Don't parse RHTML tags.") do
|
335
|
+
@options[:no_rhtml] = true
|
336
|
+
end
|
337
|
+
|
338
|
+
opts.on('-x', '--xhtml', 'Parse the input using the more strict XHTML parser.') do
|
339
|
+
@module_opts[:xhtml] = true
|
340
|
+
end
|
341
|
+
|
342
|
+
super
|
343
|
+
end
|
344
|
+
|
345
|
+
def process_result
|
346
|
+
super
|
347
|
+
|
348
|
+
input = @options[:input]
|
349
|
+
output = @options[:output]
|
350
|
+
|
351
|
+
@module_opts[:rhtml] ||= input.respond_to?(:path) && input.path =~ /\.(rhtml|erb)$/
|
352
|
+
@module_opts[:rhtml] &&= @options[:no_rhtml] != false
|
353
|
+
|
354
|
+
output.write(::Haml::HTML.new(input, @module_opts).render)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
# A class encapsulating executable functionality
|
359
|
+
# specific to the css2sass executable.
|
360
|
+
class CSS2Sass < Generic # :nodoc:
|
361
|
+
def initialize(args)
|
362
|
+
super
|
363
|
+
|
364
|
+
@module_opts = {}
|
365
|
+
|
366
|
+
require 'sass/css'
|
367
|
+
end
|
368
|
+
|
369
|
+
def set_opts(opts)
|
370
|
+
opts.banner = <<END
|
371
|
+
Usage: css2sass [options] [INPUT] [OUTPUT]
|
372
|
+
|
373
|
+
Description: Transforms a CSS file into corresponding Sass code.
|
374
|
+
|
375
|
+
Options:
|
376
|
+
END
|
377
|
+
|
378
|
+
opts.on('-a', '--alternate', 'Output using alternative Sass syntax (margin: 1px)') do
|
379
|
+
@module_opts[:alternate] = true
|
380
|
+
end
|
381
|
+
|
382
|
+
super
|
383
|
+
end
|
384
|
+
|
385
|
+
def process_result
|
386
|
+
super
|
387
|
+
|
388
|
+
input = @options[:input]
|
389
|
+
output = @options[:output]
|
390
|
+
|
391
|
+
output.write(::Sass::CSS.new(input, @module_opts).render)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
data/lib/haml/filters.rb
ADDED
@@ -0,0 +1,276 @@
|
|
1
|
+
module Haml
|
2
|
+
# The module containing the default filters,
|
3
|
+
# as well as the base module,
|
4
|
+
# Haml::Filters::Base.
|
5
|
+
module Filters
|
6
|
+
# Returns a hash of defined filters.
|
7
|
+
def self.defined
|
8
|
+
@defined ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
# The base module for Haml filters.
|
12
|
+
# User-defined filters should be modules including this module.
|
13
|
+
#
|
14
|
+
# A user-defined filter should override either Base#render or Base #compile.
|
15
|
+
# Base#render is the most common.
|
16
|
+
# It takes a string, the filter source,
|
17
|
+
# and returns another string,
|
18
|
+
# the result of the filter.
|
19
|
+
# For example:
|
20
|
+
#
|
21
|
+
# module Haml::Filters::Sass
|
22
|
+
# include Haml::Filters::Base
|
23
|
+
#
|
24
|
+
# def render(text)
|
25
|
+
# ::Sass::Engine.new(text).render
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# For details on overriding #compile, see its documentation.
|
30
|
+
#
|
31
|
+
module Base
|
32
|
+
def self.included(base) # :nodoc:
|
33
|
+
Filters.defined[base.name.split("::").last.downcase] = base
|
34
|
+
base.extend(base)
|
35
|
+
base.instance_variable_set "@lazy_requires", nil
|
36
|
+
end
|
37
|
+
|
38
|
+
# Takes a string, the source text that should be passed to the filter,
|
39
|
+
# and returns the string resulting from running the filter on <tt>text</tt>.
|
40
|
+
#
|
41
|
+
# This should be overridden in most individual filter modules
|
42
|
+
# to render text with the given filter.
|
43
|
+
# If compile is overridden, however, render doesn't need to be.
|
44
|
+
def render(text)
|
45
|
+
raise Error.new("#{self.inspect}#render not defined!")
|
46
|
+
end
|
47
|
+
|
48
|
+
# Same as render, but takes the Haml options hash as well.
|
49
|
+
# It's only safe to rely on options made available in Haml::Engine#options_for_buffer.
|
50
|
+
def render_with_options(text, options)
|
51
|
+
render(text)
|
52
|
+
end
|
53
|
+
|
54
|
+
def internal_compile(*args) # :nodoc:
|
55
|
+
resolve_lazy_requires
|
56
|
+
compile(*args)
|
57
|
+
end
|
58
|
+
|
59
|
+
# compile should be overridden when a filter needs to have access
|
60
|
+
# to the Haml evaluation context.
|
61
|
+
# Rather than applying a filter to a string at compile-time,
|
62
|
+
# compile uses the Haml::Precompiler instance to compile the string to Ruby code
|
63
|
+
# that will be executed in the context of the active Haml template.
|
64
|
+
#
|
65
|
+
# Warning: the Haml::Precompiler interface is neither well-documented
|
66
|
+
# nor guaranteed to be stable.
|
67
|
+
# If you want to make use of it,
|
68
|
+
# you'll probably need to look at the source code
|
69
|
+
# and should test your filter when upgrading to new Haml versions.
|
70
|
+
def compile(precompiler, text)
|
71
|
+
resolve_lazy_requires
|
72
|
+
filter = self
|
73
|
+
precompiler.instance_eval do
|
74
|
+
if contains_interpolation?(text)
|
75
|
+
return if options[:suppress_eval]
|
76
|
+
|
77
|
+
push_script(<<RUBY, false)
|
78
|
+
find_and_preserve(#{filter.inspect}.render_with_options(#{unescape_interpolation(text)}, _hamlout.options))
|
79
|
+
RUBY
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
rendered = Haml::Helpers::find_and_preserve(filter.render_with_options(text, precompiler.options), precompiler.options[:preserve])
|
84
|
+
|
85
|
+
if !options[:ugly]
|
86
|
+
push_text(rendered.rstrip.gsub("\n", "\n#{' ' * @output_tabs}"))
|
87
|
+
else
|
88
|
+
push_text(rendered.rstrip)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# This becomes a class method of modules that include Base.
|
94
|
+
# It allows the module to specify one or more Ruby files
|
95
|
+
# that Haml should try to require when compiling the filter.
|
96
|
+
#
|
97
|
+
# The first file specified is tried first,
|
98
|
+
# then the second, etc.
|
99
|
+
# If none are found, the compilation throws an exception.
|
100
|
+
#
|
101
|
+
# For example:
|
102
|
+
#
|
103
|
+
# module Haml::Filters::Markdown
|
104
|
+
# lazy_require 'rdiscount', 'peg_markdown', 'maruku', 'bluecloth'
|
105
|
+
#
|
106
|
+
# ...
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
def lazy_require(*reqs)
|
110
|
+
@lazy_requires = reqs
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def resolve_lazy_requires
|
116
|
+
return unless @lazy_requires
|
117
|
+
|
118
|
+
@lazy_requires[0...-1].each do |req|
|
119
|
+
begin
|
120
|
+
@required = req
|
121
|
+
require @required
|
122
|
+
return
|
123
|
+
rescue LoadError; end # RCov doesn't see this, but it is run
|
124
|
+
end
|
125
|
+
|
126
|
+
begin
|
127
|
+
@required = @lazy_requires[-1]
|
128
|
+
require @required
|
129
|
+
rescue LoadError => e
|
130
|
+
classname = self.name.match(/\w+$/)[0]
|
131
|
+
|
132
|
+
if @lazy_requires.size == 1
|
133
|
+
raise Error.new("Can't run #{classname} filter; required file '#{@lazy_requires.first}' not found")
|
134
|
+
else
|
135
|
+
raise Error.new("Can't run #{classname} filter; required #{@lazy_requires.map { |r| "'#{r}'" }.join(' or ')}, but none were found")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# :stopdoc:
|
144
|
+
|
145
|
+
begin
|
146
|
+
require 'rubygems'
|
147
|
+
rescue LoadError; end
|
148
|
+
|
149
|
+
module Haml
|
150
|
+
module Filters
|
151
|
+
module Plain
|
152
|
+
include Base
|
153
|
+
|
154
|
+
def render(text); text; end
|
155
|
+
end
|
156
|
+
|
157
|
+
module Javascript
|
158
|
+
include Base
|
159
|
+
|
160
|
+
def render_with_options(text, options)
|
161
|
+
<<END
|
162
|
+
<script type=#{options[:attr_wrapper]}text/javascript#{options[:attr_wrapper]}>
|
163
|
+
//<![CDATA[
|
164
|
+
#{text.rstrip.gsub("\n", "\n ")}
|
165
|
+
//]]>
|
166
|
+
</script>
|
167
|
+
END
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
module Cdata
|
172
|
+
include Base
|
173
|
+
|
174
|
+
def render(text)
|
175
|
+
"<![CDATA[#{("\n" + text).rstrip.gsub("\n", "\n ")}\n]]>"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
module Escaped
|
180
|
+
include Base
|
181
|
+
|
182
|
+
def render(text)
|
183
|
+
Haml::Helpers.html_escape text
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
module Ruby
|
188
|
+
include Base
|
189
|
+
lazy_require 'stringio'
|
190
|
+
|
191
|
+
def compile(precompiler, text)
|
192
|
+
return if precompiler.options[:suppress_eval]
|
193
|
+
precompiler.instance_eval do
|
194
|
+
push_silent <<-FIRST.gsub("\n", ';') + text + <<-LAST.gsub("\n", ';')
|
195
|
+
_haml_old_stdout = $stdout
|
196
|
+
$stdout = StringIO.new(_hamlout.buffer, 'a')
|
197
|
+
FIRST
|
198
|
+
_haml_old_stdout, $stdout = $stdout, _haml_old_stdout
|
199
|
+
_haml_old_stdout.close
|
200
|
+
LAST
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
module Preserve
|
206
|
+
include Base
|
207
|
+
|
208
|
+
def render(text)
|
209
|
+
Haml::Helpers.preserve text
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
module Sass
|
214
|
+
include Base
|
215
|
+
lazy_require 'sass/plugin'
|
216
|
+
|
217
|
+
def render(text)
|
218
|
+
::Sass::Engine.new(text, ::Sass::Plugin.engine_options).render
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
module ERB
|
223
|
+
include Base
|
224
|
+
lazy_require 'erb'
|
225
|
+
|
226
|
+
def compile(precompiler, text)
|
227
|
+
return if precompiler.options[:suppress_eval]
|
228
|
+
src = ::ERB.new(text).src.sub(/^#coding:.*?\n/, '').
|
229
|
+
sub(/^_erbout = '';/, "").gsub("\n", ';')
|
230
|
+
precompiler.send(:push_silent, src)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
module Textile
|
235
|
+
include Base
|
236
|
+
lazy_require 'redcloth'
|
237
|
+
|
238
|
+
def render(text)
|
239
|
+
::RedCloth.new(text).to_html(:textile)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
RedCloth = Textile
|
243
|
+
Filters.defined['redcloth'] = RedCloth
|
244
|
+
|
245
|
+
# Uses BlueCloth or RedCloth to provide only Markdown (not Textile) parsing
|
246
|
+
module Markdown
|
247
|
+
include Base
|
248
|
+
lazy_require 'rdiscount', 'peg_markdown', 'maruku', 'bluecloth'
|
249
|
+
|
250
|
+
def render(text)
|
251
|
+
engine = case @required
|
252
|
+
when 'rdiscount'
|
253
|
+
::RDiscount
|
254
|
+
when 'peg_markdown'
|
255
|
+
::PEGMarkdown
|
256
|
+
when 'maruku'
|
257
|
+
::Maruku
|
258
|
+
when 'bluecloth'
|
259
|
+
::BlueCloth
|
260
|
+
end
|
261
|
+
engine.new(text).to_html
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
module Maruku
|
266
|
+
include Base
|
267
|
+
lazy_require 'maruku'
|
268
|
+
|
269
|
+
def render(text)
|
270
|
+
::Maruku.new(text).to_html
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# :startdoc:
|