luca 0.9.8 → 0.9.9

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 (310) hide show
  1. data/CHANGELOG +49 -0
  2. data/Gemfile +8 -1
  3. data/Gemfile.lock +97 -53
  4. data/Guardfile +3 -25
  5. data/README.md +5 -16
  6. data/ROADMAP +15 -9
  7. data/Rakefile +24 -75
  8. data/app.rb +10 -42
  9. data/app/assets/javascripts/luca/basic.coffee +1 -1
  10. data/app/assets/javascripts/luca/components/application.coffee +187 -104
  11. data/app/assets/javascripts/luca/components/collection_view.coffee +115 -51
  12. data/app/assets/javascripts/luca/components/controller.coffee +87 -10
  13. data/app/assets/javascripts/luca/components/fields/base.coffee +74 -13
  14. data/app/assets/javascripts/luca/components/fields/button_field.coffee +60 -13
  15. data/app/assets/javascripts/luca/components/fields/checkbox_array.coffee +12 -7
  16. data/app/assets/javascripts/luca/components/fields/select_field.coffee +82 -23
  17. data/app/assets/javascripts/luca/components/fields/text_area_field.coffee +25 -10
  18. data/app/assets/javascripts/luca/components/fields/text_field.coffee +9 -3
  19. data/app/assets/javascripts/luca/components/form_view.coffee +105 -33
  20. data/app/assets/javascripts/luca/components/grid_layout_view.coffee +42 -0
  21. data/app/assets/javascripts/luca/components/index.coffee +6 -0
  22. data/app/assets/javascripts/luca/components/nav_bar.coffee +60 -6
  23. data/app/assets/javascripts/luca/components/page.coffee +70 -0
  24. data/app/assets/javascripts/luca/components/simple_collection_view.coffee +10 -0
  25. data/app/assets/javascripts/luca/components/table_view.coffee +7 -3
  26. data/app/assets/javascripts/luca/components/table_view_scrollable.coffee +23 -0
  27. data/app/assets/javascripts/luca/concerns/collection_event_bindings.coffee +4 -1
  28. data/app/assets/javascripts/luca/concerns/development_tool_helpers.coffee +23 -14
  29. data/app/assets/javascripts/luca/concerns/dom_helpers.coffee +2 -2
  30. data/app/assets/javascripts/luca/concerns/filterable.coffee +8 -11
  31. data/app/assets/javascripts/luca/concerns/form_model_bindings.coffee +20 -0
  32. data/app/assets/javascripts/luca/concerns/modal_view.coffee +40 -15
  33. data/app/assets/javascripts/luca/concerns/query_collection_bindings.coffee +7 -1
  34. data/app/assets/javascripts/luca/concerns/state_model.coffee +40 -26
  35. data/app/assets/javascripts/luca/concerns/templating.coffee +3 -1
  36. data/app/assets/javascripts/luca/config.coffee +5 -0
  37. data/app/assets/javascripts/luca/containers/card_view.coffee +87 -52
  38. data/app/assets/javascripts/luca/containers/container.coffee +305 -108
  39. data/app/assets/javascripts/luca/containers/modal_view.coffee +9 -9
  40. data/app/assets/javascripts/luca/containers/page_controller.coffee +25 -0
  41. data/app/assets/javascripts/luca/containers/panel_toolbar.coffee +5 -6
  42. data/app/assets/javascripts/luca/containers/tab_view.coffee +19 -10
  43. data/app/assets/javascripts/luca/containers/viewport.coffee +12 -16
  44. data/app/assets/javascripts/luca/core/collection.coffee +19 -5
  45. data/app/assets/javascripts/luca/core/events.coffee +5 -5
  46. data/app/assets/javascripts/luca/core/model.coffee +1 -1
  47. data/app/assets/javascripts/luca/core/panel.coffee +18 -6
  48. data/app/assets/javascripts/luca/core/registry/component_definition.coffee +2 -1
  49. data/app/assets/javascripts/luca/core/registry/meta_data.coffee +2 -0
  50. data/app/assets/javascripts/luca/core/registry/registry.coffee +14 -11
  51. data/app/assets/javascripts/luca/core/templates.coffee +5 -1
  52. data/app/assets/javascripts/luca/core/view.coffee +200 -47
  53. data/app/assets/javascripts/luca/dependencies.coffee +2 -0
  54. data/app/assets/javascripts/luca/development/code_sync_manager.coffee +173 -0
  55. data/app/assets/javascripts/luca/development/component.coffee +76 -0
  56. data/app/assets/javascripts/luca/development/components.coffee +57 -0
  57. data/app/assets/javascripts/luca/development/console.coffee +1 -1
  58. data/app/assets/javascripts/luca/development/index.coffee +4 -1
  59. data/app/assets/javascripts/luca/framework.coffee +7 -3
  60. data/app/assets/javascripts/luca/index.coffee +2 -1
  61. data/app/assets/javascripts/luca/managers/collection_manager.coffee +2 -3
  62. data/app/assets/javascripts/luca/managers/index.coffee +1 -1
  63. data/app/assets/javascripts/luca/managers/socket_manager.coffee +31 -8
  64. data/app/assets/javascripts/luca/templates/components/nav_bar.jst.ejs +16 -1
  65. data/app/assets/javascripts/luca/templates/containers/tab_view.jst.ejs +1 -1
  66. data/app/assets/javascripts/luca/util/index.coffee +1 -0
  67. data/app/assets/javascripts/luca/util/keybindings.coffee +24 -0
  68. data/app/assets/javascripts/luca/util/logging.coffee +15 -0
  69. data/app/assets/javascripts/luca/util/luca.coffee +9 -1
  70. data/app/assets/stylesheets/luca/components/table_view.scss +85 -0
  71. data/app/assets/stylesheets/luca/components/viewport.scss +0 -4
  72. data/app/assets/stylesheets/luca/containers/container.scss +8 -0
  73. data/app/assets/stylesheets/luca/index.css +2 -2
  74. data/bin/luca +14 -0
  75. data/config.ru +1 -2
  76. data/docs/framework.json +1 -0
  77. data/docs/luca-framework-documentation.js +1 -0
  78. data/docs/{application.md → old/application.md} +0 -0
  79. data/docs/{collection.md → old/collection.md} +0 -0
  80. data/docs/{collection_manager.md → old/collection_manager.md} +0 -0
  81. data/docs/{container_philosophy.md → old/container_philosophy.md} +0 -0
  82. data/docs/{event_binding_helpers.md → old/event_binding_helpers.md} +0 -0
  83. data/docs/{method_caching_and_computed_properties.md → old/method_caching_and_computed_properties.md} +0 -0
  84. data/docs/{view.md → old/view.md} +0 -0
  85. data/lib/generators/luca/application/templates/javascripts/dependencies.coffee +2 -5
  86. data/lib/guard/luca.rb +84 -0
  87. data/lib/luca.rb +25 -1
  88. data/lib/luca/asset_compiler.rb +117 -0
  89. data/lib/luca/cli.rb +68 -0
  90. data/lib/luca/cli/generate.rb +37 -0
  91. data/lib/luca/cli/server.rb +20 -0
  92. data/lib/luca/cli/sync.rb +40 -0
  93. data/lib/luca/cli/watch.rb +16 -0
  94. data/lib/luca/collection.rb +64 -0
  95. data/lib/luca/collection/endpoint.rb +38 -0
  96. data/lib/luca/collection/file_backend.rb +121 -0
  97. data/lib/luca/collection/redis_backend.rb +153 -0
  98. data/lib/luca/compiled_asset.rb +61 -0
  99. data/lib/luca/component_definition.rb +356 -0
  100. data/lib/luca/luca_application.rb +258 -0
  101. data/lib/luca/project.rb +73 -0
  102. data/lib/luca/project_harness.rb +96 -0
  103. data/lib/luca/rails.rb +5 -3
  104. data/lib/luca/rails/engine.rb +8 -0
  105. data/lib/luca/rails/version.rb +1 -2
  106. data/lib/luca/server.rb +7 -0
  107. data/lib/luca/stylesheet.rb +35 -0
  108. data/lib/luca/template.rb +2 -0
  109. data/lib/luca/template_asset.rb +64 -0
  110. data/lib/luca/version.rb +3 -0
  111. data/lib/luca/watcher.rb +72 -0
  112. data/lib/railties/luca/tasks.rake +7 -0
  113. data/site/.bundle/config +2 -0
  114. data/site/.gitignore +5 -0
  115. data/site/.rvmrc +1 -0
  116. data/site/CHANGELOG.md +41 -0
  117. data/site/DOCS.md +41 -0
  118. data/site/Gemfile +8 -0
  119. data/site/Gemfile.lock +134 -0
  120. data/site/LICENSE.md +19 -0
  121. data/site/config.rb +84 -0
  122. data/site/helpers/site_helpers.rb +20 -0
  123. data/site/html5bp-docs/README.md +38 -0
  124. data/site/html5bp-docs/contribute.md +104 -0
  125. data/site/html5bp-docs/crossdomain.md +21 -0
  126. data/site/html5bp-docs/css.md +135 -0
  127. data/site/html5bp-docs/extend.md +507 -0
  128. data/site/html5bp-docs/faq.md +77 -0
  129. data/site/html5bp-docs/htaccess.md +323 -0
  130. data/site/html5bp-docs/html.md +170 -0
  131. data/site/html5bp-docs/js.md +31 -0
  132. data/site/html5bp-docs/misc.md +25 -0
  133. data/site/html5bp-docs/usage.md +109 -0
  134. data/site/readme.md +47 -0
  135. data/site/source/.htaccess +540 -0
  136. data/site/source/404.html +157 -0
  137. data/site/source/app/assets/javascripts/dependencies.js.coffee +6 -0
  138. data/site/source/app/assets/javascripts/docs-docs.js +1 -0
  139. data/site/source/app/assets/javascripts/docs/application.coffee +64 -0
  140. data/site/source/app/assets/javascripts/docs/collections/docs_documentation.coffee +17 -0
  141. data/site/source/app/assets/javascripts/docs/collections/github_repositories.coffee +7 -0
  142. data/site/source/app/assets/javascripts/docs/collections/index.coffee +1 -0
  143. data/site/source/app/assets/javascripts/docs/collections/luca_documentation.coffee +17 -0
  144. data/site/source/app/assets/javascripts/docs/collections/public_gists.coffee +4 -0
  145. data/site/source/app/assets/javascripts/docs/config.coffee +5 -0
  146. data/site/source/app/assets/javascripts/docs/index.coffee +12 -0
  147. data/site/source/app/assets/javascripts/docs/lib/router.coffee +3 -0
  148. data/{spec/components/application_spec.coffee → site/source/app/assets/javascripts/docs/lib/util.coffee} +0 -0
  149. data/site/source/app/assets/javascripts/docs/models/component.coffee +99 -0
  150. data/site/source/app/assets/javascripts/docs/models/github_repository.coffee +3 -0
  151. data/site/source/app/assets/javascripts/docs/models/index.coffee +1 -0
  152. data/site/source/app/assets/javascripts/docs/templates/component_documentation.jst.ejs +55 -0
  153. data/site/source/app/assets/javascripts/docs/templates/examples_browser/overview.jst.ejs +4 -0
  154. data/site/source/app/assets/javascripts/docs/templates/examples_browser/selector.jst.ejs +11 -0
  155. data/site/source/app/assets/javascripts/docs/templates/github_repository.jst.ejs +4 -0
  156. data/site/source/app/assets/javascripts/docs/templates/layouts/main.jst.ejs +4 -0
  157. data/site/source/app/assets/javascripts/docs/templates/left_navigation.jst.ejs +5 -0
  158. data/site/source/app/assets/javascripts/docs/templates/pages/getting_started.jst.ejs +78 -0
  159. data/site/source/app/assets/javascripts/docs/templates/pages/home.jst.ejs +57 -0
  160. data/site/source/app/assets/javascripts/docs/views/components/code_editor.coffee +45 -0
  161. data/{spec/components/collection_loader_view_spec.coffee → site/source/app/assets/javascripts/docs/views/components/code_editor/index.coffee} +0 -0
  162. data/site/source/app/assets/javascripts/docs/views/components/component_documentation.coffee +72 -0
  163. data/site/source/app/assets/javascripts/docs/views/index.coffee +3 -0
  164. data/site/source/app/assets/javascripts/docs/views/pages/browse_source.coffee +46 -0
  165. data/site/source/app/assets/javascripts/docs/views/pages/browse_source/details.coffee +37 -0
  166. data/site/source/app/assets/javascripts/docs/views/pages/browse_source/list.coffee +31 -0
  167. data/site/source/app/assets/javascripts/docs/views/pages/component_editor.coffee +10 -0
  168. data/site/source/app/assets/javascripts/docs/views/pages/examples_browser.coffee +102 -0
  169. data/site/source/app/assets/javascripts/docs/views/pages/examples_browser/docs.coffee +12 -0
  170. data/site/source/app/assets/javascripts/docs/views/pages/examples_browser/source.coffee +13 -0
  171. data/site/source/app/assets/javascripts/docs/views/pages/home.coffee +10 -0
  172. data/site/source/app/assets/javascripts/docs/views/views/api_browser/index.coffee +43 -0
  173. data/site/source/app/assets/javascripts/docs/views/views/collection_view_examples/grid_layout_view_example.coffee +14 -0
  174. data/site/source/app/assets/javascripts/docs/views/views/collection_view_examples/table_view_example.coffee +39 -0
  175. data/site/source/app/assets/javascripts/docs/views/views/form_view_examples/basic_example.coffee +38 -0
  176. data/site/source/app/assets/javascripts/docs/views/views/form_view_examples/complex_layout.coffee +110 -0
  177. data/site/source/app/assets/javascripts/docs/views/views/top_navigation.coffee +6 -0
  178. data/site/source/app/assets/javascripts/luca-docs.js +1 -0
  179. data/site/source/app/assets/javascripts/luca-framework-documentation.js +1 -0
  180. data/site/source/app/assets/javascripts/site.js.coffee +4 -0
  181. data/site/source/app/assets/javascripts/vendor/codemirror.js +4786 -0
  182. data/site/source/app/assets/javascripts/vendor/coffeescript.js +346 -0
  183. data/site/source/app/assets/javascripts/vendor/css.js +465 -0
  184. data/site/source/app/assets/javascripts/vendor/htmlmixed.js +84 -0
  185. data/site/source/app/assets/javascripts/vendor/javascript.js +422 -0
  186. data/site/source/app/assets/javascripts/vendor/js-beautify.js +1353 -0
  187. data/site/source/app/assets/javascripts/vendor/modernizr-2.6.1.min.js +4 -0
  188. data/site/source/app/assets/javascripts/vendor/vim.js +2511 -0
  189. data/site/source/app/assets/stylesheets/docs/api-browser.css.scss +5 -0
  190. data/site/source/app/assets/stylesheets/docs/application.css.scss +35 -0
  191. data/site/source/app/assets/stylesheets/docs/browse-source.css.scss +5 -0
  192. data/site/source/app/assets/stylesheets/docs/scrollable-table.css.scss +5 -0
  193. data/site/source/app/assets/stylesheets/site.css.scss +2 -0
  194. data/site/source/app/assets/stylesheets/vendor/codemirror.css +240 -0
  195. data/site/source/app/assets/stylesheets/vendor/prettify-tomorrow-night-bright.css +160 -0
  196. data/site/source/app/assets/stylesheets/vendor/twilight.css +26 -0
  197. data/site/source/crossdomain.xml +15 -0
  198. data/site/source/documentation.html.haml +1 -0
  199. data/site/source/favicon_base.png +0 -0
  200. data/site/source/humans.txt +15 -0
  201. data/site/source/images/background.png +0 -0
  202. data/site/source/images/middleman.png +0 -0
  203. data/site/source/index.html.haml +1 -0
  204. data/site/source/layouts/layout.haml +55 -0
  205. data/site/source/readme.md +63 -0
  206. data/site/source/robots.txt +3 -0
  207. data/spec/{components/grid_view_spec.coffee → javascripts/components/application_spec.coffee} +0 -0
  208. data/spec/{components/pagination_control_spec.coffee → javascripts/components/collection_loader_view_spec.coffee} +0 -0
  209. data/spec/{components → javascripts/components}/collection_view_spec.coffee +1 -1
  210. data/spec/{components → javascripts/components}/controller_spec.coffee +0 -0
  211. data/spec/{components → javascripts/components}/fields/checkbox_array_spec.coffee +0 -0
  212. data/spec/javascripts/components/form_view_spec.coffee +162 -0
  213. data/spec/{components/record_manager_spec.coffee → javascripts/components/grid_view_spec.coffee} +0 -0
  214. data/spec/{components → javascripts/components}/multi_collection_view_spec.coffee +0 -0
  215. data/spec/{components/template_spec.coffee → javascripts/components/pagination_control_spec.coffee} +0 -0
  216. data/spec/{concerns/paginatable_spec.coffee → javascripts/components/record_manager_spec.coffee} +0 -0
  217. data/spec/{components → javascripts/components}/table_view_spec.coffee +0 -0
  218. data/spec/{containers/modal_view_spec.coffee → javascripts/components/template_spec.coffee} +0 -0
  219. data/spec/{concerns → javascripts/concerns}/collection_event_bindings_spec.coffee +0 -0
  220. data/spec/{concerns → javascripts/concerns}/dom_helpers_spec.coffee +0 -0
  221. data/spec/{concerns → javascripts/concerns}/filterable_spec.coffee +0 -0
  222. data/spec/{concerns → javascripts/concerns}/model_presenter_spec.coffee +0 -0
  223. data/spec/{containers/panel_view_spec.coffee → javascripts/concerns/paginatable_spec.coffee} +0 -0
  224. data/spec/{concerns → javascripts/concerns}/state_model_spec.coffee +5 -0
  225. data/spec/javascripts/containers/card_view_spec.coffee +108 -0
  226. data/spec/{containers/tab_view_spec.coffee → javascripts/containers/modal_view_spec.coffee} +0 -0
  227. data/spec/{containers/viewport_spec.coffee → javascripts/containers/panel_view_spec.coffee} +0 -0
  228. data/spec/{core/observer_spec.coffee → javascripts/containers/tab_view_spec.coffee} +0 -0
  229. data/spec/{managers/socket_manager_spec.coffee → javascripts/containers/viewport_spec.coffee} +0 -0
  230. data/spec/{core → javascripts/core}/collection_spec.coffee +1 -1
  231. data/spec/{core → javascripts/core}/concerns_spec.coffee +0 -0
  232. data/spec/{core → javascripts/core}/container_spec.coffee +0 -0
  233. data/spec/{core → javascripts/core}/define_spec.coffee +0 -0
  234. data/spec/{core → javascripts/core}/events_spec.coffee +0 -0
  235. data/spec/{core → javascripts/core}/field_spec.coffee +0 -0
  236. data/spec/{core → javascripts/core}/framework_spec.coffee +0 -0
  237. data/spec/{core → javascripts/core}/model_spec.coffee +0 -0
  238. data/spec/javascripts/core/observer_spec.coffee +0 -0
  239. data/spec/{core → javascripts/core}/util_spec.coffee +0 -0
  240. data/spec/{core → javascripts/core}/view_spec.coffee +51 -39
  241. data/spec/{dependencies → javascripts/dependencies}/index.coffee +0 -0
  242. data/spec/{dependencies → javascripts/dependencies}/jasmine-html.js +0 -0
  243. data/spec/{dependencies → javascripts/dependencies}/jasmine.js +0 -0
  244. data/spec/{dependencies → javascripts/dependencies}/sinon.js +0 -0
  245. data/spec/{helper.coffee → javascripts/helper.coffee} +0 -0
  246. data/spec/{managers → javascripts/managers}/collection_manager_spec.coffee +0 -0
  247. data/spec/javascripts/managers/socket_manager_spec.coffee +0 -0
  248. data/spec/lib/component_definition_spec.rb +63 -0
  249. data/spec/lib/input_compiler_spec.rb +9 -0
  250. data/spec/lib/luca_application_spec.rb +30 -0
  251. data/spec/support/fixtures/application.coffee +45 -0
  252. data/spec/support/fixtures/component.coffee +34 -0
  253. data/tutorials/component-definitions.md +0 -0
  254. data/tutorials/component-definitions/01_intro.md +0 -0
  255. data/tutorials/component-driven-design.md +140 -0
  256. data/tutorials/structure-of-a-project.md +63 -0
  257. data/vendor/assets/javascripts/backbone-min.js +37 -33
  258. data/vendor/assets/javascripts/backbone-query.min.js +1 -1
  259. data/vendor/assets/javascripts/hogan.js +707 -0
  260. data/vendor/assets/javascripts/jquery.js +5 -4
  261. data/vendor/assets/javascripts/keymaster.min.js +4 -0
  262. data/vendor/assets/javascripts/luca-dependencies.min.js +8 -0
  263. data/vendor/assets/javascripts/luca-development.min.js +1 -0
  264. data/vendor/assets/javascripts/luca-spec.js +6 -6
  265. data/vendor/assets/javascripts/luca-ui.js +7386 -0
  266. data/vendor/assets/javascripts/luca-ui.min.js +5 -0
  267. data/vendor/assets/javascripts/luca.full.min.js +12 -0
  268. data/vendor/assets/javascripts/luca.min.js +5 -0
  269. data/vendor/assets/javascripts/underscore-min.js +1 -5
  270. data/vendor/assets/javascripts/underscore-string.min.js +1 -1
  271. data/vendor/assets/stylesheets/luca-components.css +202 -0
  272. data/vendor/assets/stylesheets/luca-development.css +23 -0
  273. data/vendor/assets/stylesheets/luca-ui.css +198 -0
  274. metadata +324 -94
  275. data/app/assets/javascripts/luca/components/base_toolbar.coffee +0 -17
  276. data/app/assets/javascripts/luca/components/form_button_toolbar.coffee +0 -28
  277. data/app/assets/javascripts/luca/components/grid_view.coffee +0 -269
  278. data/app/assets/javascripts/luca/components/page_controller.coffee +0 -7
  279. data/app/assets/javascripts/luca/components/template.coffee +0 -5
  280. data/app/assets/javascripts/luca/components/toolbar_dialog.coffee +0 -25
  281. data/lib/luca/code_browser.rb +0 -55
  282. data/lib/luca/command_line.rb +0 -69
  283. data/lib/luca/component_documentation.rb +0 -72
  284. data/site/assets/bootstrap.min.js +0 -7
  285. data/site/assets/dependencies.js +0 -94
  286. data/site/assets/glyphicons-halflings-white.png +0 -0
  287. data/site/assets/glyphicons-halflings.png +0 -0
  288. data/site/assets/luca-ui-bootstrap.css +0 -1331
  289. data/site/assets/luca-ui-bootstrap.js +0 -9
  290. data/site/assets/luca-ui-development-tools.css +0 -234
  291. data/site/assets/luca-ui-development-tools.js +0 -18561
  292. data/site/assets/luca-ui-development-tools.min.js +0 -15
  293. data/site/assets/luca-ui-full.min.js +0 -8
  294. data/site/assets/luca-ui.min.js +0 -4
  295. data/site/assets/sandbox.css +0 -62
  296. data/site/assets/sandbox.js +0 -469
  297. data/site/docs/application.html +0 -41
  298. data/site/docs/caching.html +0 -43
  299. data/site/docs/collection.html +0 -75
  300. data/site/docs/collection_manager.html +0 -71
  301. data/site/docs/containers.html +0 -118
  302. data/site/docs/events.html +0 -153
  303. data/site/docs/view.html +0 -128
  304. data/site/img/glyphicons-halflings-white.png +0 -0
  305. data/site/img/glyphicons-halflings.png +0 -0
  306. data/site/index.html +0 -20
  307. data/site/source-map.js +0 -1
  308. data/spec/components/form_view_spec.coffee +0 -84
  309. data/spec/containers/card_view_spec.coffee +0 -50
  310. data/spec/luca-spec.coffee +0 -9
