epic 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ == 0.0.4 2010-01-30
2
+ * major enhancements
3
+ * compression and validation performed by instances rather the class
4
+ * minor enhancements
5
+ * don't growl and raise errors on validation, just display errors
6
+ * internal refactoring
7
+
1
8
  == 0.0.3 2010-01-25
2
9
  * major enhancements
3
10
  * added YUI compressor to compress JavaScript and CSS
data/Rakefile CHANGED
@@ -30,6 +30,7 @@ end
30
30
  Spec::Rake::SpecTask.new(:rcov) do |spec|
31
31
  spec.libs << 'lib' << 'spec'
32
32
  spec.pattern = 'spec/**/*_spec.rb'
33
+ spec.rcov_opts = ['--exclude', '.gem,Library,spec', '--sort', 'coverage']
33
34
  spec.rcov = true
34
35
  end
35
36
 
@@ -52,3 +53,8 @@ Rake::RDocTask.new do |rdoc|
52
53
  rdoc.rdoc_files.include('README*')
53
54
  rdoc.rdoc_files.include('lib/**/*.rb')
54
55
  end
56
+
57
+ require 'cucumber/rake/task'
58
+ Cucumber::Rake::Task.new do |t|
59
+ t.cucumber_opts = "--format pretty"
60
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{epic}
8
- s.version = "0.0.3"
8
+ s.version = "0.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jeff Coleman"]
12
- s.date = %q{2010-01-25}
12
+ s.date = %q{2010-01-30}
13
13
  s.default_executable = %q{epic}
14
14
  s.description = %q{Epic validator, wraps validation for HTML, JavaScript and CSS.}
15
15
  s.email = %q{progressions@gmail.com}
@@ -29,15 +29,36 @@ Gem::Specification.new do |s|
29
29
  "VERSION",
30
30
  "bin/epic",
31
31
  "epic.gemspec",
32
+ "features/compressor.feature",
33
+ "features/data/html/invalid.html",
34
+ "features/data/html/valid.html",
35
+ "features/data/javascripts/invalid.js",
36
+ "features/data/javascripts/invalid_uncompressed.js",
37
+ "features/data/javascripts/pre_compressed.js",
38
+ "features/data/javascripts/pre_compressed.js.min",
39
+ "features/data/javascripts/valid.js",
40
+ "features/data/javascripts/valid_uncompressed.js",
41
+ "features/data/stylesheets/valid.css",
42
+ "features/step_definitions/compressor_steps.rb",
43
+ "features/step_definitions/file_steps.rb",
44
+ "features/step_definitions/validator_steps.rb",
45
+ "features/support/env.rb",
46
+ "features/validator.feature",
32
47
  "lib/epic.rb",
33
48
  "lib/epic/base.rb",
34
49
  "lib/epic/compressor.rb",
50
+ "lib/epic/errors.rb",
35
51
  "lib/epic/validator.rb",
52
+ "lib/epic/validator/base.rb",
53
+ "lib/epic/validator/html.rb",
54
+ "lib/epic/validator/javascript.rb",
55
+ "lib/epic/validator/json.rb",
56
+ "lib/epic/validator/stylesheet.rb",
36
57
  "spec/compressor_spec.rb",
37
- "spec/epic_spec.rb",
38
58
  "spec/spec.opts",
39
59
  "spec/spec_helper.rb",
40
60
  "spec/stubs.rb",
61
+ "spec/validator_spec.rb",
41
62
  "vendor/ext/js.jar",
42
63
  "vendor/ext/jslint.js",
43
64
  "vendor/ext/yuicompressor-2.4.2.jar"
@@ -49,9 +70,9 @@ Gem::Specification.new do |s|
49
70
  s.summary = %q{Epic validation of HTML, JavaScript and CSS}
50
71
  s.test_files = [
51
72
  "spec/compressor_spec.rb",
52
- "spec/epic_spec.rb",
53
73
  "spec/spec_helper.rb",
54
- "spec/stubs.rb"
74
+ "spec/stubs.rb",
75
+ "spec/validator_spec.rb"
55
76
  ]
56
77
 
57
78
  if s.respond_to? :specification_version then
