luca 0.6.6

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 (233) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +17 -0
  3. data/Gemfile.lock +77 -0
  4. data/Guardfile +22 -0
  5. data/README.md +291 -0
  6. data/Rakefile +28 -0
  7. data/app.rb +46 -0
  8. data/assets/images/glyphicons-halflings-white.png +0 -0
  9. data/assets/images/glyphicons-halflings.png +0 -0
  10. data/assets/javascripts/dependencies/backbone-min.js +37 -0
  11. data/assets/javascripts/dependencies/backbone-query.min.js +1 -0
  12. data/assets/javascripts/dependencies/bootstrap.min.js +1 -0
  13. data/assets/javascripts/dependencies/jasmine-html.js +190 -0
  14. data/assets/javascripts/dependencies/jasmine.js +2476 -0
  15. data/assets/javascripts/dependencies/jquery.js +4 -0
  16. data/assets/javascripts/dependencies/modal.js +698 -0
  17. data/assets/javascripts/dependencies/modernizr.min.js +30 -0
  18. data/assets/javascripts/dependencies/prettify.js +28 -0
  19. data/assets/javascripts/dependencies/sinon.js +3469 -0
  20. data/assets/javascripts/dependencies/spin-min.js +2 -0
  21. data/assets/javascripts/dependencies/underscore-min.js +31 -0
  22. data/assets/javascripts/dependencies/underscore-string.min.js +14 -0
  23. data/assets/javascripts/dependencies.coffee +7 -0
  24. data/assets/javascripts/luca-ui-base.coffee +12 -0
  25. data/assets/javascripts/luca-ui-spec.coffee +2 -0
  26. data/assets/javascripts/luca-ui.coffee +3 -0
  27. data/assets/javascripts/sandbox/collections/sample.coffee +0 -0
  28. data/assets/javascripts/sandbox/config.coffee +7 -0
  29. data/assets/javascripts/sandbox/sandbox.coffee +16 -0
  30. data/assets/javascripts/sandbox/templates/features/collection_helpers.luca +33 -0
  31. data/assets/javascripts/sandbox/templates/features/form_demo_code.luca +48 -0
  32. data/assets/javascripts/sandbox/templates/features/grid_demo_code.luca +24 -0
  33. data/assets/javascripts/sandbox/templates/features/introduction.luca +11 -0
  34. data/assets/javascripts/sandbox/templates/features/view_helpers.luca +43 -0
  35. data/assets/javascripts/sandbox/templates/navigation.luca +8 -0
  36. data/assets/javascripts/sandbox/views/form_demo.coffee +47 -0
  37. data/assets/javascripts/sandbox/views/grid_demo.coffee +23 -0
  38. data/assets/javascripts/sandbox/views/pages/collection_events_sample.coffee +1 -0
  39. data/assets/javascripts/sandbox/views/pages/pages_controller.coffee +28 -0
  40. data/assets/javascripts/sandbox.coffee +4 -0
  41. data/assets/javascripts/spec-dependencies.coffee +4 -0
  42. data/assets/stylesheets/bootstrap-responsive.min.css +3 -0
  43. data/assets/stylesheets/bootstrap.min.css +610 -0
  44. data/assets/stylesheets/jasmine.css +166 -0
  45. data/assets/stylesheets/luca-ui-bootstrap.css +5 -0
  46. data/assets/stylesheets/luca-ui-spec.css +3 -0
  47. data/assets/stylesheets/luca-ui.css +3 -0
  48. data/assets/stylesheets/prettify.css +40 -0
  49. data/assets/stylesheets/sandbox/sandbox.scss +4 -0
  50. data/assets/stylesheets/sandbox.css +3 -0
  51. data/config.ru +11 -0
  52. data/lib/luca/command_line.rb +69 -0
  53. data/lib/luca/rails/engine.rb +12 -0
  54. data/lib/luca/rails/version.rb +6 -0
  55. data/lib/luca/rails.rb +9 -0
  56. data/lib/luca/template.rb +51 -0
  57. data/lib/luca/test_harness.rb +106 -0
  58. data/lib/luca.rb +1 -0
  59. data/lib/sprockets/luca_template.rb +49 -0
  60. data/lib/templates/spec_manifest_javascripts.erb +7 -0
  61. data/lib/templates/spec_manifest_stylesheets.erb +11 -0
  62. data/luca.gemspec +26 -0
  63. data/public/jasmine/index.html +26 -0
  64. data/public/sandbox/api.js +1 -0
  65. data/spec/components/application_spec.coffee +0 -0
  66. data/spec/components/collection_loader_view_spec.coffee +0 -0
  67. data/spec/components/controller_spec.coffee +0 -0
  68. data/spec/components/form_view_spec.coffee +13 -0
  69. data/spec/components/grid_view_spec.coffee +0 -0
  70. data/spec/components/record_manager_spec.coffee +0 -0
  71. data/spec/components/template_spec.coffee +0 -0
  72. data/spec/containers/card_view_spec.coffee +1 -0
  73. data/spec/containers/column_view_spec.coffee +0 -0
  74. data/spec/containers/modal_view_spec.coffee +0 -0
  75. data/spec/containers/panel_view_spec.coffee +0 -0
  76. data/spec/containers/split_view_spec.coffee +0 -0
  77. data/spec/containers/tab_view_spec.coffee +0 -0
  78. data/spec/containers/viewport_spec.coffee +0 -0
  79. data/spec/core/collection_spec.coffee +215 -0
  80. data/spec/core/container_spec.coffee +0 -0
  81. data/spec/core/field_spec.coffee +0 -0
  82. data/spec/core/observer_spec.coffee +0 -0
  83. data/spec/core/view_spec.coffee +87 -0
  84. data/spec/framework_spec.coffee +48 -0
  85. data/spec/helper.coffee +120 -0
  86. data/spec/managers/collection_manager_spec.coffee +95 -0
  87. data/spec/managers/socket_manager_spec.coffee +0 -0
  88. data/src/components/application.coffee +83 -0
  89. data/src/components/base_toolbar.coffee +16 -0
  90. data/src/components/collection_loader_view.coffee +37 -0
  91. data/src/components/controller.coffee +41 -0
  92. data/src/components/fields/button_field.coffee +40 -0
  93. data/src/components/fields/checkbox_field.coffee +41 -0
  94. data/src/components/fields/file_upload_field.coffee +15 -0
  95. data/src/components/fields/hidden_field.coffee +18 -0
  96. data/src/components/fields/select_field.coffee +100 -0
  97. data/src/components/fields/text_area_field.coffee +43 -0
  98. data/src/components/fields/text_field.coffee +42 -0
  99. data/src/components/fields/type_ahead_field.coffee +10 -0
  100. data/src/components/form_button_toolbar.coffee +26 -0
  101. data/src/components/form_view.coffee +205 -0
  102. data/src/components/grid_view.coffee +208 -0
  103. data/src/components/record_manager.coffee +215 -0
  104. data/src/components/router.coffee +34 -0
  105. data/src/components/template.coffee +19 -0
  106. data/src/containers/card_view.coffee +89 -0
  107. data/src/containers/column_view.coffee +48 -0
  108. data/src/containers/modal_view.coffee +85 -0
  109. data/src/containers/panel_view.coffee +24 -0
  110. data/src/containers/split_view.coffee +12 -0
  111. data/src/containers/tab_view.coffee +77 -0
  112. data/src/containers/viewport.coffee +16 -0
  113. data/src/core/collection.coffee +319 -0
  114. data/src/core/container.coffee +256 -0
  115. data/src/core/field.coffee +68 -0
  116. data/src/core/observer.coffee +17 -0
  117. data/src/core/view.coffee +190 -0
  118. data/src/framework.coffee +110 -0
  119. data/src/index.coffee +255 -0
  120. data/src/managers/collection_manager.coffee +168 -0
  121. data/src/managers/socket_manager.coffee +54 -0
  122. data/src/modules/deferrable.coffee +18 -0
  123. data/src/modules/local_storage.coffee +50 -0
  124. data/src/stylesheets/base.scss +78 -0
  125. data/src/stylesheets/components/form_view.scss +54 -0
  126. data/src/stylesheets/components/grid_view.scss +111 -0
  127. data/src/stylesheets/components/toolbar.scss +15 -0
  128. data/src/stylesheets/containers/container.scss +7 -0
  129. data/src/stylesheets/containers/modal_view.scss +0 -0
  130. data/src/stylesheets/containers/tab_view.scss +33 -0
  131. data/src/stylesheets/normalize.scss +430 -0
  132. data/src/templates/components/bootstrap_form_controls.luca +7 -0
  133. data/src/templates/components/collection_loader_view.luca +5 -0
  134. data/src/templates/components/form_view.luca +15 -0
  135. data/src/templates/components/grid_view.luca +9 -0
  136. data/src/templates/components/grid_view_empty_text.luca +3 -0
  137. data/src/templates/containers/basic.luca +1 -0
  138. data/src/templates/containers/tab_selector_container.luca +8 -0
  139. data/src/templates/containers/tab_view.luca +1 -0
  140. data/src/templates/containers/toolbar_wrapper.luca +1 -0
  141. data/src/templates/fields/button_field.luca +2 -0
  142. data/src/templates/fields/button_field_link.luca +5 -0
  143. data/src/templates/fields/checkbox_field.luca +9 -0
  144. data/src/templates/fields/file_upload_field.luca +8 -0
  145. data/src/templates/fields/hidden_field.luca +1 -0
  146. data/src/templates/fields/select_field.luca +7 -0
  147. data/src/templates/fields/text_area_field.luca +8 -0
  148. data/src/templates/fields/text_field.luca +13 -0
  149. data/src/templates/sample/contents.luca +1 -0
  150. data/src/templates/sample/welcome.luca +1 -0
  151. data/vendor/assets/images/glyphicons-halflings-white.png +0 -0
  152. data/vendor/assets/images/glyphicons-halflings.png +0 -0
  153. data/vendor/assets/javascripts/luca-spec-dependencies.js +6135 -0
  154. data/vendor/assets/javascripts/luca-ui-base.js +1527 -0
  155. data/vendor/assets/javascripts/luca-ui-spec.js +3654 -0
  156. data/vendor/assets/javascripts/luca-ui.js +2763 -0
  157. data/vendor/assets/luca-ui/base.css +85 -0
  158. data/vendor/assets/luca-ui/components/application.js +91 -0
  159. data/vendor/assets/luca-ui/components/base_toolbar.js +23 -0
  160. data/vendor/assets/luca-ui/components/controller.js +38 -0
  161. data/vendor/assets/luca-ui/components/fields/button_field.js +45 -0
  162. data/vendor/assets/luca-ui/components/fields/checkbox_field.js +43 -0
  163. data/vendor/assets/luca-ui/components/fields/file_upload_field.js +20 -0
  164. data/vendor/assets/luca-ui/components/fields/hidden_field.js +20 -0
  165. data/vendor/assets/luca-ui/components/fields/select_field.js +97 -0
  166. data/vendor/assets/luca-ui/components/fields/text_area_field.js +48 -0
  167. data/vendor/assets/luca-ui/components/fields/text_field.js +46 -0
  168. data/vendor/assets/luca-ui/components/fields/type_ahead_field.js +13 -0
  169. data/vendor/assets/luca-ui/components/form_button_toolbar.js +32 -0
  170. data/vendor/assets/luca-ui/components/form_view.css +32 -0
  171. data/vendor/assets/luca-ui/components/form_view.js +207 -0
  172. data/vendor/assets/luca-ui/components/grid_view.css +76 -0
  173. data/vendor/assets/luca-ui/components/grid_view.js +202 -0
  174. data/vendor/assets/luca-ui/components/record_manager.js +207 -0
  175. data/vendor/assets/luca-ui/components/router.js +36 -0
  176. data/vendor/assets/luca-ui/components/template.js +26 -0
  177. data/vendor/assets/luca-ui/components/toolbar.css +11 -0
  178. data/vendor/assets/luca-ui/containers/card_view.js +98 -0
  179. data/vendor/assets/luca-ui/containers/column_view.js +52 -0
  180. data/vendor/assets/luca-ui/containers/container.css +3 -0
  181. data/vendor/assets/luca-ui/containers/modal_view.css +0 -0
  182. data/vendor/assets/luca-ui/containers/modal_view.js +87 -0
  183. data/vendor/assets/luca-ui/containers/panel_view.js +34 -0
  184. data/vendor/assets/luca-ui/containers/split_view.js +13 -0
  185. data/vendor/assets/luca-ui/containers/tab_view.css +16 -0
  186. data/vendor/assets/luca-ui/containers/tab_view.js +80 -0
  187. data/vendor/assets/luca-ui/containers/viewport.js +18 -0
  188. data/vendor/assets/luca-ui/core/collection.js +221 -0
  189. data/vendor/assets/luca-ui/core/container.js +205 -0
  190. data/vendor/assets/luca-ui/core/field.js +59 -0
  191. data/vendor/assets/luca-ui/core/observer.js +42 -0
  192. data/vendor/assets/luca-ui/core/view.js +127 -0
  193. data/vendor/assets/luca-ui/framework.js +110 -0
  194. data/vendor/assets/luca-ui/index.js +5 -0
  195. data/vendor/assets/luca-ui/managers/collection_manager.js +98 -0
  196. data/vendor/assets/luca-ui/managers/socket_manager.js +52 -0
  197. data/vendor/assets/luca-ui/modules/deferrable.js +21 -0
  198. data/vendor/assets/luca-ui/modules/local_storage.js +81 -0
  199. data/vendor/assets/luca-ui/normalize.css +359 -0
  200. data/vendor/assets/luca-ui/stylesheets/base.css +85 -0
  201. data/vendor/assets/luca-ui/stylesheets/components/form_view.css +32 -0
  202. data/vendor/assets/luca-ui/stylesheets/components/grid_view.css +76 -0
  203. data/vendor/assets/luca-ui/stylesheets/components/toolbar.css +11 -0
  204. data/vendor/assets/luca-ui/stylesheets/containers/container.css +3 -0
  205. data/vendor/assets/luca-ui/stylesheets/containers/modal_view.css +0 -0
  206. data/vendor/assets/luca-ui/stylesheets/containers/tab_view.css +16 -0
  207. data/vendor/assets/luca-ui/stylesheets/normalize.css +359 -0
  208. data/vendor/assets/luca-ui/templates/components/bootstrap_form_controls.js +4 -0
  209. data/vendor/assets/luca-ui/templates/components/form_view.js +4 -0
  210. data/vendor/assets/luca-ui/templates/components/grid_view.js +4 -0
  211. data/vendor/assets/luca-ui/templates/components/grid_view_empty_text.js +4 -0
  212. data/vendor/assets/luca-ui/templates/containers/basic.js +4 -0
  213. data/vendor/assets/luca-ui/templates/containers/tab_selector_container.js +4 -0
  214. data/vendor/assets/luca-ui/templates/containers/tab_view.js +4 -0
  215. data/vendor/assets/luca-ui/templates/containers/toolbar_wrapper.js +4 -0
  216. data/vendor/assets/luca-ui/templates/fields/button_field.js +4 -0
  217. data/vendor/assets/luca-ui/templates/fields/button_field_link.js +4 -0
  218. data/vendor/assets/luca-ui/templates/fields/checkbox_field.js +4 -0
  219. data/vendor/assets/luca-ui/templates/fields/file_upload_field.js +4 -0
  220. data/vendor/assets/luca-ui/templates/fields/hidden_field.js +4 -0
  221. data/vendor/assets/luca-ui/templates/fields/select_field.js +4 -0
  222. data/vendor/assets/luca-ui/templates/fields/text_area_field.js +4 -0
  223. data/vendor/assets/luca-ui/templates/fields/text_field.js +4 -0
  224. data/vendor/assets/luca-ui/templates/sample/contents.js +4 -0
  225. data/vendor/assets/luca-ui/templates/sample/welcome.js +4 -0
  226. data/vendor/assets/stylesheets/luca-spec-dependencies.css +166 -0
  227. data/vendor/assets/stylesheets/luca-ui-bootstrap.css +1201 -0
  228. data/vendor/assets/stylesheets/luca-ui-spec.css +586 -0
  229. data/vendor/assets/stylesheets/luca-ui.css +586 -0
  230. data/views/index.erb +20 -0
  231. data/views/jasmine.erb +22 -0
  232. data/views/spec_harness.erb +29 -0
  233. metadata +361 -0