@@ -0,0 +1,356 @@
1
+ require 'rubygems'
2
+ require 'redcarpet'
3
+ require 'active_support/core_ext'
4
+
5
+ module Luca
6
+ class ComponentDefinition
7
+ attr_accessor :source, :markdown
8
+
9
+ ARGUMENTS_REGEX = /^\w+\:\s*\((.+)\)/
10
+
11
+ class << self
12
+ attr_accessor :markdown
13
+ end
14
+
15
+ begin
16
+ self.markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true)
17
+ rescue Exception => e
18
+
19
+ end
20
+
21
+ def initialize source
22
+ @source = source
23
+ read_source()
24
+ end
25
+
26
+ def read_source
27
+ raise "Invalid source type" unless source.match(/.coffee|.js/)
28
+ @contents = IO.read(source)
29
+ end
30
+
31
+ def update contents
32
+ # File.open(source,'w+') do |fh|
33
+ # fh.puts(contents)
34
+ # end
35
+ end
36
+
37
+ def to_change_notification
38
+ as_json(compile:true, include_contents:true)
39
+ end
40
+
41
+ def as_json options={}
42
+ base = {
43
+ source: source,
44
+ defined_in_file: source,
45
+ type: "javascript",
46
+ starts_on_line: definition_line && definition_line.line_number
47
+ }
48
+
49
+ unless class_name.nil?
50
+ base.merge!({ :class_name => class_name,
51
+ :defined_in_file => source,
52
+ :header_documentation => header_documentation,
53
+ :type_alias => type_alias,
54
+ :type => "component_definition",
55
+ :css_class_identifier => css_class_identifier,
56
+ :defines_methods => method_definition_map,
57
+ :defines_properties => property_definition_map })
58
+ end
59
+
60
+ if options[:include_contents]
61
+ base.merge!(:source_file_contents => contents)
62
+ end
63
+
64
+ if options[:compile]
65
+ base.merge!(:compiled => compiled_contents)
66
+ end
67
+
68
+ base
69
+ end
70
+
71
+ def method_definition_map
72
+ defines_methods.inject({}) do |memo, meth|
73
+ definition_line = find_definition_of(meth)
74
+ memo[meth] = {
75
+ defined_on_line: definition_line.line_number,
76
+ documentation: documentation_for(meth) || "",
77
+ arguments: argument_information_for(meth)
78
+ }
79
+ memo
80
+ end
81
+ end
82
+
83
+ def property_definition_map
84
+ defines_properties.inject({}) do |memo,property|
85
+ definition_line = find_definition_of(property)
86
+ memo[property] = {
87
+ defined_on_line: definition_line.line_number,
88
+ documentation: documentation_for(property),
89
+ default: default_value_for(property)
90
+ }
91
+ memo
92
+ end
93
+ end
94
+
95
+ def default_value_for property
96
+ definition = find_definition_of(property).line.strip
97
+ property, value = definition.split(':')
98
+ value && value.strip
99
+ end
100
+
101
+ def argument_information_for method
102
+ information = []
103
+ definition = find_definition_of(method).line.strip
104
+
105
+ if arguments = definition.match(ARGUMENTS_REGEX)
106
+ arguments = arguments.to_a[1]
107
+ information = arguments.split(',').map(&:strip).inject(information) do |memo, argument|
108
+ parts = argument.split('=').map(&:strip)
109
+ memo << {:argument=>parts[0],:value=>parts[1]}
110
+ end
111
+ end
112
+
113
+ information
114
+ end
115
+
116
+ def valid?
117
+ !class_name.nil?
118
+ end
119
+
120
+ def parse
121
+ end
122
+
123
+ def contents
124
+ @contents.to_s
125
+ end
126
+
127
+ def compiler
128
+ AssetCompiler.new(input: contents, type: "coffeescript")
129
+ end
130
+
131
+ def compiled
132
+ compiled_contents
133
+ end
134
+
135
+ def compiled_contents
136
+ compiler.output
137
+ end
138
+
139
+ def type_alias
140
+ classified = class_name && class_name.split('.').last
141
+ classified && classified.underscore
142
+ end
143
+
144
+ def view_based?
145
+ extends && !(
146
+ extends.match('.models.') ||
147
+ extends.match('.collections.') ||
148
+ extends.match(/Collection$/) ||
149
+ extends.match(/Model$/)
150
+ )
151
+ end
152
+
153
+ def css_class_identifier
154
+ return '' unless view_based?
155
+
156
+ parts = class_name.split('.')
157
+ parts -= ['views','components']
158
+
159
+ parts.map!(&:underscore)
160
+ parts.map!(&:dasherize)
161
+
162
+ parts.join('-')
163
+ end
164
+
165
+ def extends
166
+ extends_line.split(' ').last.gsub(/"|'/,'')
167
+ end
168
+
169
+ def class_name
170
+ match = definition_line && definition_line.match(/register.*["|'](.*)["|']/)
171
+ match && match[1]
172
+ end
173
+
174
+ def component_definition
175
+ self
176
+ end
177
+
178
+ def lines
179
+ line_number = 0
180
+ contents.lines.map do |line|
181
+ Line.new(line, (line_number += 1) )
182
+ end
183
+ end
184
+
185
+ def extends_line
186
+ match = lines.detect do |line|
187
+ line.component_extension?(definition_proxy_variable_name)
188
+ end
189
+
190
+ match && match.strip
191
+ end
192
+
193
+ def documentation_for method_or_property, compile=true
194
+ comment_lines = find_comments_above(method_or_property).collect(&:line)
195
+ comments = comment_lines.map do |comment_line|
196
+ comment_line.gsub(/\A\s*\#/,'').strip
197
+ end
198
+
199
+ data = comments.reverse.join("\n")
200
+
201
+ docs = if compile == true
202
+ self.class.markdown.render(data) rescue data
203
+ end
204
+
205
+ docs
206
+ end
207
+
208
+ def header_documentation
209
+ header_comments(true)
210
+ end
211
+
212
+ def header_comment_lines
213
+ header_lines = lines[ (0..(definition_line.line_number || 0) ) ]
214
+ comments = header_lines.select(&:comment?).map(&:line)
215
+
216
+ comments.map! {|line| line.gsub(/\A\s*\#[\ |\n]/,'') }
217
+ comments.reject! {|line| line.match(/\=\s*require/) }
218
+
219
+ comments
220
+ end
221
+
222
+ def header_comments compile=true
223
+ combined = header_comment_lines.join("")
224
+
225
+ if compile && self.class.markdown && self.class.markdown.respond_to?(:render)
226
+ self.class.markdown.render(combined)
227
+ else
228
+ combined
229
+ end
230
+ end
231
+
232
+ def find_comments_above method_or_property
233
+ comment_lines = []
234
+ if line = find_definition_of( method_or_property )
235
+ line_number = line.line_number
236
+ indentation_level = line.indentation_level
237
+
238
+ next_line = find_line_by_number( line_number -= 1)
239
+ while !next_line.nil? && next_line.indentation_level == indentation_level && next_line.comment?
240
+ comment_lines << next_line
241
+ next_line = find_line_by_number( line_number -= 1)
242
+ end
243
+ end
244
+
245
+ comment_lines
246
+ end
247
+
248
+ def definition_proxy_variable_name
249
+ definition_line.split('=').first.strip
250
+ end
251
+
252
+ def find_line_by_number line_number=1
253
+ lines.detect {|line| line.line_number == line_number }
254
+ end
255
+
256
+ def definition_line
257
+ lines.detect do |line|
258
+ !line.comment? && line.component_definition?
259
+ end
260
+ end
261
+
262
+ def defines
263
+ lines.select(&:defines_property_or_method?).collect(&:defines)
264
+ end
265
+
266
+ def defines_methods
267
+ lines.select(&:defines_method?).collect(&:defines)
268
+ end
269
+
270
+ def find_definition_of method_or_property
271
+ lines.select(&:defines_property_or_method?).detect {|line| line.defines && line.defines.length > 0 && line.defines == method_or_property }
272
+ end
273
+
274
+ def defines_properties
275
+ lines.select(&:defines_property?).collect(&:defines)
276
+ end
277
+
278
+ class Line
279
+ attr_accessor :line, :line_number, :found_in
280
+
281
+ def initialize(line,line_number)
282
+ @line = line
283
+ @line_number = line_number
284
+ end
285
+
286
+ def match pattern
287
+ line.match(pattern)
288
+ end
289
+
290
+ def split delimiter
291
+ line.split(delimiter)
292
+ end
293
+
294
+ def strip
295
+ line.strip
296
+ end
297
+
298
+ def details
299
+ {
300
+ type: type,
301
+ line_number: line_number,
302
+ indentation_level: indentation_level
303
+ }
304
+ end
305
+
306
+ def indentation_level
307
+ space_count = if match = line.match(/\A */)[0] and match.length > 0
308
+ match.length
309
+ else
310
+ 0
311
+ end
312
+
313
+ space_count / 2
314
+ end
315
+
316
+ def defines_method?
317
+ !comment? && indentation_level == 1 && line.match(/\s*\w+\:\s*\(.*\)/)
318
+ end
319
+
320
+ def comment?
321
+ line.match(/^(\s*)\#/) or line == "#\n"
322
+ end
323
+
324
+ def defines_property?
325
+ !comment? && !defines_method? && indentation_level == 1 && line.match(/\s*\w+\:.*\w*/)
326
+ end
327
+
328
+ def body?
329
+ indentation_level == 1 && line.match(/^\s+/)
330
+ end
331
+
332
+ def component
333
+ found_in
334
+ end
335
+
336
+ def component_definition?
337
+ line.match(/[A-Z].+\.register/)
338
+ end
339
+
340
+ def component_extension?(proxy)
341
+ line.include?("#{ proxy }.extends")
342
+ end
343
+
344
+ def defines_property_or_method?
345
+ defines_method? || defines_property?
346
+ end
347
+
348
+ def defines
349
+ if defines_property_or_method?
350
+ line.split(':').first.strip
351
+ end
352
+ end
353
+ end
354
+
355
+ end
356
+ end
@@ -0,0 +1,258 @@
1
+ require 'rubygems'
2
+ require 'redcarpet'
3
+ require 'active_support/core_ext'
4
+
5
+ module Luca
6
+ class LucaApplication
7
+ attr_accessor :application_name,
8
+ :options
9
+
10
+ # Public: creates an instance of a luca application repository.
11
+ # generally this will be a single folder inside of your asset pipeline
12
+ #
13
+ # Example:
14
+ # repo = LucaApplication.new("Tools",root:"/path/to/rails/app")
15
+ def initialize application_name, options={}
16
+ @application_name = application_name
17
+ @options = options
18
+ end
19
+
20
+ def export
21
+ contents = export_all_component_definitions.to_json
22
+ File.open(export_file_location, 'w+') do |fh|
23
+ contents = "window.#{ namespace } = window.#{ namespace } || {}; window.#{ namespace }.documentation = #{ contents };"
24
+ fh.puts( contents )
25
+ end
26
+ contents
27
+ end
28
+
29
+ def export_file_location
30
+ loc = options[:export_location] || File.join(Luca.base_path,"site","source", "javascripts")
31
+
32
+ File.join(loc, "#{ application_name.downcase }-docs.js")
33
+ end
34
+
35
+ def export_all_component_definitions
36
+ list = component_definitions.map do |cdef|
37
+ cdef.as_json(include_contents:true) rescue nil
38
+ end
39
+ list.compact
40
+ end
41
+
42
+ def component_definition_filemap
43
+ component_definitions.inject({}) do |memo, definition|
44
+ memo[ definition.class_name ] = definition.source
45
+ memo
46
+ end
47
+ end
48
+
49
+ def find_asset_wrapper_for filename
50
+ if filename.match(/\.js$/) || filename.match(/\.coffee$/)
51
+ wrapper = component_definitions(false).detect do |component_definition|
52
+ component_definition.source &&
53
+ component_definition.source.match(filename)
54
+ end
55
+ end
56
+
57
+ if filename.match(/\.mustache/) || filename.match(/\.jst/)
58
+ wrapper = templates.detect do |template|
59
+ template.source && template.source.match(filename)
60
+ end
61
+ end
62
+
63
+ if filename.match(/css|sass|less/)
64
+ wrapper = stylesheets.detect do |stylesheet|
65
+ stylesheet.source && stylesheet.source.match(filename)
66
+ end
67
+ end
68
+
69
+ return wrapper
70
+ end
71
+
72
+ def source_code_for_class class_name
73
+ find_component_definition_for_class(class_name).contents
74
+ end
75
+
76
+ def find_definition_file_for_class needle
77
+ definition = find_component_definition_for_class(needle)
78
+ definition && definition.source
79
+ end
80
+
81
+ def find_component_definition_for_class needle
82
+ component_definitions.detect {|d| d.class_name == needle }
83
+ end
84
+
85
+ def namespace
86
+ return options[:application_name].capitalize if options[:application_name]
87
+
88
+ line = initializer_file_contents.lines.to_a.detect do |l|
89
+ l.match(/Luca.initialize/)
90
+ end
91
+
92
+ match = line.match(/Luca.initialize.+['|"](.+)['|"]/)
93
+
94
+ if match && match[1]
95
+ match[1]
96
+ else
97
+ application_folder.capitalize
98
+ end
99
+ end
100
+
101
+ def valid?
102
+ !initializer_file_location.nil? and File.exists?(initializer_file_location)
103
+ end
104
+
105
+ def templates
106
+ template_file_locations.map {|path| TemplateAsset.new(path) }
107
+ end
108
+
109
+ def stylesheets
110
+ stylesheet_file_locations.map {|path| Stylesheet.new(path) }
111
+ end
112
+
113
+ def find_stylesheet(params={})
114
+ if params[:component_class]
115
+ parts = params[:component_class].split('.')
116
+ parts.map!(&:downcase)
117
+ parts.reject! {|p| p == "views" || p == "components" || p == "containers" || p == "pages" }
118
+ params[:css_class] = parts.join('_').dasherize
119
+
120
+ end
121
+
122
+ stylesheets.reject do |stylesheet|
123
+ match = false
124
+
125
+ if params[:css_class]
126
+ match = stylesheet.compiled.include?( params[:css_class] )
127
+ end
128
+
129
+ match
130
+ end
131
+ end
132
+
133
+ def component_definitions(reject_invalid=true)
134
+ list = component_file_locations.map do |path|
135
+ ComponentDefinition.new(path)
136
+ end
137
+
138
+ return list unless reject_invalid
139
+
140
+ list.select do |definition|
141
+ definition.valid?
142
+ end
143
+ end
144
+
145
+ def assets_root
146
+ options[:assets_root] || File.join(project_root,"app","assets")
147
+ end
148
+
149
+ protected
150
+ def template_extensions
151
+ options[:template_extensions] || ['jst.ejs.haml','mustache']
152
+ end
153
+
154
+ def stylesheet_extensions
155
+ options[:stylesheet_extensions] || ['css.scss']
156
+ end
157
+
158
+ def component_extensions
159
+ options[:component_extensions] || ['.coffee']
160
+ end
161
+
162
+ def application_folder
163
+ options[:application_folder] || application_name.downcase
164
+ end
165
+
166
+ def stylesheet_file_locations
167
+ stylesheet_folders.flat_map do |folder|
168
+ Dir.glob("#{ folder }/**/*.css.scss")
169
+ end
170
+ end
171
+
172
+ def component_file_locations
173
+ component_folders.flat_map do |folder|
174
+ Dir.glob("#{ folder }/**/*.coffee")
175
+ end
176
+ end
177
+
178
+ def template_file_locations
179
+ template_folders.flat_map do |folder|
180
+ template_extensions.flat_map do |extension|
181
+ Dir.glob("#{ folder }/**/*.#{ extension }")
182
+ end
183
+ end
184
+ end
185
+
186
+ def stylesheet_folders
187
+ list = Dir.entries( stylesheets_root )
188
+ list = list.slice(2, list.length)
189
+
190
+ list.map! do |path|
191
+ File.join(stylesheets_root, path)
192
+ end
193
+
194
+ list.select! {|path| File.exists?(path) && File.directory?(path) }
195
+
196
+ (list << stylesheets_root << stylesheets_location).uniq
197
+ end
198
+
199
+ def template_folders
200
+ Dir.glob("#{ javascripts_root }/**/templates*")
201
+ end
202
+
203
+ def component_folders
204
+ list = %w{views components collections models pages containers}
205
+ list += Array(options[:component_folders])
206
+
207
+ list.map! do |folder|
208
+ File.join(coffeescripts_location, folder)
209
+ end
210
+
211
+ # add the root folder
212
+ list << coffeescripts_location
213
+
214
+ list.select {|path| File.exists?(path) || File.directory?(path) }
215
+ end
216
+
217
+ def initializer_file_contents
218
+ initializer_file_location && IO.read( initializer_file_location )
219
+ end
220
+
221
+ def initializer_file_location
222
+ filename = root_coffeescript_files.detect do |file|
223
+ IO.read( File.join(coffeescripts_location, file) ).match('Luca.initialize')
224
+ end
225
+
226
+ File.join( coffeescripts_location, filename )
227
+ end
228
+
229
+ def root_coffeescript_files
230
+ Dir.entries( coffeescripts_location ).select do |file|
231
+ !File.directory?(file) && File.extname(file).match(/coffee/)
232
+ end
233
+ end
234
+
235
+ def coffeescripts_location
236
+ options[:coffeescripts_location] || File.join(javascripts_root, application_folder)
237
+ end
238
+
239
+ def stylesheets_location
240
+ options[:stylesheets_location] || File.join(stylesheets_root, application_folder)
241
+ end
242
+
243
+ def stylesheets_root
244
+ options[:stylesheets_root] || File.join(assets_root,"stylesheets")
245
+ end
246
+
247
+ def javascripts_root
248
+ options[:javascripts_root] || File.join(assets_root,"javascripts")
249
+ end
250
+
251
+
252
+
253
+ def project_root
254
+ options[:root] || (::Rails.root rescue Dir.pwd())
255
+ end
256
+
257
+ end
258
+ end