@@ -0,0 +1,29 @@
1
+
2
+ Feature: Compress JavaScript and Stylesheet files
3
+
4
+ Background:
5
+ Given I configure Epic::Base
6
+
7
+ Scenario: Compress a valid JavaScript file
8
+ Given I compress the file "javascripts/valid_uncompressed.js"
9
+ And I open the file "javascripts/valid_uncompressed.js.min"
10
+ Then I should see "var hello\=function\(a\)"
11
+ And no exceptions should have been raised
12
+ And I remove the file "javascripts/valid_uncompressed.js.min"
13
+
14
+ Scenario: Compress an invalid JavaScript file
15
+ Given I compress the file "javascripts/invalid_uncompressed.js"
16
+ Then an exception should have been raised with the message "JavaScript errors"
17
+
18
+ Scenario: Don't re-compress if compressed file exists
19
+ Given I compress the file "javascripts/pre_compressed.js"
20
+ And I open the file "javascripts/pre_compressed.js.min"
21
+ Then I should see "function alreadyCompressed\(b\)"
22
+
23
+ Scenario: Raise an error if the original file doesn't exist
24
+ Given I compress the file "javascripts/nonexistent.js"
25
+ Then an exception should have been raised with the message "No such file or directory"
26
+
27
+
28
+
29
+
@@ -0,0 +1,12 @@
1
+ <html>
2
+ <head>
3
+ <title>Title of valid HTML file</title>
4
+ </head>
5
+
6
+ <body>
7
+ <p>Hello</p>
8
+ <span>
9
+ <div>This div is inside a span</div>
10
+ </span>
11
+ </body>
12
+ </html>
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <title>Title of valid HTML file</title>
4
+ </head>
5
+
6
+ <body>
7
+ <p>Hello</p>
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ alert("hello")
@@ -0,0 +1,3 @@
1
+ var hello = function() {
2
+ alert("My name is" name)
3
+ };
@@ -0,0 +1,3 @@
1
+ function preCompressed(name) {
2
+ alert("I'm precompressed " + name);
3
+ };
@@ -0,0 +1 @@
1
+ function alreadyCompressed(b){alert("I'm precompressed "+a);}
@@ -0,0 +1 @@
1
+ alert("hello");
@@ -0,0 +1,3 @@
1
+ var hello = function(name) {
2
+ alert("My name is" + name);
3
+ };
@@ -0,0 +1,3 @@
1
+ p {
2
+ color: red;
3
+ }
@@ -0,0 +1,9 @@
1
+ Given %r{I compress the file "([^\"]*)"} do |filename|
2
+ path = "#{BASE_PATH}/#{filename}"
3
+
4
+ begin
5
+ Epic::Compressor.new(path).compress
6
+ rescue StandardError => e
7
+ @exceptions << e.message
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ Given %r{the file "([^\"]*)" exists with "([^\"]*)"} do |filename, content|
2
+ content.gsub!("\\n", "\n")
3
+ File.open("#{BASE_PATH}/#{filename}", "w") do |f|
4
+ content.split("\n").each do |line|
5
+ f.puts line
6
+ end
7
+ end
8
+ @files << "#{BASE_PATH}/#{filename}"
9
+ end
10
+
11
+ And %r{I remove the file "([^\"]*)"} do |filename|
12
+ system "rm #{BASE_PATH}/#{filename}"
13
+ end
14
+
15
+ When %r{I open the file "([^\"]*)"} do |filename|
16
+ @current_file = File.read("#{BASE_PATH}/#{filename}")
17
+ end
18
+
19
+ Then %r{I should see "([^\"]*)"} do |content|
20
+ @current_file.should match(Regexp.new(content))
21
+ end
22
+
23
+ Then %r{I should not see "([^\"]*)"} do |content|
24
+ @current_file.should_not match(Regexp.new(content))
25
+ end
@@ -0,0 +1,38 @@
1
+ Given %r{I configure Epic::Base} do
2
+ Epic::Base.configure do |config|
3
+ config.base_path = "#{BASE_PATH}"
4
+ end
5
+ end
6
+
7
+ Given %r{the file "([^\"]*)" should be valid} do |filename|
8
+ if filename =~ /\.html$/
9
+ @validator = Epic::Validator::HTML.new
10
+ elsif filename =~ /\.js$/
11
+ @validator = Epic::Validator::JavaScript.new
12
+ end
13
+ @validator.validate("#{BASE_PATH}/#{filename}").should be_true
14
+ end
15
+
16
+ Given %r{the file "([^\"]*)" should not be valid} do |filename|
17
+ if filename =~ /\.html$/
18
+ @validator = Epic::Validator::HTML.new
19
+ @validator.validate("#{BASE_PATH}/#{filename}").should be_false
20
+ elsif filename =~ /\.js$/
21
+ @validator = Epic::Validator::JavaScript.new
22
+ @validator.validate("#{BASE_PATH}/#{filename}").should be_false
23
+ end
24
+ end
25
+
26
+ Then /^an exception should have been raised with the message "([^\"]*)"$/ do |message|
27
+ found_exception = false
28
+ puts @exceptions.inspect
29
+ @exceptions.each do |exception|
30
+ found_exception ||= exception =~ Regexp.new(message)
31
+ end
32
+ found_exception.should be_true
33
+ end
34
+
35
+ Then %r{no exceptions should have been raised} do
36
+ @exceptions.should be_empty
37
+ end
38
+
@@ -0,0 +1,31 @@
1
+ require 'vendor/gems/environment'
2
+ Bundler.require_env :cucumber
3
+
4
+ require 'spec/expectations'
5
+ require 'spec/mocks'
6
+
7
+ require 'lib/epic'
8
+
9
+ require 'spec/stubs'
10
+
11
+ Before do
12
+ unless defined?(BASE_PATH)
13
+ BASE_PATH = File.expand_path("./features/data")
14
+ end
15
+
16
+ @exceptions = []
17
+ @files = []
18
+
19
+ $rspec_mocks ||= Spec::Mocks::Space.new
20
+
21
+ stub_growl
22
+ end
23
+
24
+ After do
25
+ @files.each do |file|
26
+ system "rm #{file}"
27
+ end
28
+
29
+ system "rm -rf #{BASE_PATH}/tmp"
30
+ system "mkdir #{BASE_PATH}/tmp"
31
+ end
@@ -0,0 +1,17 @@
1
+ Feature: Test the validator
2
+
3
+ Background:
4
+ Given I configure Epic::Base
5
+
6
+ Scenario: Validate a valid HTML file
7
+ Given the file "html/valid.html" should be valid
8
+
9
+ Scenario: Validate an invalid HTML file
10
+ Given the file "html/invalid.html" should not be valid
11
+
12
+ Scenario: Validate a valid JavaScript file
13
+ Given the file "javascripts/valid.js" should be valid
14
+
15
+ Scenario: Validate an invalid JavaScript file
16
+ Given the file "javascripts/invalid.js" should not be valid
17
+
@@ -1,5 +1,6 @@
1
1
  dir = File.dirname(__FILE__)
