radiant 0.6.6 → 0.6.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of radiant might be problematic. Click here for more details.

Files changed (208) hide show
  1. data/CHANGELOG +15 -0
  2. data/CONTRIBUTORS +8 -0
  3. data/app/controllers/admin/page_controller.rb +1 -11
  4. data/app/controllers/admin/welcome_controller.rb +5 -6
  5. data/app/controllers/application.rb +2 -0
  6. data/app/controllers/site_controller.rb +1 -0
  7. data/app/helpers/admin/page_helper.rb +36 -0
  8. data/app/helpers/admin/regions_helper.rb +28 -0
  9. data/app/helpers/admin/user_helper.rb +6 -0
  10. data/app/helpers/application_helper.rb +2 -1
  11. data/app/models/user.rb +7 -8
  12. data/app/views/admin/extension/index.html.haml +28 -0
  13. data/app/views/admin/layout/edit.html.haml +44 -0
  14. data/app/views/admin/layout/index.html.haml +25 -0
  15. data/app/views/admin/layout/remove.html.haml +16 -0
  16. data/app/views/admin/page/_meta_row.html.haml +6 -0
  17. data/app/views/admin/page/_node.html.haml +25 -0
  18. data/app/views/admin/page/_part.html.haml +17 -0
  19. data/app/views/admin/page/_tag_reference.html.haml +3 -0
  20. data/app/views/admin/page/children.html.haml +2 -0
  21. data/app/views/admin/page/edit.html.haml +114 -0
  22. data/app/views/admin/page/index.html.haml +28 -0
  23. data/app/views/admin/page/remove.html.haml +20 -0
  24. data/app/views/admin/snippet/edit.html.haml +36 -0
  25. data/app/views/admin/snippet/index.html.haml +20 -0
  26. data/app/views/admin/snippet/remove.html.haml +19 -0
  27. data/app/views/admin/user/edit.html.haml +80 -0
  28. data/app/views/admin/user/index.html.haml +23 -0
  29. data/app/views/admin/user/preferences.html.haml +28 -0
  30. data/app/views/admin/user/remove.html.haml +18 -0
  31. data/app/views/admin/welcome/login.html.haml +44 -0
  32. data/app/views/layouts/application.html.haml +54 -0
  33. data/app/views/site/not_found.html.haml +3 -0
  34. data/db/migrate/019_add_salt_to_users.rb +11 -0
  35. data/db/schema.rb +2 -1
  36. data/lib/login_system.rb +1 -0
  37. data/lib/radiant.rb +1 -1
  38. data/lib/radiant/admin_ui.rb +65 -0
  39. data/lib/radiant/admin_ui/region_partials.rb +18 -0
  40. data/lib/radiant/admin_ui/region_set.rb +35 -0
  41. data/lib/tasks/extensions.rake +33 -0
  42. data/public/javascripts/admin/admin.js +8 -2
  43. data/public/javascripts/admin/sitemap.js +2 -1
  44. data/public/stylesheets/admin/main.css +4 -0
  45. data/spec/controllers/admin/abstract_model_controller_spec.rb +2 -0
  46. data/spec/controllers/admin/page_controller_spec.rb +3 -28
  47. data/spec/controllers/admin/user_controller_spec.rb +1 -1
  48. data/spec/controllers/admin/welcome_controller_spec.rb +26 -0
  49. data/spec/helpers/admin/page_helper_spec.rb +4 -0
  50. data/spec/helpers/admin/regions_helper_spec.rb +47 -0
  51. data/spec/helpers/admin/user_helper_spec.rb +7 -0
  52. data/spec/helpers/application_helper_spec.rb +7 -3
  53. data/spec/lib/login_system_spec.rb +5 -0
  54. data/spec/lib/radiant/admin_ui/region_partials_spec.rb +35 -0
  55. data/spec/lib/radiant/admin_ui/region_set_spec.rb +61 -0
  56. data/spec/lib/radiant/admin_ui_spec.rb +74 -18
  57. data/spec/models/user_spec.rb +11 -4
  58. data/spec/scenarios/users_scenario.rb +2 -2
  59. data/vendor/plugins/haml/MIT-LICENSE +20 -0
  60. data/vendor/plugins/haml/README.rdoc +319 -0
  61. data/vendor/plugins/haml/Rakefile +158 -0
  62. data/vendor/plugins/haml/TODO +9 -0
  63. data/vendor/plugins/haml/VERSION +1 -0
  64. data/vendor/plugins/haml/bin/css2sass +7 -0
  65. data/vendor/plugins/haml/bin/haml +8 -0
  66. data/vendor/plugins/haml/bin/html2haml +7 -0
  67. data/vendor/plugins/haml/bin/sass +8 -0
  68. data/vendor/plugins/haml/extra/haml-mode.el +328 -0
  69. data/vendor/plugins/haml/extra/sass-mode.el +88 -0
  70. data/vendor/plugins/haml/init.rb +2 -0
  71. data/vendor/plugins/haml/lib/haml.rb +977 -0
  72. data/vendor/plugins/haml/lib/haml/buffer.rb +229 -0
  73. data/vendor/plugins/haml/lib/haml/engine.rb +274 -0
  74. data/vendor/plugins/haml/lib/haml/error.rb +23 -0
  75. data/vendor/plugins/haml/lib/haml/exec.rb +347 -0
  76. data/vendor/plugins/haml/lib/haml/filters.rb +249 -0
  77. data/vendor/plugins/haml/lib/haml/helpers.rb +413 -0
  78. data/vendor/plugins/haml/lib/haml/helpers/action_view_extensions.rb +45 -0
  79. data/vendor/plugins/haml/lib/haml/helpers/action_view_mods.rb +122 -0
  80. data/vendor/plugins/haml/lib/haml/html.rb +188 -0
  81. data/vendor/plugins/haml/lib/haml/precompiler.rb +757 -0
  82. data/vendor/plugins/haml/lib/haml/template.rb +43 -0
  83. data/vendor/plugins/haml/lib/haml/template/patch.rb +58 -0
  84. data/vendor/plugins/haml/lib/haml/template/plugin.rb +72 -0
  85. data/vendor/plugins/haml/lib/sass.rb +833 -0
  86. data/vendor/plugins/haml/lib/sass/constant.rb +245 -0
  87. data/vendor/plugins/haml/lib/sass/constant/color.rb +101 -0
  88. data/vendor/plugins/haml/lib/sass/constant/literal.rb +53 -0
  89. data/vendor/plugins/haml/lib/sass/constant/number.rb +87 -0
  90. data/vendor/plugins/haml/lib/sass/constant/operation.rb +30 -0
  91. data/vendor/plugins/haml/lib/sass/constant/string.rb +22 -0
  92. data/vendor/plugins/haml/lib/sass/css.rb +378 -0
  93. data/vendor/plugins/haml/lib/sass/engine.rb +459 -0
  94. data/vendor/plugins/haml/lib/sass/error.rb +35 -0
  95. data/vendor/plugins/haml/lib/sass/plugin.rb +165 -0
  96. data/vendor/plugins/haml/lib/sass/plugin/merb.rb +56 -0
  97. data/vendor/plugins/haml/lib/sass/plugin/rails.rb +24 -0
  98. data/vendor/plugins/haml/lib/sass/tree/attr_node.rb +53 -0
  99. data/vendor/plugins/haml/lib/sass/tree/comment_node.rb +20 -0
  100. data/vendor/plugins/haml/lib/sass/tree/directive_node.rb +46 -0
  101. data/vendor/plugins/haml/lib/sass/tree/node.rb +42 -0
  102. data/vendor/plugins/haml/lib/sass/tree/rule_node.rb +89 -0
  103. data/vendor/plugins/haml/lib/sass/tree/value_node.rb +16 -0
  104. data/vendor/plugins/haml/test/benchmark.rb +82 -0
  105. data/vendor/plugins/haml/test/haml/engine_test.rb +587 -0
  106. data/vendor/plugins/haml/test/haml/helper_test.rb +187 -0
  107. data/vendor/plugins/haml/test/haml/html2haml_test.rb +60 -0
  108. data/vendor/plugins/haml/test/haml/markaby/standard.mab +52 -0
  109. data/vendor/plugins/haml/test/haml/mocks/article.rb +6 -0
  110. data/vendor/plugins/haml/test/haml/results/content_for_layout.xhtml +16 -0
  111. data/vendor/plugins/haml/test/haml/results/eval_suppressed.xhtml +11 -0
  112. data/vendor/plugins/haml/test/haml/results/filters.xhtml +82 -0
  113. data/vendor/plugins/haml/test/haml/results/helpers.xhtml +94 -0
  114. data/vendor/plugins/haml/test/haml/results/helpful.xhtml +10 -0
  115. data/vendor/plugins/haml/test/haml/results/just_stuff.xhtml +64 -0
  116. data/vendor/plugins/haml/test/haml/results/list.xhtml +12 -0
  117. data/vendor/plugins/haml/test/haml/results/original_engine.xhtml +22 -0
  118. data/vendor/plugins/haml/test/haml/results/partials.xhtml +21 -0
  119. data/vendor/plugins/haml/test/haml/results/silent_script.xhtml +74 -0
  120. data/vendor/plugins/haml/test/haml/results/standard.xhtml +42 -0
  121. data/vendor/plugins/haml/test/haml/results/tag_parsing.xhtml +28 -0
  122. data/vendor/plugins/haml/test/haml/results/very_basic.xhtml +7 -0
  123. data/vendor/plugins/haml/test/haml/results/whitespace_handling.xhtml +94 -0
  124. data/vendor/plugins/haml/test/haml/rhtml/_av_partial_1.rhtml +12 -0
  125. data/vendor/plugins/haml/test/haml/rhtml/_av_partial_2.rhtml +8 -0
  126. data/vendor/plugins/haml/test/haml/rhtml/action_view.rhtml +62 -0
  127. data/vendor/plugins/haml/test/haml/rhtml/standard.rhtml +54 -0
  128. data/vendor/plugins/haml/test/haml/template_test.rb +168 -0
  129. data/vendor/plugins/haml/test/haml/templates/_av_partial_1.haml +9 -0
  130. data/vendor/plugins/haml/test/haml/templates/_av_partial_2.haml +5 -0
  131. data/vendor/plugins/haml/test/haml/templates/_partial.haml +8 -0
  132. data/vendor/plugins/haml/test/haml/templates/_text_area.haml +3 -0
  133. data/vendor/plugins/haml/test/haml/templates/action_view.haml +47 -0
  134. data/vendor/plugins/haml/test/haml/templates/breakage.haml +8 -0
  135. data/vendor/plugins/haml/test/haml/templates/content_for_layout.haml +10 -0
  136. data/vendor/plugins/haml/test/haml/templates/eval_suppressed.haml +11 -0
  137. data/vendor/plugins/haml/test/haml/templates/filters.haml +81 -0
  138. data/vendor/plugins/haml/test/haml/templates/helpers.haml +69 -0
  139. data/vendor/plugins/haml/test/haml/templates/helpful.haml +11 -0
  140. data/vendor/plugins/haml/test/haml/templates/just_stuff.haml +77 -0
  141. data/vendor/plugins/haml/test/haml/templates/list.haml +12 -0
  142. data/vendor/plugins/haml/test/haml/templates/original_engine.haml +17 -0
  143. data/vendor/plugins/haml/test/haml/templates/partialize.haml +1 -0
  144. data/vendor/plugins/haml/test/haml/templates/partials.haml +12 -0
  145. data/vendor/plugins/haml/test/haml/templates/silent_script.haml +40 -0
  146. data/vendor/plugins/haml/test/haml/templates/standard.haml +42 -0
  147. data/vendor/plugins/haml/test/haml/templates/tag_parsing.haml +24 -0
  148. data/vendor/plugins/haml/test/haml/templates/very_basic.haml +4 -0
  149. data/vendor/plugins/haml/test/haml/templates/whitespace_handling.haml +87 -0
  150. data/vendor/plugins/haml/test/haml/test_helper.rb +15 -0
  151. data/vendor/plugins/haml/test/profile.rb +65 -0
  152. data/vendor/plugins/haml/test/sass/engine_test.rb +276 -0
  153. data/vendor/plugins/haml/test/sass/plugin_test.rb +159 -0
  154. data/vendor/plugins/haml/test/sass/results/alt.css +4 -0
  155. data/vendor/plugins/haml/test/sass/results/basic.css +9 -0
  156. data/vendor/plugins/haml/test/sass/results/compact.css +5 -0
  157. data/vendor/plugins/haml/test/sass/results/complex.css +87 -0
  158. data/vendor/plugins/haml/test/sass/results/compressed.css +1 -0
  159. data/vendor/plugins/haml/test/sass/results/constants.css +14 -0
  160. data/vendor/plugins/haml/test/sass/results/expanded.css +19 -0
  161. data/vendor/plugins/haml/test/sass/results/import.css +29 -0
  162. data/vendor/plugins/haml/test/sass/results/mixins.css +95 -0
  163. data/vendor/plugins/haml/test/sass/results/multiline.css +24 -0
  164. data/vendor/plugins/haml/test/sass/results/nested.css +22 -0
  165. data/vendor/plugins/haml/test/sass/results/parent_ref.css +13 -0
  166. data/vendor/plugins/haml/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  167. data/vendor/plugins/haml/test/sass/results/subdir/subdir.css +1 -0
  168. data/vendor/plugins/haml/test/sass/templates/_partial.sass +2 -0
  169. data/vendor/plugins/haml/test/sass/templates/alt.sass +16 -0
  170. data/vendor/plugins/haml/test/sass/templates/basic.sass +23 -0
  171. data/vendor/plugins/haml/test/sass/templates/bork.sass +2 -0
  172. data/vendor/plugins/haml/test/sass/templates/bork2.sass +2 -0
  173. data/vendor/plugins/haml/test/sass/templates/compact.sass +17 -0
  174. data/vendor/plugins/haml/test/sass/templates/complex.sass +310 -0
  175. data/vendor/plugins/haml/test/sass/templates/compressed.sass +15 -0
  176. data/vendor/plugins/haml/test/sass/templates/constants.sass +97 -0
  177. data/vendor/plugins/haml/test/sass/templates/expanded.sass +17 -0
  178. data/vendor/plugins/haml/test/sass/templates/import.sass +11 -0
  179. data/vendor/plugins/haml/test/sass/templates/importee.sass +14 -0
  180. data/vendor/plugins/haml/test/sass/templates/mixins.sass +76 -0
  181. data/vendor/plugins/haml/test/sass/templates/multiline.sass +20 -0
  182. data/vendor/plugins/haml/test/sass/templates/nested.sass +25 -0
  183. data/vendor/plugins/haml/test/sass/templates/parent_ref.sass +25 -0
  184. data/vendor/plugins/haml/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  185. data/vendor/plugins/haml/test/sass/templates/subdir/subdir.sass +6 -0
  186. metadata +185 -24
  187. data/app/views/admin/extension/index.html.erb +0 -40
  188. data/app/views/admin/layout/edit.html.erb +0 -39
  189. data/app/views/admin/layout/index.html.erb +0 -38
  190. data/app/views/admin/layout/remove.html.erb +0 -17
  191. data/app/views/admin/page/_meta_row.html.erb +0 -4
  192. data/app/views/admin/page/_node.html.erb +0 -28
  193. data/app/views/admin/page/_part.html.erb +0 -13
  194. data/app/views/admin/page/_tag_reference.html.erb +0 -4
  195. data/app/views/admin/page/children.html.erb +0 -4
  196. data/app/views/admin/page/edit.html.erb +0 -140
  197. data/app/views/admin/page/index.html.erb +0 -31
  198. data/app/views/admin/page/remove.html.erb +0 -14
  199. data/app/views/admin/snippet/edit.html.erb +0 -29
  200. data/app/views/admin/snippet/index.html.erb +0 -36
  201. data/app/views/admin/snippet/remove.html.erb +0 -16
  202. data/app/views/admin/user/edit.html.erb +0 -54
  203. data/app/views/admin/user/index.html.erb +0 -43
  204. data/app/views/admin/user/preferences.html.erb +0 -29
  205. data/app/views/admin/user/remove.html.erb +0 -16
  206. data/app/views/admin/welcome/login.html.erb +0 -51
  207. data/app/views/layouts/application.html.erb +0 -83
  208. data/app/views/site/not_found.html.erb +0 -3
