hum 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +7 -0
  5. data/README.md +35 -0
  6. data/Rakefile +1 -0
  7. data/bin/hum +5 -0
  8. data/hum.gemspec +24 -0
  9. data/lib/hum.rb +7 -0
  10. data/lib/hum/array.rb +61 -0
  11. data/lib/hum/engine.rb +401 -0
  12. data/lib/hum/exec.rb +111 -0
  13. data/lib/hum/string.rb +8 -0
  14. data/lib/hum/version.rb +3 -0
  15. data/test/hum/templates/comma/comma.array +1 -0
  16. data/test/hum/templates/comma/comma.css +6 -0
  17. data/test/hum/templates/comma/comma.haml +6 -0
  18. data/test/hum/templates/comma/comma.haml_tags +1 -0
  19. data/test/hum/templates/comma/comma.html +0 -0
  20. data/test/hum/templates/comma/comma.sass +2 -0
  21. data/test/hum/templates/comma/comma_clean.sass +1 -0
  22. data/test/hum/templates/comma/comma_end.html +9 -0
  23. data/test/hum/templates/complex_parent/complex_parent.array +1 -0
  24. data/test/hum/templates/complex_parent/complex_parent.css +18 -0
  25. data/test/hum/templates/complex_parent/complex_parent.haml +12 -0
  26. data/test/hum/templates/complex_parent/complex_parent.haml_tags +1 -0
  27. data/test/hum/templates/complex_parent/complex_parent.html +0 -0
  28. data/test/hum/templates/complex_parent/complex_parent.sass +12 -0
  29. data/test/hum/templates/complex_parent/complex_parent_clean.sass +6 -0
  30. data/test/hum/templates/complex_parent/complex_parent_end.html +18 -0
  31. data/test/hum/templates/deep_nest/deep_nest.array +1 -0
  32. data/test/hum/templates/deep_nest/deep_nest.css +15 -0
  33. data/test/hum/templates/deep_nest/deep_nest.haml +19 -0
  34. data/test/hum/templates/deep_nest/deep_nest.haml_tags +1 -0
  35. data/test/hum/templates/deep_nest/deep_nest.html +0 -0
  36. data/test/hum/templates/deep_nest/deep_nest.sass +10 -0
  37. data/test/hum/templates/deep_nest/deep_nest_clean.sass +5 -0
  38. data/test/hum/templates/deep_nest/deep_nest_end.html +27 -0
  39. data/test/hum/templates/deep_nest/deep_nest_start.scss +15 -0
  40. data/test/hum/templates/line_nest/line_nest.array +1 -0
  41. data/test/hum/templates/line_nest/line_nest.css +6 -0
  42. data/test/hum/templates/line_nest/line_nest.haml +9 -0
  43. data/test/hum/templates/line_nest/line_nest.haml_tags +1 -0
  44. data/test/hum/templates/line_nest/line_nest.html +0 -0
  45. data/test/hum/templates/line_nest/line_nest.sass +5 -0
  46. data/test/hum/templates/line_nest/line_nest_clean.sass +2 -0
  47. data/test/hum/templates/line_nest/line_nest_end.html +15 -0
  48. data/test/hum/templates/nest/nest.array +1 -0
  49. data/test/hum/templates/nest/nest.css +9 -0
  50. data/test/hum/templates/nest/nest.haml +7 -0
  51. data/test/hum/templates/nest/nest.haml_tags +1 -0
  52. data/test/hum/templates/nest/nest.html +0 -0
  53. data/test/hum/templates/nest/nest.sass +6 -0
  54. data/test/hum/templates/nest/nest_clean.sass +3 -0
  55. data/test/hum/templates/nest/nest_end.html +12 -0
  56. data/test/hum/templates/parent_nest/parent_nest.array +1 -0
  57. data/test/hum/templates/parent_nest/parent_nest.css +12 -0
  58. data/test/hum/templates/parent_nest/parent_nest.haml +8 -0
  59. data/test/hum/templates/parent_nest/parent_nest.haml_tags +1 -0
  60. data/test/hum/templates/parent_nest/parent_nest.html +0 -0
  61. data/test/hum/templates/parent_nest/parent_nest.sass +8 -0
  62. data/test/hum/templates/parent_nest/parent_nest_clean.sass +4 -0
  63. data/test/hum/templates/parent_nest/parent_nest_end.html +12 -0
  64. data/test/hum/templates/parent_select/parent_select.array +1 -0
  65. data/test/hum/templates/parent_select/parent_select.css +4 -0
  66. data/test/hum/templates/parent_select/parent_select.haml +6 -0
  67. data/test/hum/templates/parent_select/parent_select.haml_tags +1 -0
  68. data/test/hum/templates/parent_select/parent_select.html +0 -0
  69. data/test/hum/templates/parent_select/parent_select.sass +4 -0
  70. data/test/hum/templates/parent_select/parent_select_clean.sass +2 -0
  71. data/test/hum/templates/parent_select/parent_select_end.html +9 -0
  72. data/test/hum/templates/simple/simple.array +1 -0
  73. data/test/hum/templates/simple/simple.css +9 -0
  74. data/test/hum/templates/simple/simple.haml +7 -0
  75. data/test/hum/templates/simple/simple.haml_tags +1 -0
  76. data/test/hum/templates/simple/simple.html +0 -0
  77. data/test/hum/templates/simple/simple.sass +8 -0
  78. data/test/hum/templates/simple/simple_clean.sass +3 -0
  79. data/test/hum/templates/simple/simple_end.html +10 -0
  80. data/test/hum/templates/single/single.array +1 -0
  81. data/test/hum/templates/single/single.css +3 -0
  82. data/test/hum/templates/single/single.haml +5 -0
  83. data/test/hum/templates/single/single.haml_tags +1 -0
  84. data/test/hum/templates/single/single.html +0 -0
  85. data/test/hum/templates/single/single.sass +2 -0
  86. data/test/hum/templates/single/single_clean.sass +1 -0
  87. data/test/hum/templates/single/single_end.html +8 -0
  88. data/test/run_tests.rb +119 -0
  89. metadata +241 -0