2
2
  $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'epic'))
3
4
 
4
5
  require 'rubygems'
5
6
  require 'f'
@@ -8,5 +9,6 @@ require 'active_support'
8
9
  require 'w3c_validators'
9
10
 
10
11
  require 'epic/base'
12
+ require 'epic/errors'
11
13
  require 'epic/validator'
12
- require 'epic/compressor'
14
+ require 'compressor'
@@ -6,36 +6,25 @@ module Epic #:nodoc
6
6
  class Base
7
7
  class << self
8
8
  def configuration
9
- @@configuration ||= Epic::Configuration.new
9
+ @configuration ||= Epic::Configuration.new
10
10
  end
11
11
 
12
12
  def configure
13
13
  yield configuration
14
14
  end
15
-
16
- # Parses out the <tt>base_path</tt> setting from a path to display it in a
17
- # less verbose way.
18
- #
19
- def display_path(path)
20
- path = File.expand_path(path)
21
- path.gsub(base_path.to_s, "")
22
- end
23
-
24
- def base_path
25
- configuration.base_path
26
- end
27
15
  end
28
16
 
29
17
  def configuration
30
- self.class.configuration
18
+ Epic::Base.configuration
31
19
  end
32
20
 
33
21
  # Parses out the <tt>base_path</tt> setting from a path to display it in a
34
22
  # less verbose way.
35
23
  #
36
- def display_path(path)
37
- path = File.expand_path(path)
38
- path.gsub(base_path.to_s, "")
24
+ def display_path(filename=nil)
25
+ filename ||= path
26
+ display_path = File.expand_path(filename)
27
+ display_path.gsub(base_path.to_s, "")
39
28
  end
40
29
 
41
30
  def base_path
@@ -43,7 +32,7 @@ module Epic #:nodoc
43
32
  end
44
33
 
45
34
  def tmp_path
46
- configuration.tmp_path || ""
35
+ configuration.tmp_path || "#{base_path}/tmp" || ""
47
36
  end
48
37
  end
49
38
  end
@@ -1,126 +1,139 @@
1
1
  module Epic #:nodoc:
2
- module Compressor #:nodoc:
3
- # Compresses a file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
4
- #
5
- # === Usage
6
- #
7
- # Epic::Compressor::Base.compress("filename.js", "type" => "js")
8
- #
9
- # Epic::Compressor::Base.compress("filename.css", "type" => "css")
10
- #
11
- # Outputs the compressed file to <tt>_path_.min.</tt>
12
- #
13
- # === Options
14
- #
15
- # "type":: "js" or "css". Identifies the file type.
16
- #
17
- # "obfuscate":: true or false. Change internal variable names within the code.
18
- #
19
- # "verbose":: true or false. Output warnings about code quality.
20
- #
21
- # "preserve_semi":: true or false. Preserve unnecessary semicolons.
22
- #
23
- # TODO: Make it support multiple compressors.
24
- #
25
- # TODO: Convert it to an object, so you instantiate the Compressor class and then call it
26
- # on a file or a string.
27
- #
28
- # TODO: Get some stringify_keys! action going so you can send in symbols or strings.
2
+ # Compresses a file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
3
+ #
4
+ # === Usage
5
+ #
6
+ # Epic::Compressor.compress("filename.js")
7
+ #
8
+ # Epic::Compressor.compress("filename.css")
9
+ #
10
+ # Outputs the compressed file to <tt>_path_.min.</tt>
11
+ #
12
+ # === Options
13
+ #
14
+ # "type" "js" or "css". Identifies the file type. Only needed if the file does
15
+ # not have a standard extension.
16
+ #
17
+ # "obfuscate" true or false. Change internal variable names within the code.
18
+ #
19
+ # "verbose" true or false. Output warnings about code quality.
20
+ #
21
+ # "preserve_semi" true or false. Preserve unnecessary semicolons.
22
+ #
23
+ # TODO: Make it support multiple compressors.
24
+ #
25
+ class Compressor < Epic::Base
26
+ include Epic::Errors
27
+
28
+ # The path of the original file being compressed.
29
+ #
30
+ attr_accessor :path
31
+
32
+ # The type of file, whether :js or :css.
29
33
  #
30
- class Base < Epic::Base
31
- def self.compress(path, options={})
32
- options.stringify_keys!
33
- compressed_display_path = display_path(path)
34
- compressed_path = "#{path}.min"
34
+ attr_accessor :type
35
+
36
+ def initialize(path)
37
+ @path = path
38
+ if path =~ /\.js$/
39
+ @type = :js
40
+ elsif path =~ /\.css$/
41
+ @type = :css
42
+ end
43
+ @errors = []
44
+ end
45
+
46
+ def compress(params={})
47
+ # if the compressed_file exists, don't create it again
48
+ #
49
+ compress_path(params) unless File.exists?(compressed_path)
35
50
 
