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,169 @@
1
+
2
+ class WWW_App
3
+ class Clean
4
+
5
+ attr_reader :name, :origin, :actual
6
+
7
+ def initialize name, val
8
+ @name = name[" "] ? name : name.inspect
9
+ @origin = val
10
+ @actual = val
11
+ end
12
+
13
+ def update val
14
+ @actual = val
15
+ end
16
+
17
+ #
18
+ # Examples:
19
+ #
20
+ # clean_as :upcase, :string, :in, [1,2,3]
21
+ # clean_as :upcase, :string, :switch, {...}
22
+ #
23
+ def clean_as *args
24
+ begin
25
+ cleaner = args.shift
26
+ case
27
+ when args.first.is_a?(Array)
28
+ send cleaner, *(args.shift)
29
+ when args.first.is_a?(Hash)
30
+ send cleaner, args.shift
31
+ else
32
+ send cleaner
33
+ end
34
+ end while !args.empty?
35
+
36
+ self
37
+ end
38
+
39
+ def not_nil
40
+ if actual.nil?
41
+ fail "Invalid: #{name} is required."
42
+ end
43
+
44
+ self
45
+ end
46
+
47
+ def string
48
+ return self if actual.is_a?(String)
49
+ fail "Invalid: #{name} must be a String: #{actual.inspect}"
50
+ end
51
+
52
+ def number
53
+ return self if actual.is_a?(Numeric)
54
+ fail "Invalid: #{name} must be a Number: #{actual.inspect}"
55
+ end
56
+
57
+ def not_empty_string
58
+ string
59
+ update actual.strip
60
+ if actual.empty?
61
+ fail "Invalid: #{name} must not be empty."
62
+ end
63
+
64
+ self
65
+ end
66
+
67
+ def downcase
68
+ not_empty_string
69
+ update actual.downcase
70
+
71
+ self
72
+ end
73
+
74
+ def upcase
75
+ not_empty_string
76
+ update actual.upcase
77
+
78
+ self
79
+ end
80
+
81
+ def color
82
+ not_empty_string
83
+ if !(actual =~ /\A#[A-Z0-9]{3,10}\Z/i)
84
+ fail "Invalid: color for #{name}: #{origin.inspect}."
85
+ end
86
+
87
+ self
88
+ end
89
+
90
+ def max_length max, msg = nil
91
+ not_nil
92
+ if actual.length > 200
93
+ fail(msg || "#{name} can not be more than #{max}")
94
+ end
95
+
96
+ self
97
+ end
98
+
99
+ def match regex, msg = nil
100
+ string
101
+ if !(actual =~ regex)
102
+ fail(msg || "Invalid: #{name} has invalid chars")
103
+ end
104
+
105
+ self
106
+ end
107
+
108
+ VALID_URL_REGEXP = /\A[a-z0-9\_\-\:\/\?\&\(\)\@\.]{1,200}\Z/i
109
+ def url
110
+ max = 200
111
+ not_empty_string
112
+ max_length max, "#{name} needs to be #{max} or less chars."
113
+ match VALID_URL_REGEXP
114
+
115
+ self
116
+ end
117
+
118
+ def in *raw
119
+ choices = raw.flatten
120
+ if !choices.include?(actual)
121
+ fail "Invalid: #{name} can't be, #{actual.inspect}, but one of: #{choices.join ", "}"
122
+ end
123
+
124
+ self
125
+ end
126
+
127
+ def switch choices
128
+ self.in(choices.keys)
129
+ update choices[actual]
130
+
131
+ self
132
+ end
133
+
134
+ def map action, *args
135
+ update(
136
+ actual.map { |v|
137
+ Clean.new("#{name} value", v).
138
+ send(action, *args).
139
+ actual
140
+ }
141
+ )
142
+
143
+ self
144
+ end
145
+
146
+ def number_between min, max
147
+ number
148
+ if actual < min || actual > max
149
+ fail "Invalid: #{name}, #{actual.inspect}, must be between: #{min} and #{max}"
150
+ end
151
+
152
+ self
153
+ end
154
+
155
+ # ================= HTML-specific =====================================================
156
+
157
+ VALID_FONT_REGEXP = /\A[a-z0-9\-\_\ ]{1,100}\Z/i
158
+
159
+ def fonts
160
+ map :not_empty_string
161
+ map :match, VALID_FONT_REGEXP, "only allow 1-100 characters: letters, numbers, spaces, - _"
162
+
163
+ self
164
+ end
165
+
166
+ # =====================================================================================
167
+
168
+ end # === class Clean
169
+ end # === class WWW_App
@@ -0,0 +1,86 @@
1
+
2
+ about(:input) {
3
+ self_close
4
+
5
+ input!(:hidden, :Symbol, :Symbol) {
6
+ attrs :type=>:hidden, :name=>args.second, :value=>args.third)
7
+ }
8
+
9
+ fieldset {
10
+ input {
11
+ attrs(:value=> '')
12
+ }
13
+ }
14
+
15
+ fieldset(:Symbol) {
16
+ input {
17
+ attrs type: 'text'.freeze, name: args_of(:parent).first
18
+ }
19
+ }
20
+
21
+ fieldset(:password) {
22
+ input! {
23
+ attrs :type=>'password'.freeze, :name=>'password'.freeze
24
+ }
25
+ }
26
+
27
+ fieldset(:password, :Symbol) {
28
+ input {
29
+ attrs :name => args_of(:parent).second
30
+ }
31
+ }
32
+
33
+ fieldset(:password_confirm) {
34
+ input! {
35
+ attrs :type=>'password'.freeze, :name=>'password_confirm'.freeze, :value=>''
36
+ on(:validate) { should_equal :password }
37
+ }
38
+ }
39
+
40
+ }
41
+
42
+
43
+ # -------------------------------------------------------------------
44
+ # -------------------------------------------------------------------
45
+ # -------------------------------------------------------------------
46
+ # -------------------------------------------------------------------
47
+ # -------------------------------------------------------------------
48
+ form.sign_in! {
49
+
50
+ title "Sign-in"
51
+
52
+ div.main {
53
+
54
+ fieldset(:username) do
55
+ box {
56
+ label 'Username'
57
+ tip 'some tip'
58
+ }
59
+
60
+ input {
61
+ on(:validate){ validate "[0-9a-zA-Z.-_]{0,25}" }
62
+ }
63
+ end
64
+
65
+ fieldset(:password) do
66
+ title 'Pass phrase:'
67
+ input
68
+ end
69
+
70
+ fieldset(:password_confirm) do
71
+ title 'Confirm pass phrase:'
72
+ input
73
+ end
74
+ }
75
+
76
+ div.footer {
77
+ div.buttons do
78
+ submit 'Sign-in'
79
+ cancel 'Cancel' do
80
+ reset
81
+ hide
82
+ end
83
+ end
84
+ }
85
+
86
+ }
@@ -0,0 +1,53 @@
1
+
2
+
3
+ class WWW_App
4
+ class Code_ify < BasicObject
5
+ def initialize &blok
6
+ @code = []
7
+ @target = @code
8
+ @indent = []
9
+ instance_eval(&blok) if blok
10
+ end
11
+
12
+ def method_missing *args, &blok
13
+ @target << {:name=>args.shift, :args=>args}
14
+
15
+ if blok
16
+ @indent << 1
17
+ @target.last[:blok] = []
18
+ @target.last[:indent] = @indent.size
19
+
20
+ orig = @target
21
+ @target = @target.last[:blok]
22
+ instance_eval(&blok)
23
+
24
+ @indent.pop
25
+ @target = orig
26
+ end
27
+
28
+ self
29
+ end
30
+
31
+ def to_text
32
+ @code.map { |e|
33
+ to_string e
34
+ }.join "\n".freeze
35
+ end
36
+
37
+ private
38
+ def to_string e
39
+ if e.is_a? ::Array
40
+ return e.map { |ee| to_string ee }.join "\n".freeze
41
+ end
42
+
43
+ s = %^#{e[:name]}(#{e[:args].map(&:inspect).join ', '.freeze})^
44
+ if e[:blok]
45
+ first_indent = ' '.freeze * e[:indent]
46
+ last_indent = ' '.freeze * (e[:indent] - 1)
47
+ s << %^ {\n#{first_indent}#{to_string e[:blok]}\n#{last_indent}}^
48
+ end
49
+ s
50
+ end
51
+
52
+ end # === class
53
+ end # === class