wireframe-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.
Files changed (169) hide show
  1. data/README.rdoc +332 -0
  2. data/VERSION.yml +4 -0
  3. data/bin/css2sass +7 -0
  4. data/bin/haml +9 -0
  5. data/bin/html2haml +7 -0
  6. data/bin/sass +8 -0
  7. data/lib/haml/buffer.rb +255 -0
  8. data/lib/haml/engine.rb +268 -0
  9. data/lib/haml/error.rb +22 -0
  10. data/lib/haml/exec.rb +395 -0
  11. data/lib/haml/filters.rb +276 -0
  12. data/lib/haml/helpers/action_view_extensions.rb +45 -0
  13. data/lib/haml/helpers/action_view_mods.rb +181 -0
  14. data/lib/haml/helpers.rb +468 -0
  15. data/lib/haml/html.rb +218 -0
  16. data/lib/haml/precompiler.rb +889 -0
  17. data/lib/haml/shared.rb +45 -0
  18. data/lib/haml/template/patch.rb +58 -0
  19. data/lib/haml/template/plugin.rb +72 -0
  20. data/lib/haml/template.rb +51 -0
  21. data/lib/haml/util.rb +77 -0
  22. data/lib/haml/version.rb +47 -0
  23. data/lib/haml.rb +1042 -0
  24. data/lib/sass/css.rb +388 -0
  25. data/lib/sass/engine.rb +499 -0
  26. data/lib/sass/environment.rb +33 -0
  27. data/lib/sass/error.rb +35 -0
  28. data/lib/sass/plugin/merb.rb +56 -0
  29. data/lib/sass/plugin/rails.rb +24 -0
  30. data/lib/sass/plugin.rb +203 -0
  31. data/lib/sass/repl.rb +51 -0
  32. data/lib/sass/script/bool.rb +13 -0
  33. data/lib/sass/script/color.rb +97 -0
  34. data/lib/sass/script/funcall.rb +28 -0
  35. data/lib/sass/script/functions.rb +122 -0
  36. data/lib/sass/script/lexer.rb +152 -0
  37. data/lib/sass/script/literal.rb +60 -0
  38. data/lib/sass/script/number.rb +231 -0
  39. data/lib/sass/script/operation.rb +30 -0
  40. data/lib/sass/script/parser.rb +142 -0
  41. data/lib/sass/script/string.rb +42 -0
  42. data/lib/sass/script/unary_operation.rb +21 -0
  43. data/lib/sass/script/variable.rb +20 -0
  44. data/lib/sass/script.rb +38 -0
  45. data/lib/sass/tree/attr_node.rb +64 -0
  46. data/lib/sass/tree/comment_node.rb +34 -0
  47. data/lib/sass/tree/debug_node.rb +22 -0
  48. data/lib/sass/tree/directive_node.rb +50 -0
  49. data/lib/sass/tree/file_node.rb +27 -0
  50. data/lib/sass/tree/for_node.rb +29 -0
  51. data/lib/sass/tree/if_node.rb +27 -0
  52. data/lib/sass/tree/mixin_def_node.rb +18 -0
  53. data/lib/sass/tree/mixin_node.rb +34 -0
  54. data/lib/sass/tree/node.rb +99 -0
  55. data/lib/sass/tree/rule_node.rb +120 -0
  56. data/lib/sass/tree/variable_node.rb +24 -0
  57. data/lib/sass/tree/while_node.rb +20 -0
  58. data/lib/sass.rb +1062 -0
  59. data/test/benchmark.rb +99 -0
  60. data/test/haml/engine_test.rb +734 -0
  61. data/test/haml/helper_test.rb +224 -0
  62. data/test/haml/html2haml_test.rb +92 -0
  63. data/test/haml/markaby/standard.mab +52 -0
  64. data/test/haml/mocks/article.rb +6 -0
  65. data/test/haml/results/content_for_layout.xhtml +15 -0
  66. data/test/haml/results/eval_suppressed.xhtml +9 -0
  67. data/test/haml/results/filters.xhtml +62 -0
  68. data/test/haml/results/helpers.xhtml +93 -0
  69. data/test/haml/results/helpful.xhtml +10 -0
  70. data/test/haml/results/just_stuff.xhtml +68 -0
  71. data/test/haml/results/list.xhtml +12 -0
  72. data/test/haml/results/nuke_inner_whitespace.xhtml +40 -0
  73. data/test/haml/results/nuke_outer_whitespace.xhtml +148 -0
  74. data/test/haml/results/original_engine.xhtml +20 -0
  75. data/test/haml/results/partial_layout.xhtml +5 -0
  76. data/test/haml/results/partials.xhtml +21 -0
  77. data/test/haml/results/render_layout.xhtml +3 -0
  78. data/test/haml/results/silent_script.xhtml +74 -0
  79. data/test/haml/results/standard.xhtml +42 -0
  80. data/test/haml/results/tag_parsing.xhtml +23 -0
  81. data/test/haml/results/very_basic.xhtml +5 -0
  82. data/test/haml/results/whitespace_handling.xhtml +89 -0
  83. data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
  84. data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
  85. data/test/haml/rhtml/action_view.rhtml +62 -0
  86. data/test/haml/rhtml/standard.rhtml +54 -0
  87. data/test/haml/template_test.rb +204 -0
  88. data/test/haml/templates/_av_partial_1.haml +9 -0
  89. data/test/haml/templates/_av_partial_1_ugly.haml +9 -0
  90. data/test/haml/templates/_av_partial_2.haml +5 -0
  91. data/test/haml/templates/_av_partial_2_ugly.haml +5 -0
  92. data/test/haml/templates/_layout.erb +3 -0
  93. data/test/haml/templates/_layout_for_partial.haml +3 -0
  94. data/test/haml/templates/_partial.haml +8 -0
  95. data/test/haml/templates/_text_area.haml +3 -0
  96. data/test/haml/templates/action_view.haml +47 -0
  97. data/test/haml/templates/action_view_ugly.haml +47 -0
  98. data/test/haml/templates/breakage.haml +8 -0
  99. data/test/haml/templates/content_for_layout.haml +10 -0
  100. data/test/haml/templates/eval_suppressed.haml +11 -0
  101. data/test/haml/templates/filters.haml +66 -0
  102. data/test/haml/templates/helpers.haml +95 -0
  103. data/test/haml/templates/helpful.haml +11 -0
  104. data/test/haml/templates/just_stuff.haml +83 -0
  105. data/test/haml/templates/list.haml +12 -0
  106. data/test/haml/templates/nuke_inner_whitespace.haml +32 -0
  107. data/test/haml/templates/nuke_outer_whitespace.haml +144 -0
  108. data/test/haml/templates/original_engine.haml +17 -0
  109. data/test/haml/templates/partial_layout.haml +3 -0
  110. data/test/haml/templates/partialize.haml +1 -0
  111. data/test/haml/templates/partials.haml +12 -0
  112. data/test/haml/templates/render_layout.haml +2 -0
  113. data/test/haml/templates/silent_script.haml +40 -0
  114. data/test/haml/templates/standard.haml +42 -0
  115. data/test/haml/templates/standard_ugly.haml +1 -0
  116. data/test/haml/templates/tag_parsing.haml +21 -0
  117. data/test/haml/templates/very_basic.haml +4 -0
  118. data/test/haml/templates/whitespace_handling.haml +87 -0
  119. data/test/linked_rails.rb +12 -0
  120. data/test/sass/css2sass_test.rb +193 -0
  121. data/test/sass/engine_test.rb +786 -0
  122. data/test/sass/functions_test.rb +96 -0
  123. data/test/sass/more_results/more1.css +9 -0
  124. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  125. data/test/sass/more_results/more_import.css +29 -0
  126. data/test/sass/more_templates/_more_partial.sass +2 -0
  127. data/test/sass/more_templates/more1.sass +23 -0
  128. data/test/sass/more_templates/more_import.sass +11 -0
  129. data/test/sass/plugin_test.rb +208 -0
  130. data/test/sass/results/alt.css +4 -0
  131. data/test/sass/results/basic.css +9 -0
  132. data/test/sass/results/compact.css +5 -0
  133. data/test/sass/results/complex.css +87 -0
  134. data/test/sass/results/compressed.css +1 -0
  135. data/test/sass/results/expanded.css +19 -0
  136. data/test/sass/results/import.css +29 -0
  137. data/test/sass/results/line_numbers.css +49 -0
  138. data/test/sass/results/mixins.css +95 -0
  139. data/test/sass/results/multiline.css +24 -0
  140. data/test/sass/results/nested.css +22 -0
  141. data/test/sass/results/parent_ref.css +13 -0
  142. data/test/sass/results/script.css +16 -0
  143. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  144. data/test/sass/results/subdir/subdir.css +3 -0
  145. data/test/sass/results/units.css +11 -0
  146. data/test/sass/script_test.rb +153 -0
  147. data/test/sass/templates/_partial.sass +2 -0
  148. data/test/sass/templates/alt.sass +16 -0
  149. data/test/sass/templates/basic.sass +23 -0
  150. data/test/sass/templates/bork.sass +2 -0
  151. data/test/sass/templates/bork2.sass +2 -0
  152. data/test/sass/templates/compact.sass +17 -0
  153. data/test/sass/templates/complex.sass +309 -0
  154. data/test/sass/templates/compressed.sass +15 -0
  155. data/test/sass/templates/expanded.sass +17 -0
  156. data/test/sass/templates/import.sass +11 -0
  157. data/test/sass/templates/importee.sass +19 -0
  158. data/test/sass/templates/line_numbers.sass +13 -0
  159. data/test/sass/templates/mixins.sass +76 -0
  160. data/test/sass/templates/multiline.sass +20 -0
  161. data/test/sass/templates/nested.sass +25 -0
  162. data/test/sass/templates/parent_ref.sass +25 -0
  163. data/test/sass/templates/script.sass +101 -0
  164. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  165. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  166. data/test/sass/templates/subdir/subdir.sass +6 -0
  167. data/test/sass/templates/units.sass +11 -0
  168. data/test/test_helper.rb +21 -0
  169. metadata +247 -0