36
- options["type"] ||= "js"
37
- options["type"] = options["type"].to_s
38
-
39
- # if the compressed_file exists, don't create it again
40
- #
41
- unless File.exists?(compressed_path)
42
- $stdout.print " #{compressed_display_path} compressing . . . "
43
- compressed = ''
44
-
45
- # set options and defaults
46
- #
47
- if options.delete("obfuscate")
48
- options["nomunge"] = ""
49
- end
50
- if options.delete("verbose")
51
- options["verbose"] = ""
52
- end
53
- options["charset"] = "utf-8"
54
-
55
- if options["type"].to_s == "js" && !options["preserve_semi"]
56
- options["preserve-semi"] = ""
57
- end
58
-
59
- # join the options together for appending to the command line
60
- #
61
- options_string = options.map {|k,v| "--#{k} #{v}"}.join(" ")
51
+ File.read(compressed_path)
52
+ end
53
+
54
+ def compressed_path
55
+ @compressed_path ||= "#{path}.min"
56
+ end
57
+
58
+ def compressed_display_path
59
+ @compressed_display_path ||= display_path(path)
60
+ end
61
+
62
+ def compress_path(params)
63
+ params.stringify_keys!
62
64
 
63
- # call the compressor
64
- #
65
- compressor_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/yuicompressor-2.4.2.jar")
66
- raise "#{compressor_path} does not exist" unless File.exists?(compressor_path)
67
-
68
- command = "java -jar #{compressor_path} #{options_string} #{path} -o #{compressed_path} 2>&1"
69
- result = F.execute(command, :return => true)
70
-
71
- result.split("\n").each do |line|
72
- if line =~ /\[ERROR\] (\d+):(\d+):(.*)/
73
- line_number = $1.to_i
74
- error = "Error at #{compressed_display_path} line #{line_number} character #{$2}: #{$3}"
75
- error += F.get_line_from_file(path, line_number)
76
-
77
- $stdout.puts error
78
- g(error)
79
- end
80
- end
81
-
82
- if result =~ /ERROR/
83
- raise "JavaScript errors in #{compressed_display_path}"
84
- else
85
- $stdout.puts "OK"
86
- end
87
- end
88
-
89
- # The compressed file should exist now. If it does, use it. If not, raise an error.
90
- #
91
- if File.exists?(compressed_path)
92
- compressed = File.read(compressed_path)
93
- else
94
- raise "File does not exist: #{compressed_display_path}"
95
- end
65
+ $stdout.print " #{compressed_display_path} compressing . . . "
66
+ compressed = ''
96
67
 
97
- compressed
98
- end
68
+ options_string = convert_params_to_string(params)
69
+
70
+ result = execute_compressor(options_string)
71
+
72
+ parse_errors(result)
73
+
74
+ if valid?
75
+ $stdout.puts "OK"
76
+ else
77
+ display_errors
78
+ raise "JavaScript errors in #{compressed_display_path}"
79
+ end
99
80
  end
100
81
 
101
- # Compresses a CSS file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
102
- #
103
- # === Usage
82
+ # call the compressor
104
83
  #
105
- # Epic::Compressor::Stylesheet.compress("filename.css")
106
- #
107
- class Stylesheet < Base
108
- def self.compress(path)
109
- super(path, "type" => "css")
110
- end
84
+ def execute_compressor(options_string)
85
+ command = "java -jar #{compressor_path} #{options_string} #{path} -o #{compressed_path} 2>&1"
86
+ result = F.execute(command, :return => true)
111
87
  end
112
88
 
113
- # Compresses a JavaScript file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
114
- #
115
- # === Usage
89
+ def parse_errors(result="")
90
+ result.to_s.split("\n").each do |line|
91
+ if line =~ /\[ERROR\] (\d+):(\d+):(.*)/
92
+ line_number = $1.to_i
93
+ error = "Error at #{compressed_display_path} line #{line_number} character #{$2}: #{$3}"
94
+ error += F.get_line_from_file(path, line_number)
95
+
96
+ errors << error
97
+ end
98
+ end
99
+ end
100
+
101
+ # join the options together for appending to the command line
116
102
  #
117
- # Epic::Compressor::JavaScript.compress("filename.js")
103
+ def convert_params_to_string(params)
104
+ options = parse_options(params)
105
+ options.map {|k,v| "--#{k} #{v}"}.join(" ")
106
+ end
107
+
108
+ # set options and defaults
118
109
  #
119
- class JavaScript < Base
120
- # TODO: Add options hash
121
- def self.compress(filename)
122
- super(filename, "type" => "js")
110
+ def parse_options(options)
111
+ options["type"] ||= type
112
+ options["type"] = options["type"].to_s
113
+
114
+ if options.delete("obfuscate")
115
+ options["nomunge"] = ""
116
+ end
117
+ if options.delete("verbose")
118
+ options["verbose"] = ""
123
119
  end
