www_app 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +21 -0
  5. data/README.md +84 -0
  6. data/TODO.md +13 -0
  7. data/VERSION +1 -0
  8. data/bin/www_app +46 -0
  9. data/doc/Design.md +123 -0
  10. data/doc/Why_this_arch.rb +104 -0
  11. data/lib/public/jquery-2.1.1.js +4 -0
  12. data/lib/public/jquery.serialize-object.min.js +8 -0
  13. data/lib/public/underscore-1.7.0.js +6 -0
  14. data/lib/public/underscore-min.map +1 -0
  15. data/lib/public/underscore.string-2.3.0.js +1 -0
  16. data/lib/public/www_app.js +824 -0
  17. data/lib/www_app/Clean.rb +169 -0
  18. data/lib/www_app/dsl.rb +86 -0
  19. data/lib/www_app/source.rb +53 -0
  20. data/lib/www_app.rb +1024 -0
  21. data/specs/as_ruby/0000-new.rb +23 -0
  22. data/specs/as_ruby/0010-attrs.rb +29 -0
  23. data/specs/as_ruby/0011-class.rb +39 -0
  24. data/specs/as_ruby/0011-href.rb +37 -0
  25. data/specs/as_ruby/0011-id.rb +39 -0
  26. data/specs/as_ruby/0020-tag.rb +21 -0
  27. data/specs/as_ruby/0020-tag_content.rb +43 -0
  28. data/specs/as_ruby/0021-body.rb +16 -0
  29. data/specs/as_ruby/0021-form.rb +22 -0
  30. data/specs/as_ruby/0021-link.rb +26 -0
  31. data/specs/as_ruby/0021-script.rb +44 -0
  32. data/specs/as_ruby/0030-mustache.rb +113 -0
  33. data/specs/as_ruby/0040-css.rb +174 -0
  34. data/specs/as_ruby/0050-on.rb +64 -0
  35. data/specs/client-side/index.html +90 -0
  36. data/specs/client-side/index.js +777 -0
  37. data/specs/lib/config.ru +96 -0
  38. data/specs/lib/helpers.rb +230 -0
  39. data/specs/lib/qunit/qunit-1.15.0.css +237 -0
  40. data/specs/lib/qunit/qunit-1.15.0.js +2495 -0
  41. data/specs/lib/sample.rb +23 -0
  42. data/specs/sampe.2.rb +14 -0
  43. data/specs/sample.3.rb +17 -0
  44. data/specs/sample.rb +44 -0
  45. data/www_app.gemspec +38 -0
  46. metadata +271 -0