@@ -0,0 +1,268 @@
1
+ require 'haml/helpers'
2
+ require 'haml/buffer'
3
+ require 'haml/precompiler'
4
+ require 'haml/filters'
5
+ require 'haml/error'
6
+
7
+ module Haml
8
+ # This is the class where all the parsing and processing of the Haml
9
+ # template is done. It can be directly used by the user by creating a
10
+ # new instance and calling <tt>to_html</tt> to render the template. For example:
11
+ #
12
+ # template = File.read('templates/really_cool_template.haml')
13
+ # haml_engine = Haml::Engine.new(template)
14
+ # output = haml_engine.to_html
15
+ # puts output
16
+ class Engine
17
+ include Precompiler
18
+
19
+ # Allow reading and writing of the options hash
20
+ attr :options, true
21
+
22
+ # This string contains the source code that is evaluated
23
+ # to produce the Haml document.
24
+ attr :precompiled, true
25
+
26
+ # A string containing the indentation used for the Haml document.
27
+ # nil if the indentation is ambiguous
28
+ # (for example, for a single-level document).
29
+ attr :indentation, true
30
+
31
+ # True if the format is XHTML
32
+ def xhtml?
33
+ not html?
34
+ end
35
+
36
+ # True if the format is any flavor of HTML
37
+ def html?
38
+ html4? or html5?
39
+ end
40
+
41
+ # True if the format is HTML4
42
+ def html4?
43
+ @options[:format] == :html4
44
+ end
45
+
46
+ # True if the format is HTML5
47
+ def html5?
48
+ @options[:format] == :html5
49
+ end
50
+
51
+ # Creates a new instace of Haml::Engine that will compile the given
52
+ # template string when <tt>render</tt> is called.
53
+ # See the Haml module documentation for available options.
54
+ #
55
+ #--
56
+ # When adding options, remember to add information about them
57
+ # to lib/haml.rb!
58
+ #++
59
+ #
60
+ def initialize(template, options = {})
61
+ @options = {
62
+ :suppress_eval => false,
63
+ :attr_wrapper => "'",
64
+
65
+ # Don't forget to update the docs in lib/haml.rb if you update these
66
+ :autoclose => %w[meta img link br hr input area param col base],
67
+ :preserve => %w[textarea pre],
68
+
69
+ :filename => '(haml)',
70
+ :line => 1,
71
+ :ugly => false,
72
+ :format => :xhtml,
73
+ :escape_html => false
74
+ }
75
+ @options.merge! options
76
+ @index = 0
77
+
78
+ unless [:xhtml, :html4, :html5].include?(@options[:format])
79
+ raise Haml::Error, "Invalid format #{@options[:format].inspect}"
80
+ end
81
+
82
+ # :eod is a special end-of-document marker
83
+ @template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod]
84
+ @template_index = 0
85
+ @to_close_stack = []
86
+ @output_tabs = 0
87
+ @template_tabs = 0
88
+ @flat = false
89
+ @newlines = 0
90
+ @precompiled = ''
91
+ @to_merge = []
92
+ @tab_change = 0
93
+ @temp_count = 0
94
+
95
+ if @options[:filters]
96
+ warn <<END
97
+ DEPRECATION WARNING:
98
+ The Haml :filters option is deprecated and will be removed in version 2.2.
99
+ Filters are now automatically registered.
100
+ END
101
+ end
102
+
103
+ precompile
104
+ rescue Haml::Error => e
105
+ e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}" if @index
106
+ raise
107
+ end
108
+
109
+ # Processes the template and returns the result as a string.
110
+ #
111
+ # +scope+ is the context in which the template is evaluated.
112
+ # If it's a Binding or Proc object,
113
+ # Haml uses it as the second argument to Kernel#eval;
114
+ # otherwise, Haml just uses its #instance_eval context.
115
+ #
116
+ # Note that Haml modifies the evaluation context
117
+ # (either the scope object or the "self" object of the scope binding).
118
+ # It extends Haml::Helpers, and various instance variables are set
119
+ # (all prefixed with "haml").
120
+ # For example:
121
+ #
122
+ # s = "foobar"
123
+ # Haml::Engine.new("%p= upcase").render(s) #=> "<p>FOOBAR</p>"
124
+ #
125
+ # # s now extends Haml::Helpers
126
+ # s.responds_to?(:html_attrs) #=> true
127
+ #
128
+ # +locals+ is a hash of local variables to make available to the template.
129
+ # For example:
130
+ #
131
+ # Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "<p>Hello, world!</p>"
132
+ #
133
+ # If a block is passed to render,
134
+ # that block is run when +yield+ is called
135
+ # within the template.
136
+ #
137
+ # Due to some Ruby quirks,
138
+ # if scope is a Binding or Proc object and a block is given,
139
+ # the evaluation context may not be quite what the user expects.
140
+ # In particular, it's equivalent to passing <tt>eval("self", scope)</tt> as scope.
141
+ # This won't have an effect in most cases,
142
+ # but if you're relying on local variables defined in the context of scope,
143
+ # they won't work.
144
+ def render(scope = Object.new, locals = {}, &block)
145
+ buffer = Haml::Buffer.new(scope.instance_variable_get('@haml_buffer'), options_for_buffer)
146
+
147
+ if scope.is_a?(Binding) || scope.is_a?(Proc)
148
+ scope_object = eval("self", scope)
149
+ scope = scope_object.instance_eval{binding} if block_given?
150
+ else
151
+ scope_object = scope
152
+ scope = scope_object.instance_eval{binding}
153
+ end
154
+
155
+ set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object)
156
+
157
+ scope_object.instance_eval do
158
+ extend Haml::Helpers
159
+ @haml_buffer = buffer
160
+ end
161
+
162
+ eval(@precompiled, scope, @options[:filename], @options[:line])
163
+
164
+ # Get rid of the current buffer
165
+ scope_object.instance_eval do
166
+ @haml_buffer = buffer.upper
167
+ end
168
+
169
+ buffer.buffer
170
+ end
171
+ alias_method :to_html, :render
172
+
173
+ # Returns a proc that, when called,
174
+ # renders the template and returns the result as a string.
175
+ #
176
+ # +scope+ works the same as it does for render.
177
+ #
178
+ # The first argument of the returned proc is a hash of local variable names to values.
179
+ # However, due to an unfortunate Ruby quirk,
180
+ # the local variables which can be assigned must be pre-declared.
181
+ # This is done with the +local_names+ argument.
182
+ # For example:
183
+ #
184
+ # # This works
185
+ # Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
186
+ # #=> "<p>Hello!</p>"
187
+ #
188
+ # # This doesn't
189
+ # Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
190
+ # #=> NameError: undefined local variable or method `foo'
191
+ #
192
+ # The proc doesn't take a block;
193
+ # any yields in the template will fail.
194
+ def render_proc(scope = Object.new, *local_names)
195
+ if scope.is_a?(Binding) || scope.is_a?(Proc)
196
+ scope_object = eval("self", scope)
197
+ else
198
+ scope_object = scope
199
+ scope = scope_object.instance_eval{binding}
200
+ end
201
+
202
+ eval("Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};" +
203
+ precompiled_with_ambles(local_names) + "}\n", scope, @options[:filename], @options[:line])
204
+ end
205
+
206
+ # Defines a method on +object+
207
+ # with the given name
208
+ # that renders the template and returns the result as a string.
209
+ #
210
+ # If +object+ is a class or module,
211
+ # the method will instead by defined as an instance method.
212
+ # For example:
213
+ #
214
+ # t = Time.now
215
+ # Haml::Engine.new("%p\n Today's date is\n .date= self.to_s").def_method(t, :render)
216
+ # t.render #=> "<p>\n Today's date is\n <div class='date'>Fri Nov 23 18:28:29 -0800 2007</div>\n</p>\n"
217
+ #
218
+ # Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
219
+ # "foobar".upcased_div #=> "<div class='upcased'>FOOBAR</div>\n"
220
+ #
221
+ # The first argument of the defined method is a hash of local variable names to values.
222
+ # However, due to an unfortunate Ruby quirk,
223
+ # the local variables which can be assigned must be pre-declared.
224
+ # This is done with the +local_names+ argument.
225
+ # For example:
226
+ #
227
+ # # This works
228
+ # obj = Object.new
229
+ # Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
230
+ # obj.render(:foo => "Hello!") #=> "<p>Hello!</p>"
231
+ #
232
+ # # This doesn't
233
+ # obj = Object.new
234
+ # Haml::Engine.new("%p= foo").def_method(obj, :render)
235
+ # obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'
236
+ #
237
+ # Note that Haml modifies the evaluation context
238
+ # (either the scope object or the "self" object of the scope binding).
239
+ # It extends Haml::Helpers, and various instance variables are set
240
+ # (all prefixed with "haml").
241
+ def def_method(object, name, *local_names)
242
+ method = object.is_a?(Module) ? :module_eval : :instance_eval
243
+
244
+ object.send(method, "def #{name}(_haml_locals = {}); #{precompiled_with_ambles(local_names)}; end",
245
+ @options[:filename], @options[:line])
246
+ end
247
+
248
+ private
249
+
250
+ def set_locals(locals, scope, scope_object)
251
+ scope_object.send(:instance_variable_set, '@_haml_locals', locals)
252
+ set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
253
+ eval(set_locals, scope)
254
+ end
255
+
256
+ # Returns a hash of options that Haml::Buffer cares about.
257
+ # This should remain loadable from #inspect.
258
+ def options_for_buffer
259
+ {
260
+ :autoclose => @options[:autoclose],
261
+ :preserve => @options[:preserve],
262
+ :attr_wrapper => @options[:attr_wrapper],
263
+ :ugly => @options[:ugly],
264
+ :format => @options[:format]
265
+ }
266
+ end
267
+ end
268
+ end
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.new(@options).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