@@ -0,0 +1,10 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
6
+ bin/*.css
7
+ bin/*.html
8
+ bin/*.sass
9
+ bin/*.scss
10
+ *.sass-cache
@@ -0,0 +1,3 @@
1
+ ## 0.0.1
2
+
3
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in hum.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (C) 2011 Jeffrey Wegesin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ # Hum
2
+
3
+ Hum generates HTML from your SASS or CSS.
4
+
5
+ `gem install hum`
6
+
7
+ Here's an example of what he can do:
8
+
9
+ #He'll eat this CSS
10
+ .foo{
11
+ border-width: 1px;
12
+ }
13
+ .foo .bar{
14
+ font-size: 12px;
15
+ }
16
+ .foo .bar p{
17
+ color: black;
18
+ }
19
+
20
+ #And crap out this HTML
21
+ <div class="foo">
22
+ <div class="bar">
23
+ <p></p>
24
+ </div>
25
+ </div>
26
+
27
+ To do that run
28
+
29
+ `hum [stylesheet].css`
30
+
31
+ You can also watch a directory for changes by using
32
+
33
+ `hum --watch`
34
+
35
+ He can't generate HTML from SASS directly yet, so you must specify a CSS file.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/hum ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../lib/hum'
3
+ require 'hum/exec'
4
+ opts = Hum::Exec::Hum.new(ARGV)
5
+ opts.parse!
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "hum/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "hum"
7
+ s.version = Hum::VERSION
8
+ s.authors = ["Jeffrey Wegesin"]
9
+ s.email = ["jeff@jwegesin.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Generate HTML from your SASS or CSS}
12
+ s.description = %q{Hum generates HTML from your SASS or CSS. View more info at github.com/jefweg/hum}
13
+
14
+ s.rubyforge_project = "hum"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency 'sass'
22
+ s.add_dependency 'haml'
23
+ s.add_dependency 'fssm'
24
+ end
@@ -0,0 +1,7 @@
1
+ dir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
3
+ require "hum/version"
4
+
5
+ module Hum
6
+
7
+ end
@@ -0,0 +1,61 @@
1
+ class Array
2
+ #find a specific line
3
+ def find_line(target, found = nil)
4
+ self.each do |css|
5
+ if css[:line] == target
6
+ found = css
7
+ end
8
+ end
9
+ found
10
+ end
11
+
12
+ #find the parent of a line
13
+ def find_parent(of_this_hash, found = nil)
14
+
15
+ #target the line number
16
+ line_number = of_this_hash[:line] - 1
17
+
18
+ #find the line
19
+ found = self.find_line(line_number)
20
+
21
+ #finds the direct parent with the correct tab
22
+ until found.nil? or found[:tab] == of_this_hash[:tab] - 1
23
+
24
+ #go up the tree
25
+ line_number -= 1
26
+
27
+ #find the line
28
+ found = self.find_line(line_number)
29
+ end
30
+
31
+ #return the right parent
32
+ found
33
+ end
34
+
35
+ #find the children from a line to a hash
36
+ def find_all_kids(line, to_line, kids = [])
37
+
38
+ #find the parent
39
+ parent = self.find_line(line)
40
+
41
+ #target the line number
42
+ line_number = line + 1
43
+
44
+ #find the first found
45
+ found = self.find_line(line_number)
46
+
47
+ until found.nil? or line_number == to_line or parent[:tab] == found[:tab]
48
+ #add the line to the array
49
+ kids << found
50
+
51
+ #increment the line number
52
+ line_number += 1
53
+
54
+ #find the new found
55
+ found = self.find_line(line_number)
56
+ end
57
+
58
+ #return the kids
59
+ kids
60
+ end
61
+ end
@@ -0,0 +1,401 @@
1
+ require 'rubygems'
2
+ require 'haml'
3
+ require 'sass'
4
+ require 'sass/css'
5
+ require 'hum/string'
6
+ require 'hum/array'
7
+
8
+ module Hum
9
+ #Hum
10
+ class Engine
11
+ #Engine
12
+
13
+ def initialize
14
+ end
15
+
16
+ def load(file)
17
+ #the array that holds the parsed CSS
18
+ @tree = []
19
+
20
+ #the name of the input file
21
+ @input_name = File.basename(file)
22
+
23
+ #read the input file
24
+ @input_file = File.open(file, 'r')
25
+
26
+ #the output path
27
+ @output_path = File.absolute_path(file).gsub(/\..*/, ".html")
28
+
29
+ #the name of the output file
30
+ @output_name = File.basename(@output_path)
31
+
32
+ #create the output file
33
+ @output_file = File.open(@output_path, "w")
34
+ end
35
+
36
+ #runs through all the commands
37
+ def run
38
+ #renders SASS from CSS
39
+ render_sass
40
+
41
+ #remove property value pairs
42
+ clean_sass
43
+
44
+ #parse CSS into an array of hashes
45
+ build_hashes
46
+
47
+ #generate HAML tags
48
+ render_haml_tags
49
+
50
+ #generate HAML
51
+ output_haml
52
+
53
+ #output the html
54
+ @output_file.write(output_html)
55
+
56
+ #close the input file
57
+ @input_file.close()
58
+
59
+ #close the output file
60
+ @output_file.close()
61
+
62
+ puts "updated #{@output_name}!\n"
63
+ end
64
+
65
+ def render_sass
66
+ return _render_sass
67
+ end
68
+
69
+ def clean_sass
70
+ return _clean_sass
71
+ end
72
+
73
+ def build_hashes
74
+ return _build_hashes
75
+ end
76
+
77
+ def render_haml_tags
78
+ return _render_haml_tags
79
+ end
80
+
81
+ def output_haml
82
+ return _output_haml
83
+ end
84
+
85
+ def output_html
86
+ return _output_html
87
+ end
88
+
89
+
90
+ private
91
+
92
+
93
+ def _render_sass
94
+
95
+ #if input file is scss, output CSS and convert to SASS
96
+ #if input file is sass, output CSS and continue
97
+ #if input file is CSS, do below
98
+
99
+ #convert to SASS
100
+ content = @input_file.read
101
+ #remove all comments
102
+ content.gsub!(/\/\*([\s\S]*?)\*\//, "")
103
+ #render sass
104
+ @sass = Sass::CSS.new(content).render(:sass)
105
+ end
106
+
107
+ def _clean_sass
108
+ #remove all property: value; pairs
109
+ @sass.gsub!((/.*: .*/), "")
110
+ #remove duplicate new lines
111
+ @sass.gsub!((/\n+/), "\n")
112
+ end
113
+
114
+ def _build_hashes
115
+ i = 1
116
+ #parse into an array of hashes
117
+ @sass.each do |code|
118
+ hash = {
119
+ :line => i,
120
+ :select => _grab_select(code),
121
+ :tab => _grab_tab(code)
122
+ }
123
+ @tree << hash
124
+ i += 1
125
+ end
126
+ _check_for_parents
127
+ @tree
128
+ end
129
+
130
+ def _check_for_parents
131
+ #in each line
132
+ @tree.each do |hash|
133
+
134
+ #check each selector
135
+ hash[:select].each { |code|
136
+
137
+ #if the selector starts with &
138
+ if code.match("&")
139
+
140
+ #find the parent
141
+ hash[:parent] = @tree.find_parent(hash)[:line]
142
+
143
+ #find all the kids
144
+ _check_for_kids(hash)
145
+
146
+ end
147
+ }#end of hash[:select]
148
+
149
+ end #end of @tree.each
150
+
151
+ _process_parents_and_kids
152
+
153
+ end
154
+
155
+ def _process_parents_and_kids
156
+
157
+ #look for all parents & kids and modify them
158
+ @tree.each do |hash|
159
+
160
+ #if the hash has a parent
161
+ if hash[:parent]
162
+
163
+ #find the parent
164
+ parent = @tree.find_line(hash[:parent])
165
+
166
+ #if the selector array is only one
167
+ if parent[:select].length == 1
168
+
169
+ #replace the & with the parent selector
170
+ hash[:select].each do |elm|
171
+ elm.gsub!("&", parent[:select].first)
172
+ end
173
+
174
+ #update the tab to the parent tab
175
+ hash[:tab] = parent[:tab]
176
+ end
177
+
178
+ #if this hash has any kids
179
+ if hash[:kids]
180
+
181
+ #loop through each kid
182
+ hash[:kids].each do |kid|
183
+
184
+ #find the kid
185
+ child = @tree.find_line(kid)
186
+
187
+ #and decrease the tab by one
188
+ child[:tab] -= 1
189
+ end
190
+ end
191
+
192
+ end
193
+ end
194
+
195
+ end
196
+
197
+ def _check_for_kids(of_this_hash)
198
+
199
+ #target the line number
200
+ line_number = of_this_hash[:line] + 1
201
+
202
+ #find the line
203
+ found = @tree.find_line(line_number)
204
+
205
+ #finds the children
206
+ until found.nil? or found[:tab] <= of_this_hash[:tab]
207
+
208
+ #only create a kids hash if there are kids
209
+ if of_this_hash[:kids].nil?
210
+ of_this_hash[:kids] = []
211
+ end
212
+
213
+ #add the line to the kids array
214
+ of_this_hash[:kids] << found[:line]
215
+
216
+ #go up the tree
217
+ line_number += 1
218
+
219
+ #find the line
220
+ found = @tree.find_line(line_number)
221
+ end
222
+
223
+ end
224
+
225
+ def _grab_select(code)
226
+ result = []
227
+ temp = code.gsub(/\n/, "").gsub(/ /, "")
228
+ if temp.match(", ")
229
+ result = temp.split(", ")
230
+ else
231
+ result.push(temp)
232
+ end
233
+ end
234
+
235
+ def _grab_tab(code)
236
+ tmp = code[/[ \t]+/]
237
+ if !tmp.nil?
238
+ tmp = tmp.length / 2
239
+ else
240
+ tmp = 0
241
+ end
242
+ end
243
+
244
+ def _render_haml_tags
245
+ @tree.each do |code|
246
+ code[:haml] = []
247
+ code[:select].each do |tag|
248
+ code[:haml].push(_grab_haml_tag(tag))
249
+ end
250
+ end
251
+ @tree
252
+ end
253
+
254
+ def _grab_haml_tag(code)
255
+ #give all classes that start with . or # a DIV element
256
+ if code.match(/^\./) or code.match(/^\#/)
257
+ tag = "%div" + code
258
+ else
259
+ tag = "%" + code
260
+ end
261
+
262
+ #give all descending tags a %
263
+ if tag.match(" ")
264
+ tag = tag.gsub(" ", " %")
265
+ end
266
+ tag
267
+ end
268
+
269
+ #Output the HAML
270
+ def _output_haml
271
+ #convert to HAML
272
+ @haml = "%html\n"
273
+ @haml += "\t%head\n"
274
+ @haml += "\t\t%link{:type => 'text/css', :rel => 'stylesheet', :href => '#{@input_name}'}\n"
275
+ #@haml += "\t\t:javascript\n"
276
+ #@haml += "\t\t\tsetTimeout(function(){ parent.location.reload(true); }, 3000)\n"
277
+ @haml += "\t%body\n"
278
+ @tree.each do |hash|
279
+
280
+ #empty the kids
281
+ kids = []
282
+ tabs = "\t\t"
283
+
284
+ #set the base tab
285
+ if hash[:tab] > 0
286
+ tabs += "\t" * hash[:tab]
287
+ end
288
+
289
+ #if this code was generated from a parent, find the kids
290
+ if !hash[:parent].nil?
291
+ kids = @tree.find_all_kids(hash[:parent], hash[:line])
292
+ end
293
+
294
+ hash[:haml].each { |haml_tag|
295
+
296
+ @haml += _generate_haml_line(tabs, haml_tag, hash)
297
+
298
+ #if there were kids
299
+ if kids.length != 0
300
+ kids.each { |hash|
301
+
302
+ #reset the base tab
303
+ tabs = "\t\t"
304
+
305
+ #set the base tab
306
+ tabs += "\t" * hash[:tab]
307
+
308
+ hash[:haml].each do |haml_tag|
309
+ #generate the HAML
310
+ @haml += _generate_haml_line(tabs, haml_tag, hash)
311
+ end
312
+
313
+ }
314
+ end
315
+ }
316
+ end
317
+ @haml
318
+ end
319
+
320
+ def _generate_haml_line(tabs, element, hash, haml = "")
321
+
322
+ #handle a string of descending selectors
323
+ if element.match(" ")
324
+
325
+ #so we can give the right indent
326
+ tabs = "\t"
327
+ add_tab = 0
328
+
329
+ #collect the descending selectors
330
+ nests = element.split(" ")
331
+
332
+ #loop through them and generate the HAML
333
+ nests.each do |nest|
334
+
335
+ tabs += "\t"
336
+
337
+ #if this is the last descending selector, add content
338
+ if add_tab == nests.length - 1
339
+ haml += tabs + nest + _grab_content(hash)
340
+
341
+ #add a new line
342
+ else
343
+ haml += tabs + nest + "\n"
344
+ end
345
+
346
+ add_tab += 1
347
+ end
348
+
349
+ #otherwise per normal
350
+ else
351
+
352
+ #if the hash is from a parent
353
+ if !hash[:parent].nil?
354
+ tabs = "\t\t" + "\t" * @tree.find_line(hash[:parent])[:tab]
355
+ end
356
+
357
+ haml += tabs + element + _grab_content(hash)
358
+ end
359
+
360
+ #returns HAML
361
+ haml
362
+ end
363
+
364
+ #insert the inner content for HTML tags
365
+ def _grab_content(hash, found = "")
366
+
367
+ #find the next hash
368
+ next_hash = @tree.find_line(hash[:line] + 1)
369
+
370
+ #pick the content
371
+ if !next_hash.nil? && next_hash[:tab] > hash[:tab]
372
+ found = "\n"
373
+ else
374
+ found = " Inner content\n"
375
+ end
376
+
377
+ #if the hash has a parent
378
+ if !hash[:parent].nil?
379
+
380
+ #find the kids
381
+ kids = @tree.find_all_kids(hash[:parent], hash[:line])
382
+
383
+ #if there are no kids
384
+ if !kids.empty?
385
+ found = "\n"
386
+ end
387
+
388
+ end
389
+
390
+ found
391
+
392
+ end
393
+
394
+ def _output_html
395
+ #convert HAML to HAML
396
+ @html = Haml::Engine.new(@haml).render
397
+ @html
398
+ end
399
+ end
400
+
401
+ end