@@ -0,0 +1,245 @@
1
+ require 'sass/constant/operation'
2
+ require 'sass/constant/literal'
3
+
4
+ module Sass
5
+ module Constant # :nodoc:
6
+ # The character that begins a constant.
7
+ CONSTANT_CHAR = ?!
8
+
9
+ # Whitespace characters
10
+ WHITESPACE = [?\ , ?\t, ?\n, ?\r]
11
+
12
+ # The character used to escape values
13
+ ESCAPE_CHAR = ?\\
14
+
15
+ # The character used to open and close strings
16
+ STRING_CHAR = ?"
17
+
18
+ # A mapping of syntactically-significant characters
19
+ # to parsed symbols
20
+ SYMBOLS = {
21
+ ?( => :open,
22
+ ?) => :close,
23
+ ?+ => :plus,
24
+ ?- => :minus,
25
+ ?* => :times,
26
+ ?/ => :div,
27
+ ?% => :mod,
28
+ CONSTANT_CHAR => :const,
29
+ STRING_CHAR => :str,
30
+ ESCAPE_CHAR => :esc
31
+ }
32
+
33
+ # The regular expression used to parse constants
34
+ MATCH = /^#{Regexp.escape(CONSTANT_CHAR.chr)}([^\s#{(SYMBOLS.keys + [ ?= ]).map {|c| Regexp.escape("#{c.chr}") }.join}]+)\s*((?:\|\|)?=)\s*(.+)/
35
+
36
+ # First-order operations
37
+ FIRST_ORDER = [:times, :div, :mod]
38
+
39
+ # Second-order operations
40
+ SECOND_ORDER = [:plus, :minus]
41
+
42
+ class << self
43
+ def parse(value, constants, line)
44
+ begin
45
+ operationalize(parenthesize(tokenize(value)), constants).to_s
46
+ rescue Sass::SyntaxError => e
47
+ if e.message == "Constant arithmetic error"
48
+ e.instance_eval do
49
+ @message += ": #{value.dump}."
50
+ end
51
+ end
52
+ e.sass_line = line
53
+ raise e
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def tokenize(value)
60
+ escaped = false
61
+ is_string = false
62
+ beginning_of_token = true
63
+ str = ''
64
+ to_return = []
65
+
66
+ reset_str = Proc.new do
67
+ to_return << str unless str.empty?
68
+ ''
69
+ end
70
+
71
+ value.each_byte do |byte|
72
+ unless escaped
73
+ if byte == ESCAPE_CHAR
74
+ escaped = true
75
+ next
76
+ end
77
+
78
+ last = to_return[-1]
79
+
80
+ # Do we need to open or close a string literal?
81
+ if byte == STRING_CHAR
82
+ is_string = !is_string
83
+
84
+ # Adjacent strings should be concatenated
85
+ if is_string && last && (!last.is_a?(Symbol) || last == :close)
86
+ to_return << :concat
87
+ end
88
+
89
+ str = reset_str.call
90
+ next
91
+ end
92
+
93
+ unless is_string
94
+
95
+ # Are we looking at whitespace?
96
+ if WHITESPACE.include?(byte)
97
+ str = reset_str.call
98
+ next
99
+ end
100
+
101
+ symbol = SYMBOLS[byte]
102
+
103
+ # Adjacent values without an operator should be concatenated
104
+ if (symbol.nil? || symbol == :open || symbol == :const) &&
105
+ last && (!last.is_a?(Symbol) || last == :close)
106
+ to_return << :concat
107
+ end
108
+
109
+ # String then open with no whitespace means funcall
110
+ if symbol == :open && !str.empty?
111
+ str = reset_str.call
112
+ to_return << :funcall
113
+ end
114
+
115
+ # Time for a unary minus!
116
+ if beginning_of_token && symbol == :minus
117
+ beginning_of_token = true
118
+ to_return << :neg
119
+ next
120
+ end
121
+
122
+ # Is this a constant?
123
+ if beginning_of_token && symbol == :const
124
+ beginning_of_token = true
125
+ to_return << :const
126
+ next
127
+ end
128
+
129
+ # Are we looking at an operator?
130
+ if symbol && (symbol != :mod || str.empty?)
131
+ str = reset_str.call
132
+ beginning_of_token = true
133
+ to_return << symbol
134
+ next
135
+ end
136
+ end
137
+ end
138
+
139
+ escaped = false
140
+ beginning_of_token = false
141
+ str << byte.chr
142
+ end
143
+
144
+ if is_string
145
+ raise Sass::SyntaxError.new("Unterminated string: #{value.dump}.")
146
+ end
147
+ str = reset_str.call
148
+ to_return
149
+ end
150
+
151
+ def parenthesize(value)
152
+ parenthesize_helper(0, value, value.length)[0]
153
+ end
154
+
155
+ def parenthesize_helper(i, value, value_len, return_after_expr = false)
156
+ to_return = []
157
+ beginning = i
158
+ token = value[i]
159
+
160
+ while i < value_len && token != :close
161
+ if token == :open
162
+ to_return.push(*value[beginning...i])
163
+ sub, i = parenthesize_helper(i + 1, value, value_len)
164
+ beginning = i
165
+ to_return << sub
166
+ elsif token == :neg
167
+ if value[i + 1].nil?
168
+ # This is never actually reached, but we'll leave it in just in case.
169
+ raise Sass::SyntaxError.new("Unterminated unary minus.")
170
+ elsif value[i + 1] == :open
171
+ to_return.push(*value[beginning...i])
172
+ sub, i = parenthesize_helper(i + 2, value, value_len)
173
+ beginning = i
174
+ to_return << [:neg, sub]
175
+ elsif value[i + 1].is_a?(::Symbol)
176
+ to_return.push(*value[beginning...i])
177
+ sub, i = parenthesize_helper(i + 1, value, value_len, true)
178
+ beginning = i
179
+ to_return << [:neg, sub]
180
+ else
181
+ to_return.push(*value[beginning...i])
182
+ to_return << [:neg, value[i + 1]]
183
+ beginning = i = i + 2
184
+ end
185
+ return to_return[0], i if return_after_expr
186
+ elsif token == :const
187
+ raise Sass::SyntaxError.new("Unterminated constant.") if value[i + 1].nil?
188
+ raise Sass::SyntaxError.new("Invalid constant.") unless value[i + 1].is_a?(::String)
189
+
190
+ to_return.push(*value[beginning...i])
191
+ to_return << [:const, value[i + 1]]
192
+ beginning = i = i + 2
193
+ return to_return[0], i if return_after_expr
194
+ else
195
+ i += 1
196
+ end
197
+
198
+ token = value[i]
199
+ end
200
+ to_return.push(*value[beginning...i])
201
+ return to_return, i + 1
202
+ end
203
+
204
+ #--
205
+ # TODO: Don't pass around original value;
206
+ # have Constant.parse automatically add it to exception.
207
+ #++
208
+ def operationalize(value, constants)
209
+ value = [value] unless value.is_a?(Array)
210
+ if value.length == 1
211
+ value = value[0]
212
+ if value.is_a? Array
213
+ operationalize(value, constants)
214
+ elsif value.is_a? Operation
215
+ value
216
+ else
217
+ Literal.parse(value)
218
+ end
219
+ elsif value.length == 2
220
+ if value[0] == :neg
221
+ Operation.new(Sass::Constant::Number.new('0'), operationalize(value[1], constants), :minus)
222
+ elsif value[0] == :const
223
+ Literal.parse(get_constant(value[1], constants))
224
+ else
225
+ raise SyntaxError.new("Constant arithmetic error")
226
+ end
227
+ elsif value.length == 3
228
+ Operation.new(operationalize(value[0], constants), operationalize(value[2], constants), value[1])
229
+ else
230
+ if SECOND_ORDER.include?(value[1]) && FIRST_ORDER.include?(value[3])
231
+ operationalize([value[0], value[1], operationalize(value[2..4], constants), *value[5..-1]], constants)
232
+ else
233
+ operationalize([operationalize(value[0..2], constants), *value[3..-1]], constants)
234
+ end
235
+ end
236
+ end
237
+
238
+ def get_constant(value, constants)
239
+ to_return = constants[value]
240
+ raise SyntaxError.new("Undefined constant: \"!#{value}\".") unless to_return
241
+ to_return
242
+ end
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,101 @@
1
+ require 'sass/constant/literal'
2
+
3
+ module Sass::Constant # :nodoc:
4
+ class Color < Literal # :nodoc:
5
+
6
+ HTML4_COLORS = {
7
+ 'black' => 0x000000,
8
+ 'silver' => 0xc0c0c0,
9
+ 'gray' => 0x808080,
10
+ 'white' => 0xffffff,
11
+ 'maroon' => 0x800000,
12
+ 'red' => 0xff0000,
13
+ 'purple' => 0x800080,
14
+ 'fuchsia' => 0xff00ff,
15
+ 'green' => 0x008000,
16
+ 'lime' => 0x00ff00,
17
+ 'olive' => 0x808000,
18
+ 'yellow' => 0xffff00,
19
+ 'navy' => 0x000080,
20
+ 'blue' => 0x0000ff,
21
+ 'teal' => 0x008080,
22
+ 'aqua' => 0x00ffff
23
+ }
24
+
25
+ REGEXP = /\##{"([0-9a-fA-F]{1,2})" * 3}/
26
+
27
+ def parse(value)
28
+ if (value =~ REGEXP)
29
+ @value = value.scan(REGEXP)[0].map { |num| num.ljust(2, num).to_i(16) }
30
+ else
31
+ color = HTML4_COLORS[value.downcase]
32
+ @value = (0..2).map{ |n| color >> (n << 3) & 0xff }.reverse
33
+ end
34
+ end
35
+
36
+ def plus(other)
37
+ if other.is_a? Sass::Constant::String
38
+ Sass::Constant::String.from_value(self.to_s + other.to_s)
39
+ else
40
+ piecewise(other, :+)
41
+ end
42
+ end
43
+
44
+ def minus(other)
45
+ if other.is_a? Sass::Constant::String
46
+ raise NoMethodError.new(nil, :minus)
47
+ else
48
+ piecewise(other, :-)
49
+ end
50
+ end
51
+
52
+ def times(other)
53
+ if other.is_a? Sass::Constant::String
54
+ raise NoMethodError.new(nil, :times)
55
+ else
56
+ piecewise(other, :*)
57
+ end
58
+ end
59
+
60
+ def div(other)
61
+ if other.is_a? Sass::Constant::String
62
+ raise NoMethodError.new(nil, :div)
63
+ else
64
+ piecewise(other, :/)
65
+ end
66
+ end
67
+
68
+ def mod(other)
69
+ if other.is_a? Sass::Constant::String
70
+ raise NoMethodError.new(nil, :mod)
71
+ else
72
+ piecewise(other, :%)
73
+ end
74
+ end
75
+
76
+ def to_s
77
+ red, green, blue = @value.map { |num| num.to_s(16).rjust(2, '0') }
78
+ "##{red}#{green}#{blue}"
79
+ end
80
+
81
+ protected
82
+
83
+ def self.filter_value(value)
84
+ value.map { |num| num.to_i }
85
+ end
86
+
87
+ private
88
+
89
+ def piecewise(other, operation)
90
+ other_num = other.is_a? Number
91
+ other_val = other.value
92
+
93
+ rgb = []
94
+ for i in (0...3)
95
+ res = @value[i].send(operation, other_num ? other_val : other_val[i])
96
+ rgb[i] = [ [res, 255].min, 0 ].max
97
+ end
98
+ Color.from_value(rgb)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,53 @@
1
+ # Let the subclasses see the superclass
2
+ module Sass::Constant; class Literal; end; end; # :nodoc:
3
+
4
+ require 'sass/constant/string'
5
+ require 'sass/constant/number'
6
+ require 'sass/constant/color'
7
+
8
+ class Sass::Constant::Literal # :nodoc:
9
+ # The regular expression matching numbers.
10
+ NUMBER = /^(-?\d*?\.?)(\d+)([^\d\s]*)$/
11
+
12
+ html_color_matcher = Sass::Constant::Color::HTML4_COLORS.keys.map { |c| "^#{c}$" }.join '|'
13
+
14
+ # The regular expression matching colors.
15
+ COLOR = /^\# (?: [\da-f]{3} | [\da-f]{6} ) | #{html_color_matcher}/ix
16
+
17
+ def self.parse(value)
18
+ case value
19
+ when NUMBER
20
+ Sass::Constant::Number.new(value)
21
+ when COLOR
22
+ Sass::Constant::Color.new(value)
23
+ else
24
+ Sass::Constant::String.new(value)
25
+ end
26
+ end
27
+
28
+ def initialize(value = nil)
29
+ self.parse(value) if value
30
+ end
31
+
32
+ def perform
33
+ self
34
+ end
35
+
36
+ def concat(other)
37
+ Sass::Constant::String.from_value("#{self.to_s} #{other.to_s}")
38
+ end
39
+
40
+ attr_reader :value
41
+
42
+ protected
43
+
44
+ def self.filter_value(value)
45
+ value
46
+ end
47
+
48
+ def self.from_value(value)
49
+ instance = self.new
50
+ instance.instance_variable_set('@value', self.filter_value(value))
51
+ instance
52
+ end
53
+ end
@@ -0,0 +1,87 @@
1
+ require 'sass/constant/literal'
2
+
3
+ module Sass::Constant # :nodoc:
4
+ class Number < Literal # :nodoc:
5
+
6
+ attr_reader :unit
7
+
8
+ def parse(value)
9
+ first, second, unit = value.scan(Literal::NUMBER)[0]
10
+ @value = first.empty? ? second.to_i : "#{first}#{second}".to_f
11
+ @unit = unit unless unit.empty?
12
+ end
13
+
14
+ def plus(other)
15
+ if other.is_a? Number
16
+ operate(other, :+)
17
+ elsif other.is_a? Color
18
+ other.plus(self)
19
+ else
20
+ Sass::Constant::String.from_value(self.to_s + other.to_s)
21
+ end
22
+ end
23
+
24
+ def minus(other)
25
+ if other.is_a? Number
26
+ operate(other, :-)
27
+ else
28
+ raise NoMethodError.new(nil, :minus)
29
+ end
30
+ end
31
+
32
+ def times(other)
33
+ if other.is_a? Number
34
+ operate(other, :*)
35
+ elsif other.is_a? Color
36
+ other.times(self)
37
+ else
38
+ raise NoMethodError.new(nil, :times)
39
+ end
40
+ end
41
+
42
+ def div(other)
43
+ if other.is_a? Number
44
+ operate(other, :/)
45
+ else
46
+ raise NoMethodError.new(nil, :div)
47
+ end
48
+ end
49
+
50
+ def mod(other)
51
+ if other.is_a? Number
52
+ operate(other, :%)
53
+ else
54
+ raise NoMethodError.new(nil, :mod)
55
+ end
56
+ end
57
+
58
+ def to_s
59
+ value = @value
60
+ value = value.to_i if value % 1 == 0.0
61
+ "#{value}#{@unit}"
62
+ end
63
+
64
+ protected
65
+
66
+ def self.from_value(value, unit=nil)
67
+ instance = super(value)
68
+ instance.instance_variable_set('@unit', unit)
69
+ instance
70
+ end
71
+
72
+ def operate(other, operation)
73
+ unit = nil
74
+ if other.unit.nil?
75
+ unit = self.unit
76
+ elsif self.unit.nil?
77
+ unit = other.unit
78
+ elsif other.unit == self.unit
79
+ unit = self.unit
80
+ else
81
+ raise Sass::SyntaxError.new("Incompatible units: #{self.unit} and #{other.unit}.")
82
+ end
83
+
84
+ Number.from_value(self.value.send(operation, other.value), unit)
85
+ end
86
+ end
87
+ end