120
+ options["charset"] = "utf-8"
121
+
122
+ if options["type"].to_s == "js" && !options["preserve_semi"]
123
+ options["preserve-semi"] = ""
124
+ end
125
+
126
+ options
127
+ end
128
+
129
+ def compressor_path
130
+ compressor_path = File.expand_path("#{vendor_path}/ext/yuicompressor-2.4.2.jar")
131
+ raise "#{compressor_path} does not exist" unless File.exists?(compressor_path)
132
+ compressor_path
133
+ end
134
+
135
+ def vendor_path
136
+ File.join(File.dirname(__FILE__), "..", "..", "vendor")
124
137
  end
125
138
  end
126
139
  end
@@ -0,0 +1,18 @@
1
+ module Epic #:nodoc:
2
+ module Errors #:nodoc:
3
+ def errors
4
+ @errors ||= []
5
+ end
6
+
7
+ def valid?
8
+ errors.empty?
9
+ end
10
+
11
+ def display_errors
12
+ errors.each do |err|
13
+ $stdout.puts
14
+ $stdout.puts err.to_s
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,118 +1,5 @@
1
- require 'epic/base'
2
-
3
- module Epic
4
- module Validator
5
- class HTML < Epic::Base
6
- def validator
7
- @validator ||= W3CValidators::MarkupValidator.new
8
- end
9
-
10
- def validate(path)
11
- $stdout.print " #{path} validating . . . "
12
-
13
- doctype = configuration.doctype || "HTML 4.01 Transitional"
14
- validator.set_doctype!(doctype)
15
-
16
- results = validator.validate_file(path)
17
-
18
- valid = results.errors.length <= 0
19
-
20
- if valid
21
- $stdout.puts "OK"
22
- else
23
- $stdout.puts "validation errors"
24
- results.errors.each do |err|
25
- $stdout.puts
26
- $stdout.puts err.to_s
27
- end
28
- end
29
-
30
- valid
31
- end
32
- end
33
-
34
- class JavaScript < Base
35
- def use_jslint_settings?
36
- !jslint_settings.blank?
37
- end
38
-
39
- def jslint_settings
40
- configuration.jslint_settings
41
- end
42
-
43
- def jslint_settings_count
44
- jslint_settings.to_s.split("\n").size
45
- end
46
-
47
- def pre_process(content)
48
- content
49
- end
50
-
51
- def validate(path)
52
- display = display_path(path)
53
- $stdout.print " #{display} validating . . . "
54
- output = ""
55
-
56
- File.open(path) do |f|
57
- output = f.read
58
- end
59
-
60
- output = pre_process(output)
61
-
62
- FileUtils.mkdir_p(tmp_path)
63
-
64
- js_fragment_path = File.expand_path("#{tmp_path}/#{File.basename(path)}_fragment")
65
- fragment_display_path = display_path(js_fragment_path)
66
-
67
- if File.exists?(js_fragment_path)
68
- puts "That already exists?"
69
- else
70
- File.open(js_fragment_path,'w') do |f|
71
- f.puts jslint_settings if use_jslint_settings?
72
- f.puts output
73
- end
74
-
75
- jslint_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/jslint.js")
76
- raise "#{jslint_path} does not exist" unless File.exists?(jslint_path)
77
- rhino_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/js.jar")
78
- raise "#{rhino_path} does not exist" unless File.exists?(rhino_path)
79
-
80
- results = F.execute("java -jar #{rhino_path} #{jslint_path} #{js_fragment_path}", :return => true)
81
-
82
- if results =~ /jslint: No problems found/
83
- $stdout.puts "OK"
84
- else
85
- $stdout.puts "errors found!"
86
- results.split("\n").each do |result|
87
- if result =~ /line (\d+) character (\d+): (.*)/
88
- line_number = $1.to_i
89
- error = "Error at #{fragment_display_path} line #{line_number-jslint_settings_count} character #{$2}: #{$3}"
90
- error += F.get_line_from_file(js_fragment_path, line_number)
91
-
92
- $stdout.puts error
93
- end
94
- end
95
- message = "JavaScript Errors embedded in #{display}"
96
- g(message)
97
- raise message
98
- end
99
- end
100
- end
101
- end
102
-
103
- class JSON < JavaScript
104
- def pre_process(output)
105
- output
106
- end
107
-
108
- def jslint_settings
109
- end
110
- end
111
-
112
- class Stylesheet < Base
113
- def validate(filename)
114
- true
115
- end
116
- end
117
- end
118
- end
1
+ require 'validator/base'
2
+ require 'validator/html'
3
+ require 'validator/javascript'
4
+ require 'validator/json'
5
+ require 'validator/stylesheet'
@@ -0,0 +1,14 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc:
3
+ class Base < Epic::Base
4
+ include Epic::Errors
5
+
6
+ attr_accessor :path, :errors
7
+
8
+ def initialize(path=nil)
9
+ @path = path
10
+ @errors = []
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc:
3
+ class HTML < Epic::Validator::Base
4
+ def validator
5
+ @validator ||= W3CValidators::MarkupValidator.new
6
+ end
7
+
8
+ def doctype
9
+ configuration.doctype || "HTML 4.01 Transitional"
10
+ end
11
+
12
+ def validate(filename=nil)
13
+ @path = filename || path
14
+ $stdout.print " #{display_path} validating . . . "
15
+
16
+ validator.set_doctype!(doctype)
17
+
18
+ results = validator.validate_file(path)
19
+
20
+ @errors = results.errors
21
+
22
+ if valid?
23
+ $stdout.puts "OK"
24
+ else
25
+ $stdout.puts "validation errors"
26
+ display_errors
27
+ end
28
+
29
+ valid?
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,82 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc
3
+ class JavaScript < Epic::Validator::Base
4
+ def jslint_settings
5
+ configuration.jslint_settings.to_s
6
+ end
7
+
8
+ def jslint_settings_count
9
+ jslint_settings.split("\n").size
10
+ end
11
+
12
+ def pre_process(content)
13
+ jslint_settings + content
14
+ end
15
+
16
+ def js_fragment_path
17
+ File.expand_path("#{tmp_path}/#{File.basename(path)}_fragment")
18
+ end
19
+
20
+ def jslint_path
21
+ jslint_path = File.expand_path("#{vendor_path}/ext/jslint.js")
22
+ raise "#{jslint_path} does not exist" unless File.exists?(jslint_path)
23
+ jslint_path
24
+ end
25
+
26
+ def rhino_path
27
+ rhino_path = File.expand_path("#{vendor_path}/ext/js.jar")
28
+ raise "#{rhino_path} does not exist" unless File.exists?(rhino_path)
29
+ rhino_path
30
+ end
31
+
32
+ def vendor_path
33
+ File.join(File.dirname(__FILE__), "..", "..", "..", "vendor")
34
+ end
35
+
36
+ def valid_results?(results)
37
+ fragment_display_path = display_path(js_fragment_path)
38
+ unless results =~ /jslint: No problems found/
39
+ results.split("\n").each do |result|
40
+ if result =~ /line (\d+) character (\d+): (.*)/
41
+ line_number = $1.to_i
42
+ error = "Error at #{fragment_display_path} line #{line_number-jslint_settings_count} character #{$2}: #{$3}"
43
+ error += F.get_line_from_file(js_fragment_path, line_number)
44
+
45
+ errors << error
46
+ end
47
+ end
48
+ end
49
+ errors.length <= 0
50
+ end
51
+
52
+ def validate_path
53
+ raw_output = File.read(path)
54
+ output = pre_process(raw_output)
55
+
56
+ FileUtils.mkdir_p(tmp_path)
57
+
58
+ File.open(js_fragment_path,'w') do |f|
59
+ f.puts output
60
+ end
61
+
62
+ F.execute("java -jar #{rhino_path} #{jslint_path} #{js_fragment_path}", :return => true)
63
+ end
64
+
65
+ def validate(filename=nil)
66
+ @path = filename || path
67
+ $stdout.print " #{display_path} validating . . . "
68
+
69
+ results = validate_path
70
+
71
+ if valid_results?(results)
72
+ $stdout.puts "OK"
73
+ else
74
+ $stdout.puts "errors found!"
75
+ display_errors
76
+ end
77
+
78
+ errors.length <= 0
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,13 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc
3
+ class JSON < JavaScript
4
+ def pre_process(output)
5
+ output
6
+ end
7
+
8
+ def jslint_settings
9
+ ""
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc
3
+ class Stylesheet < Base
4
+ def validate(path=nil)
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -11,7 +11,7 @@ describe "Compressor" do
11
11
  File.stub!(:exists?).with(/file.js/).and_return(true)