@@ -0,0 +1,96 @@
1
+
2
+
3
+ require 'cuba'
4
+ require 'da99_rack_protect'
5
+ require 'multi_json'
6
+
7
+ Cuba.use Da99_Rack_Protect.config { |c|
8
+ c.config :host, [:localhost, 'www_app.com']
9
+ }
10
+
11
+ Cuba.use Rack::ShowExceptions
12
+
13
+ Cuba.use(Class.new {
14
+ def initialize app
15
+ @app = app
16
+ end
17
+
18
+ def call env
19
+ results = @app.call(env)
20
+ if results.first == 404
21
+ if env['PATH_INFO'] == '/'
22
+ return [
23
+ 200,
24
+ {"Content-Type" => "text/html"},
25
+ [File.read("./specs/client-side/index.html").gsub("{token}", env['rack.session']['csrf'])]
26
+ ]
27
+ end
28
+
29
+ [
30
+ Rack::Directory.new(File.expand_path('./specs/lib')),
31
+ Rack::Directory.new(File.expand_path('./specs/client-side')),
32
+ Rack::Directory.new(File.expand_path('./lib/public'))
33
+ ].detect { |r|
34
+ status, headers, body = r.call(env)
35
+ return [status, headers, body] if status != 404
36
+ false
37
+ }
38
+ end
39
+
40
+ results
41
+ end
42
+ })
43
+
44
+ Cuba.define do
45
+
46
+ on post do
47
+ data = (req.env["rack.request.form_hash"]).dup
48
+ data.delete('authenticity_token')
49
+
50
+ res['Content-Type'] = 'application/json';
51
+
52
+ on "repeat/error_msg" do
53
+ res.write MultiJson.dump({
54
+ 'data' => data,
55
+ 'clean_html' => {
56
+ 'error_msg' => "<span>#{data['error_msg'] || 'Unknown error.'}</span>"
57
+ }
58
+ })
59
+ end
60
+
61
+ on "repeat/success_msg" do
62
+ res.write MultiJson.dump({
63
+ 'data' => data,
64
+ 'clean_html' => {
65
+ 'success_msg' => "<span>#{ data['success_msg'] || 'Unknown success'}</span>"
66
+ }
67
+ })
68
+ end
69
+
70
+ on "repeat/vals" do
71
+ res.write MultiJson.dump({
72
+ 'data' => data.select { |k,v| k['val'] },
73
+ 'clean_html' => {
74
+ 'success_msg' => 'Success in repeating vals.'
75
+ }
76
+ })
77
+ end
78
+
79
+ on(default) {
80
+ res.status = 404
81
+ res.write 'Missing'
82
+ }
83
+ end
84
+
85
+ on get do
86
+
87
+ on(default) {
88
+ res.status = 404
89
+ res.write 'Missing'
90
+ }
91
+
92
+ end # === on get
93
+
94
+ end # === Cuba.define
95
+
96
+ run Cuba
@@ -0,0 +1,230 @@
1
+
2
+ require 'Bacon_Colored'
3
+ require 'www_app'
4
+ require 'pry'
5
+ require "differ"
6
+ require "sanitize"
7
+ require "escape_escape_escape"
8
+
9
+ Differ.format = :color
10
+
11
+ TEMPLATE = File.read(__FILE__).
12
+ split('__END__').
13
+ last.
14
+ strip
15
+
16
+ def norm ugly
17
+ ugly.
18
+ strip.
19
+ split("\n").
20
+ map(&:strip).
21
+ join("\n")
22
+ end
23
+
24
+ def strip_each_line str
25
+ str.split("\n").map(&:strip).join "\n"
26
+ end
27
+
28
+ def get_content tag, html
29
+ ( html.match(/\<#{tag}\>(.+)\<\/#{tag}\>/)[1] || '' ).
30
+ split("\n").
31
+ map(&:strip).
32
+ join "\n"
33
+ end
34
+
35
+ def style html
36
+ get_content 'style', html
37
+ end
38
+
39
+ def script html
40
+ get_content 'script', html
41
+ end
42
+
43
+ def body html
44
+ get_content 'body', html
45
+ end
46
+
47
+ def to_html h
48
+ TEMPLATE.gsub(/!([a-z\_]+)/) { |sub|
49
+ key = $1.to_sym
50
+ case key
51
+ when :style
52
+ Sanitize::CSS.stylesheet(
53
+ (h[key] || '').strip,
54
+ Escape_Escape_Escape::CONFIG
55
+ )
56
+ when :body
57
+ Escape_Escape_Escape.html(h[key] || '')
58
+ when :title
59
+ Escape_Escape_Escape.html(h[key] || '[No Title]')
60
+ else
61
+ fail "Unknown key: #{key.inspect}"
62
+ end
63
+ }
64
+ end
65
+
66
+ def should_equal target, &blok
67
+ a = norm(WWW_App.new(&blok).to_html)
68
+ t = norm( target )
69
+ return(a.should == t) if a == t
70
+
71
+ puts " ======== ACTUAL =========="
72
+ puts a
73
+ puts " ======== TARGET =========="
74
+ puts t
75
+ puts " =========================="
76
+ puts Differ.diff_by_word(a,t)
77
+ puts " =========================="
78
+ fail "No match"
79
+ end
80
+
81
+ module Bacon
82
+ class Context
83
+
84
+ def target *args
85
+ @target_args = args
86
+ end
87
+
88
+ def actual vals = {}, &blok
89
+ if !@target_args
90
+ return WWW_App.new(&blok).render(vals)
91
+ end
92
+
93
+ include_tag = if @target_args.first == :outer
94
+ !!@target_args.shift
95
+ end
96
+
97
+ @target_args.unshift(:body) if @target_args.size == 1
98
+ norm_target = norm @target_args.last
99
+
100
+ tag = @target_args.first
101
+ html = WWW_App.new(&blok).render(vals)
102
+ section = case
103
+ when include_tag
104
+ html[/(<#{tag}[^\>]*>.+<\/#{tag}>)/m] && $1
105
+ else
106
+ html[/<#{tag}[^\>]*>(.+)<\/#{tag}>/m] && $1
107
+ end || html
108
+ norm_actual = norm section
109
+
110
+ if norm_target != norm_actual
111
+ puts " ======== TARGET =========="
112
+ puts norm_target
113
+ puts " ======== ACTUAL =========="
114
+ puts norm_actual
115
+ puts " ====== ORIGINAL ACTUAL ==="
116
+ puts html
117
+ puts " =========================="
118
+ end
119
+
120
+ norm_actual.should == norm_target
121
+ end
122
+
123
+ end # === class Context ===
124
+ end # === module Bacon ===
125
+
126
+ class WWW_App_Test
127
+
128
+ def initialize applet, output
129
+ @app = applet
130
+ @err = nil
131
+ @test = WWW_App.new("__main_test___", output)
132
+ @test.extend Computers
133
+ @test.send :test_app, @app
134
+ end
135
+
136
+ def run
137
+ begin
138
+ @app.run
139
+ rescue Object => e
140
+ fail_expected = @test.tokens.detect { |v|
141
+ v.is_a?(String) && WWW_App.standard_key(v) == "SHOULD RAISE"
142
+ }
143
+ raise e unless fail_expected
144
+ @test.send :test_err, e
145
+ end
146
+ @test.run
147
+ end
148
+
149
+ module Computers
150
+
151
+ class << self
152
+ def aliases
153
+ @map ||= {}
154
+ end
155
+ end # === class self
156
+
157
+ private
158
+ def test_app app = :none
159
+ if app != :none
160
+ @test_app = app
161
+ end
162
+ @test_app
163
+ end
164
+
165
+ def test_err e = :none
166
+ if e != :none
167
+ @test_err = e
168
+ end
169
+ @test_err
170
+ end
171
+
172
+
173
+ public
174
+ aliases[:value_should_equals_equals] = "value should =="
175
+ def value_should_equals_equals sender, to, args
176
+ name = sender.stack.last
177
+ target = args.last
178
+ @test_app.get(name).should == target
179
+ end
180
+
181
+ def should_raise sender, to, args
182
+ err_name = args.last
183
+ @test_err.message.should.match /#{Regexp.escape err_name}/
184
+ @test_err.message
185
+ end
186
+
187
+ def message_should_match sender, to, args
188
+ str_regex = args.last
189
+ msg = sender.stack.last
190
+ msg.should.match /#{Regexp.escape str_regex}/i
191
+ end
192
+
193
+ aliases[:stack_should_equal_equal] = "stack should =="
194
+ def stack_should_equal_equal sender, to, args
195
+ @test_app.stack.should == args
196
+ end
197
+
198
+ def should_not_raise sender, to, args
199
+ @err.should == nil
200
+ end
201
+
202
+ aliases[:last_console_message_should_equal_equal] = "last console message should =="
203
+ def last_console_message_should_equal_equal sender, to, args
204
+ @test_app.console.last.should == args.last
205
+ end
206
+
207
+ aliases[:console_should_equal_equal] = "console should =="
208
+ def console_should_equal_equal sender, to, args
209
+ @test_app.console.should == args
210
+ end
211
+ end # === module Computers
212
+
213
+ end # === class
214
+
215
+
216
+ __END__
217
+ <!DOCTYPE html>
218
+ <html lang="en">
219
+ <head>
220
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
221
+ <title>!title</title>
222
+ <style type="text/css">
223
+ !style
224
+ </style>
225
+ </head>
226
+ <body>!body</body>
227
+ </html>
228
+
229
+
230
+
@@ -0,0 +1,237 @@
1
+ /*!
2
+ * QUnit 1.15.0
3
+ * http://qunitjs.com/
4
+ *
5
+ * Copyright 2014 jQuery Foundation and other contributors
6
+ * Released under the MIT license
7
+ * http://jquery.org/license
8
+ *
9
+ * Date: 2014-08-08T16:00Z
10
+ */
11
+
12
+ /** Font Family and Sizes */
13
+
14
+ #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
15
+ font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
16
+ }
17
+
18
+ #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
19
+ #qunit-tests { font-size: smaller; }
20
+
21
+
22
+ /** Resets */
23
+
24
+ #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
25
+ margin: 0;
26
+ padding: 0;
27
+ }
28
+
29
+
30
+ /** Header */
31
+
32
+ #qunit-header {
33
+ padding: 0.5em 0 0.5em 1em;
34
+
35
+ color: #8699A4;
36
+ background-color: #0D3349;
37
+
38
+ font-size: 1.5em;
39
+ line-height: 1em;
40
+ font-weight: 400;
41
+
42
+ border-radius: 5px 5px 0 0;
43
+ }
44
+
45
+ #qunit-header a {
46
+ text-decoration: none;
47
+ color: #C2CCD1;
48
+ }
49
+
50
+ #qunit-header a:hover,
51
+ #qunit-header a:focus {
52
+ color: #FFF;
53
+ }
54
+
55
+ #qunit-testrunner-toolbar label {
56
+ display: inline-block;
57
+ padding: 0 0.5em 0 0.1em;
58
+ }
59
+
60
+ #qunit-banner {
61
+ height: 5px;
62
+ }
63
+
64
+ #qunit-testrunner-toolbar {
65
+ padding: 0.5em 1em 0.5em 1em;
66
+ color: #5E740B;
67
+ background-color: #EEE;
68
+ overflow: hidden;
69
+ }
70
+
71
+ #qunit-userAgent {
72
+ padding: 0.5em 1em 0.5em 1em;
73
+ background-color: #2B81AF;
74
+ color: #FFF;
75
+ text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
76
+ }
77
+
78
+ #qunit-modulefilter-container {
79
+ float: right;
80
+ }
81
+
82
+ /** Tests: Pass/Fail */
83
+
84
+ #qunit-tests {
85
+ list-style-position: inside;
86
+ }
87
+
88
+ #qunit-tests li {
89
+ padding: 0.4em 1em 0.4em 1em;
90
+ border-bottom: 1px solid #FFF;
91
+ list-style-position: inside;
92
+ }
93
+
94
+ #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
95
+ display: none;
96
+ }
97
+
98
+ #qunit-tests li strong {
99
+ cursor: pointer;
100
+ }
101
+
102
+ #qunit-tests li a {
103
+ padding: 0.5em;
104
+ color: #C2CCD1;
105
+ text-decoration: none;
106
+ }
107
+ #qunit-tests li a:hover,
108
+ #qunit-tests li a:focus {
109
+ color: #000;
110
+ }
111
+
112
+ #qunit-tests li .runtime {
113
+ float: right;
114
+ font-size: smaller;
115
+ }
116
+
117
+ .qunit-assert-list {
118
+ margin-top: 0.5em;
119
+ padding: 0.5em;
120
+
121
+ background-color: #FFF;
122
+
123
+ border-radius: 5px;
124
+ }
125
+
126
+ .qunit-collapsed {
127
+ display: none;
128
+ }
129
+
130
+ #qunit-tests table {
131
+ border-collapse: collapse;
132
+ margin-top: 0.2em;
133
+ }
134
+
135
+ #qunit-tests th {
136
+ text-align: right;
137
+ vertical-align: top;
138
+ padding: 0 0.5em 0 0;
139
+ }
140
+
141
+ #qunit-tests td {
142
+ vertical-align: top;
143
+ }
144
+
145
+ #qunit-tests pre {
146
+ margin: 0;
147
+ white-space: pre-wrap;
148
+ word-wrap: break-word;
149
+ }
150
+
151
+ #qunit-tests del {
152
+ background-color: #E0F2BE;
153
+ color: #374E0C;
154
+ text-decoration: none;
155
+ }
156
+
157
+ #qunit-tests ins {
158
+ background-color: #FFCACA;
159
+ color: #500;
160
+ text-decoration: none;
161
+ }
162
+
163
+ /*** Test Counts */
164
+
165
+ #qunit-tests b.counts { color: #000; }
166
+ #qunit-tests b.passed { color: #5E740B; }
167
+ #qunit-tests b.failed { color: #710909; }
168
+
169
+ #qunit-tests li li {
170
+ padding: 5px;
171
+ background-color: #FFF;
172
+ border-bottom: none;
173
+ list-style-position: inside;
174
+ }
175
+
176
+ /*** Passing Styles */
177
+
178
+ #qunit-tests li li.pass {
179
+ color: #3C510C;
180
+ background-color: #FFF;
181
+ border-left: 10px solid #C6E746;
182
+ }
183
+
184
+ #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
185
+ #qunit-tests .pass .test-name { color: #366097; }
186
+
187
+ #qunit-tests .pass .test-actual,
188
+ #qunit-tests .pass .test-expected { color: #999; }
189
+
190
+ #qunit-banner.qunit-pass { background-color: #C6E746; }
191
+
192
+ /*** Failing Styles */
193
+
194
+ #qunit-tests li li.fail {
195
+ color: #710909;
196
+ background-color: #FFF;
197
+ border-left: 10px solid #EE5757;
198
+ white-space: pre;
199
+ }
200
+
201
+ #qunit-tests > li:last-child {
202
+ border-radius: 0 0 5px 5px;
203
+ }
204
+
205
+ #qunit-tests .fail { color: #000; background-color: #EE5757; }
206
+ #qunit-tests .fail .test-name,
207
+ #qunit-tests .fail .module-name { color: #000; }
208
+
209
+ #qunit-tests .fail .test-actual { color: #EE5757; }
210
+ #qunit-tests .fail .test-expected { color: #008000; }
211
+
212
+ #qunit-banner.qunit-fail { background-color: #EE5757; }
213
+
214
+
215
+ /** Result */
216
+
217
+ #qunit-testresult {
218
+ padding: 0.5em 1em 0.5em 1em;
219
+
220
+ color: #2B81AF;
221
+ background-color: #D2E0E6;
222
+
223
+ border-bottom: 1px solid #FFF;
224
+ }
225
+ #qunit-testresult .module-name {
226
+ font-weight: 700;
227
+ }
228
+
229
+ /** Fixture */
230
+
231
+ #qunit-fixture {
232
+ position: absolute;
233
+ top: -10000px;
234
+ left: -10000px;
235
+ width: 1000px;
236
+ height: 1000px;
237
+ }