seaweed 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/public/jsdiff.js ADDED
@@ -0,0 +1,161 @@
1
+ /*
2
+ * Javascript Diff Algorithm
3
+ * By John Resig (http://ejohn.org/)
4
+ * Modified by Chu Alan "sprite"
5
+ *
6
+ * Released under the MIT license.
7
+ *
8
+ * More Info:
9
+ * http://ejohn.org/projects/javascript-diff-algorithm/
10
+ */
11
+
12
+ function escape(s) {
13
+ var n = s;
14
+ n = n.replace(/&/g, "&");
15
+ n = n.replace(/</g, "&lt;");
16
+ n = n.replace(/>/g, "&gt;");
17
+ n = n.replace(/"/g, "&quot;");
18
+
19
+ return n;
20
+ }
21
+
22
+ function diffString( o, n ) {
23
+ o = o.replace(/\s+$/, '');
24
+ n = n.replace(/\s+$/, '');
25
+
26
+ var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
27
+ var str = "";
28
+
29
+ var oSpace = o.match(/\s+/g);
30
+ if (oSpace == null) {
31
+ oSpace = ["\n"];
32
+ } else {
33
+ oSpace.push("\n");
34
+ }
35
+ var nSpace = n.match(/\s+/g);
36
+ if (nSpace == null) {
37
+ nSpace = ["\n"];
38
+ } else {
39
+ nSpace.push("\n");
40
+ }
41
+
42
+ if (out.n.length == 0) {
43
+ for (var i = 0; i < out.o.length; i++) {
44
+ str += '<del>' + escape(out.o[i]) + oSpace[i] + "</del>";
45
+ }
46
+ } else {
47
+ if (out.n[0].text == null) {
48
+ for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
49
+ str += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
50
+ }
51
+ }
52
+
53
+ for ( var i = 0; i < out.n.length; i++ ) {
54
+ if (out.n[i].text == null) {
55
+ str += '<ins>' + escape(out.n[i]) + nSpace[i] + "</ins>";
56
+ } else {
57
+ var pre = "";
58
+
59
+ for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
60
+ pre += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
61
+ }
62
+ str += " " + out.n[i].text + nSpace[i] + pre;
63
+ }
64
+ }
65
+ }
66
+
67
+ return str;
68
+ }
69
+
70
+ function randomColor() {
71
+ return "rgb(" + (Math.random() * 100) + "%, " +
72
+ (Math.random() * 100) + "%, " +
73
+ (Math.random() * 100) + "%)";
74
+ }
75
+ function diffString2( o, n ) {
76
+ o = o.replace(/\s+$/, '');
77
+ n = n.replace(/\s+$/, '');
78
+
79
+ var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
80
+
81
+ var oSpace = o.match(/\s+/g);
82
+ if (oSpace == null) {
83
+ oSpace = ["\n"];
84
+ } else {
85
+ oSpace.push("\n");
86
+ }
87
+ var nSpace = n.match(/\s+/g);
88
+ if (nSpace == null) {
89
+ nSpace = ["\n"];
90
+ } else {
91
+ nSpace.push("\n");
92
+ }
93
+
94
+ var os = "";
95
+ var colors = new Array();
96
+ for (var i = 0; i < out.o.length; i++) {
97
+ colors[i] = randomColor();
98
+
99
+ if (out.o[i].text != null) {
100
+ os += '<span style="background-color: ' +colors[i]+ '">' +
101
+ escape(out.o[i].text) + oSpace[i] + "</span>";
102
+ } else {
103
+ os += "<del>" + escape(out.o[i]) + oSpace[i] + "</del>";
104
+ }
105
+ }
106
+
107
+ var ns = "";
108
+ for (var i = 0; i < out.n.length; i++) {
109
+ if (out.n[i].text != null) {
110
+ ns += '<span style="background-color: ' +colors[out.n[i].row]+ '">' +
111
+ escape(out.n[i].text) + nSpace[i] + "</span>";
112
+ } else {
113
+ ns += "<ins>" + escape(out.n[i]) + nSpace[i] + "</ins>";
114
+ }
115
+ }
116
+
117
+ return { o : os , n : ns };
118
+ }
119
+
120
+ function diff( o, n ) {
121
+ var ns = new Object();
122
+ var os = new Object();
123
+
124
+ for ( var i = 0; i < n.length; i++ ) {
125
+ if ( ns[ n[i] ] == null )
126
+ ns[ n[i] ] = { rows: new Array(), o: null };
127
+ ns[ n[i] ].rows.push( i );
128
+ }
129
+
130
+ for ( var i = 0; i < o.length; i++ ) {
131
+ if ( os[ o[i] ] == null )
132
+ os[ o[i] ] = { rows: new Array(), n: null };
133
+ os[ o[i] ].rows.push( i );
134
+ }
135
+
136
+ for ( var i in ns ) {
137
+ if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
138
+ n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
139
+ o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
140
+ }
141
+ }
142
+
143
+ for ( var i = 0; i < n.length - 1; i++ ) {
144
+ if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
145
+ n[i+1] == o[ n[i].row + 1 ] ) {
146
+ n[i+1] = { text: n[i+1], row: n[i].row + 1 };
147
+ o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
148
+ }
149
+ }
150
+
151
+ for ( var i = n.length - 1; i > 0; i-- ) {
152
+ if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
153
+ n[i-1] == o[ n[i].row - 1 ] ) {
154
+ n[i-1] = { text: n[i-1], row: n[i].row - 1 };
155
+ o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
156
+ }
157
+ }
158
+
159
+ return { o: o, n: n };
160
+ }
161
+
data/public/spec.css ADDED
@@ -0,0 +1,29 @@
1
+ .failed {
2
+ color: #900;
3
+ }
4
+ .passed {
5
+ color: #090;
6
+ }
7
+ .pending {
8
+ color: #990;
9
+ }
10
+ .errors {
11
+ border-collapse: collapse;
12
+ }
13
+ .errors td, .errors th {
14
+ padding: 4px;
15
+ }
16
+ .errors th {
17
+ text-align: left;
18
+ background: #eee;
19
+ }
20
+ del, ins {
21
+ margin: 0 0.2em;
22
+ font-weight: bold;
23
+ }
24
+ del {
25
+ color: #900;
26
+ }
27
+ ins {
28
+ color: #090;
29
+ }
data/views/index.slim ADDED
@@ -0,0 +1,15 @@
1
+ doctype html
2
+ head
3
+ script type="text/javascript" src="ie.js"
4
+ script type="text/javascript" src="jquery-1.5.2.js"
5
+ script type="text/javascript" src="jsdiff.js"
6
+ link rel="stylesheet" href="spec.css" type="text/css"
7
+ script type="text/javascript" src="/assets/Spec.js"
8
+
9
+ body
10
+ javascript:
11
+ Spec.initializeEnvironment();
12
+ - @scripts.each do |file_name|
13
+ script type="text/javascript" src="/assets/#{{file_name.sub /\.coffee$/, '.js'}}"
14
+ javascript:
15
+ Spec.finalize();
metadata CHANGED
@@ -1,156 +1,156 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: seaweed
3
- version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Tobias Cohen
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-03-17 00:00:00 +11:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2012-06-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: coffee-script
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
33
22
  type: :runtime
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: json
37
23
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: json
32
+ requirement: !ruby/object:Gem::Requirement
39
33
  none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- hash: 3