12
12
  @file = "compressed file"
13
13
  File.stub(:read).and_return(@file)
14
- Epic::Compressor::Base.compress("file.js", "type" => "js").should == @file
14
+ Epic::Compressor.new("file.js").compress.should == @file
15
15
  end
16
16
 
17
17
  describe "generate a compressed file if one doesn't exist" do
@@ -22,47 +22,47 @@ describe "Compressor" do
22
22
 
23
23
  it "should log what it's doing" do
24
24
  $stdout.should_receive(:print).with(/file.js compressing . . ./)
25
- Epic::Compressor::Base.compress("file.js", "type" => "js")
25
+ Epic::Compressor.new("file.js").compress
26
26
  end
27
27
 
28
28
  it "should run the compressor" do
29
29
  F.should_receive(:execute).with(/yuicompressor/, :return => true).and_return("")
30
- Epic::Compressor::Base.compress("file.js", "type" => "js")
30
+ Epic::Compressor.new("file.js").compress
31
31
  end
32
32
 
33
33
  describe "options" do
34
34
  it "should set nomunge" do
35
35
  F.should_receive(:execute).with(/nomunge/, :return => true).and_return("")
36
- Epic::Compressor::Base.compress("file.js", "type" => "js", "obfuscate" => true)
36
+ Epic::Compressor.new("file.js").compress("obfuscate" => true)
37
37
  end
38
38
 
39
39
  it "should not set nomunge" do
40
40
  F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
41
41
  F.should_not_receive(:execute).with(/nomunge/, :return => true).and_return("")
42
- Epic::Compressor::Base.compress("file.js", "type" => "js", "obfuscate" => false)
42
+ Epic::Compressor.new("file.js").compress("obfuscate" => false)
43
43
  end
44
44
 
45
45
  it "should set verbose" do
