csses 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 1.0.0 / 2008-01-03
2
+
3
+ * 1 major enhancement
4
+ * Initial release as a gem!
@@ -0,0 +1,22 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/csses.rb
6
+ lib/csses_helpers.rb
7
+ rails_generators/csses/USAGE
8
+ rails_generators/csses/csses_generator.rb
9
+ rails_generators/csses/templates/application.css.erb
10
+ tasks/annotations.rake
11
+ tasks/doc.rake
12
+ tasks/gem.rake
13
+ tasks/manifest.rake
14
+ tasks/rubyforge.rake
15
+ tasks/setup.rb
16
+ tasks/spec.rake
17
+ tasks/test.rake
18
+ test/test_csses.rb
19
+ test/test_csses_helpers.rb
20
+ test/test_site/test_no_parens.html.erb
21
+ test/test_site/test_unless.html.erb
22
+ test/test_site/view.html.erb
@@ -0,0 +1,74 @@
1
+ csses
2
+ by Chris Shea
3
+ http://ruby.tie-rack.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Generate a clean CSS file based on your Rails view and helpers.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * All HTML elements handled
12
+ * Most Rails HTML helper methods handled
13
+ * Probably not perfect, but does a lot you would rather not have to
14
+ * Doesn't update the generated CSS, but soon it will
15
+
16
+ == SYNOPSIS:
17
+ In your RAILS_ROOT, run <tt>script/generate css</tt>
18
+
19
+ And it takes this:
20
+ <h1 id="pomp">The Grand Demonstration</h1>
21
+ <p class="wing">Super Mario Bros. 3 reference</p>
22
+ <%= image_tag('joy.png', :class => 'happy') %>
23
+ <%= link_to('Read', {:action => :read, :id => 4}, {:id => 'four'}) %>
24
+ <!-- and it works for form tags too -->
25
+
26
+ and makes this:
27
+ a {}
28
+ a:visited {}
29
+ a:hover {}
30
+ a:active {}
31
+ a#four {}
32
+ a#four:visited {}
33
+ a#four:hover {}
34
+ a#four:active {}
35
+ h1 {}
36
+ h1#pomp {}
37
+ img {}
38
+ img.happy {}
39
+ p {}
40
+ p.wing {}
41
+
42
+ == REQUIREMENTS:
43
+
44
+ * Rails 2.x
45
+ * HTML, raw or generated, in your views and helpers
46
+
47
+ == INSTALL:
48
+
49
+ * sudo gem install csses
50
+
51
+ == LICENSE:
52
+
53
+ (The MIT License)
54
+
55
+ Copyright (c) 2008 Christopher Shea
56
+
57
+ Permission is hereby granted, free of charge, to any person obtaining
58
+ a copy of this software and associated documentation files (the
59
+ 'Software'), to deal in the Software without restriction, including
60
+ without limitation the rights to use, copy, modify, merge, publish,
61
+ distribute, sublicense, and/or sell copies of the Software, and to
62
+ permit persons to whom the Software is furnished to do so, subject to
63
+ the following conditions:
64
+
65
+ The above copyright notice and this permission notice shall be
66
+ included in all copies or substantial portions of the Software.
67
+
68
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
69
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
70
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
71
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
72
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
73
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
74
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,23 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ load 'tasks/setup.rb'
6
+
7
+ ensure_in_path 'lib'
8
+ require 'csses'
9
+
10
+ task :default => 'spec:run'
11
+
12
+ PROJ.name = 'csses'
13
+ PROJ.summary = 'Generate a CSS slate for your Rails applications'
14
+ PROJ.authors = 'Chris Shea'
15
+ PROJ.email = 'chris@ruby.tie-rack.org'
16
+ PROJ.url = 'http://csses.rubyforge.org'
17
+ PROJ.description = paragraphs_of('README.txt', 1).join("\n\n")
18
+ PROJ.changes = paragraphs_of('History.txt', 0..1).join("\n\n")
19
+ PROJ.rubyforge_name = 'csses'
20
+
21
+ PROJ.spec_opts << '--color'
22
+
23
+ # EOF
@@ -0,0 +1,68 @@
1
+ # Ah... CSSes...
2
+
3
+ require 'csses_helpers'
4
+
5
+ # The CSSes class takes some files, figures out what HTML is referenced
6
+ # or generated in them, and puts those all into an array called elements.
7
+ class CSSes
8
+ VERSION = '1.0.0'
9
+
10
+ UNFASHIONABLE_ELEMENTS = %w(html head meta title)
11
+ RAILS_HELPERS = { /\blink_to\w*\b/ => 'a',
12
+ /\bimage_tag\b/ => 'img',
13
+ /\blabel\b/ => 'label',
14
+ /\bform(?:_(?:for|tag))\b/ => 'form',
15
+ /\btext_area(?:_tag)?\b/ => 'textarea',
16
+ /\btext_field(?:_tag)?\b/ => 'input',
17
+ /\bcheck_box_tag\b/ => 'input',
18
+ /\bfield_set_tag\b/ => 'fieldset',
19
+ /\bfile_field_tag\b/ => 'input',
20
+ /\bimage_submit_tag\b/ => 'input',
21
+ /\bpassword_field_tag\b/ => 'input',
22
+ /\bradio_button_tag\b/ => 'input',
23
+ /\bselect_tag\b/ => 'select',
24
+ /\bsubmit_tag\b/ => 'input' }
25
+ RAILS_HTML_ID_OR_CLASS = /(?::(id|class))\s*=>\s*['"](\w+)['"]/
26
+
27
+ attr_reader :elements
28
+
29
+ # Give it a list of files as an array (not splatted), get back, well,
30
+ # a CSS object, but one with an array of CSS elements as an attribute.
31
+ def initialize(files)
32
+ @elements = []
33
+ files.each do |file|
34
+ source = File.read(file)
35
+ @elements << source.scan(/<(\w+)/)
36
+ source.scan(/<(\w+)\s+[^>]*(class|id)="(\w+)"/).each do |elem|
37
+ @elements << "#{elem[0]}#{css_sym_for_attribute(elem[1])}#{elem[2]}"
38
+ end
39
+ RAILS_HELPERS.each do |regex, tag|
40
+ source.scan(/#{regex}.*/).each do |line|
41
+ if line.match(RAILS_HTML_ID_OR_CLASS)
42
+ @elements << "#{tag}#{css_sym_for_attribute($1)}#{$2}"
43
+ end
44
+ @elements << tag
45
+ end
46
+ end
47
+ end
48
+
49
+ @elements.flatten!
50
+ @elements.uniq!
51
+ @elements.sort!
52
+ @elements -= UNFASHIONABLE_ELEMENTS
53
+
54
+ apply_pseudo_classes!
55
+ end
56
+
57
+ private
58
+
59
+ # Generates the typical pseudo-classes for anchors (visited, hover, active).
60
+ def apply_pseudo_classes!
61
+ @elements.each_with_index do |e, i|
62
+ if e.match(/\Aa(?:[#\.]\w+)?/)
63
+ @elements[i] = [e, "#{e}:visited", "#{e}:hover", "#{e}:active"]
64
+ end
65
+ end
66
+ @elements.flatten!
67
+ end
68
+ end
@@ -0,0 +1,15 @@
1
+ # Assuming there will be more than one method here one day,
2
+ # this file is called csses_helpers.rb.
3
+
4
+ # You know how CSS selectors use the octothorpe for IDs
5
+ # and the dot for classes? This translates that.
6
+ def css_sym_for_attribute(attribute)
7
+ case attribute
8
+ when 'id'
9
+ '#'
10
+ when 'class'
11
+ '.'
12
+ else
13
+ raise ArgumentError
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Generates public/stylesheets/application.css based on the appearance
3
+ of html elements in your views and helpers.
4
+
5
+ Example:
6
+ ./script/generate css
7
+
8
+ This will create:
9
+ public/stylesheets/application.css
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '../../lib')
2
+
3
+ require 'csses'
4
+ class CssesGenerator < Rails::Generator::Base
5
+ attr_reader :css
6
+
7
+ def initialize(*args)
8
+ super
9
+ files_to_scan = Dir.glob('app/views/**/*.erb') + Dir.glob('app/helpers/*.rb')
10
+ @css = CSSes.new(files_to_scan)
11
+ end
12
+
13
+ def manifest
14
+ record do |m|
15
+ m.directory "public/stylesheets"
16
+ m.template 'application.css.erb', 'public/stylesheets/application.css'
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,4 @@
1
+ <% css.elements.each do |element| -%>
2
+ <%= element %> {}
3
+
4
+ <% end -%>
@@ -0,0 +1,30 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ desc "Enumerate all annotations"
6
+ task :notes do
7
+ Bones::AnnotationExtractor.enumerate(
8
+ PROJ, "OPTIMIZE|FIXME|TODO", :tag => true)
9
+ end
10
+
11
+ namespace :notes do
12
+ desc "Enumerate all OPTIMIZE annotations"
13
+ task :optimize do
14
+ Bones::AnnotationExtractor.enumerate(PROJ, "OPTIMIZE")
15
+ end
16
+
17
+ desc "Enumerate all FIXME annotations"
18
+ task :fixme do
19
+ Bones::AnnotationExtractor.enumerate(PROJ, "FIXME")
20
+ end
21
+
22
+ desc "Enumerate all TODO annotations"
23
+ task :todo do
24
+ Bones::AnnotationExtractor.enumerate(PROJ, "TODO")
25
+ end
26
+ end
27
+
28
+ end # if HAVE_BONES
29
+
30
+ # EOF
@@ -0,0 +1,49 @@
1
+ # $Id$
2
+
3
+ require 'rake/rdoctask'
4
+
5
+ namespace :doc do
6
+
7
+ desc 'Generate RDoc documentation'
8
+ Rake::RDocTask.new do |rd|
9
+ rd.main = PROJ.rdoc_main
10
+ rd.options << '-d' if !WIN32 and `which dot` =~ %r/\/dot/
11
+ rd.rdoc_dir = PROJ.rdoc_dir
12
+
13
+ incl = Regexp.new(PROJ.rdoc_include.join('|'))
14
+ excl = Regexp.new(PROJ.rdoc_exclude.join('|'))
15
+ files = PROJ.files.find_all do |fn|
16
+ case fn
17
+ when excl; false
18
+ when incl; true
19
+ else false end
20
+ end
21
+ rd.rdoc_files.push(*files)
22
+
23
+ title = "#{PROJ.name}-#{PROJ.version} Documentation"
24
+ title = "#{PROJ.rubyforge_name}'s " + title if PROJ.rubyforge_name != title
25
+
26
+ rd.options << "-t #{title}"
27
+ end
28
+
29
+ desc 'Generate ri locally for testing'
30
+ task :ri => :clobber_ri do
31
+ sh "#{RDOC} --ri -o ri ."
32
+ end
33
+
34
+ desc 'Remove ri products'
35
+ task :clobber_ri do
36
+ rm_r 'ri' rescue nil
37
+ end
38
+
39
+ end # namespace :doc
40
+
41
+ desc 'Alias to doc:rdoc'
42
+ task :doc => 'doc:rdoc'
43
+
44
+ desc 'Remove all build products'
45
+ task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
46
+
47
+ remove_desc_for_task %w(doc:clobber_rdoc doc:clobber_ri)
48
+
49
+ # EOF
@@ -0,0 +1,89 @@
1
+ # $Id$
2
+
3
+ require 'rake/gempackagetask'
4
+
5
+ namespace :gem do
6
+
7
+ PROJ.spec = Gem::Specification.new do |s|
8
+ s.name = PROJ.name
9
+ s.version = PROJ.version
10
+ s.summary = PROJ.summary
11
+ s.authors = Array(PROJ.authors)
12
+ s.email = PROJ.email
13
+ s.homepage = Array(PROJ.url).first
14
+ s.rubyforge_project = PROJ.rubyforge_name
15
+
16
+ s.description = PROJ.description
17
+
18
+ PROJ.dependencies.each do |dep|
19
+ s.add_dependency(*dep)
20
+ end
21
+
22
+ s.files = PROJ.files
23
+ s.executables = PROJ.executables.map {|fn| File.basename(fn)}
24
+ s.extensions = PROJ.files.grep %r/extconf\.rb$/
25
+
26
+ s.bindir = 'bin'
27
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
28
+ s.require_paths = dirs unless dirs.empty?
29
+
30
+ incl = Regexp.new(PROJ.rdoc_include.join('|'))
31
+ excl = PROJ.rdoc_exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
32
+ excl = Regexp.new(excl.join('|'))
33
+ rdoc_files = PROJ.files.find_all do |fn|
34
+ case fn
35
+ when excl; false
36
+ when incl; true
37
+ else false end
38
+ end
39
+ s.rdoc_options = PROJ.rdoc_opts + ['--main', PROJ.rdoc_main]
40
+ s.extra_rdoc_files = rdoc_files
41
+ s.has_rdoc = true
42
+
43
+ if test ?f, PROJ.test_file
44
+ s.test_file = PROJ.test_file
45
+ else
46
+ s.test_files = PROJ.tests.to_a
47
+ end
48
+
49
+ # Do any extra stuff the user wants
50
+ # spec_extras.each do |msg, val|
51
+ # case val
52
+ # when Proc
53
+ # val.call(s.send(msg))
54
+ # else
55
+ # s.send "#{msg}=", val
56
+ # end
57
+ # end
58
+ end
59
+
60
+ desc 'Show information about the gem'
61
+ task :debug do
62
+ puts PROJ.spec.to_ruby
63
+ end
64
+
65
+ Rake::GemPackageTask.new(PROJ.spec) do |pkg|
66
+ pkg.need_tar = PROJ.need_tar
67
+ pkg.need_zip = PROJ.need_zip
68
+ end
69
+
70
+ desc 'Install the gem'
71
+ task :install => [:clobber, :package] do
72
+ sh "#{SUDO} #{GEM} install pkg/#{PROJ.spec.file_name}"
73
+ end
74
+
75
+ desc 'Uninstall the gem'
76
+ task :uninstall do
77
+ sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' #{PROJ.name}"
78
+ end
79
+
80
+ end # namespace :gem
81
+
82
+ desc 'Alias to gem:package'
83
+ task :gem => 'gem:package'
84
+
85
+ task :clobber => 'gem:clobber_package'
86
+
87
+ remove_desc_for_task %w(gem:clobber_package)
88
+
89
+ # EOF
@@ -0,0 +1,41 @@
1
+ # $Id$
2
+
3
+ require 'find'
4
+
5
+ namespace :manifest do
6
+
7
+ desc 'Verify the manifest'
8
+ task :check do
9
+ fn = 'Manifest.tmp'
10
+ files = []
11
+ exclude = Regexp.new(PROJ.exclude.join('|'))
12
+ Find.find '.' do |path|
13
+ path.sub! %r/^(\.\/|\/)/o, ''
14
+ next unless test ?f, path
15
+ next if path =~ exclude
16
+ files << path
17
+ end
18
+
19
+ File.open(fn, 'w') {|fp| fp.puts files.sort}
20
+ system "#{DIFF} -du Manifest.txt #{fn}"
21
+ rm fn rescue nil
22
+ end
23
+
24
+ desc 'Create a new manifest'
25
+ task :create do
26
+ fn = 'Manifest.txt'
27
+ files = []
28
+ exclude = Regexp.new(PROJ.exclude.join('|'))
29
+ Find.find '.' do |path|
30
+ path.sub! %r/^(\.\/|\/)/o, ''
31
+ next unless test ?f, path
32
+ next if path =~ exclude
33
+ files << path
34
+ end
35
+
36
+ files << fn unless test ?f, fn
37
+ File.open(fn, 'w') {|fp| fp.puts files.sort}
38
+ end
39
+ end
40
+
41
+ # EOF
@@ -0,0 +1,57 @@
1
+ # $Id$
2
+
3
+ if PROJ.rubyforge_name && HAVE_RUBYFORGE
4
+
5
+ require 'rubyforge'
6
+ require 'rake/contrib/sshpublisher'
7
+
8
+ namespace :gem do
9
+ desc 'Package and upload to RubyForge'
10
+ task :release => [:clobber, :package] do |t|
11
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
12
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
13
+ pkg = "pkg/#{PROJ.spec.full_name}"
14
+
15
+ if $DEBUG then
16
+ puts "release_id = rf.add_release #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, #{PROJ.version.inspect}, \"#{pkg}.tgz\""
17
+ puts "rf.add_file #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, release_id, \"#{pkg}.gem\""
18
+ end
19
+
20
+ rf = RubyForge.new
21
+ puts 'Logging in'
22
+ rf.login
23
+
24
+ c = rf.userconfig
25
+ c['release_notes'] = PROJ.description if PROJ.description
26
+ c['release_changes'] = PROJ.changes if PROJ.changes
27
+ c['preformatted'] = true
28
+
29
+ files = [(PROJ.need_tar ? "#{pkg}.tgz" : nil),
30
+ (PROJ.need_zip ? "#{pkg}.zip" : nil),
31
+ "#{pkg}.gem"].compact
32
+
33
+ puts "Releasing #{PROJ.name} v. #{PROJ.version}"
34
+ rf.add_release PROJ.rubyforge_name, PROJ.name, PROJ.version, *files
35
+ end
36
+ end # namespace :gem
37
+
38
+
39
+ namespace :doc do
40
+ desc "Publish RDoc to RubyForge"
41
+ task :release => %w(doc:clobber_rdoc doc:rdoc) do
42
+ config = YAML.load(
43
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
44
+ )
45
+
46
+ host = "#{config['username']}@rubyforge.org"
47
+ remote_dir = "/var/www/gforge-projects/#{PROJ.rubyforge_name}/"
48
+ remote_dir << PROJ.rdoc_remote_dir || PROJ.name
49
+ local_dir = PROJ.rdoc_dir
50
+
51
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
52
+ end
53
+ end # namespace :doc
54
+
55
+ end # if HAVE_RUBYFORGE
56
+
57
+ # EOF
@@ -0,0 +1,144 @@
1
+ # $Id$
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'fileutils'
6
+ require 'ostruct'
7
+
8
+ PROJ = OpenStruct.new
9
+
10
+ PROJ.name = nil
11
+ PROJ.summary = nil
12
+ PROJ.description = nil
13
+ PROJ.changes = nil
14
+ PROJ.authors = nil
15
+ PROJ.email = nil
16
+ PROJ.url = nil
17
+ PROJ.version = ENV['VERSION'] || '0.0.0'
18
+ PROJ.rubyforge_name = nil
19
+ PROJ.exclude = %w(tmp$ bak$ ~$ CVS \.svn ^pkg ^doc)
20
+
21
+ # Rspec
22
+ PROJ.specs = FileList['spec/**/*_spec.rb']
23
+ PROJ.spec_opts = []
24
+
25
+ # Test::Unit
26
+ PROJ.tests = FileList['test/**/test_*.rb']
27
+ PROJ.test_file = 'test/all.rb'
28
+ PROJ.test_opts = []
29
+
30
+ # Rcov
31
+ PROJ.rcov_opts = ['--sort', 'coverage', '-T']
32
+
33
+ # Rdoc
34
+ PROJ.rdoc_opts = []
35
+ PROJ.rdoc_include = %w(^lib ^bin ^ext txt$)
36
+ PROJ.rdoc_exclude = %w(extconf\.rb$ ^Manifest\.txt$)
37
+ PROJ.rdoc_main = 'README.txt'
38
+ PROJ.rdoc_dir = 'doc'
39
+ PROJ.rdoc_remote_dir = nil
40
+
41
+ # Extensions
42
+ PROJ.extensions = FileList['ext/**/extconf.rb']
43
+ PROJ.ruby_opts = %w(-w)
44
+ PROJ.libs = []
45
+ %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
46
+
47
+ # Gem Packaging
48
+ PROJ.files =
49
+ if test ?f, 'Manifest.txt'
50
+ files = File.readlines('Manifest.txt').map {|fn| fn.chomp.strip}
51
+ files.delete ''
52
+ files
53
+ else [] end
54
+ PROJ.executables = PROJ.files.find_all {|fn| fn =~ %r/^bin/}
55
+ PROJ.dependencies = []
56
+ PROJ.need_tar = true
57
+ PROJ.need_zip = false
58
+
59
+ # File Annotations
60
+ PROJ.annotation_exclude = []
61
+ PROJ.annotation_extensions = %w(.txt .rb .erb) << ''
62
+
63
+ # Load the other rake files in the tasks folder
64
+ Dir.glob('tasks/*.rake').sort.each {|fn| import fn}
65
+
66
+ # Setup some constants
67
+ WIN32 = %r/win32/ =~ RUBY_PLATFORM unless defined? WIN32
68
+
69
+ DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
70
+
71
+ def quiet( &block )
72
+ io = [STDOUT.dup, STDERR.dup]
73
+ STDOUT.reopen DEV_NULL
74
+ STDERR.reopen DEV_NULL
75
+ block.call
76
+ ensure
77
+ STDOUT.reopen io.first
78
+ STDERR.reopen io.last
79
+ end
80
+
81
+ DIFF = if WIN32 then 'diff.exe'
82
+ else
83
+ if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
84
+ else 'diff' end
85
+ end unless defined? DIFF
86
+
87
+ SUDO = if WIN32 then ''
88
+ else
89
+ if quiet {system 'which sudo'} then 'sudo'
90
+ else '' end
91
+ end
92
+
93
+ RCOV = WIN32 ? 'rcov.cmd' : 'rcov'
94
+ GEM = WIN32 ? 'gem.cmd' : 'gem'
95
+
96
+ %w(rcov spec/rake/spectask rubyforge bones).each do |lib|
97
+ begin
98
+ require lib
99
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
100
+ rescue LoadError
101
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", false}
102
+ end
103
+ end
104
+
105
+ # Reads a file at +path+ and spits out an array of the +paragraphs+
106
+ # specified.
107
+ #
108
+ # changes = paragraphs_of('History.txt', 0..1).join("\n\n")
109
+ # summary, *description = paragraphs_of('README.txt', 3, 3..8)
110
+ #
111
+ def paragraphs_of(path, *paragraphs)
112
+ File.read(path).delete("\r").split(/\n\n+/).values_at(*paragraphs)
113
+ end
114
+
115
+ # Adds the given gem _name_ to the current project's dependency list. An
116
+ # optional gem _version_ can be given. If omitted, the newest gem version
117
+ # will be used.
118
+ #
119
+ def depend_on( name, version = nil )
120
+ spec = Gem.source_index.find_name(name).last
121
+ version = spec.version.to_s if version.nil? and !spec.nil?
122
+
123
+ PROJ.dependencies << (version.nil? ? [name] : [name, ">= #{version}"])
124
+ end
125
+
126
+ # Adds the given _path_ to the include path if it is not already there
127
+ #
128
+ def ensure_in_path( path )
129
+ path = File.expand_path(path)
130
+ $:.unshift(path) if test(?d, path) and not $:.include?(path)
131
+ end
132
+
133
+ # Find a rake task using the task name and remove any description text. This
134
+ # will prevent the task from being displayed in the list of available tasks.
135
+ #
136
+ def remove_desc_for_task( names )
137
+ Array(names).each do |task_name|
138
+ task = Rake.application.tasks.find {|t| t.name == task_name}
139
+ next if task.nil?
140
+ task.instance_variable_set :@comment, nil
141
+ end
142
+ end
143
+
144
+ # EOF
@@ -0,0 +1,40 @@
1
+ # $Id$
2
+
3
+ if HAVE_SPEC_RAKE_SPECTASK
4
+
5
+ namespace :spec do
6
+
7
+ desc 'Run all specs with basic output'
8
+ Spec::Rake::SpecTask.new(:run) do |t|
9
+ t.spec_opts = PROJ.spec_opts
10
+ t.spec_files = PROJ.specs
11
+ end
12
+
13
+ desc 'Run all specs with text output'
14
+ Spec::Rake::SpecTask.new(:specdoc) do |t|
15
+ t.spec_opts = PROJ.spec_opts + ['--format', 'specdoc']
16
+ t.spec_files = PROJ.specs
17
+ end
18
+
19
+ if HAVE_RCOV
20
+ desc 'Run all specs with RCov'
21
+ Spec::Rake::SpecTask.new(:rcov) do |t|
22
+ t.spec_opts = PROJ.spec_opts
23
+ t.spec_files = PROJ.specs
24
+ t.rcov = true
25
+ t.rcov_opts = PROJ.rcov_opts + ['--exclude', 'spec']
26
+ end
27
+ end
28
+
29
+ end # namespace :spec
30
+
31
+ desc 'Alias to spec:run'
32
+ task :spec => 'spec:run'
33
+
34
+ task :clobber => 'spec:clobber_rcov' if HAVE_RCOV
35
+
36
+ remove_desc_for_task %w(spec:clobber_rcov)
37
+
38
+ end # if HAVE_SPEC_RAKE_SPECTASK
39
+
40
+ # EOF
@@ -0,0 +1,40 @@
1
+ # $Id$
2
+
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+
7
+ Rake::TestTask.new(:run) do |t|
8
+ t.libs = PROJ.libs
9
+ t.test_files = if test ?f, PROJ.test_file then [PROJ.test_file]
10
+ else PROJ.tests end
11
+ t.ruby_opts += PROJ.ruby_opts
12
+ t.ruby_opts += PROJ.test_opts
13
+ end
14
+
15
+ if HAVE_RCOV
16
+ desc 'Run rcov on the unit tests'
17
+ task :rcov => :clobber_rcov do
18
+ opts = PROJ.rcov_opts.join(' ')
19
+ files = if test ?f, PROJ.test_file then [PROJ.test_file]
20
+ else PROJ.tests end
21
+ files = files.join(' ')
22
+ sh "#{RCOV} #{files} #{opts}"
23
+ end
24
+
25
+ desc 'Remove rcov products'
26
+ task :clobber_rcov do
27
+ rm_r 'coverage' rescue nil
28
+ end
29
+ end
30
+
31
+ end # namespace :test
32
+
33
+ desc 'Alias to test:run'
34
+ task :test => 'test:run'
35
+
36
+ task :clobber => 'test:clobber_rcov' if HAVE_RCOV
37
+
38
+ remove_desc_for_task %w(test:clobber_rcov)
39
+
40
+ # EOF
@@ -0,0 +1,108 @@
1
+ require 'test/unit'
2
+ require 'lib/csses'
3
+
4
+ module Test::Unit::Assertions
5
+ def assert_include(item, obj, message = nil)
6
+ assert_respond_to obj, :include?
7
+ message ||= "#{obj.inspect}\ndoes not include\n#{item.inspect}."
8
+ assert_block message do obj.include? item end
9
+ end
10
+
11
+ def deny_include(item, obj, message = nil)
12
+ assert_respond_to obj, :include?
13
+ message ||= "#{obj.inspect} includes #{item.inspect}."
14
+ assert_block message do !obj.include? item end
15
+ end
16
+
17
+ # Thanks ZenTest!
18
+ end
19
+
20
+ class CSSesTest < Test::Unit::TestCase
21
+
22
+ def setup
23
+ files = Dir.glob('test/test_site/*')
24
+ @css = CSSes.new(files)
25
+ @css_unless = CSSes.new(['test/test_site/test_unless.html.erb'])
26
+ @css_without_parens = CSSes.new(['test/test_site/test_no_parens.html.erb'])
27
+ @css_without_anything = CSSes.new([])
28
+ end
29
+
30
+ def test_000_no_unfashionable_elements
31
+ CSSes::UNFASHIONABLE_ELEMENTS.each do |not_allowed|
32
+ deny_include(not_allowed, @css.elements)
33
+ end
34
+ end
35
+
36
+ def test_001_h1
37
+ assert_include('h1', @css.elements)
38
+ end
39
+
40
+ def test_002_h1_with_id
41
+ assert_include('h1#h1_id', @css.elements, 'CSS should include entries for ids')
42
+ end
43
+
44
+ def test_003_h1_with_class
45
+ assert_include('h1.h1_class', @css.elements, 'CSS should include entries for classes')
46
+ end
47
+
48
+ def test_004_link_to
49
+ assert_include('a', @css.elements, 'CSS should know that link_to makes anchors')
50
+ end
51
+
52
+ def test_005_link_to_without_parens
53
+ assert_include('a', @css_without_parens.elements, 'CSS should handle parenthesis-less helper calls')
54
+ end
55
+
56
+ def test_006_link_to_unless
57
+ assert_include('a', @css_unless.elements, 'CSS should know that link_to_unless makes anchors')
58
+ end
59
+
60
+ def test_007_anchor_pseudo_class_visited
61
+ assert_include('a:visited', @css.elements, 'CSS should create the visited pseudo-class for anchors')
62
+ end
63
+
64
+ def test_008_anchor_pseudo_class_hover
65
+ assert_include('a:hover', @css.elements, 'CSS should create the hover pseudo-class for anchors')
66
+ end
67
+
68
+ def test_009_anchor_pseudo_class_active
69
+ assert_include('a:active', @css.elements, 'CSS should create the active pseudo-class for anchors')
70
+ end
71
+
72
+ def test_010_anchor_pseudo_class_with_id
73
+ assert_include('a#a_id:visited', @css.elements, 'CSS should handle ids with pseudoclasses')
74
+ end
75
+
76
+ def test_011_anchor_pseudo_class_with_class
77
+ assert_include('a.a_class:hover', @css.elements, 'CSS should handle classes with pseudoclasses')
78
+ end
79
+
80
+ def test_012_image_tag
81
+ assert_include('img', @css.elements, 'CSS should know that image_tag makes img tags')
82
+ end
83
+
84
+ def test_013_image_tag_with_id
85
+ assert_include('img#img_id', @css.elements, 'CSS should handle image_tags with ids')
86
+ end
87
+
88
+ def test_014_image_tag_with_class
89
+ assert_include('img.img_class', @css.elements, 'CSS should handle image_tags with classes')
90
+ end
91
+
92
+ def test_015_link_to_with_id
93
+ assert_include('a#link_to_id', @css.elements, 'CSS should handle link_to with ids')
94
+ end
95
+
96
+ def test_016_link_to_with_class
97
+ assert_include('a.link_to_class', @css.elements, 'CSS should handle link_to with classes')
98
+ end
99
+
100
+ def test_017_link_to_with_rails_id_not_html_id
101
+ deny_include('a#not_an_html_id', @css.elements, "CSS shouldn't fall for rails ids in link_to calls")
102
+ end
103
+
104
+ def test_018_form_helpers
105
+ assert_include('label#label_id', @css.elements, 'CSS should handle labels')
106
+ end
107
+
108
+ end
@@ -0,0 +1,13 @@
1
+ class TestCSSesHelpers < Test::Unit::TestCase
2
+ def test_001_css_sym_for_attribute_with_class
3
+ assert_equal('.', css_sym_for_attribute('class'))
4
+ end
5
+
6
+ def test_002_css_sym_for_attribute_with_id
7
+ assert_equal('#', css_sym_for_attribute('id'))
8
+ end
9
+
10
+ def test_003_css_sym_for_attribute_on_junk
11
+ assert_raise(ArgumentError) { css_sym_for_attribute('junk') }
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ <%= link_to 'No parens', 'http://www.google.com' %>
@@ -0,0 +1 @@
1
+ <%= link_to_unless(false, 'Test link_to_unless', 'http://example.com') %>
@@ -0,0 +1,23 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
4
+ <title>Test View</title>
5
+ </head>
6
+ <body id="view.html">
7
+ <h1>Heading</h1>
8
+ <h1 id="h1_id">Heading with ID</h1>
9
+ <h1 class="h1_class">Heading with class</h1>
10
+
11
+ <%= link_to('Test link_to', 'http://example.com') %>
12
+
13
+ <a href="http://soveryverymuchclass" class="a_class">Test classes with pseudoclasses</a>
14
+ <a href="http://ihaveatotallycoolidentity" id="a_id">Test ids with pseudoclasses</a>
15
+ <%= image_tag('portrait_of_the_artist.gif') %>
16
+ <%= image_tag('baltimore_orioles.jpg', :class => 'img_class') %>
17
+ <%= image_tag('sideways_pony.png', :id => 'img_id') %>
18
+ <%= link_to('Test link_to with id', {:controller => 'test'}, {:id => 'link_to_id'}) %>
19
+ <%= link_to('Test link_to with class', {:action => 'test'}, {:class => 'link_to_class'}) %>
20
+ <%= link_to('Test link_to with resource id, no html id', :action => 'test', :id => not_an_html_id) %>
21
+
22
+ <%= label(:test, :test_title, 'A Test Title', :id => 'label_id') %>
23
+ </body>
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: csses
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Shea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-01-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: "== DESCRIPTION: Generate a clean CSS file based on your Rails view and helpers."
17
+ email: chris@ruby.tie-rack.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - History.txt
24
+ - README.txt
25
+ files:
26
+ - History.txt
27
+ - Manifest.txt
28
+ - README.txt
29
+ - Rakefile
30
+ - lib/csses.rb
31
+ - lib/csses_helpers.rb
32
+ - rails_generators/csses/USAGE
33
+ - rails_generators/csses/csses_generator.rb
34
+ - rails_generators/csses/templates/application.css.erb
35
+ - tasks/annotations.rake
36
+ - tasks/doc.rake
37
+ - tasks/gem.rake
38
+ - tasks/manifest.rake
39
+ - tasks/rubyforge.rake
40
+ - tasks/setup.rb
41
+ - tasks/spec.rake
42
+ - tasks/test.rake
43
+ - test/test_csses.rb
44
+ - test/test_csses_helpers.rb
45
+ - test/test_site/test_no_parens.html.erb
46
+ - test/test_site/test_unless.html.erb
47
+ - test/test_site/view.html.erb
48
+ has_rdoc: true
49
+ homepage: http://csses.rubyforge.org
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --main
53
+ - README.txt
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: csses
71
+ rubygems_version: 1.0.1
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Generate a CSS slate for your Rails applications
75
+ test_files:
76
+ - test/test_csses.rb
77
+ - test/test_csses_helpers.rb