seaweed 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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()