46
46
  F.should_receive(:execute).with(/verbose/, :return => true).and_return("")
47
- Epic::Compressor::Base.compress("file.js", "type" => "js", "verbose" => true)
47
+ Epic::Compressor.new("file.js").compress("verbose" => true)
48
48
  end
49
49
 
50
50
  it "should not set verbose" do
51
51
  F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
52
52
  F.should_not_receive(:execute).with(/verbose/, :return => true).and_return("")
53
- Epic::Compressor::Base.compress("file.js", "type" => "js", "verbose" => false)
53
+ Epic::Compressor.new("file.js").compress("verbose" => false)
54
54
  end
55
55
 
56
56
  it "should set preserve-semi on javascript" do
57
57
  F.should_receive(:execute).with(/preserve-semi/, :return => true).and_return("")
58
- Epic::Compressor::Base.compress("file.js", "type" => "js")
58
+ Epic::Compressor.new("file.js").compress
59
59
  end
60
60
 
61
61
  it "should not set preserve-semi on css" do
62
62
  File.stub!(:exists?).with(/file.css/).and_return(true)
63
63
  F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
64
64
  F.should_not_receive(:execute).with(/preserve-semi/, :return => true).and_return("")
65
- Epic::Compressor::Base.compress("file.css", "type" => "css")
65
+ Epic::Compressor.new("file.css").compress
66
66
  end
67
67
  end
68
68
 
@@ -73,55 +73,22 @@ describe "Compressor" do
73
73
 
74
74
  it "should raise an exception" do
75
75
  lambda {
76
- Epic::Compressor::Base.compress("file.js", "type" => "js")
77
- }.should raise_error(/JavaScript errors/)
78
- end
79
-
80
- it "should growl" do
81
- @g.should_receive(:notify)
82
- lambda {
83
- Epic::Compressor::Base.compress("file.js", "type" => "js")
76
+ Epic::Compressor.new("file.js").compress
84
77
  }.should raise_error(/JavaScript errors/)
85
78
  end
86
79
 
87
80
  it "should show the source code" do
88
81
  F.should_receive(:get_line_from_file).with("file.js", 12).and_return("")
89
82
  lambda {
90
- Epic::Compressor::Base.compress("file.js", "type" => "js")
83
+ Epic::Compressor.new("file.js").compress
91
84
  }.should raise_error(/JavaScript errors/)
92
85
  end
93
86
  end
94
87
 
95
88
  it "should report OK" do
96
89
  $stdout.should_receive(:puts).with("OK")
97
- Epic::Compressor::Base.compress("file.js", "type" => "js")
90
+ Epic::Compressor.new("file.js").compress
98
91
  end
99
-
100
- it "should raise an error if the compressed file doesn't exist" do
101
- # File.stub!(:exists?).with(/file.js/).and_return(true)
102
- # File.stub!(:exists?).with(/file.js.min/).and_return(false)
103
- # lambda {
104
- Epic::Compressor::Base.compress("file.js", "type" => "js")
105
- # }.should raise_error(/File does not exist/)
106
- end
107
- end
108
- end
109
-
110
- describe "JavaScript" do
111
- it "should call Base with type js" do
112
- File.stub(:exists?).with(/file.js/).and_return(true)
113
- @file = "compressed file"
114
- File.stub(:read).and_return(@file)
115
- Epic::Compressor::JavaScript.compress("file.js").should == @file
116
- end
117
- end
118
-
119
- describe "Stylesheet" do
120
- it "should call Base with type css" do
121
- File.stub(:exists?).with(/file.css/).and_return(true)
122
- @file = "compressed file"
123
- File.stub(:read).and_return(@file)
124
- Epic::Compressor::Stylesheet.compress("file.css").should == @file
125
92
  end
126
93
  end
127
94
  end
@@ -40,6 +40,18 @@ describe "Validator" do
40
40
  Epic::Validator::HTML.new.validate("path")
41
41
  end
42
42
 
43
+ describe "new syntax" do
44
+ it "should call validator" do
45
+ W3CValidators::MarkupValidator.should_receive(:new).and_return(@validator)
46
+ Epic::Validator::HTML.new("path").validate
47
+ end
48
+
49
+ it "should print OK" do
50
+ $stdout.should_receive(:puts).with(/OK/)
51
+ Epic::Validator::HTML.new("path").validate
52
+ end
53
+ end
54
+
43
55
  describe "errors" do
44
56
  before(:each) do
45
57
  class ResultsMock
@@ -70,6 +82,17 @@ describe "Validator" do
70
82
  $stdout.should_receive(:puts).with("validation errors")
71
83
  Epic::Validator::HTML.new.validate("path")
72
84
  end
85
+
86
+ describe "new syntax" do
87
+ it "should be false" do
88
+ Epic::Validator::HTML.new("path").validate.should be_false
89
+ end
90
+
91
+ it "should output a message" do
92
+ $stdout.should_receive(:puts).with("validation errors")
93
+ Epic::Validator::HTML.new("path").validate
94
+ end
95
+ end
73
96
  end
74
97
  end
75
98
 
@@ -91,6 +114,20 @@ describe "Validator" do
91
114
  @file.should_receive(:puts).with(@jslint_settings)
92
115
  Epic::Validator::JavaScript.new.validate("path")
