www_app 1.0.0

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.
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
+ }