middleman 2.0.4 → 2.0.5

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 (172) hide show
  1. data/CHANGELOG +8 -0
  2. data/lib/middleman.rb +7 -1
  3. data/lib/middleman/vendor/padrino-core-0.10.0/.document +5 -0
  4. data/lib/middleman/vendor/padrino-core-0.10.0/.gitignore +22 -0
  5. data/lib/middleman/vendor/padrino-core-0.10.0/LICENSE +20 -0
  6. data/lib/middleman/vendor/padrino-core-0.10.0/README.rdoc +294 -0
  7. data/lib/middleman/vendor/padrino-core-0.10.0/Rakefile +5 -0
  8. data/lib/middleman/vendor/padrino-core-0.10.0/bin/padrino +9 -0
  9. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core.rb +119 -0
  10. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application.rb +259 -0
  11. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application/rendering.rb +228 -0
  12. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application/routing.rb +821 -0
  13. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application/showexceptions.rb +18 -0
  14. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/caller.rb +45 -0
  15. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/adapter.rb +24 -0
  16. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/base.rb +152 -0
  17. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/console.rb +20 -0
  18. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/rake.rb +24 -0
  19. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/rake_tasks.rb +59 -0
  20. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/command.rb +27 -0
  21. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/images/404.png +0 -0
  22. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/images/500.png +0 -0
  23. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/loader.rb +182 -0
  24. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/cz.yml +30 -0
  25. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/da.yml +30 -0
  26. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/de.yml +30 -0
  27. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/en.yml +30 -0
  28. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/es.yml +30 -0
  29. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/fr.yml +30 -0
  30. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/hu.yml +30 -0
  31. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/it.yml +37 -0
  32. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/ja.yml +30 -0
  33. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/nl.yml +30 -0
  34. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/no.yml +31 -0
  35. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/pl.yml +30 -0
  36. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/pt_br.yml +37 -0
  37. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/ru.yml +30 -0
  38. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/tr.yml +30 -0
  39. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/uk.yml +30 -0
  40. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/zh_cn.yml +30 -0
  41. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/zh_tw.yml +30 -0
  42. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/logger.rb +344 -0
  43. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/mounter.rb +192 -0
  44. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/reloader.rb +247 -0
  45. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/router.rb +79 -0
  46. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/server.rb +70 -0
  47. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/support_lite.rb +135 -0
  48. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/tasks.rb +23 -0
  49. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/version.rb +15 -0
  50. data/lib/middleman/vendor/padrino-core-0.10.0/padrino-core.gemspec +38 -0
  51. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/.components +6 -0
  52. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/.gitignore +7 -0
  53. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/complex.rb +27 -0
  54. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/simple.rb +33 -0
  55. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/a.rb +9 -0
  56. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/b.rb +4 -0
  57. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/c.rb +1 -0
  58. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/circular/e.rb +13 -0
  59. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/circular/f.rb +2 -0
  60. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/circular/g.rb +2 -0
  61. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/d.rb +4 -0
  62. data/lib/middleman/vendor/padrino-core-0.10.0/test/helper.rb +101 -0
  63. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_application.rb +83 -0
  64. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_core.rb +79 -0
  65. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_dependencies.rb +44 -0
  66. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_filters.rb +266 -0
  67. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_logger.rb +91 -0
  68. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_mounter.rb +176 -0
  69. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_reloader_complex.rb +66 -0
  70. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_reloader_simple.rb +97 -0
  71. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_rendering.rb +437 -0
  72. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_router.rb +146 -0
  73. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_routing.rb +1491 -0
  74. data/lib/middleman/vendor/padrino-helpers-0.10.0/.document +5 -0
  75. data/lib/middleman/vendor/padrino-helpers-0.10.0/.gitignore +21 -0
  76. data/lib/middleman/vendor/padrino-helpers-0.10.0/LICENSE +20 -0
  77. data/lib/middleman/vendor/padrino-helpers-0.10.0/README.rdoc +239 -0
  78. data/lib/middleman/vendor/padrino-helpers-0.10.0/Rakefile +5 -0
  79. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers.rb +51 -0
  80. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/asset_tag_helpers.rb +288 -0
  81. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/form_builder/abstract_form_builder.rb +220 -0
  82. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/form_builder/standard_form_builder.rb +43 -0
  83. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/form_helpers.rb +446 -0
  84. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/format_helpers.rb +260 -0
  85. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/cz.yml +103 -0
  86. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/da.yml +91 -0
  87. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/de.yml +78 -0
  88. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/en.yml +103 -0
  89. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/es.yml +103 -0
  90. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/fr.yml +79 -0
  91. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/hu.yml +103 -0
  92. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/it.yml +85 -0
  93. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/ja.yml +103 -0
  94. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/nl.yml +78 -0
  95. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/no.yml +91 -0
  96. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/pl.yml +95 -0
  97. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/pt_br.yml +103 -0
  98. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/ru.yml +103 -0
  99. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/tr.yml +103 -0
  100. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/uk.yml +103 -0
  101. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/zh_cn.yml +103 -0
  102. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/zh_tw.yml +103 -0
  103. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/number_helpers.rb +273 -0
  104. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers.rb +128 -0
  105. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/abstract_handler.rb +103 -0
  106. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/erb_handler.rb +79 -0
  107. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/haml_handler.rb +64 -0
  108. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/slim_handler.rb +82 -0
  109. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/render_helpers.rb +40 -0
  110. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/tag_helpers.rb +59 -0
  111. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/translation_helpers.rb +21 -0
  112. data/lib/middleman/vendor/padrino-helpers-0.10.0/padrino-helpers.gemspec +27 -0
  113. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/app.rb +73 -0
  114. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/capture_concat.erb +14 -0
  115. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/capture_concat.haml +12 -0
  116. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/capture_concat.slim +13 -0
  117. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_for.erb +11 -0
  118. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_for.haml +9 -0
  119. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_for.slim +9 -0
  120. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_tag.erb +11 -0
  121. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_tag.haml +9 -0
  122. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_tag.slim +9 -0
  123. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/current_engine.erb +5 -0
  124. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/current_engine.haml +5 -0
  125. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/current_engine.slim +5 -0
  126. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/fields_for.erb +20 -0
  127. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/fields_for.haml +15 -0
  128. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/fields_for.slim +15 -0
  129. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_for.erb +56 -0
  130. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_for.haml +47 -0
  131. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_for.slim +47 -0
  132. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_tag.erb +56 -0
  133. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_tag.haml +45 -0
  134. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_tag.slim +45 -0
  135. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/link_to.erb +5 -0
  136. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/link_to.haml +4 -0
  137. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/link_to.slim +4 -0
  138. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/mail_to.erb +3 -0
  139. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/mail_to.haml +3 -0
  140. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/mail_to.slim +3 -0
  141. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/meta_tag.erb +3 -0
  142. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/meta_tag.haml +3 -0
  143. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/meta_tag.slim +3 -0
  144. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/partials/_erb.erb +1 -0
  145. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/partials/_haml.haml +1 -0
  146. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/partials/_slim.slim +1 -0
  147. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/simple_partial.erb +1 -0
  148. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/simple_partial.haml +1 -0
  149. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/simple_partial.slim +1 -0
  150. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/app.rb +45 -0
  151. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engine.haml +5 -0
  152. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engines/_erb.erb +1 -0
  153. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engines/_haml.haml +1 -0
  154. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engines/_slim.slim +1 -0
  155. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/erb/test.erb +1 -0
  156. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/explicit_engine.haml +5 -0
  157. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/haml/test.haml +1 -0
  158. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/template/_user.haml +7 -0
  159. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/template/haml_template.haml +1 -0
  160. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/template/some_template.haml +2 -0
  161. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/helper.rb +78 -0
  162. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_asset_tag_helpers.rb +320 -0
  163. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_form_builder.rb +998 -0
  164. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_form_helpers.rb +645 -0
  165. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_format_helpers.rb +227 -0
  166. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_number_helpers.rb +136 -0
  167. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_output_helpers.rb +133 -0
  168. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_render_helpers.rb +69 -0
  169. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_tag_helpers.rb +100 -0
  170. data/lib/middleman/version.rb +1 -1
  171. data/middleman.gemspec +6 -2
  172. metadata +218 -67