93
116
  end
117
+
118
+ describe "new syntax" do
119
+ it "should set jslint settings" do
120
+ Epic::Base.configure do |config|
121
+ config.jslint_settings = @jslint_settings
122
+ end
123
+ Epic::Validator::JavaScript.new("path").jslint_settings.should == @jslint_settings
124
+ end
125
+
126
+ it "should put jslint settings in the file" do
127
+ @file.should_receive(:puts).with(@jslint_settings)
128
+ Epic::Validator::JavaScript.new("path").validate
129
+ end
130
+ end
94
131
  end
95
132
 
96
133
  describe "valid" do
@@ -115,25 +152,14 @@ describe "Validator" do
115
152
  F.stub!(:get_line_from_file).with(anything, 5)
116
153
  end
117
154
 
118
- it "should growl" do
119
- @g.should_receive(:notify).with(anything, anything, /JavaScript Errors/, anything, anything)
120
- lambda {
121
- Epic::Validator::JavaScript.new.validate("path")
122
- }.should raise_error
123
- end
124
-
125
155
  it "should output errors" do
126
156
  $stdout.should_receive(:puts).with(/Unnecessary semicolon/)
127
157
  $stdout.should_receive(:puts).with(/Unknown thingamajig/)
128
- lambda {
129
- Epic::Validator::JavaScript.new.validate("path")
130
- }.should raise_error
158
+ Epic::Validator::JavaScript.new.validate("path").should be_false
131
159
  end
132
160
 
133
- it "should raise error" do
134
- lambda {
135
- Epic::Validator::JavaScript.new.validate("path")
136
- }.should raise_error(/JavaScript Errors/)
161
+ it "should be false" do
162
+ Epic::Validator::JavaScript.new.validate("path").should be_false
137
163
  end
138
164
  end
139
165
  end
@@ -161,25 +187,14 @@ describe "Validator" do
161
187
  F.stub!(:get_line_from_file).with(anything, 5)
162
188
  end
163
189
 
164
- it "should growl" do
165
- @g.should_receive(:notify).with(anything, anything, /JavaScript Errors/, anything, anything)
166
- lambda {
167
- Epic::Validator::JSON.new.validate("path")
168
- }.should raise_error
169
- end
170
-
171
190
  it "should output errors" do
172
191
  $stdout.should_receive(:puts).with(/Unnecessary semicolon/)
173
192
  $stdout.should_receive(:puts).with(/Unknown thingamajig/)
174
- lambda {
175
- Epic::Validator::JSON.new.validate("path")
176
- }.should raise_error
193
+ Epic::Validator::JSON.new.validate("path").should be_false
177
194
  end
178
195
 
179
- it "should raise error" do
180
- lambda {
181
- Epic::Validator::JSON.new.validate("path")
182
- }.should raise_error(/JavaScript Errors/)
196
+ it "should return false" do
197
+ Epic::Validator::JSON.new.validate("path").should be_false
183
198
  end
184
199
  end
185
200
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Coleman
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-25 00:00:00 -06:00
12
+ date: 2010-01-30 00:00:00 -06:00
13
13
  default_executable: epic
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -62,15 +62,36 @@ files:
62
62
  - VERSION
63
63
  - bin/epic
64
64
  - epic.gemspec
65
+ - features/compressor.feature
66
+ - features/data/html/invalid.html
67
+ - features/data/html/valid.html
68
+ - features/data/javascripts/invalid.js
69
+ - features/data/javascripts/invalid_uncompressed.js
70
+ - features/data/javascripts/pre_compressed.js
71
+ - features/data/javascripts/pre_compressed.js.min
72
+ - features/data/javascripts/valid.js
73
+ - features/data/javascripts/valid_uncompressed.js
74
+ - features/data/stylesheets/valid.css
75
+ - features/step_definitions/compressor_steps.rb
76
+ - features/step_definitions/file_steps.rb
77
+ - features/step_definitions/validator_steps.rb
78
+ - features/support/env.rb
79
+ - features/validator.feature
65
80
  - lib/epic.rb
66
81
  - lib/epic/base.rb
67
82
  - lib/epic/compressor.rb
83
+ - lib/epic/errors.rb
68
84
  - lib/epic/validator.rb
85
+ - lib/epic/validator/base.rb
86
+ - lib/epic/validator/html.rb
87
+ - lib/epic/validator/javascript.rb
88
+ - lib/epic/validator/json.rb
89
+ - lib/epic/validator/stylesheet.rb
69
90
  - spec/compressor_spec.rb
70
- - spec/epic_spec.rb
71
91
  - spec/spec.opts
72
92
  - spec/spec_helper.rb
73
93
  - spec/stubs.rb
94
+ - spec/validator_spec.rb
74
95
  - vendor/ext/js.jar
75
96
  - vendor/ext/jslint.js
76
97
  - vendor/ext/yuicompressor-2.4.2.jar
@@ -104,6 +125,6 @@ specification_version: 3
104
125
  summary: Epic validation of HTML, JavaScript and CSS
105
126
  test_files:
106
127
  - spec/compressor_spec.rb
107
- - spec/epic_spec.rb
108
128
  - spec/spec_helper.rb
109
129
  - spec/stubs.rb
130
+ - spec/validator_spec.rb