44
- segments:
45
- - 0
46
- version: "0"
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
47
38
  type: :runtime
48
- version_requirements: *id002
49
- - !ruby/object:Gem::Dependency
50
- name: celerity
51
39
  prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
53
41
  none: false
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- hash: 3
58
- segments:
59
- - 0
60
- version: "0"
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: sprockets
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
61
54
  type: :runtime
62
- version_requirements: *id003
63
- - !ruby/object:Gem::Dependency
64
- name: sinatra
65
55
  prerelease: false
66
- requirement: &id004 !ruby/object:Gem::Requirement
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: sinatra
64
+ requirement: !ruby/object:Gem::Requirement
67
65
  none: false
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- hash: 3
72
- segments:
73
- - 0
74
- version: "0"
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
75
70
  type: :runtime
76
- version_requirements: *id004
77
- - !ruby/object:Gem::Dependency
78
- name: slim
79
71
  prerelease: false
80
- requirement: &id005 !ruby/object:Gem::Requirement
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: slim
80
+ requirement: !ruby/object:Gem::Requirement
81
81
  none: false
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- hash: 3
86
- segments:
87
- - 0
88
- version: "0"
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
89
86
  type: :runtime
90
- version_requirements: *id005
91
- - !ruby/object:Gem::Dependency
92
- name: watchr
93
87
  prerelease: false
