drnic-haml 2.3.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/.yardopts +5 -0
- data/CONTRIBUTING +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +347 -0
- data/REVISION +1 -0
- data/Rakefile +371 -0
- data/VERSION +1 -0
- data/VERSION_NAME +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 +663 -0
- data/extra/sass-mode.el +205 -0
- data/extra/update_watch.rb +13 -0
- data/init.rb +8 -0
- data/lib/haml.rb +40 -0
- data/lib/haml/buffer.rb +307 -0
- data/lib/haml/engine.rb +301 -0
- data/lib/haml/error.rb +22 -0
- data/lib/haml/exec.rb +470 -0
- data/lib/haml/filters.rb +341 -0
- data/lib/haml/helpers.rb +560 -0
- data/lib/haml/helpers/action_view_extensions.rb +40 -0
- data/lib/haml/helpers/action_view_mods.rb +176 -0
- data/lib/haml/herb.rb +96 -0
- data/lib/haml/html.rb +308 -0
- data/lib/haml/precompiler.rb +997 -0
- data/lib/haml/shared.rb +78 -0
- data/lib/haml/template.rb +51 -0
- data/lib/haml/template/patch.rb +58 -0
- data/lib/haml/template/plugin.rb +71 -0
- data/lib/haml/util.rb +244 -0
- data/lib/haml/version.rb +64 -0
- data/lib/sass.rb +24 -0
- data/lib/sass/css.rb +423 -0
- data/lib/sass/engine.rb +491 -0
- data/lib/sass/environment.rb +79 -0
- data/lib/sass/error.rb +162 -0
- data/lib/sass/files.rb +133 -0
- data/lib/sass/plugin.rb +170 -0
- data/lib/sass/plugin/merb.rb +57 -0
- data/lib/sass/plugin/rails.rb +23 -0
- data/lib/sass/repl.rb +58 -0
- data/lib/sass/script.rb +55 -0
- data/lib/sass/script/bool.rb +17 -0
- data/lib/sass/script/color.rb +183 -0
- data/lib/sass/script/funcall.rb +50 -0
- data/lib/sass/script/functions.rb +199 -0
- data/lib/sass/script/lexer.rb +191 -0
- data/lib/sass/script/literal.rb +177 -0
- data/lib/sass/script/node.rb +14 -0
- data/lib/sass/script/number.rb +381 -0
- data/lib/sass/script/operation.rb +45 -0
- data/lib/sass/script/parser.rb +222 -0
- data/lib/sass/script/string.rb +12 -0
- data/lib/sass/script/unary_operation.rb +34 -0
- data/lib/sass/script/variable.rb +31 -0
- data/lib/sass/tree/comment_node.rb +84 -0
- data/lib/sass/tree/debug_node.rb +30 -0
- data/lib/sass/tree/directive_node.rb +70 -0
- data/lib/sass/tree/for_node.rb +48 -0
- data/lib/sass/tree/if_node.rb +54 -0
- data/lib/sass/tree/import_node.rb +69 -0
- data/lib/sass/tree/mixin_def_node.rb +29 -0
- data/lib/sass/tree/mixin_node.rb +48 -0
- data/lib/sass/tree/node.rb +252 -0
- data/lib/sass/tree/prop_node.rb +106 -0
- data/lib/sass/tree/root_node.rb +56 -0
- data/lib/sass/tree/rule_node.rb +220 -0
- data/lib/sass/tree/variable_node.rb +34 -0
- data/lib/sass/tree/while_node.rb +31 -0
- data/rails/init.rb +1 -0
- data/test/benchmark.rb +99 -0
- data/test/haml/engine_test.rb +1129 -0
- data/test/haml/helper_test.rb +282 -0
- data/test/haml/html2haml_test.rb +258 -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 +12 -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 +162 -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/spec_test.rb +44 -0
- data/test/haml/template_test.rb +217 -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 +8 -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/haml/util_test.rb +92 -0
- data/test/linked_rails.rb +12 -0
- data/test/sass/css2sass_test.rb +294 -0
- data/test/sass/engine_test.rb +956 -0
- data/test/sass/functions_test.rb +126 -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 +229 -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 +261 -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/bork1.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +307 -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/nested_bork1.sass +2 -0
- data/test/sass/templates/nested_bork2.sass +2 -0
- data/test/sass/templates/nested_bork3.sass +2 -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 +44 -0
- metadata +298 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'haml/helpers/action_view_mods'
|
|
2
|
+
|
|
3
|
+
module Haml
|
|
4
|
+
module Helpers
|
|
5
|
+
# This module contains various useful helper methods
|
|
6
|
+
# that either tie into ActionView or the rest of the ActionPack stack,
|
|
7
|
+
# or are only useful in that context.
|
|
8
|
+
# Thus, the methods defined here are only available
|
|
9
|
+
# if ActionView is installed.
|
|
10
|
+
module ActionViewExtensions
|
|
11
|
+
# Returns a value for the "class" attribute
|
|
12
|
+
# unique to this controller/action pair.
|
|
13
|
+
# This can be used to target styles specifically at this action or controller.
|
|
14
|
+
# For example, if the current action were `EntryController#show`,
|
|
15
|
+
#
|
|
16
|
+
# %div{:class => page_class} My Div
|
|
17
|
+
#
|
|
18
|
+
# would become
|
|
19
|
+
#
|
|
20
|
+
# <div class="entry show">My Div</div>
|
|
21
|
+
#
|
|
22
|
+
# Then, in a stylesheet (shown here as {Sass}),
|
|
23
|
+
# you could refer to this specific action:
|
|
24
|
+
#
|
|
25
|
+
# .entry.show
|
|
26
|
+
# font-weight: bold
|
|
27
|
+
#
|
|
28
|
+
# or to all actions in the entry controller:
|
|
29
|
+
#
|
|
30
|
+
# .entry
|
|
31
|
+
# color: #00f
|
|
32
|
+
#
|
|
33
|
+
# @return [String] The class name for the current page
|
|
34
|
+
def page_class
|
|
35
|
+
controller.controller_name + " " + controller.action_name
|
|
36
|
+
end
|
|
37
|
+
alias_method :generate_content_class_names, :page_class
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
module ActionView
|
|
2
|
+
class Base
|
|
3
|
+
def render_with_haml(*args, &block)
|
|
4
|
+
options = args.first
|
|
5
|
+
|
|
6
|
+
# If render :layout is used with a block,
|
|
7
|
+
# it concats rather than returning a string
|
|
8
|
+
# so we need it to keep thinking it's Haml
|
|
9
|
+
# until it hits the sub-render
|
|
10
|
+
if is_haml? && !(options.is_a?(Hash) && options[:layout] && block_given?)
|
|
11
|
+
return non_haml { render_without_haml(*args, &block) }
|
|
12
|
+
end
|
|
13
|
+
render_without_haml(*args, &block)
|
|
14
|
+
end
|
|
15
|
+
alias_method :render_without_haml, :render
|
|
16
|
+
alias_method :render, :render_with_haml
|
|
17
|
+
|
|
18
|
+
# Rails >2.1
|
|
19
|
+
if Haml::Util.has?(:instance_method, self, :output_buffer)
|
|
20
|
+
def output_buffer_with_haml
|
|
21
|
+
return haml_buffer.buffer if is_haml?
|
|
22
|
+
output_buffer_without_haml
|
|
23
|
+
end
|
|
24
|
+
alias_method :output_buffer_without_haml, :output_buffer
|
|
25
|
+
alias_method :output_buffer, :output_buffer_with_haml
|
|
26
|
+
|
|
27
|
+
def set_output_buffer_with_haml(new)
|
|
28
|
+
if is_haml?
|
|
29
|
+
haml_buffer.buffer = new
|
|
30
|
+
else
|
|
31
|
+
set_output_buffer_without_haml new
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
alias_method :set_output_buffer_without_haml, :output_buffer=
|
|
35
|
+
alias_method :output_buffer=, :set_output_buffer_with_haml
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
module Helpers
|
|
40
|
+
# In Rails <=2.1, we've got to override considerable capturing infrastructure.
|
|
41
|
+
# In Rails >2.1, we can make do with only overriding #capture
|
|
42
|
+
# (which no longer behaves differently in helper contexts).
|
|
43
|
+
unless Haml::Util.has?(:instance_method, ActionView::Base, :output_buffer)
|
|
44
|
+
module CaptureHelper
|
|
45
|
+
def capture_with_haml(*args, &block)
|
|
46
|
+
# Rails' #capture helper will just return the value of the block
|
|
47
|
+
# if it's not actually in the template context,
|
|
48
|
+
# as detected by the existance of an _erbout variable.
|
|
49
|
+
# We've got to do the same thing for compatibility.
|
|
50
|
+
|
|
51
|
+
if is_haml? && block_is_haml?(block)
|
|
52
|
+
capture_haml(*args, &block)
|
|
53
|
+
else
|
|
54
|
+
capture_without_haml(*args, &block)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
alias_method :capture_without_haml, :capture
|
|
58
|
+
alias_method :capture, :capture_with_haml
|
|
59
|
+
|
|
60
|
+
def capture_erb_with_buffer_with_haml(buffer, *args, &block)
|
|
61
|
+
if is_haml?
|
|
62
|
+
capture_haml(*args, &block)
|
|
63
|
+
else
|
|
64
|
+
capture_erb_with_buffer_without_haml(buffer, *args, &block)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
alias_method :capture_erb_with_buffer_without_haml, :capture_erb_with_buffer
|
|
68
|
+
alias_method :capture_erb_with_buffer, :capture_erb_with_buffer_with_haml
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
module TextHelper
|
|
72
|
+
def concat_with_haml(string, binding = nil)
|
|
73
|
+
if is_haml?
|
|
74
|
+
haml_buffer.buffer.concat(string)
|
|
75
|
+
else
|
|
76
|
+
concat_without_haml(string, binding)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
alias_method :concat_without_haml, :concat
|
|
80
|
+
alias_method :concat, :concat_with_haml
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
module CaptureHelper
|
|
84
|
+
def capture_with_haml(*args, &block)
|
|
85
|
+
if Haml::Helpers.block_is_haml?(block)
|
|
86
|
+
capture_haml(*args, &block)
|
|
87
|
+
else
|
|
88
|
+
capture_without_haml(*args, &block)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
alias_method :capture_without_haml, :capture
|
|
92
|
+
alias_method :capture, :capture_with_haml
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
module TagHelper
|
|
97
|
+
def content_tag_with_haml(name, *args, &block)
|
|
98
|
+
return content_tag_without_haml(name, *args, &block) unless is_haml?
|
|
99
|
+
|
|
100
|
+
preserve = haml_buffer.options[:preserve].include?(name.to_s)
|
|
101
|
+
|
|
102
|
+
if block_given? && block_is_haml?(block) && preserve
|
|
103
|
+
return content_tag_without_haml(name, *args) {preserve(&block)}
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
returning content_tag_without_haml(name, *args, &block) do |content|
|
|
107
|
+
return Haml::Helpers.preserve(content) if preserve && content
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
alias_method :content_tag_without_haml, :content_tag
|
|
112
|
+
alias_method :content_tag, :content_tag_with_haml
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
class InstanceTag
|
|
116
|
+
# Includes TagHelper
|
|
117
|
+
|
|
118
|
+
def haml_buffer
|
|
119
|
+
@template_object.send :haml_buffer
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def is_haml?
|
|
123
|
+
@template_object.send :is_haml?
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
unless defined?(ActionView::Helpers::ActiveRecordInstanceTag)
|
|
127
|
+
alias_method :content_tag_without_haml, :content_tag
|
|
128
|
+
alias_method :content_tag, :content_tag_with_haml
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
module FormTagHelper
|
|
133
|
+
def form_tag_with_haml(url_for_options = {}, options = {}, *parameters_for_url, &proc)
|
|
134
|
+
if is_haml?
|
|
135
|
+
if block_given?
|
|
136
|
+
oldproc = proc
|
|
137
|
+
proc = haml_bind_proc do |*args|
|
|
138
|
+
concat "\n"
|
|
139
|
+
tab_up
|
|
140
|
+
oldproc.call(*args)
|
|
141
|
+
tab_down
|
|
142
|
+
concat haml_indent
|
|
143
|
+
end
|
|
144
|
+
concat haml_indent
|
|
145
|
+
end
|
|
146
|
+
res = form_tag_without_haml(url_for_options, options, *parameters_for_url, &proc) + "\n"
|
|
147
|
+
concat "\n" if block_given?
|
|
148
|
+
res
|
|
149
|
+
else
|
|
150
|
+
form_tag_without_haml(url_for_options, options, *parameters_for_url, &proc)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
alias_method :form_tag_without_haml, :form_tag
|
|
154
|
+
alias_method :form_tag, :form_tag_with_haml
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
module FormHelper
|
|
158
|
+
def form_for_with_haml(object_name, *args, &proc)
|
|
159
|
+
if block_given? && is_haml?
|
|
160
|
+
oldproc = proc
|
|
161
|
+
proc = haml_bind_proc do |*args|
|
|
162
|
+
tab_up
|
|
163
|
+
oldproc.call(*args)
|
|
164
|
+
tab_down
|
|
165
|
+
concat haml_indent
|
|
166
|
+
end
|
|
167
|
+
concat haml_indent
|
|
168
|
+
end
|
|
169
|
+
form_for_without_haml(object_name, *args, &proc)
|
|
170
|
+
concat "\n" if block_given? && is_haml?
|
|
171
|
+
end
|
|
172
|
+
alias_method :form_for_without_haml, :form_for
|
|
173
|
+
alias_method :form_for, :form_for_with_haml
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
data/lib/haml/herb.rb
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Modified version of ERB specifically used to help convert ERB templates to Haml
|
|
2
|
+
class ERB
|
|
3
|
+
class HamlCompiler < Compiler # :nodoc:
|
|
4
|
+
class Buffer # :nodoc:
|
|
5
|
+
def initialize(compiler, delimiter)
|
|
6
|
+
@compiler = compiler
|
|
7
|
+
@line = []
|
|
8
|
+
@script = ""
|
|
9
|
+
@delimiter = delimiter
|
|
10
|
+
@compiler.pre_cmd.each do |x|
|
|
11
|
+
push(x)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
attr_reader :script
|
|
15
|
+
|
|
16
|
+
def push(cmd)
|
|
17
|
+
@line << cmd
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def cr
|
|
21
|
+
@script << (@line.join(@delimiter))
|
|
22
|
+
@line = []
|
|
23
|
+
@script << @delimiter
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def close
|
|
27
|
+
return unless @line
|
|
28
|
+
@compiler.post_cmd.each do |x|
|
|
29
|
+
push(x)
|
|
30
|
+
end
|
|
31
|
+
@script << (@line.join(@delimiter))
|
|
32
|
+
@line = nil
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def compile(s, delimiter = '; ')
|
|
37
|
+
out = Buffer.new(self, delimiter)
|
|
38
|
+
|
|
39
|
+
content = ''
|
|
40
|
+
scanner = make_scanner(s)
|
|
41
|
+
scanner.scan do |token|
|
|
42
|
+
if scanner.stag.nil?
|
|
43
|
+
case token
|
|
44
|
+
when PercentLine
|
|
45
|
+
out.push("#{@put_cmd} #{content.dump}") if content.size > 0
|
|
46
|
+
content = ''
|
|
47
|
+
out.push(token.to_s)
|
|
48
|
+
out.cr
|
|
49
|
+
when :cr
|
|
50
|
+
out.cr
|
|
51
|
+
when '<%', '<%=', '<%#'
|
|
52
|
+
scanner.stag = token
|
|
53
|
+
out.push("#{@put_cmd} #{content.dump}") if content.size > 0
|
|
54
|
+
content = ''
|
|
55
|
+
when "\n"
|
|
56
|
+
content << "\n"
|
|
57
|
+
out.push("#{@put_cmd} #{content.dump}")
|
|
58
|
+
out.cr
|
|
59
|
+
content = ''
|
|
60
|
+
when '<%%'
|
|
61
|
+
content << '<%'
|
|
62
|
+
else
|
|
63
|
+
content << token
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
case token
|
|
67
|
+
when '%>'
|
|
68
|
+
case scanner.stag
|
|
69
|
+
when '<%'
|
|
70
|
+
if content[-1] == ?\n
|
|
71
|
+
content.chop!
|
|
72
|
+
out.push(content)
|
|
73
|
+
out.cr
|
|
74
|
+
else
|
|
75
|
+
out.push(content)
|
|
76
|
+
end
|
|
77
|
+
when '<%='
|
|
78
|
+
out.push("#{@insert_cmd}((#{content}).to_s)")
|
|
79
|
+
when '<%#'
|
|
80
|
+
# out.push("# #{content.dump}")
|
|
81
|
+
end
|
|
82
|
+
scanner.stag = nil
|
|
83
|
+
content = ''
|
|
84
|
+
when '%%>'
|
|
85
|
+
content << '%>'
|
|
86
|
+
else
|
|
87
|
+
content << token
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
out.push("#{@put_cmd} #{content.dump}") if content.size > 0
|
|
92
|
+
out.close
|
|
93
|
+
out.script
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
data/lib/haml/html.rb
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../haml'
|
|
2
|
+
|
|
3
|
+
require 'haml/engine'
|
|
4
|
+
require 'rubygems'
|
|
5
|
+
require 'cgi'
|
|
6
|
+
require 'haml/herb'
|
|
7
|
+
require 'parse_tree'
|
|
8
|
+
|
|
9
|
+
module Haml
|
|
10
|
+
class HTML
|
|
11
|
+
# A module containing utility methods that every Hpricot node
|
|
12
|
+
# should have.
|
|
13
|
+
module Node
|
|
14
|
+
# Returns the Haml representation of the given node.
|
|
15
|
+
#
|
|
16
|
+
# @param tabs [Fixnum] The indentation level of the resulting Haml.
|
|
17
|
+
# @option options (see Haml::HTML#initialize)
|
|
18
|
+
def to_haml(tabs, options)
|
|
19
|
+
parse_text(self.to_s, tabs)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def tabulate(tabs)
|
|
25
|
+
' ' * tabs
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def parse_text(text, tabs)
|
|
29
|
+
text.strip!
|
|
30
|
+
if text.empty?
|
|
31
|
+
String.new
|
|
32
|
+
else
|
|
33
|
+
lines = text.split("\n")
|
|
34
|
+
|
|
35
|
+
lines.map do |line|
|
|
36
|
+
line.strip!
|
|
37
|
+
"#{tabulate(tabs)}#{'\\' if Haml::Engine::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
|
|
38
|
+
end.join
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Haml monkeypatches various Hpricot classes
|
|
46
|
+
# to add methods for conversion to Haml.
|
|
47
|
+
module Hpricot
|
|
48
|
+
# @see Hpricot
|
|
49
|
+
module Node
|
|
50
|
+
include Haml::HTML::Node
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @see Hpricot
|
|
54
|
+
class BaseEle
|
|
55
|
+
include Haml::HTML::Node
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
require 'hpricot'
|
|
60
|
+
|
|
61
|
+
module Haml
|
|
62
|
+
# Converts HTML documents into Haml templates.
|
|
63
|
+
# Depends on [Hpricot](http://code.whytheluckystiff.net/hpricot/) for HTML parsing.
|
|
64
|
+
#
|
|
65
|
+
# Example usage:
|
|
66
|
+
#
|
|
67
|
+
# Haml::Engine.new("<a href='http://google.com'>Blat</a>").render
|
|
68
|
+
# #=> "%a{:href => 'http://google.com'} Blat"
|
|
69
|
+
class HTML
|
|
70
|
+
# @param template [String, Hpricot::Node] The HTML template to convert
|
|
71
|
+
# @option options :rhtml [Boolean] (false) Whether or not to parse
|
|
72
|
+
# ERB's `<%= %>` and `<% %>` into Haml's `=` and `-`
|
|
73
|
+
# @option options :xhtml [Boolean] (false) Whether or not to parse
|
|
74
|
+
# the HTML strictly as XHTML
|
|
75
|
+
def initialize(template, options = {})
|
|
76
|
+
@options = options
|
|
77
|
+
|
|
78
|
+
if template.is_a? Hpricot::Node
|
|
79
|
+
@template = template
|
|
80
|
+
else
|
|
81
|
+
if template.is_a? IO
|
|
82
|
+
template = template.read
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
Haml::Util.check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)}
|
|
86
|
+
|
|
87
|
+
if @options[:rhtml]
|
|
88
|
+
template = convert_to_hamlified_markup(template)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
method = @options[:xhtml] ? Hpricot.method(:XML) : method(:Hpricot)
|
|
92
|
+
@template = method.call(template.gsub('&', '&'))
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Processes the document and returns the result as a string
|
|
97
|
+
# containing the Haml template.
|
|
98
|
+
def render
|
|
99
|
+
@template.to_haml(0, @options)
|
|
100
|
+
end
|
|
101
|
+
alias_method :to_haml, :render
|
|
102
|
+
|
|
103
|
+
TEXT_REGEXP = /^(\s*).*$/
|
|
104
|
+
|
|
105
|
+
# @see Hpricot
|
|
106
|
+
class ::Hpricot::Doc
|
|
107
|
+
# @see Haml::HTML::Node#to_haml
|
|
108
|
+
def to_haml(tabs, options)
|
|
109
|
+
(children || []).inject('') {|s, c| s << c.to_haml(0, options)}
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# @see Hpricot
|
|
114
|
+
class ::Hpricot::XMLDecl
|
|
115
|
+
# @see Haml::HTML::Node#to_haml
|
|
116
|
+
def to_haml(tabs, options)
|
|
117
|
+
"#{tabulate(tabs)}!!! XML\n"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @see Hpricot
|
|
122
|
+
class ::Hpricot::CData
|
|
123
|
+
# @see Haml::HTML::Node#to_haml
|
|
124
|
+
def to_haml(tabs, options)
|
|
125
|
+
"#{tabulate(tabs)}:cdata\n#{parse_text(self.content, tabs + 1)}"
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @see Hpricot
|
|
130
|
+
class ::Hpricot::DocType
|
|
131
|
+
# @see Haml::HTML::Node#to_haml
|
|
132
|
+
def to_haml(tabs, options)
|
|
133
|
+
attrs = public_id.scan(/DTD\s+([^\s]+)\s*([^\s]*)\s*([^\s]*)\s*\/\//)[0]
|
|
134
|
+
raise Haml::SyntaxError.new("Invalid doctype") if attrs == nil
|
|
135
|
+
|
|
136
|
+
type, version, strictness = attrs.map { |a| a.downcase }
|
|
137
|
+
if type == "html"
|
|
138
|
+
version = "1.0"
|
|
139
|
+
strictness = "transitional"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if version == "1.0" || version.empty?
|
|
143
|
+
version = nil
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
if strictness == 'transitional' || strictness.empty?
|
|
147
|
+
strictness = nil
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
version = " #{version}" if version
|
|
151
|
+
if strictness
|
|
152
|
+
strictness[0] = strictness[0] - 32
|
|
153
|
+
strictness = " #{strictness}"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
"#{tabulate(tabs)}!!!#{version}#{strictness}\n"
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# @see Hpricot
|
|
161
|
+
class ::Hpricot::Comment
|
|
162
|
+
# @see Haml::HTML::Node#to_haml
|
|
163
|
+
def to_haml(tabs, options)
|
|
164
|
+
"#{tabulate(tabs)}/\n#{parse_text(self.content, tabs + 1)}"
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# @see Hpricot
|
|
169
|
+
class ::Hpricot::Elem
|
|
170
|
+
# @see Haml::HTML::Node#to_haml
|
|
171
|
+
def to_haml(tabs, options)
|
|
172
|
+
output = tab_prefix = "#{tabulate(tabs)}"
|
|
173
|
+
if options[:rhtml] && name[0...5] == 'haml:'
|
|
174
|
+
output = (self.children || []).inject("") do |out, child|
|
|
175
|
+
if child.text?
|
|
176
|
+
text = CGI.unescapeHTML(child.inner_text).strip
|
|
177
|
+
text.gsub!(/(^[- ]+)|([- ]+$)/, '')
|
|
178
|
+
next out if text.empty?
|
|
179
|
+
out + tab_prefix + send("haml_tag_#{name[5..-1]}", text, tab_prefix)
|
|
180
|
+
elsif child.name[0...10] == 'haml:block'
|
|
181
|
+
out + child.to_haml(tabs + 1, options)
|
|
182
|
+
elsif child.name[0...5] == 'haml:'
|
|
183
|
+
out + child.to_haml(tabs, options)
|
|
184
|
+
else
|
|
185
|
+
out + child.to_haml(tabs, options)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
return output
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
output += "%#{name}" unless name == 'div' &&
|
|
192
|
+
(static_id?(options) || static_classname?(options))
|
|
193
|
+
|
|
194
|
+
if attributes
|
|
195
|
+
if static_id?(options)
|
|
196
|
+
output += "##{attributes['id']}"
|
|
197
|
+
remove_attribute('id')
|
|
198
|
+
end
|
|
199
|
+
if static_classname?(options)
|
|
200
|
+
attributes['class'].split(' ').each { |c| output += ".#{c}" }
|
|
201
|
+
remove_attribute('class')
|
|
202
|
+
end
|
|
203
|
+
output += haml_attributes(options) if attributes.length > 0
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
(self.children || []).inject(output + "\n") do |output, child|
|
|
207
|
+
output + child.to_haml(tabs + 1, options)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
private
|
|
212
|
+
|
|
213
|
+
def dynamic_attributes
|
|
214
|
+
@dynamic_attributes ||= begin
|
|
215
|
+
Haml::Util.map_hash(attributes) do |name, value|
|
|
216
|
+
next if value.empty?
|
|
217
|
+
full_match = nil
|
|
218
|
+
ruby_value = value.gsub(%r{<haml:loud>\s*(.+?)\s*</haml:loud>}) do
|
|
219
|
+
full_match = $`.empty? && $'.empty?
|
|
220
|
+
full_match ? $1: "\#{#{$1}}"
|
|
221
|
+
end
|
|
222
|
+
next if ruby_value == value
|
|
223
|
+
[name, full_match ? ruby_value : %("#{ruby_value}")]
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def haml_tag_loud(text, tab_prefix = '')
|
|
229
|
+
if text =~ /\n/
|
|
230
|
+
lines = text.strip.split(/\n+/)
|
|
231
|
+
pad_size = lines.map { |line| line.length }.max + 1
|
|
232
|
+
out = lines.map { |line| tab_prefix + " " + line.ljust(pad_size) + '|' }.join("\n")
|
|
233
|
+
out[0...4] = "= "
|
|
234
|
+
out + "\n"
|
|
235
|
+
else
|
|
236
|
+
"= #{text.gsub(/\n\s*/, ' ').strip}\n"
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def haml_tag_silent(text, tab_prefix = '')
|
|
241
|
+
text.strip.split("\n").map { |line| "- #{line.strip}" }.join("\n#{tab_prefix}") + "\n"
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def haml_tag_block(text, tab_prefix = '')
|
|
245
|
+
"#{text.strip}\n"
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def static_attribute?(name, options)
|
|
249
|
+
attributes[name] and !dynamic_attribute?(name, options)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def dynamic_attribute?(name, options)
|
|
253
|
+
options[:rhtml] and dynamic_attributes.key?(name)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def static_id?(options)
|
|
257
|
+
static_attribute?('id', options)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def static_classname?(options)
|
|
261
|
+
static_attribute?('class', options)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Returns a string representation of an attributes hash
|
|
265
|
+
# that's prettier than that produced by Hash#inspect
|
|
266
|
+
def haml_attributes(options)
|
|
267
|
+
attrs = attributes.map do |name, value|
|
|
268
|
+
value = dynamic_attribute?(name, options) ? dynamic_attributes[name] : value.inspect
|
|
269
|
+
name = name.index(/\W/) ? name.inspect : ":#{name}"
|
|
270
|
+
"#{name} => #{value}"
|
|
271
|
+
end
|
|
272
|
+
"{ #{attrs.join(', ')} }"
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
private
|
|
277
|
+
|
|
278
|
+
TOKEN_DELIMITER = '__oHg5SJYRHA0__'
|
|
279
|
+
|
|
280
|
+
def convert_to_hamlified_markup(string)
|
|
281
|
+
output = ''
|
|
282
|
+
compiler = ERB::HamlCompiler.new(nil)
|
|
283
|
+
compiler.insert_cmd = compiler.put_cmd = '_erbout.concat'
|
|
284
|
+
|
|
285
|
+
lines = compiler.compile(string, TOKEN_DELIMITER).split(TOKEN_DELIMITER)
|
|
286
|
+
lines.each do |code|
|
|
287
|
+
code.gsub!(/(^[- ]+)|([- ]+$)/, '')
|
|
288
|
+
output << if code[0...15] == '_erbout.concat '
|
|
289
|
+
code[0...15] = ''
|
|
290
|
+
eval(code)
|
|
291
|
+
elsif code =~ /^_erbout\.concat\(\((.*)\)\.to_s\)$/m
|
|
292
|
+
"<haml:loud>#{$1}</haml:loud>"
|
|
293
|
+
elsif code == 'end'
|
|
294
|
+
"</haml:block></haml:silent>"
|
|
295
|
+
else
|
|
296
|
+
begin
|
|
297
|
+
ParseTree.translate(code)
|
|
298
|
+
"<haml:silent>#{code}</haml:silent>"
|
|
299
|
+
rescue Exception
|
|
300
|
+
"<haml:silent>#{code}<haml:block>"
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
output
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
end
|
|
308
|
+
end
|