@@ -0,0 +1,166 @@
1
+ body {
2
+ font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
3
+ }
4
+
5
+
6
+ .jasmine_reporter a:visited, .jasmine_reporter a {
7
+ color: #303;
8
+ }
9
+
10
+ .jasmine_reporter a:hover, .jasmine_reporter a:active {
11
+ color: blue;
12
+ }
13
+
14
+ .run_spec {
15
+ float:right;
16
+ padding-right: 5px;
17
+ font-size: .8em;
18
+ text-decoration: none;
19
+ }
20
+
21
+ .jasmine_reporter {
22
+ margin: 0 5px;
23
+ }
24
+
25
+ .banner {
26
+ color: #303;
27
+ background-color: #fef;
28
+ padding: 5px;
29
+ }
30
+
31
+ .logo {
32
+ float: left;
33
+ font-size: 1.1em;
34
+ padding-left: 5px;
35
+ }
36
+
37
+ .logo .version {
38
+ font-size: .6em;
39
+ padding-left: 1em;
40
+ }
41
+
42
+ .runner.running {
43
+ background-color: yellow;
44
+ }
45
+
46
+
47
+ .options {
48
+ text-align: right;
49
+ font-size: .8em;
50
+ }
51
+
52
+
53
+
54
+
55
+ .suite {
56
+ border: 1px outset gray;
57
+ margin: 5px 0;
58
+ padding-left: 1em;
59
+ }
60
+
61
+ .suite .suite {
62
+ margin: 5px;
63
+ }
64
+
65
+ .suite.passed {
66
+ background-color: #dfd;
67
+ }
68
+
69
+ .suite.failed {
70
+ background-color: #fdd;
71
+ }
72
+
73
+ .spec {
74
+ margin: 5px;
75
+ padding-left: 1em;
76
+ clear: both;
77
+ }
78
+
79
+ .spec.failed, .spec.passed, .spec.skipped {
80
+ padding-bottom: 5px;
81
+ border: 1px solid gray;
82
+ }
83
+
84
+ .spec.failed {
85
+ background-color: #fbb;
86
+ border-color: red;
87
+ }
88
+
89
+ .spec.passed {
90
+ background-color: #bfb;
91
+ border-color: green;
92
+ }
93
+
94
+ .spec.skipped {
95
+ background-color: #bbb;
96
+ }
97
+
98
+ .messages {
99
+ border-left: 1px dashed gray;
100
+ padding-left: 1em;
101
+ padding-right: 1em;
102
+ }
103
+
104
+ .passed {
105
+ background-color: #cfc;
106
+ display: none;
107
+ }
108
+
109
+ .failed {
110
+ background-color: #fbb;
111
+ }
112
+
113
+ .skipped {
114
+ color: #777;
115
+ background-color: #eee;
116
+ display: none;
117
+ }
118
+
119
+
120
+ /*.resultMessage {*/
121
+ /*white-space: pre;*/
122
+ /*}*/
123
+
124
+ .resultMessage span.result {
125
+ display: block;
126
+ line-height: 2em;
127
+ color: black;
128
+ }
129
+
130
+ .resultMessage .mismatch {
131
+ color: black;
132
+ }
133
+
134
+ .stackTrace {
135
+ white-space: pre;
136
+ font-size: .8em;
137
+ margin-left: 10px;
138
+ max-height: 5em;
139
+ overflow: auto;
140
+ border: 1px inset red;
141
+ padding: 1em;
142
+ background: #eef;
143
+ }
144
+
145
+ .finished-at {
146
+ padding-left: 1em;
147
+ font-size: .6em;
148
+ }
149
+
150
+ .show-passed .passed,
151
+ .show-skipped .skipped {
152
+ display: block;
153
+ }
154
+
155
+
156
+ #jasmine_content {
157
+ position:fixed;
158
+ right: 100%;
159
+ }
160
+
161
+ .runner {
162
+ border: 1px solid gray;
163
+ display: block;
164
+ margin: 5px 0;
165
+ padding: 2px 0 2px 10px;
166
+ }
@@ -0,0 +1,5 @@
1
+ /*
2
+ *= require ./bootstrap-responsive.min
3
+ *= require ./bootstrap.min
4
+ *= require_tree ./luca-ui
5
+ */
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree ./luca-ui
3
+ */
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree ./luca-ui
3
+ */
@@ -0,0 +1,40 @@
1
+ /* desert scheme ported from vim to google prettify */
2
+ pre { display: block; background-color: #333 }
3
+ pre .nocode { background-color: none; color: #000 }
4
+ pre .str { color: #ffa0a0 } /* string - pink */
5
+ pre .kwd { color: #f0e68c; font-weight: bold }
6
+ pre .com { color: #87ceeb } /* comment - skyblue */
7
+ pre .typ { color: #98fb98 } /* type - lightgreen */
8
+ pre .lit { color: #cd5c5c } /* literal - darkred */
9
+ pre .pun { color: #fff } /* punctuation */
10
+ pre .pln { color: #fff } /* plaintext */
11
+ pre .tag { color: #f0e68c; font-weight: bold } /* html/xml tag - lightyellow */
12
+ pre .atn { color: #bdb76b; font-weight: bold } /* attribute name - khaki */
13
+ pre .atv { color: #ffa0a0 } /* attribute value - pink */
14
+ pre .dec { color: #98fb98 } /* decimal - lightgreen */
15
+
16
+ /* Specify class=linenums on a pre to get line numbering */
17
+ ol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE } /* IE indents via margin-left */
18
+ li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
19
+ /* Alternate shading for lines */
20
+ li.L1,li.L3,li.L5,li.L7,li.L9 { }
21
+
22
+ @media print {
23
+ pre { background-color: none }
24
+ pre .str, code .str { color: #060 }
25
+ pre .kwd, code .kwd { color: #006; font-weight: bold }
26
+ pre .com, code .com { color: #600; font-style: italic }
27
+ pre .typ, code .typ { color: #404; font-weight: bold }
28
+ pre .lit, code .lit { color: #044 }
29
+ pre .pun, code .pun { color: #440 }
30
+ pre .pln, code .pln { color: #000 }
31
+ pre .tag, code .tag { color: #006; font-weight: bold }
32
+ pre .atn, code .atn { color: #404 }
33
+ pre .atv, code .atv { color: #060 }
34
+ }
35
+
36
+ pre.prettyprint li {
37
+ font-family: 'Monaco';
38
+ font-size: 20px;
39
+ line-height: 24px;
40
+ }
@@ -0,0 +1,4 @@
1
+ #container, #viewport {
2
+ width: 1024px;
3
+ margin: 40px auto;
4
+ }
@@ -0,0 +1,3 @@
1
+ /*
2
+ * = require_tree ./sandbox
3
+ */
data/config.ru ADDED
@@ -0,0 +1,11 @@
1
+ require './app'
2
+
3
+ # I'm leaning more towards not mounting the sprockets rack application and just relying on the precompiler with guard.
4
+ # If you want to mount the Sprockets Rack Application, uncomment the following lines:
5
+ map "/assets" do
6
+ run App.sprockets
7
+ end
8
+
9
+ map "/" do
10
+ run App
11
+ end
@@ -0,0 +1,69 @@
1
+ require 'optparse'
2
+
3
+ module Luca
4
+ class CommandLine
5
+ BANNER = <<-EOS
6
+ luca-ui generator
7
+
8
+ used to generate an application skeleton, or components
9
+
10
+ example:
11
+
12
+ luca new MyApp
13
+
14
+ EOS
15
+
16
+ attr_accessor :keystore, :arguments
17
+
18
+ GRAMMAR = %w{}
19
+
20
+ def initialize arguments=[]
21
+ arguments = arguments.split if arguments.is_a? String
22
+ parse_options arguments
23
+
24
+ if !@options[:action]
25
+ puts @option_parser.banner
26
+ exit
27
+ end
28
+ end
29
+
30
+ def options
31
+ @options
32
+ end
33
+
34
+ def parse_options arguments=[]
35
+ @options = {}
36
+
37
+ @option_parser = OptionParser.new do |opts|
38
+ opts.separator ""
39
+ opts.separator "Actions:"
40
+
41
+ opts.on("-n",'--new APPLICATION_NAME','Create a new luca-ui app skeleton') do |s|
42
+ @options[:action] = "new"
43
+ end
44
+
45
+ opts.separator ""
46
+ opts.separator "Common Options:"
47
+
48
+ opts.on_tail("-h","--help",'You are looking at it') do
49
+ puts opts
50
+ exit
51
+ end
52
+
53
+ opts.on_tail('-v','--version','display Sentry version') do
54
+ puts "Luca Version #{ Luca::VERSION }"
55
+ exit
56
+ end
57
+ end
58
+
59
+ @option_parser.banner = BANNER
60
+
61
+ arguments.collect! do |arg|
62
+ GRAMMAR.include?(arg.downcase) ? "--#{ arg.downcase }" : arg
63
+ end
64
+
65
+ @option_parser.parse!( arguments )
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,12 @@
1
+ module Luca
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ initializer "luca.register_template" do |app|
5
+ app.assets.register_engine ".luca", Luca::Template
6
+ Luca::TestHarness.set(:sprockets,app.assets)
7
+ Luca::TestHarness.set :root, File.expand_path('../../../../', __FILE__)
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,6 @@
1
+ module Luca
2
+ module Rails
3
+ VERSION = "0.6.6"
4
+ end
5
+ end
6
+
data/lib/luca/rails.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Luca
2
+ module Rails
3
+ require 'luca/template'
4
+ require 'luca/test_harness'
5
+ require 'luca/rails/engine'
6
+ require 'luca/rails/version'
7
+ end
8
+ end
9
+
@@ -0,0 +1,51 @@
1
+ require 'tilt'
2
+
3
+ module Luca
4
+ class Template < Tilt::Template
5
+ attr_accessor :namespace
6
+ def self.default_mime_type
7
+ 'application/javascript'
8
+ end
9
+
10
+ def self.engine_initialized?
11
+ defined? ::EJS
12
+ defined? ::Haml
13
+ end
14
+
15
+ def initialize_engine
16
+ require_template_library 'ejs'
17
+ require_template_library 'haml'
18
+ end
19
+
20
+ def prepare
21
+ options = @options.merge(:filename => eval_file, :line => line, :escape_attrs => false)
22
+ @engine = ::Haml::Engine.new(data, options)
23
+ self.namespace = "window.JST"
24
+ end
25
+
26
+ def evaluate(scope, locals, &block)
27
+ compiled = @engine.render(scope, locals, &block)
28
+ code = EJS.compile(compiled)
29
+ tmpl = scope.logical_path
30
+
31
+ tmpl.gsub! /^.*\/templates\//, ''
32
+
33
+ <<-JST
34
+
35
+ (function() {
36
+ #{namespace} || (#{namespace} = {});
37
+ #{namespace}[#{ tmpl.inspect }] = #{indent(code)};
38
+ }).call(this);
39
+
40
+ JST
41
+ end
42
+
43
+ private
44
+
45
+ def indent(string)
46
+ string.gsub(/$(.)/m, "\\1 ").strip
47
+ end
48
+
49
+ end
50
+ end
51
+
@@ -0,0 +1,106 @@
1
+ require 'sinatra/base'
2
+
3
+ module Luca
4
+ module AssetHelpers
5
+ def asset_path(source)
6
+ "/assets/" + settings.sprockets.find_asset(source).digest_path
7
+ end
8
+ end
9
+
10
+ class TestHarness < Sinatra::Base
11
+
12
+ class << self
13
+ attr_accessor :config_file, :spec_environment
14
+ end
15
+
16
+ def self.parse_configuration_file
17
+ self.spec_environment = YAML.load_file(config_file)
18
+ end
19
+
20
+ def self.configure!
21
+ spec_javascripts = File.join(::Rails.root,'spec','javascripts')
22
+ locations = [ File.join(spec_javascripts,'luca.yml'), File.join(::Rails.root,'config','luca.yml') ]
23
+
24
+ @config_file = locations.detect {|f| File.exists?(f) }
25
+
26
+ tmp_path = File.join(::Rails.root,'tmp')
27
+
28
+ unless sprockets.paths.include?(spec_javascripts)
29
+ sprockets.append_path(spec_javascripts)
30
+ end
31
+
32
+ unless sprockets.paths.include?(tmp_path)
33
+ sprockets.append_path( tmp_path )
34
+ end
35
+
36
+ if File.exists?( @config_file )
37
+ parse_configuration_file
38
+ else
39
+ # TODO - Provide error output to the test harness URL with instructions
40
+ # in the case the luca.yml config file does not exist
41
+ end
42
+ end
43
+
44
+ def self.load_environment
45
+ configure!
46
+ end
47
+
48
+ def self.get_suite application
49
+ @suite ||= load_environment.try(:[],"apps").try(:[], application)
50
+ end
51
+
52
+ # which files contain the actual specs
53
+ def self.get_specs application
54
+ get_suite( application ).try(:[],"specs") || []
55
+ end
56
+
57
+ # which stylesheets ( if any ) are required to serve the spec harness
58
+ def self.get_stylesheets application
59
+ get_suite( application ).try(:[],"stylesheets") || []
60
+ end
61
+
62
+ # which javascripts should we build and serve into a sprockets manifest
63
+ def self.get_javascripts application
64
+ get_suite( application ).try(:[],"scripts") || []
65
+ end
66
+
67
+ # which assets to include directly
68
+ def self.get_assets application
69
+ get_suite( application ).try(:[],"assets") || []
70
+ end
71
+
72
+ def self.create_tempfile type, contents
73
+ filename = File.join(::Rails.root,'tmp', rand(8**8).to_s(10) + ".#{ type }" )
74
+ File.open(filename,'w+') {|fh| fh.puts(contents)}
75
+ filename
76
+ end
77
+
78
+ get "/specs/:application/specs_manifest.js" do
79
+ @javascripts = self.class.get_specs( params[:application] )
80
+ template_file = File.join(self.class.root,'lib','templates','spec_manifest_javascripts.erb')
81
+ @temp_file = self.class.create_tempfile( 'js', ERB.new( IO.read(template_file) ).result( binding ) )
82
+
83
+ self.class.sprockets[ @temp_file ].to_s
84
+ end
85
+
86
+ get "/specs/:application/manifest.css" do
87
+ @stylesheets = self.class.get_stylesheets( params[:application] )
88
+ template_file = File.join(self.class.root,'lib','templates','spec_manifest_stylesheets.erb')
89
+ @temp_file = self.class.create_tempfile( 'css', ERB.new( IO.read(template_file) ).result( binding ) )
90
+
91
+ self.class.sprockets[ @temp_file ].to_s
92
+ end
93
+
94
+ get "/specs/:application/manifest.js" do
95
+ @javascripts = self.class.get_javascripts( params[:application] )
96
+ template_file = File.join(self.class.root,'lib','templates','spec_manifest_javascripts.erb')
97
+ @temp_file = self.class.create_tempfile( 'js', ERB.new( IO.read(template_file) ).result( binding ) )
98
+ self.class.sprockets[ @temp_file ].to_s
99
+ end
100
+
101
+ get "/specs/:application" do
102
+ @assets = self.class.get_assets( params[:application] )
103
+ erb :spec_harness
104
+ end
105
+ end
106
+ end
data/lib/luca.rb ADDED
@@ -0,0 +1 @@
1
+ require 'luca/rails'
@@ -0,0 +1,49 @@
1
+ require 'tilt'
2
+
3
+ module Sprockets
4
+ class LucaTemplate < Tilt::Template
5
+ attr_accessor :namespace
6
+ def self.default_mime_type
7
+ 'application/javascript'
8
+ end
9
+
10
+ def self.engine_initialized?
11
+ defined? ::EJS
12
+ defined? ::Haml
13
+ end
14
+
15
+ def initialize_engine
16
+ require_template_library 'ejs'
17
+ require_template_library 'haml'
18
+ end
19
+
20
+ def prepare
21
+ options = @options.merge(:filename => eval_file, :line => line, :escape_attrs => false)
22
+ @engine = ::Haml::Engine.new(data, options)
23
+ self.namespace = "Luca.templates"
24
+ end
25
+
26
+ def evaluate(scope, locals, &block)
27
+ compiled = @engine.render(scope, locals, &block)
28
+ code = EJS.compile(compiled)
29
+ tmpl = scope.logical_path
30
+
31
+ tmpl.gsub! /^.*\/templates\//, ''
32
+
33
+ <<-JST
34
+ (function() {
35
+ #{namespace} || (#{namespace} = {});
36
+ #{namespace}[#{ tmpl.inspect }] = #{indent(code)};
37
+ }).call(this);
38
+ JST
39
+ end
40
+
41
+ private
42
+
43
+ def indent(string)
44
+ string.gsub(/$(.)/m, "\\1 ").strip
45
+ end
46
+
47
+ end
48
+ end
49
+
@@ -0,0 +1,7 @@
1
+ <% for script in @javascripts %>
2
+ <% if File.directory?(script) %>
3
+ //= require_tree <%= script %>
4
+ <% else %>
5
+ //= require <%= script %>
6
+ <% end %>
7
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% for stylesheet in @stylesheets %>
2
+ <% if File.directory?(stylesheet) %>
3
+ /*
4
+ * require_tree <%= stylesheet %>
5
+ */
6
+ <% else %>
7
+ /*
8
+ * require <%= stylesheet %>
9
+ */
10
+ <% end %>
11
+ <% end %>
data/luca.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/luca/rails/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "luca"
6
+ s.version = Luca::Rails::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Jonathan Soeder"]
9
+ s.email = ["jonathan.soeder@gmail.com"]
10
+ s.homepage = "http://datapimp.github.com/luca"
11
+ s.summary = "A Backbone.JS Component Framework"
12
+ s.description = "This gem allows you to use the luca-ui backbone.js component framework easily with the assets pipeline"
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+
16
+ s.add_dependency "railties", "~> 3.1"
17
+ s.add_dependency "thor", "~> 0.14"
18
+ s.add_dependency "sinatra", ">= 0.9.2"
19
+ s.add_development_dependency "bundler", "~> 1.0.0"
20
+ s.add_development_dependency "rails", "~> 3.1"
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.executables = `git ls-files`.split("\n").select{|f| f =~ /^bin/}
24
+ s.require_paths = ['lib']
25
+ end
26
+
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
3
+ <html>
4
+ <head>
5
+ <title>Jasmine Test Runner</title>
6
+ <link rel="stylesheet" type="text/css" href="../jasmine.css">
7
+ <script type="text/javascript" src="../jasmine.js"></script>
8
+ <script type="text/javascript" src="../jasmine-html.js"></script>
9
+
10
+ <!-- include source files here... -->
11
+ <script type="text/javascript" src="../dependencies.js"></script>
12
+ <script type="text/javascript" src="../javascripts/luca-ui.js"></script>
13
+
14
+ <!-- include spec files here... -->
15
+ <script type="text/javascript" src="../javascripts/luca-ui-spec.js"></script>
16
+
17
+ </head>
18
+ <body>
19
+
20
+ <script type="text/javascript">
21
+ jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
22
+ jasmine.getEnv().execute();
23
+ </script>
24
+
25
+ </body>
26
+ </html>
@@ -0,0 +1 @@
1
+ [{"name":"Franz Hintz","location":"Port Lisa","email":"troy@larkin.name","website":"www.kub.biz"},{"name":"Savion Doyle","location":"Hesselfurt","email":"edyth.schmeler@quitzon.net","website":"www.boyerbeier.name"},{"name":"Alexzander Mante","location":"Port Zane","email":"lorna.jacobs@hellerbrekke.net","website":"www.rolfsonherman.com"},{"name":"Ava Bogan","location":"West Melanychester","email":"wallace.stiedemann@rempel.net","website":"www.reinger.biz"},{"name":"Kim Gleason","location":"North Jaylanbury","email":"barney@satterfield.biz","website":"www.erdmangreen.net"},{"name":"Sarina Mraz","location":"Keithview","email":"tanya@aufderharcrist.info","website":"www.gleason.biz"},{"name":"Newton Turner","location":"Thielberg","email":"favian@cruickshank.com","website":"www.pricebarrows.biz"},{"name":"Karlie Rempel","location":"Port Caleigh","email":"rahul@vandervortbailey.info","website":"www.raynormaggio.name"},{"name":"Frankie Greenholt","location":"Nikolasbury","email":"barney_jerde@strosinleuschke.name","website":"www.stamm.name"},{"name":"Courtney Hayes","location":"McKenziebury","email":"arnoldo@gerlach.biz","website":"www.sporer.org"},{"name":"Haven Hermiston","location":"Dooleymouth","email":"mylene@feeneyjenkins.net","website":"www.koch.biz"},{"name":"Cortez McLaughlin","location":"East Gustave","email":"mina.ritchie@brown.org","website":"www.murphyward.name"},{"name":"Ambrose Anderson","location":"Roxanestad","email":"earl.wiegand@baumbach.name","website":"www.hansen.org"},{"name":"Rowland Gorczany","location":"Quigleyberg","email":"elvis_becker@corwinberge.info","website":"www.aufderhar.name"},{"name":"Lourdes Willms","location":"Hickleshire","email":"ru@marquardtmoen.biz","website":"www.mosciski.com"},{"name":"Dave Hahn","location":"Lanceview","email":"abdul.homenick@brownmckenzie.net","website":"www.fay.name"},{"name":"Weston Prosacco","location":"Maverickborough","email":"aunta.schinner@dach.biz","website":"www.gusikowskigorczany.org"},{"name":"Antone Von","location":"New Alana","email":"nicholaus_hettinger@schulist.name","website":"www.zboncak.biz"},{"name":"Pat Upton","location":"Jairofurt","email":"marcellus@nienowreynolds.info","website":"www.stroman.net"},{"name":"Clark Murazik","location":"Lake Kody","email":"jaida@heel.info","website":"www.heaney.biz"},{"name":"Patience Skiles","location":"East Travis","email":"patrick_schaden@mcglynn.com","website":"www.mraz.info"},{"name":"Lavina Jacobson","location":"Port Kristyfort","email":"eleonore@kreiger.biz","website":"www.carter.biz"},{"name":"Mike Gerlach","location":"Gutkowskichester","email":"jazlyn@hartmann.com","website":"www.huelsferry.org"},{"name":"Green Rippin","location":"South Dimitri","email":"genoveva.gibson@yost.name","website":"www.pfannerstill.com"},{"name":"Rudolph Jakubowski","location":"Port Daniellafurt","email":"bridgette_hoeger@lakin.net","website":"www.beer.net"},{"name":"Caleb Lubowitz","location":"East Whitneyborough","email":"kraig@zemlak.org","website":"www.mitchell.com"},{"name":"Araceli Monahan","location":"New Heberbury","email":"carlee@davis.org","website":"www.mohr.net"},{"name":"Ruben Wisoky","location":"VonRuedenfort","email":"adela_gusikowski@ohara.biz","website":"www.cummerata.biz"},{"name":"Earnestine Schuster","location":"Port Kieran","email":"arden@kshlerin.org","website":"www.grimesauer.com"},{"name":"Pete Predovic","location":"West Brown","email":"jeanie@rutherford.org","website":"www.thiel.net"},{"name":"Paris Koepp","location":"New Ubaldoburgh","email":"baby.gusikowski@wizatreutel.net","website":"www.pfefferjaskolski.org"},{"name":"Mozelle Boehm","location":"South Reyes","email":"kitty@rau.biz","website":"www.ritchie.net"},{"name":"Austen Baumbach","location":"Georgetteview","email":"mercedes.armstrong@haley.com","website":"www.prohaskabayer.org"},{"name":"Lavonne O'Reilly","location":"West Ella","email":"lew@rodriguez.net","website":"www.gusikowski.info"},{"name":"Mckenzie West","location":"Lake Devin","email":"trever@gerlach.net","website":"www.heller.net"},{"name":"Albertha Schowalter","location":"New Aileenshire","email":"althea_wiegand@goldner.info","website":"www.kaulke.net"},{"name":"Wilhelmine Considine","location":"Port Howard","email":"tre@cronaoberbrunner.info","website":"www.rowe.org"},{"name":"Dina Keebler","location":"Elisaburgh","email":"suzanne@oconnellwilliamson.net","website":"www.parker.org"},{"name":"Jerad Kuphal","location":"Opheliamouth","email":"antonietta_hoppe@herzog.org","website":"www.nicolas.name"},{"name":"Wallace Murazik","location":"Jackview","email":"dameon@nikolausdamore.info","website":"www.morar.info"},{"name":"Christian Hyatt","location":"Kautzershire","email":"fausto_bins@adams.info","website":"www.padberg.name"},{"name":"Kyler Rohan","location":"East Feltonview","email":"pearline@erdmanschuster.com","website":"www.runolfsdottir.com"},{"name":"Alene Walter","location":"East Devante","email":"rozella@borerrenner.info","website":"www.muller.name"},{"name":"Yessenia Veum","location":"Beattyfurt","email":"kathlyn.cremin@stiedemann.info","website":"www.bayer.com"},{"name":"Ally Gerhold","location":"Gibsonville","email":"osvaldo.torp@ullrichlegros.com","website":"www.schoen.biz"},{"name":"Ephraim Kihn","location":"Champlinview","email":"cesar@schultz.info","website":"www.schimmelaltenwerth.net"},{"name":"Flavio Donnelly","location":"New Ole","email":"reina@rau.biz","website":"www.okeefepouros.biz"},{"name":"Kristopher Hermiston","location":"Shanellebury","email":"flo@stiedemann.name","website":"www.hermanwisoky.net"},{"name":"Michale Littel","location":"Marcelinashire","email":"aliya.wyman@steuber.name","website":"www.wintheiser.biz"},{"name":"Brendon Harber","location":"East Griffin","email":"demetrius_kris@cristkaulke.org","website":"www.bruenhoppe.net"},{"name":"Kristian Runolfsdottir","location":"New Omerbury","email":"alvina@luettgen.org","website":"www.kaulkekunde.org"},{"name":"Natalia Bashirian","location":"West Camylleberg","email":"kamron@kirlin.biz","website":"www.nicolasmayer.com"},{"name":"Francisca Purdy","location":"East Lorenamouth","email":"avery@zulaufbeatty.com","website":"www.schultz.info"},{"name":"Esteban Kunze","location":"Walkerside","email":"elyse.olson@lemke.com","website":"www.kulas.com"},{"name":"Angelica Jenkins","location":"South Naomiebury","email":"luciano.parker@schadenpredovic.info","website":"www.witting.info"},{"name":"Jovanny Glover","location":"North Candidaberg","email":"marjolaine_mraz@stamm.org","website":"www.zieme.net"},{"name":"Easton Purdy","location":"Winfieldstad","email":"meta@fadel.net","website":"www.aufderhar.com"},{"name":"Markus Cremin","location":"Fernburgh","email":"deion@abshire.info","website":"www.bins.info"},{"name":"Adrian Harris","location":"Audiefurt","email":"kennedy@nitzsche.info","website":"www.labadie.com"},{"name":"Roberta Predovic","location":"Kihnville","email":"quentin@senger.biz","website":"www.stroman.org"},{"name":"Alejandrin Beatty","location":"Hauckshire","email":"jovan_prosacco@williamson.com","website":"www.haag.biz"},{"name":"Yasmeen Jewess","location":"West Jarod","email":"rhianna.spencer@homenickjohnson.net","website":"www.prosacco.biz"},{"name":"Beryl Kozey","location":"Louieburgh","email":"fern@reynoldskutch.org","website":"www.bailey.net"},{"name":"Earl Will","location":"Lake Autumn","email":"mya.spencer@boyle.biz","website":"www.stanton.org"},{"name":"Maurice Hilll","location":"Noeliaberg","email":"annalise_hahn@white.net","website":"www.cruickshank.net"},{"name":"Hiram Anderson","location":"Starkside","email":"rosina.skiles@powlowski.org","website":"www.sanford.name"},{"name":"Taryn Jewess","location":"Martamouth","email":"german@murazik.info","website":"www.farrellkirlin.biz"},{"name":"Marge Bosco","location":"New Brenda","email":"wilber_haag@hettinger.biz","website":"www.beatty.org"},{"name":"Catharine Bahringer","location":"Derekton","email":"verna@smitham.com","website":"www.grady.info"},{"name":"Eleonore Kuvalis","location":"Kendramouth","email":"laurie.greenholt@rodriguez.info","website":"www.ernserwolf.net"},{"name":"Issac Carter","location":"Allisonland","email":"laria.leuschke@nicolas.org","website":"www.shields.name"},{"name":"Terrence Wisozk","location":"East Lindsey","email":"caesar@auer.biz","website":"www.nikolaus.info"},{"name":"Donavon Morissette","location":"Staceyview","email":"adrien_altenwerth@christiansen.com","website":"www.cummings.name"},{"name":"Zelda Lindgren","location":"West Carolannetown","email":"eleanore.davis@runolfsdottir.info","website":"www.andersonhamill.org"},{"name":"Darius Bergnaum","location":"Port Jazminborough","email":"anastacio@lesch.org","website":"www.reynoldchimmel.com"},{"name":"Althea Huel","location":"East Joannyton","email":"kyler.shields@mckenzie.biz","website":"www.spencer.info"},{"name":"Esperanza Lindgren","location":"South Sincere","email":"jazlyn@heathcote.com","website":"www.rolfson.com"},{"name":"Devonte Boyer","location":"North Adrianachester","email":"petra_moriette@yundt.biz","website":"www.mraz.biz"},{"name":"Roman Heathcote","location":"North Fayeton","email":"marlin_greenholt@kshlerin.org","website":"www.harvey.com"},{"name":"Julius Barrows","location":"Stokeston","email":"estevan_borer@stoltenberg.name","website":"www.howell.org"},{"name":"Marlen Kub","location":"Metaview","email":"vivien.halvorson@roberts.biz","website":"www.schustergusikowski.net"},{"name":"Gwen Fisher","location":"Leannonchester","email":"sherwood@cartwrightlynch.name","website":"www.keelinghyatt.net"},{"name":"Ariel Davis","location":"Garlandchester","email":"reina_mann@strosin.name","website":"www.ko.info"},{"name":"Ceasar Breitenberg","location":"West Sigmund","email":"rex.blanda@fritsch.biz","website":"www.padberg.biz"},{"name":"Olin Weimann","location":"Port Jeffmouth","email":"dimitri.mclaughlin@hoeger.com","website":"www.schmeler.org"},{"name":"Cara Jones","location":"Keelingfort","email":"hubert.crist@goldner.name","website":"www.bailey.biz"},{"name":"Cesar Nicolas","location":"Kesslerside","email":"beaulah@waters.com","website":"www.kerluke.info"},{"name":"Elise Reynolds","location":"Norbertoton","email":"fanny@breitenberg.com","website":"www.durgan.org"},{"name":"Oswaldo Haag","location":"North Dahliaton","email":"rhett.bogan@abshire.biz","website":"www.heelrohan.net"},{"name":"Amya Veum","location":"Estellaton","email":"stewart@hammeskuhlman.org","website":"www.boganschmeler.org"},{"name":"Mable Williamson","location":"East Jaycefurt","email":"vernie@klingrowe.biz","website":"www.larkin.name"},{"name":"Orlo Simonis","location":"Gloverbury","email":"jacques@dietrich.org","website":"www.jones.info"},{"name":"Loyal Collier","location":"Isobelland","email":"abdiel_torp@okeefe.com","website":"www.hagenesjewe.name"},{"name":"Evelyn Okuneva","location":"New Cade","email":"robin@wunsch.biz","website":"www.wolff.info"},{"name":"Justina Swift","location":"East Masonland","email":"stephan@wilkinsonhermann.biz","website":"www.bernier.biz"},{"name":"Jayde Lehner","location":"Svenview","email":"ivory@wehner.org","website":"www.rowe.name"},{"name":"Ima Murray","location":"Port Ronny","email":"marcelino.schumm@trantow.net","website":"www.ryan.info"},{"name":"Ignatius Kunze","location":"Mablemouth","email":"connor.ferry@bednar.info","website":"www.beahan.biz"},{"name":"Alexie Kohler","location":"South Zaria","email":"leonardo@dibbert.com","website":"www.beier.biz"},{"name":"Lorena Mohr","location":"Port Rachelleport","email":"jerrell_lockman@turner.org","website":"www.hane.name"}]
File without changes