94
- requirement: &id006 !ruby/object:Gem::Requirement
88
+ version_requirements: !ruby/object:Gem::Requirement
95
89
  none: false
96
- requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- hash: 3
100
- segments:
101
- - 0
102
- version: "0"
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: watchr
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
103
102
  type: :runtime
104
- version_requirements: *id006
105
- description: Seaweed is Coffeescript behavioral testing framework, with a command line tool that can be used to run specs automatically.
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: Seaweed is Coffeescript behavioral testing framework, with a command
111
+ line tool that can be used to run specs automatically.
106
112
  email: me@tobiascohen.com
107
- executables:
113
+ executables:
108
114
  - seaweed
109
115
  extensions: []
110
-
111
116
  extra_rdoc_files: []
112
-
113
- files:
117
+ files:
114
118
  - bin/seaweed
115
- - server/public/jquery-1.5.js
116
- - server/public/spec.css
117
- - server/server.rb
118
- - server/views/index.slim
119
- - lib/required_files.rb
119
+ - lib/seaweed/runner.rb
120
+ - lib/seaweed/server.rb
121
+ - lib/seaweed/version.rb
122
+ - lib/seaweed.rb
123
+ - lib/Spec/ObjectExtensions.coffee
124
+ - lib/Spec/WindowExtensions.coffee
120
125
  - lib/Spec.coffee
121
- has_rdoc: true
126
+ - public/ie.js
127
+ - public/jquery-1.5.2.js
128
+ - public/jsdiff.js
129
+ - public/spec.css
130
+ - views/index.slim
122
131
  homepage: https://github.com/tobico/seaweed
123
- licenses:
132
+ licenses:
124
133
  - MIT
125
134
  post_install_message:
126
135
  rdoc_options: []
127
-
128
- require_paths:
136
+ require_paths:
129
137
  - lib
130
- required_ruby_version: !ruby/object:Gem::Requirement
138
+ required_ruby_version: !ruby/object:Gem::Requirement
131
139
  none: false
132
- requirements:
133
- - - ">="
134
- - !ruby/object:Gem::Version
135
- hash: 3
136
- segments:
137
- - 0
138
- version: "0"
139
- required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
145
  none: false
141
- requirements:
142
- - - ">="
143
- - !ruby/object:Gem::Version
144
- hash: 3
145
- segments:
146
- - 0
147
- version: "0"
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
148
150
  requirements: []
149
-
150
151
  rubyforge_project:
151
- rubygems_version: 1.3.7
152
+ rubygems_version: 1.8.23
152
153
  signing_key:
153
154
  specification_version: 3
154
155
  summary: Coffeescript testing framework
155
156
  test_files: []