@@ -0,0 +1,192 @@
1
+ module Padrino
2
+ ##
3
+ # Represents a particular mounted padrino application
4
+ # Stores the name of the application (app folder name) and url mount path
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # Mounter.new("blog_app", :app_class => "Blog").to("/blog")
9
+ # Mounter.new("blog_app", :app_file => "/path/to/blog/app.rb").to("/blog")
10
+ #
11
+ class Mounter
12
+ class MounterException < RuntimeError #:nodoc:
13
+ end
14
+
15
+ attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host
16
+
17
+ def initialize(name, options={})
18
+ @name = name.to_s
19
+ @app_class = options[:app_class] || @name.camelize
20
+ @app_file = options[:app_file] || locate_app_file
21
+ @app_obj = options[:app_obj] || app_constant || locate_app_object
22
+ ensure_app_file! || ensure_app_object!
23
+ @app_root = options[:app_root] || File.dirname(@app_file)
24
+ @uri_root = "/"
25
+ Padrino::Reloader.exclude_constants << @app_class
26
+ end
27
+
28
+ ##
29
+ # Registers the mounted application onto Padrino
30
+ #
31
+ # ==== Examples
32
+ #
33
+ # Mounter.new("blog_app").to("/blog")
34
+ #
35
+ def to(mount_url)
36
+ @uri_root = mount_url
37
+ Padrino.insert_mounted_app(self)
38
+ self
39
+ end
40
+
41
+ ##
42
+ # Registers the mounted application onto Padrino for the given host
43
+ #
44
+ # ==== Examples
45
+ #
46
+ # Mounter.new("blog_app").to("/blog").host("blog.padrino.org")
47
+ # Mounter.new("blog_app").host("blog.padrino.org")
48
+ # Mounter.new("catch_all").host(/.*\.padrino.org/)
49
+ #
50
+ def host(mount_host)
51
+ @app_host = mount_host
52
+ Padrino.insert_mounted_app(self)
53
+ self
54
+ end
55
+
56
+ ##
57
+ # Maps Padrino application onto a Padrino::Router
58
+ # For use in constructing a Rack application
59
+ #
60
+ # @app.map_onto(router)
61
+ #
62
+ def map_onto(router)
63
+ app_data, app_obj = self, @app_obj
64
+ app_obj.set :uri_root, app_data.uri_root
65
+ app_obj.set :app_name, app_data.name
66
+ app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
67
+ app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
68
+ app_obj.set :public, Padrino.root('public', app_data.uri_root) unless File.exists?(app_obj.public)
69
+ app_obj.set :static, File.exist?(app_obj.public) if app_obj.nil?
70
+ app_obj.setup_application! # We need to initialize here the app.
71
+ router.map(:to => app_obj, :path => app_data.uri_root, :host => app_data.app_host)
72
+ end
73
+
74
+ ###
75
+ # Returns the route objects for the mounted application
76
+ #
77
+ def routes
78
+ app_obj.routes
79
+ end
80
+
81
+ ###
82
+ # Returns the basic route information for each named route
83
+ #
84
+ #
85
+ def named_routes
86
+ app_obj.routes.map { |route|
87
+ name_array = "(#{route.named.to_s.split("_").map { |piece| %Q[:#{piece}] }.join(", ")})"
88
+ request_method = route.conditions[:request_method][0]
89
+ full_path = File.join(uri_root, route.original_path)
90
+ next if route.named.blank? || request_method == 'HEAD'
91
+ OpenStruct.new(:verb => request_method, :identifier => route.named, :name => name_array, :path => full_path)
92
+ }.compact
93
+ end
94
+
95
+ ##
96
+ # Makes two Mounters equal if they have the same name and uri_root
97
+ #
98
+ def ==(other)
99
+ other.is_a?(Mounter) && self.app_class == other.app_class && self.uri_root == other.uri_root
100
+ end
101
+
102
+ ##
103
+ # Returns the class object for the app if defined, nil otherwise
104
+ #
105
+ def app_constant
106
+ klass = Object
107
+ for piece in app_class.split("::")
108
+ piece = piece.to_sym
109
+ if klass.const_defined?(piece)
110
+ klass = klass.const_get(piece)
111
+ else
112
+ return
113
+ end
114
+ end
115
+ klass
116
+ end
117
+
118
+ protected
119
+ ##
120
+ # Locates and requires the file to load the app constant
121
+ #
122
+ def locate_app_object
123
+ @_app_object ||= begin
124
+ ensure_app_file!
125
+ Padrino.require_dependencies(app_file)
126
+ app_constant
127
+ end
128
+ end
129
+
130
+ ##
131
+ # Returns the determined location of the mounted application main file
132
+ #
133
+ def locate_app_file
134
+ candidates = []
135
+ candidates << app_constant.app_file if app_constant.respond_to?(:app_file) && File.exist?(app_constant.app_file.to_s)
136
+ candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
137
+ candidates << Padrino.mounted_root(name.downcase, "app.rb")
138
+ candidates << Padrino.root("app", "app.rb")
139
+ candidates.find { |candidate| File.exist?(candidate) }
140
+ end
141
+
142
+ ###
143
+ # Raises an exception unless app_file is located properly
144
+ #
145
+ def ensure_app_file!
146
+ message = "Unable to locate source file for app '#{app_class}', try with :app_file => '/path/app.rb'"
147
+ raise MounterException, message unless @app_file
148
+ end
149
+
150
+ ###
151
+ # Raises an exception unless app_obj is defined properly
152
+ #
153
+ def ensure_app_object!
154
+ message = "Unable to locate app for '#{app_class}', try with :app_class => 'MyAppClass'"
155
+ raise MounterException, message unless @app_obj
156
+ end
157
+ end
158
+
159
+ class << self
160
+ attr_writer :mounted_root # Set root directory where padrino searches mounted apps
161
+
162
+ ##
163
+ # Returns the root to the mounted apps base directory
164
+ #
165
+ def mounted_root(*args)
166
+ Padrino.root(@mounted_root ||= "", *args)
167
+ end
168
+
169
+ ##
170
+ # Returns the mounted padrino applications (MountedApp objects)
171
+ #
172
+ def mounted_apps
173
+ @mounted_apps ||= []
174
+ end
175
+
176
+ ##
177
+ # Inserts a Mounter object into the mounted applications (avoids duplicates)
178
+ #
179
+ def insert_mounted_app(mounter)
180
+ Padrino.mounted_apps.push(mounter) unless Padrino.mounted_apps.include?(mounter)
181
+ end
182
+
183
+ ##
184
+ # Mounts a new sub-application onto Padrino project
185
+ #
186
+ # Padrino.mount("blog_app").to("/blog")
187
+ #
188
+ def mount(name, options={})
189
+ Mounter.new(name, options)
190
+ end
191
+ end # Mounter
192
+ end # Padrino
@@ -0,0 +1,247 @@
1
+ require 'pathname'
2
+
3
+ module Padrino
4
+ ##
5
+ # High performance source code reloader middleware
6
+ #
7
+ module Reloader
8
+ ##
9
+ # This reloader is suited for use in a many environments because each file
10
+ # will only be checked once and only one system call to stat(2) is made.
11
+ #
12
+ # Please note that this will not reload files in the background, and does so
13
+ # only when explicitly invoked.
14
+ #
15
+ MTIMES = {}
16
+ LOADED_FILES = {}
17
+ LOADED_CLASSES = {}
18
+
19
+ class << self
20
+ ##
21
+ # Specified folders can be excluded from the code reload detection process.
22
+ # Default excluded directories at Padrino.root are: test, spec, features, tmp, config, db and public
23
+ #
24
+ def exclude
25
+ @_exclude ||= %w(test spec tmp features config public db).map { |path| Padrino.root(path) }
26
+ end
27
+
28
+ ##
29
+ # Specified constants can be excluded from the code unloading process.
30
+ #
31
+ def exclude_constants
32
+ @_exclude_constants ||= []
33
+ end
34
+
35
+ ##
36
+ # Specified constants can be configured to be reloaded on every request.
37
+ # Default included constants are: [none]
38
+ #
39
+ def include_constants
40
+ @_include_constants ||= []
41
+ end
42
+ ##
43
+ # Reload all files with changes detected.
44
+ #
45
+ def reload!
46
+ # Detect changed files
47
+ rotation do |file, mtime|
48
+ # Retrive the last modified time
49
+ new_file = MTIMES[file].nil?
50
+ previous_mtime = MTIMES[file] ||= mtime
51
+ logger.devel "Detected a new file #{file}" if new_file
52
+ # We skip to next file if it is not new and not modified
53
+ next unless new_file || mtime > previous_mtime
54
+ # Now we can reload our file
55
+ apps = mounted_apps_of(file)
56
+ if apps.present?
57
+ apps.each { |app| app.app_obj.reload! }
58
+ else
59
+ safe_load(file, :force => new_file)
60
+ # Reload also apps
61
+ Padrino.mounted_apps.each do |app|
62
+ app.app_obj.reload! if app.app_obj.dependencies.include?(file)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ ##
69
+ # Remove files and classes loaded with stat
70
+ #
71
+ def clear!
72
+ MTIMES.clear
73
+ LOADED_CLASSES.each do |file, klasses|
74
+ klasses.each { |klass| remove_constant(klass) }
75
+ LOADED_CLASSES.delete(file)
76
+ end
77
+ LOADED_FILES.each do |file, dependencies|
78
+ dependencies.each { |dependency| $LOADED_FEATURES.delete(dependency) }
79
+ $LOADED_FEATURES.delete(file)
80
+ end
81
+ end
82
+
83
+ ##
84
+ # Returns true if any file changes are detected and populates the MTIMES cache
85
+ #
86
+ def changed?
87
+ changed = false
88
+ rotation do |file, mtime|
89
+ new_file = MTIMES[file].nil?
90
+ previous_mtime = MTIMES[file] ||= mtime
91
+ changed = true if new_file || mtime > previous_mtime
92
+ end
93
+ changed
94
+ end
95
+ alias :run! :changed?
96
+
97
+ ##
98
+ # We lock dependencies sets to prevent reloading of protected constants
99
+ #
100
+ def lock!
101
+ klasses = ObjectSpace.classes.map { |klass| klass.to_s.split("::")[0] }.uniq
102
+ klasses = klasses | Padrino.mounted_apps.map { |app| app.app_class }
103
+ Padrino::Reloader.exclude_constants.concat(klasses)
104
+ end
105
+
106
+ ##
107
+ # A safe Kernel::require which issues the necessary hooks depending on results
108
+ #
109
+ def safe_load(file, options={})
110
+ force, file = options[:force], figure_path(file)
111
+
112
+ # Check if file was changed or if force a reload
113
+ reload = MTIMES[file] && File.mtime(file) > MTIMES[file]
114
+ return if !force && !reload && MTIMES[file]
115
+
116
+ # Removes all classes declared in the specified file
117
+ if klasses = LOADED_CLASSES.delete(file)
118
+ klasses.each { |klass| remove_constant(klass) }
119
+ end
120
+
121
+ # Remove all loaded fatures with our file
122
+ if features = LOADED_FILES[file]
123
+ features.each { |feature| $LOADED_FEATURES.delete(feature) }
124
+ end
125
+
126
+ # Duplicate objects and loaded features before load file
127
+ klasses = ObjectSpace.classes.dup
128
+ files = $LOADED_FEATURES.dup
129
+
130
+ # Now we can reload dependencies of our file
131
+ if features = LOADED_FILES.delete(file)
132
+ features.each { |feature| safe_load(feature, :force => true) }
133
+ end
134
+
135
+ # And finally load the specified file
136
+ begin
137
+ logger.devel "Loading #{file}" if !reload
138
+ logger.debug "Reloading #{file}" if reload
139
+ $LOADED_FEATURES.delete(file)
140
+ verbosity_was, $-v = $-v, nil
141
+ loaded = false
142
+ require(file)
143
+ loaded = true
144
+ MTIMES[file] = File.mtime(file)
145
+ rescue SyntaxError => e
146
+ logger.error "Cannot require #{file} because of syntax error: #{e.message}"
147
+ ensure
148
+ $-v = verbosity_was
149
+ new_constants = (ObjectSpace.classes - klasses).uniq
150
+ if loaded
151
+ # Store the file details
152
+ LOADED_CLASSES[file] = new_constants
153
+ LOADED_FILES[file] = ($LOADED_FEATURES - files - [file]).uniq
154
+ # Track only features in our Padrino.root
155
+ LOADED_FILES[file].delete_if { |feature| !in_root?(feature) }
156
+ else
157
+ logger.devel "Failed to load #{file}; removing partially defined constants"
158
+ new_constants.each { |klass| remove_constant(klass) }
159
+ end
160
+
161
+ end
162
+ end
163
+
164
+ ##
165
+ # Returns true if the file is defined in our padrino root
166
+ #
167
+ def figure_path(file)
168
+ return file if Pathname.new(file).absolute?
169
+ $:.each do |path|
170
+ found = File.join(path, file)
171
+ return File.expand_path(found) if File.exist?(found)
172
+ end
173
+ file
174
+ end
175
+
176
+ ##
177
+ # Removes the specified class and constant.
178
+ #
179
+ def remove_constant(const)
180
+ return if exclude_constants.compact.uniq.any? { |c| (const.to_s =~ %r{^#{Regexp.escape(c)}}) } &&
181
+ !include_constants.compact.uniq.any? { |c| (const.to_s =~ %r{^#{Regexp.escape(c)}}) }
182
+ begin
183
+ parts = const.to_s.split("::")
184
+ base = parts.size == 1 ? Object : parts[0..-2].join("::").constantize
185
+ object = parts[-1].to_s
186
+ base.send(:remove_const, object)
187
+ logger.devel "Removed constant: #{const}"
188
+ rescue NameError; end
189
+ end
190
+
191
+ private
192
+ ##
193
+ # Return the mounted_apps providing the app location
194
+ # Can be an array because in one app.rb we can define multiple Padrino::Appplications
195
+ #
196
+ def mounted_apps_of(file)
197
+ file = figure_path(file)
198
+ Padrino.mounted_apps.find_all { |app| File.identical?(file, app.app_file) }
199
+ end
200
+
201
+ ##
202
+ # Returns true if file is in our Padrino.root
203
+ #
204
+ def in_root?(file)
205
+ # This is better but slow:
206
+ # Pathname.new(Padrino.root).find { |f| File.identical?(Padrino.root(f), figure_path(file)) }
207
+ figure_path(file) =~ %r{^#{Regexp.escape(Padrino.root)}}
208
+ end
209
+
210
+ ##
211
+ # Searches Ruby files in your +Padrino.load_paths+ , Padrino::Application.load_paths
212
+ # and monitors them for any changes.
213
+ #
214
+ def rotation
215
+ files = Padrino.load_paths.map { |path| Dir["#{path}/**/*.rb"] }.flatten
216
+ files = files | Padrino.mounted_apps.map { |app| app.app_file }
217
+ files = files | Padrino.mounted_apps.map { |app| app.app_obj.dependencies }.flatten
218
+ files.uniq.map { |file|
219
+ file = File.expand_path(file)
220
+ next if Padrino::Reloader.exclude.any? { |base| file =~ %r{^#{Regexp.escape(base)}} } || !File.exist?(file)
221
+ yield(file, File.mtime(file))
222
+ }.compact
223
+ end
224
+ end # self
225
+
226
+ ##
227
+ # This class acts as a Rack middleware to be added to the application stack. This middleware performs a
228
+ # check and reload for source files at the start of each request, but also respects a specified cool down time
229
+ # during which no further action will be taken.
230
+ #
231
+ class Rack
232
+ def initialize(app, cooldown=1)
233
+ @app = app
234
+ @cooldown = cooldown
235
+ @last = (Time.now - cooldown)
236
+ end
237
+
238
+ def call(env)
239
+ if @cooldown && Time.now > @last + @cooldown
240
+ Thread.list.size > 1 ? Thread.exclusive { Padrino.reload! } : Padrino.reload!
241
+ @last = Time.now
242
+ end
243
+ @app.call(env)
244
+ end
245
+ end
246
+ end # Reloader
247
+ end # Padrino
@@ -0,0 +1,79 @@
1
+ module Padrino
2
+ ##
3
+ # This class is an extended version of Rack::URLMap
4
+ #
5
+ # Padrino::Router like Rack::URLMap dispatches in such a way that the
6
+ # longest paths are tried first, since they are most specific.
7
+ #
8
+ # Features:
9
+ #
10
+ # * Map a path to the specified App
11
+ # * Ignore server names (this solve issues with vhost and domain aliases)
12
+ # * Use hosts instead of server name for mappings (this help us with our vhost and doman aliases)
13
+ #
14
+ # ==== Options
15
+ #
16
+ # :to:: The class of application that you want mount
17
+ # :path:: Map the app to the given path
18
+ # :host:: Map the app to the given host
19
+ #
20
+ # ==== Examples
21
+ #
22
+ # routes = Padrino::Router.new do
23
+ # map(:path => "/", :to => PadrinoWeb, :host => "padrino.local")
24
+ # map(:path => "/", :to => Admin, :host => "admin.padrino.local")
25
+ # end
26
+ # run routes
27
+ #
28
+ # routes = Padrino::Router.new do
29
+ # map(:path => "/", :to => PadrinoWeb, :host => /*.padrino.local/)
30
+ # end
31
+ # run routes
32
+ #
33
+ class Router
34
+ def initialize(*mapping, &block)
35
+ @mapping = []
36
+ mapping.each { |m| map(m) }
37
+ instance_eval(&block) if block
38
+ end
39
+
40
+ def sort!
41
+ @mapping = @mapping.sort_by { |h, p, m, a| -p.size }
42
+ end
43
+
44
+ def map(options={})
45
+ path = options[:path] || "/"
46
+ host = options[:host]
47
+ app = options[:to]
48
+
49
+ raise ArgumentError, "paths need to start with /" if path[0] != ?/
50
+ raise ArgumentError, "app is required" if app.nil?
51
+
52
+ path = path.chomp('/')
53
+ match = Regexp.new("^#{Regexp.quote(path).gsub('/', '/+')}(.*)", nil, 'n')
54
+ host = Regexp.new("^#{Regexp.quote(host)}$", true, 'n') unless host.nil? || host.is_a?(Regexp)
55
+
56
+ @mapping << [host, path, match, app]
57
+ sort!
58
+ end
59
+
60
+ def call(env)
61
+ rPath = env["PATH_INFO"].to_s
62
+ script_name = env['SCRIPT_NAME']
63
+ hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT')
64
+ @mapping.each do |host, path, match, app|
65
+ next unless host.nil? || hHost =~ host
66
+ next unless rPath =~ match && rest = $1
67
+ next unless rest.empty? || rest[0] == ?/
68
+
69
+ rest = "/" if rest.empty?
70
+
71
+ return app.call(
72
+ env.merge(
73
+ 'SCRIPT_NAME' => (script_name + path),
74
+ 'PATH_INFO' => rest))
75
+ end
76
+ [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{rPath}"]]
77
+ end
78
+ end # Router
79
+ end # Padrino