156
-
@@ -1,62 +0,0 @@
1
- require 'tsort'
2
-
3
- class RequiredFiles < Hash
4
- include TSort
5
-
6
- attr_accessor :paths
7
-
8
- # Adds a file to required list, and recursively scans and adds all other
9
- # files required by this file
10
- def add name
11
- file_name = full_path name
12
- if file_name && !self[name.to_sym]
13
- directives = parse_directives file_name
14
- self[name.to_sym] = {
15
- :file_name => file_name,
16
- :requires => directives['require']
17
- }
18
- requested = (directives['require'] | directives['request'])
19
- requested.each{ |file| add file }
20
- end
21
- end
22
-
23
- # Gets an array of file paths sorted in dependency order
24
- def sorted_files
25
- tsort.map{ |key| self[key][:file_name] }
26
- end
27
-
28
- private
29
- # Searches for file in path with given name and returns full file path,
30
- # or nil if not found
31
- def full_path name
32
- file_path = @paths.find { |path| File.exists? "#{path}/#{name}.coffee" }
33
- raise "File not found: #{name}" unless file_path
34
- file_path && "#{file_path}/#{name}.coffee"
35
- end
36
-
37
- # Scans a coffeescript file for #require and #request directives.
38
- #
39
- # Example requirement directives:
40
- # #require ST
41
- # #require ST/Model/Index
42
- def parse_directives name
43
- directives = {
44
- 'require' => [],
45
- 'request' => []
46
- }
47
- File.open name do |file|
48
- file.each do |line|
49
- if line.match /^#(require|request)\s+(\S+)\s*$/
50
- directives[$1] << $2
51
- end
52
- end
53
- end
54
- directives
55
- end
56
-
57
- # Callback functions for tsort
58
- alias tsort_each_node each_key
59
- def tsort_each_child node
60
- self[node][:requires].each{ |name| yield name.to_sym }
61
- end
62
- end
@@ -1,9 +0,0 @@
1
- .failed {
2
- color: #900;
3
- }
4
- .passed {
5
- color: #090;
6
- }
7
- .pending {
8
- color: #990;
9
- }
data/server/server.rb DELETED
@@ -1,88 +0,0 @@
1
- require 'rubygems'
2
- require 'sinatra'
3
- require 'slim'
4
- require 'coffee-script'
5
-
6
- # Patch in Sinatra support for Slim
7
- module Sinatra
8
- module Templates
9
- def slim(template, options={}, locals={})
10
- render :slim, template, options, locals
11
- end
12
- end
13
- end
14
-
15
- # Configure slim for prettier code formatting
16
- Slim::Engine.set_default_options :pretty => true
17
-
18
- # Hide redundant log messages
19
- disable :logging
20
-
21
- # Dynamically compiles coffeescript, first checking to see if it has changed
22
- def compile source, target
23
- begin
24
- # Get modified time of source file
25
- mtime = File.mtime source
26
-
27
- # If compled JavaScript file already exists and is up to date, return the
28
- # existing file instead of compiling again
29
- return File.read target if File.exists?(target) && File.mtime(target) == mtime
30
-
31
- # Create base dir for compiled file
32
- dir = target.sub /\/[^\/]+$/, ''
33
- Dir.mkdir dir unless File.exists? dir
34
-
35
- # Compile CoffeeScript to JavaScript file
36
- File.open target, 'w' do |f|
37
- f.write CoffeeScript.compile(File.read source)
38
- end
39
-
40
- # Mark compiled file with same modified date as source
41
- File.utime mtime, mtime, target
42
-
43
- # Return our newly compiled JavaScript
44
- File.read target
45
- rescue CoffeeScript::CompilationError => e
46
- # Display CoffeeScript compilation error in a prettier format
47
- message = if e.message.match /^SyntaxError: (.*) on line (\d+)\D*$/
48
- "#{source}:#{$2}".ljust(40) + " #{$1}"
49
- elsif e.message.match /^Parse error on line (\d+): (.*)$/
50
- "#{source}:#{$1}".ljust(40) + " #{$2}"
51
- else
52
- "#{source} - #{e.message}"
53
- end
54
- puts "\e[31m#{message}\e[0m"
55
-
56
- # Generate JS to display compilation error on HTML page
57
- html = "<pre class=\"failed\">#{message}</pre>"
58
- "$(function(){$(document.body).prepend(#{html.to_json});});"
59
- end
60
- end
61
-
62
- # Processes request for seaweed Spec library
63
- get "/Spec.js" do
64
- compile File.expand_path('../../lib/Spec.coffee', __FILE__), "compiled/spec.js"
65
- end
66
-
67
- # Processes request for project lib files
68
- get %r{^/lib/(.+)\.js$} do |file|
69
- compile "lib/#{file}.coffee", "compiled/#{file}.js"
70
- end
71
-
72
- # Processes request for project spec files
73
- get %r{^/spec/(.+)\.js$} do |file|
74
- compile "spec/#{file}.coffee", "compiled/#{file}.js"
75
- end
76
-
77
- # Processes request for page index
78
- get "/" do
79
- # Build ordered list of required files to run all specs
80
- requirements = RequiredFiles.new
81
- requirements.paths = ['spec', 'lib']
82
- Dir['spec/**/*.spec.coffee'].each do |file|
83
- requirements.add $1 if file.match /^spec\/(.*).coffee$/
84
- end
85
- @scripts = requirements.sorted_files
86
-
87
- slim :index
88
- end
@@ -1,11 +0,0 @@
1
- doctype html
2
- head
3
- script src="jquery-1.5.js"
4
- link rel="stylesheet" href="spec.css" type="text/css"
5
- script src="Spec.js"
6
- - @scripts.each do |file_name|
7
- script src="#{{file_name.sub /\.coffee$/, '.js'}}"
8
-
9
- body
10
- coffee:
11
- $ -> Spec.finalize()