middleman-core 3.2.2 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (273) hide show
  1. checksums.yaml +4 -4
  2. data/features/cli_init.feature +18 -8
  3. data/features/helpers_select_tag.feature +1 -1
  4. data/features/layouts_dir.feature +8 -0
  5. data/features/markdown_redcarpet.feature +2 -2
  6. data/fixtures/asciidoc-app/source/layouts/default.erb +0 -1
  7. data/fixtures/capture-html-app/source/capture_html_haml.html.haml +1 -1
  8. data/fixtures/content-for-app/source/content_for_haml.html.haml +1 -1
  9. data/fixtures/frontmatter-settings-app/source/layouts/override.erb +1 -2
  10. data/fixtures/frontmatter-settings-neighbor-app/source/layouts/override.erb +1 -2
  11. data/fixtures/layouts-dir-app/source/ambiguous.html.erb +5 -0
  12. data/fixtures/layouts-dir-app/source/layouts/other.erb +3 -0
  13. data/fixtures/layouts-dir-app/source/other.erb +3 -0
  14. data/fixtures/link-to-app/source/link_to_haml.html.haml +1 -1
  15. data/fixtures/link-to-app/source/link_to_slim.html.slim +1 -1
  16. data/fixtures/nested-layout-app/source/layouts/inner_haml.haml +1 -1
  17. data/fixtures/nested-layout-app/source/layouts/inner_slim.slim +1 -1
  18. data/fixtures/nested-layout-app/source/layouts/outer_haml.haml +1 -1
  19. data/fixtures/nested-layout-app/source/layouts/outer_slim.slim +1 -1
  20. data/lib/middleman-core/application.rb +12 -3
  21. data/lib/middleman-core/cli/build.rb +5 -3
  22. data/lib/middleman-core/cli/console.rb +1 -1
  23. data/lib/middleman-core/cli/init.rb +1 -1
  24. data/lib/middleman-core/core_extensions.rb +0 -1
  25. data/lib/middleman-core/core_extensions/file_watcher.rb +11 -11
  26. data/lib/middleman-core/core_extensions/rendering.rb +40 -66
  27. data/lib/middleman-core/extension.rb +167 -0
  28. data/lib/middleman-core/extensions.rb +2 -151
  29. data/lib/middleman-core/logger.rb +2 -2
  30. data/lib/middleman-core/meta_pages/assets/config.css +13 -0
  31. data/lib/middleman-core/meta_pages/assets/meta.css +19 -3
  32. data/lib/middleman-core/meta_pages/assets/sitemap.css +18 -1
  33. data/lib/middleman-core/meta_pages/config_setting.rb +7 -9
  34. data/lib/middleman-core/meta_pages/sitemap_resource.rb +24 -15
  35. data/lib/middleman-core/meta_pages/sitemap_tree.rb +5 -1
  36. data/lib/middleman-core/meta_pages/templates/config.html.erb +2 -2
  37. data/lib/middleman-core/meta_pages/templates/index.html.erb +18 -8
  38. data/lib/middleman-core/meta_pages/templates/sitemap.html.erb +4 -5
  39. data/lib/middleman-core/preview_server.rb +6 -3
  40. data/lib/middleman-core/renderers/erb.rb +12 -14
  41. data/lib/middleman-core/renderers/haml.rb +10 -0
  42. data/lib/middleman-core/renderers/markdown.rb +5 -1
  43. data/lib/middleman-core/renderers/sass.rb +0 -4
  44. data/lib/middleman-core/renderers/slim.rb +16 -3
  45. data/lib/middleman-core/sitemap/resource.rb +1 -1
  46. data/lib/middleman-core/step_definitions.rb +2 -1
  47. data/lib/middleman-core/templates.rb +3 -1
  48. data/lib/middleman-core/templates/shared/Gemfile.tt +4 -1
  49. data/lib/middleman-core/templates/shared/config.tt +3 -1
  50. data/lib/middleman-core/templates/shared/gitignore +2 -1
  51. data/lib/middleman-core/util.rb +22 -16
  52. data/lib/middleman-core/version.rb +1 -1
  53. data/lib/middleman-more/core_extensions/compass.rb +3 -3
  54. data/lib/middleman-more/core_extensions/default_helpers.rb +18 -15
  55. data/lib/middleman-more/extensions/asset_hash.rb +1 -0
  56. data/middleman-core.gemspec +9 -6
  57. metadata +69 -227
  58. data/features/sass_cache_path.feature +0 -22
  59. data/fixtures/sass-cache-path-custom-app/config.rb +0 -3
  60. data/fixtures/sass-cache-path-custom-app/source/stylesheets/plain.css.sass +0 -4
  61. data/fixtures/sass-cache-path-default-app/config.rb +0 -3
  62. data/fixtures/sass-cache-path-default-app/source/stylesheets/plain.css.sass +0 -4
  63. data/lib/vendored-middleman-deps/hooks-0.2.0/CHANGES.textile +0 -9
  64. data/lib/vendored-middleman-deps/hooks-0.2.0/Gemfile +0 -3
  65. data/lib/vendored-middleman-deps/hooks-0.2.0/README.rdoc +0 -107
  66. data/lib/vendored-middleman-deps/hooks-0.2.0/Rakefile +0 -12
  67. data/lib/vendored-middleman-deps/hooks-0.2.0/hooks.gemspec +0 -22
  68. data/lib/vendored-middleman-deps/hooks-0.2.0/lib/hooks.rb +0 -109
  69. data/lib/vendored-middleman-deps/hooks-0.2.0/lib/hooks/inheritable_attribute.rb +0 -33
  70. data/lib/vendored-middleman-deps/hooks-0.2.0/test/hooks_test.rb +0 -141
  71. data/lib/vendored-middleman-deps/hooks-0.2.0/test/inheritable_attribute_test.rb +0 -55
  72. data/lib/vendored-middleman-deps/hooks-0.2.0/test/test_helper.rb +0 -10
  73. data/lib/vendored-middleman-deps/padrino-core-0.11.4/.document +0 -5
  74. data/lib/vendored-middleman-deps/padrino-core-0.11.4/.gitignore +0 -22
  75. data/lib/vendored-middleman-deps/padrino-core-0.11.4/.yardopts +0 -1
  76. data/lib/vendored-middleman-deps/padrino-core-0.11.4/LICENSE.txt +0 -20
  77. data/lib/vendored-middleman-deps/padrino-core-0.11.4/README.rdoc +0 -294
  78. data/lib/vendored-middleman-deps/padrino-core-0.11.4/Rakefile +0 -5
  79. data/lib/vendored-middleman-deps/padrino-core-0.11.4/bin/padrino +0 -9
  80. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core.rb +0 -200
  81. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application.rb +0 -297
  82. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application/flash.rb +0 -229
  83. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application/rendering.rb +0 -317
  84. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application/rendering/extensions/erubis.rb +0 -64
  85. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application/rendering/extensions/haml.rb +0 -28
  86. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application/rendering/extensions/slim.rb +0 -14
  87. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application/routing.rb +0 -1077
  88. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/application/showexceptions.rb +0 -21
  89. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/caller.rb +0 -53
  90. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/cli/adapter.rb +0 -24
  91. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/cli/base.rb +0 -159
  92. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/cli/console.rb +0 -20
  93. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/cli/rake.rb +0 -47
  94. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/cli/rake_tasks.rb +0 -52
  95. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/command.rb +0 -38
  96. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/images/404.png +0 -0
  97. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/images/500.png +0 -0
  98. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/loader.rb +0 -224
  99. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/cs.yml +0 -33
  100. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/da.yml +0 -33
  101. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/de.yml +0 -33
  102. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/en.yml +0 -33
  103. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/es.yml +0 -33
  104. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/fr.yml +0 -33
  105. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/hu.yml +0 -33
  106. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/it.yml +0 -39
  107. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/ja.yml +0 -33
  108. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/lv.yml +0 -33
  109. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/nl.yml +0 -33
  110. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/no.yml +0 -33
  111. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/pl.yml +0 -33
  112. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/pt_br.yml +0 -39
  113. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/ro.yml +0 -33
  114. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/ru.yml +0 -34
  115. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/sv.yml +0 -33
  116. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/tr.yml +0 -33
  117. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/uk.yml +0 -33
  118. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/zh_cn.yml +0 -33
  119. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/locale/zh_tw.yml +0 -33
  120. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/logger.rb +0 -438
  121. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/module.rb +0 -58
  122. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/mounter.rb +0 -234
  123. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/reloader.rb +0 -341
  124. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/router.rb +0 -95
  125. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/server.rb +0 -77
  126. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/support_lite.rb +0 -260
  127. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/tasks.rb +0 -21
  128. data/lib/vendored-middleman-deps/padrino-core-0.11.4/lib/padrino-core/version.rb +0 -20
  129. data/lib/vendored-middleman-deps/padrino-core-0.11.4/padrino-core.gemspec +0 -43
  130. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/app_gem/Gemfile +0 -4
  131. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/app_gem/app/app.rb +0 -3
  132. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/app_gem/app_gem.gemspec +0 -17
  133. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/app_gem/lib/app_gem.rb +0 -7
  134. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/app_gem/lib/app_gem/version.rb +0 -3
  135. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/apps/.components +0 -6
  136. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/apps/.gitignore +0 -7
  137. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/apps/complex.rb +0 -32
  138. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/apps/simple.rb +0 -33
  139. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/dependencies/a.rb +0 -9
  140. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/dependencies/b.rb +0 -4
  141. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/dependencies/c.rb +0 -1
  142. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/dependencies/circular/e.rb +0 -13
  143. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/dependencies/circular/f.rb +0 -2
  144. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/dependencies/circular/g.rb +0 -2
  145. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/fixtures/dependencies/d.rb +0 -4
  146. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/helper.rb +0 -83
  147. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/mini_shoulda.rb +0 -45
  148. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_application.rb +0 -125
  149. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_core.rb +0 -77
  150. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_csrf_protection.rb +0 -80
  151. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_dependencies.rb +0 -44
  152. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_filters.rb +0 -348
  153. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_flash.rb +0 -168
  154. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_locale.rb +0 -21
  155. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_logger.rb +0 -210
  156. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_mounter.rb +0 -199
  157. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_reloader_complex.rb +0 -75
  158. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_reloader_simple.rb +0 -98
  159. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_rendering.rb +0 -545
  160. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_rendering_extensions.rb +0 -14
  161. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_restful_routing.rb +0 -33
  162. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_router.rb +0 -146
  163. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_routing.rb +0 -1927
  164. data/lib/vendored-middleman-deps/padrino-core-0.11.4/test/test_support_lite.rb +0 -56
  165. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/.document +0 -5
  166. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/.gitignore +0 -21
  167. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/.yardopts +0 -1
  168. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/LICENSE.txt +0 -20
  169. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/README.rdoc +0 -239
  170. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/Rakefile +0 -5
  171. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers.rb +0 -57
  172. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/asset_tag_helpers.rb +0 -401
  173. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/breadcrumb_helpers.rb +0 -183
  174. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/form_builder/abstract_form_builder.rb +0 -317
  175. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/form_builder/standard_form_builder.rb +0 -40
  176. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/form_helpers.rb +0 -919
  177. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/format_helpers.rb +0 -372
  178. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/cs.yml +0 -103
  179. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/da.yml +0 -91
  180. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/de.yml +0 -81
  181. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/en.yml +0 -103
  182. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/es.yml +0 -103
  183. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/fr.yml +0 -79
  184. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/hu.yml +0 -103
  185. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/it.yml +0 -89
  186. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/ja.yml +0 -103
  187. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/lv.yml +0 -103
  188. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/nl.yml +0 -82
  189. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/no.yml +0 -91
  190. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/pl.yml +0 -95
  191. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/pt_br.yml +0 -103
  192. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/ro.yml +0 -103
  193. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/ru.yml +0 -103
  194. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/sv.yml +0 -103
  195. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/tr.yml +0 -103
  196. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/uk.yml +0 -103
  197. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/zh_cn.yml +0 -103
  198. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/locale/zh_tw.yml +0 -103
  199. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/number_helpers.rb +0 -283
  200. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/output_helpers.rb +0 -207
  201. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/output_helpers/abstract_handler.rb +0 -96
  202. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/output_helpers/erb_handler.rb +0 -78
  203. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/output_helpers/haml_handler.rb +0 -63
  204. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/output_helpers/slim_handler.rb +0 -78
  205. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/render_helpers.rb +0 -59
  206. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/tag_helpers.rb +0 -292
  207. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/lib/padrino-helpers/translation_helpers.rb +0 -36
  208. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/padrino-helpers.gemspec +0 -27
  209. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/app.rb +0 -84
  210. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/button_to.erb +0 -8
  211. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/button_to.haml +0 -5
  212. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/button_to.slim +0 -6
  213. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/capture_concat.erb +0 -14
  214. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/capture_concat.haml +0 -12
  215. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/capture_concat.slim +0 -12
  216. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/content_for.erb +0 -14
  217. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/content_for.haml +0 -12
  218. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/content_for.slim +0 -12
  219. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/content_tag.erb +0 -11
  220. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/content_tag.haml +0 -9
  221. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/content_tag.slim +0 -9
  222. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/current_engine.erb +0 -5
  223. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/current_engine.haml +0 -5
  224. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/current_engine.slim +0 -5
  225. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/fields_for.erb +0 -20
  226. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/fields_for.haml +0 -15
  227. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/fields_for.slim +0 -15
  228. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/form_for.erb +0 -72
  229. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/form_for.haml +0 -59
  230. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/form_for.slim +0 -59
  231. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/form_tag.erb +0 -95
  232. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/form_tag.haml +0 -78
  233. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/form_tag.slim +0 -79
  234. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/link_to.erb +0 -5
  235. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/link_to.haml +0 -4
  236. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/link_to.slim +0 -4
  237. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/mail_to.erb +0 -3
  238. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/mail_to.haml +0 -3
  239. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/mail_to.slim +0 -3
  240. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/meta_tag.erb +0 -3
  241. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/meta_tag.haml +0 -3
  242. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/meta_tag.slim +0 -3
  243. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/partials/_erb.erb +0 -1
  244. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/partials/_haml.haml +0 -1
  245. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/partials/_slim.slim +0 -1
  246. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/simple_partial.erb +0 -1
  247. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/simple_partial.haml +0 -1
  248. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/markup_app/views/simple_partial.slim +0 -1
  249. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/app.rb +0 -58
  250. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/current_engine.haml +0 -5
  251. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/current_engines/_erb.erb +0 -1
  252. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/current_engines/_haml.haml +0 -1
  253. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/current_engines/_slim.slim +0 -1
  254. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/double_capture_erb.erb +0 -3
  255. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/double_capture_haml.haml +0 -2
  256. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/double_capture_slim.slim +0 -2
  257. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/erb/test.erb +0 -1
  258. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/explicit_engine.haml +0 -5
  259. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/haml/test.haml +0 -1
  260. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/template/_user.haml +0 -7
  261. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/template/haml_template.haml +0 -1
  262. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/fixtures/render_app/views/template/some_template.haml +0 -2
  263. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/helper.rb +0 -67
  264. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_asset_tag_helpers.rb +0 -359
  265. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_breadcrumb_helpers.rb +0 -134
  266. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_form_builder.rb +0 -1178
  267. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_form_helpers.rb +0 -1030
  268. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_format_helpers.rb +0 -241
  269. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_locale.rb +0 -20
  270. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_number_helpers.rb +0 -143
  271. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_output_helpers.rb +0 -154
  272. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_render_helpers.rb +0 -94
  273. data/lib/vendored-middleman-deps/padrino-helpers-0.11.4/test/test_tag_helpers.rb +0 -117
@@ -1,317 +0,0 @@
1
- require 'padrino-core/support_lite' unless defined?(SupportLite)
2
-
3
- module Padrino
4
- ##
5
- # Padrino enhances the Sinatra 'render' method to have support for
6
- # automatic template engine detection, enhanced layout functionality,
7
- # locale enabled rendering, among other features.
8
- #
9
- module Rendering
10
- ##
11
- # A SafeTemplate assumes that its output is safe.
12
- #
13
- module SafeTemplate
14
- def render(*)
15
- super.html_safe
16
- end
17
- end
18
-
19
- ##
20
- # Exception responsible for when an expected template did not exist.
21
- #
22
- class TemplateNotFound < RuntimeError
23
- end
24
-
25
- ##
26
- # This is an array of file patterns to ignore. If your editor add a
27
- # suffix during editing to your files please add it like:
28
- #
29
- # @example
30
- # Padrino::Rendering::IGNORE_FILE_PATTERN << /~$/
31
- #
32
- IGNORE_FILE_PATTERN = [
33
- /~$/ # This is for Gedit
34
- ] unless defined?(IGNORE_FILE_PATTERN)
35
-
36
- ##
37
- # Default options used in the resolve_template-method.
38
- #
39
- DEFAULT_RENDERING_OPTIONS = { :strict_format => false, :raise_exceptions => true } unless defined?(DEFAULT_RENDERING_OPTIONS)
40
-
41
- class << self
42
- ##
43
- # Default engine configurations for Padrino::Rendering.
44
- #
45
- # @return {Hash<Symbol,Hash>}
46
- # The configurations, keyed by engine.
47
- def engine_configurations
48
- @engine_configurations ||= {}
49
- end
50
-
51
- def registered(app)
52
- included(app)
53
- engine_configurations.each do |engine, configs|
54
- app.set engine, configs
55
- end
56
- end
57
-
58
- def included(base)
59
- base.send(:include, InstanceMethods)
60
- base.extend(ClassMethods)
61
- end
62
- end
63
-
64
- ##
65
- # Class methods responsible for rendering templates as part of a request.
66
- #
67
- module ClassMethods
68
- ##
69
- # Use layout like rails does or if a block given then like sinatra.
70
- # If used without a block, sets the current layout for the route.
71
- #
72
- # By default, searches in your:
73
- #
74
- # +app+/+views+/+layouts+/+application+.(+haml+|+erb+|+xxx+)
75
- # +app+/+views+/+layout_name+.(+haml+|+erb+|+xxx+)
76
- #
77
- # If you define +layout+ :+custom+ then searches for your layouts in
78
- # +app+/+views+/+layouts+/+custom+.(+haml+|+erb+|+xxx+)
79
- # +app+/+views+/+custom+.(+haml+|+erb+|+xxx+)
80
- #
81
- # @param [Symbol] name (:layout)
82
- # The layout to use.
83
- #
84
- # @yield []
85
- #
86
- def layout(name=:layout, &block)
87
- return super(name, &block) if block_given?
88
- @layout = name
89
- end
90
-
91
- ##
92
- # Returns the cached template file to render for a given url,
93
- # content_type and locale.
94
- #
95
- # @param [Array<template_path, content_type, locale>] render_options
96
- #
97
- def fetch_template_file(render_options)
98
- (@_cached_templates ||= {})[render_options]
99
- end
100
-
101
- ##
102
- # Caches the template file for the given rendering options.
103
- #
104
- # @param [String] template_file
105
- # The path of the template file.
106
- #
107
- # @param [Array<template_path, content_type, locale>] render_options
108
- #
109
- def cache_template_file!(template_file, render_options)
110
- (@_cached_templates ||= {})[render_options] = template_file || []
111
- end
112
-
113
- ##
114
- # Returns the cached layout path.
115
- #
116
- # @param [Symbol, nil] given_layout
117
- # The requested layout.
118
- #
119
- def fetch_layout_path(given_layout=nil)
120
- layout_name = given_layout || @layout || :application
121
- @_cached_layout ||= {}
122
- cached_layout_path = @_cached_layout[layout_name]
123
- return cached_layout_path if cached_layout_path
124
- has_layout_at_root = Dir["#{views}/#{layout_name}.*"].any?
125
- layout_path = has_layout_at_root ? layout_name.to_sym : File.join('layouts', layout_name.to_s).to_sym
126
- @_cached_layout[layout_name] = layout_path unless reload_templates?
127
- layout_path
128
- end
129
- end
130
-
131
- # Instance methods that allow enhanced rendering to function properly in Padrino.
132
- module InstanceMethods
133
- attr_reader :current_engine
134
-
135
- ##
136
- # Get/Set the content_type
137
- #
138
- # @param [String, nil] type
139
- # The Content-Type to use.
140
- #
141
- # @param [Symbol, nil] type.
142
- # Look and parse the given symbol to the matched Content-Type.
143
- #
144
- # @param [Hash] params
145
- # Additional params to append to the Content-Type.
146
- #
147
- # @example
148
- # case content_type
149
- # when :js then do_some
150
- # when :css then do_another
151
- # end
152
- #
153
- # content_type :js
154
- # # => set the response with 'application/javascript' Content-Type
155
- # content_type 'text/html'
156
- #
157
- # # => set directly the Content-Type to 'text/html'
158
- #
159
- def content_type(type=nil, params={})
160
- unless type.nil?
161
- super(type, params)
162
- @_content_type = type
163
- end
164
- @_content_type
165
- end
166
-
167
- private
168
- ##
169
- # Enhancing Sinatra render functionality for:
170
- #
171
- # * Using layout similar to rails
172
- # * Use render 'path/to/my/template' (without symbols)
173
- # * Use render 'path/to/my/template' (with engine lookup)
174
- # * Use render 'path/to/template.haml' (with explicit engine lookup)
175
- # * Use render 'path/to/template', :layout => false
176
- # * Use render 'path/to/template', :layout => false, :engine => 'haml'
177
- #
178
- def render(engine, data=nil, options={}, locals={}, &block)
179
-
180
- # If engine is nil, ignore engine parameter and shift up all arguments
181
- # render nil, "index", { :layout => true }, { :localvar => "foo" }
182
- engine, data, options = data, options, locals if engine.nil? && data
183
-
184
- # Data is a hash of options when no engine isn't explicit
185
- # render "index", { :layout => true }, { :localvar => "foo" }
186
- # Data is options, and options is locals in this case
187
- data, options, locals = nil, data, options if data.is_a?(Hash)
188
-
189
- # If data is unassigned then this is a likely a template to be resolved
190
- # This means that no engine was explicitly defined
191
- data, engine = *resolve_template(engine, options.dup) if data.nil?
192
-
193
- # Use @layout if it exists
194
- layout_was = options[:layout]
195
- options[:layout] = @layout if options[:layout].nil? || options[:layout] == true
196
- # Resolve layouts similar to in Rails
197
- if options[:layout].nil? && !settings.templates.has_key?(:layout)
198
- layout_path, layout_engine = *resolved_layout
199
-
200
- # We need to force layout false so sinatra don't try to render it
201
- options[:layout] = layout_path || false
202
- options[:layout] = false unless layout_engine == engine # TODO allow different layout engine
203
- options[:layout_engine] = layout_engine || engine if options[:layout]
204
- elsif options[:layout].present?
205
- options[:layout] = settings.fetch_layout_path(options[:layout] || @layout)
206
- end
207
- # Default to original layout value if none found.
208
- options[:layout] ||= layout_was
209
-
210
- # Cleanup the template.
211
- @current_engine, engine_was = engine, @current_engine
212
- @_out_buf, _buf_was = ActiveSupport::SafeBuffer.new, @_out_buf
213
-
214
- # Pass arguments to Sinatra render method.
215
- super(engine, data, options.dup, locals, &block)
216
- ensure
217
- @current_engine = engine_was
218
- @_out_buf = _buf_was
219
- end
220
-
221
- ##
222
- # Returns the located layout tuple to be used for the rendered template
223
- # (if available).
224
- #
225
- # @example
226
- # resolve_layout
227
- # # => ["/layouts/custom", :erb]
228
- # # => [nil, nil]
229
- #
230
- def resolved_layout
231
- located_layout = resolve_template(settings.fetch_layout_path, :raise_exceptions => false, :strict_format => true)
232
- located_layout ? located_layout : [nil, nil]
233
- end
234
-
235
- ##
236
- # Returns the template path and engine that match content_type (if present),
237
- # I18n.locale.
238
- #
239
- # @param [String] template_path
240
- # The path of the template.
241
- #
242
- # @param [Hash] options
243
- # Additional options.
244
- #
245
- # @option options [Boolean] :strict_format (false)
246
- # The resolved template must match the content_type of the request.
247
- #
248
- # @option options [Boolean] :raise_exceptions (false)
249
- # Raises a {TemplateNotFound} exception if the template cannot be located.
250
- #
251
- # @return [Array<Symbol, Symbol>]
252
- # The path and format of the template.
253
- #
254
- # @raise [TemplateNotFound]
255
- # The template could not be found.
256
- #
257
- # @example
258
- # get "/foo", :provides => [:html, :js] do; render 'path/to/foo'; end
259
- # # If you request "/foo.js" with I18n.locale == :ru => [:"/path/to/foo.ru.js", :erb]
260
- # # If you request "/foo" with I18n.locale == :de => [:"/path/to/foo.de.haml", :haml]
261
- #
262
- def resolve_template(template_path, options={})
263
- began_at = Time.now
264
- _content_type = content_type || :html
265
- # Fetch cached template for rendering options
266
- template_path = template_path.to_s[0] == ?/ ? template_path.to_s : "/#{template_path}"
267
- rendering_options = [template_path, _content_type, locale]
268
- cached_template = settings.fetch_template_file(rendering_options)
269
- if cached_template
270
- logger.debug :cached, began_at, cached_template[0] if settings.logging? && defined?(logger)
271
- return cached_template
272
- end
273
-
274
- # Resolve view path and options.
275
- options.reverse_merge!(DEFAULT_RENDERING_OPTIONS)
276
- view_path = options.delete(:views) || settings.views || "./views"
277
- target_extension = File.extname(template_path)[1..-1] || "none" # explicit template extension
278
- template_path = template_path.chomp(".#{target_extension}")
279
-
280
- # Generate potential template candidates
281
- templates = Dir[File.join(view_path, template_path) + ".*"].map do |file|
282
- template_engine = File.extname(file)[1..-1].to_sym # Retrieves engine extension
283
- template_file = file.sub(view_path, '').chomp(".#{template_engine}").to_sym # retrieves template filename
284
- [template_file, template_engine] unless IGNORE_FILE_PATTERN.any? { |pattern| template_engine.to_s =~ pattern }
285
- end
286
-
287
- # Check if we have a simple content type
288
- simple_content_type = [:html, :plain].include?(_content_type)
289
-
290
- # Resolve final template to render
291
- located_template =
292
- templates.find { |file, e| file.to_s == "#{template_path}.#{locale}.#{_content_type}" } ||
293
- templates.find { |file, e| file.to_s == "#{template_path}.#{locale}" && simple_content_type } ||
294
- templates.find { |file, e| File.extname(file.to_s) == ".#{target_extension}" or e.to_s == target_extension.to_s } ||
295
- templates.find { |file, e| file.to_s == "#{template_path}.#{_content_type}" } ||
296
- templates.find { |file, e| file.to_s == "#{template_path}" && simple_content_type } ||
297
- (!options[:strict_format] && templates.first) # If not strict, fall back to the first located template.
298
-
299
- raise TemplateNotFound, "Template '#{template_path}' not found in '#{view_path}'!" if !located_template && options[:raise_exceptions]
300
- settings.cache_template_file!(located_template, rendering_options) unless settings.reload_templates?
301
- logger.debug :template, began_at, located_template[0] if located_template && settings.logging? && defined?(logger)
302
- located_template
303
- end
304
-
305
- ##
306
- # Return the I18n.locale if I18n is defined.
307
- #
308
- def locale
309
- I18n.locale if defined?(I18n)
310
- end
311
- end
312
- end
313
- end
314
-
315
- require 'padrino-core/application/rendering/extensions/haml'
316
- require 'padrino-core/application/rendering/extensions/erubis'
317
- require 'padrino-core/application/rendering/extensions/slim'
@@ -1,64 +0,0 @@
1
- begin
2
- require 'erubis'
3
-
4
- module Padrino
5
- module Erubis
6
- ##
7
- # SafeBufferEnhancer is an Erubis Enhancer that compiles templates that
8
- # are fit for using ActiveSupport::SafeBuffer as a Buffer.
9
- #
10
- # @api private
11
- module SafeBufferEnhancer
12
- def add_expr_literal(src, code)
13
- src << " #{@bufvar}.concat((" << code << ').to_s);'
14
- end
15
-
16
- def add_expr_escaped(src, code)
17
- src << " #{@bufvar}.safe_concat " << code << ';'
18
- end
19
-
20
- def add_text(src, text)
21
- src << " #{@bufvar}.safe_concat '" << escape_text(text) << "';" unless text.empty?
22
- end
23
- end
24
-
25
- ##
26
- # SafeBufferTemplate is the classic Erubis template, augmented with
27
- # SafeBufferEnhancer.
28
- #
29
- # @api private
30
- class SafeBufferTemplate < ::Erubis::Eruby
31
- include SafeBufferEnhancer
32
- end
33
-
34
- ##
35
- # Modded ErubisTemplate that doesn't insist in an String as output
36
- # buffer.
37
- #
38
- # @api private
39
- class Template < Tilt::ErubisTemplate
40
- def render(*args)
41
- app = args.first
42
- app_class = app.class
43
- @padrino_app = app.kind_of?(Padrino::Application) ||
44
- (app_class.respond_to?(:erb) && app_class.erb[:engine_class] == Padrino::Erubis::SafeBufferTemplate)
45
- super
46
- end
47
-
48
- def precompiled_preamble(locals)
49
- buf = @padrino_app ? "ActiveSupport::SafeBuffer.new" : "''"
50
- old_postamble = super.split("\n")[0..-2]
51
- [old_postamble, "#{@outvar} = _buf = (#{@outvar} || #{buf})"].join("\n")
52
- end
53
- end
54
- end
55
- end
56
-
57
- Tilt.prefer(Padrino::Erubis::Template, :erb)
58
-
59
- if defined? Padrino::Rendering
60
- Padrino::Rendering.engine_configurations[:erb] =
61
- {:engine_class => Padrino::Erubis::SafeBufferTemplate}
62
- end
63
- rescue LoadError
64
- end
@@ -1,28 +0,0 @@
1
- begin
2
- require 'haml'
3
- require 'haml/helpers/xss_mods'
4
- require 'haml/helpers/action_view_extensions'
5
-
6
- module Haml
7
- module Helpers
8
- include XssMods
9
- include ActionViewExtensions
10
- end
11
-
12
- module Util
13
- def self.rails_xss_safe?
14
- true
15
- end
16
- end
17
- end
18
-
19
- if defined? Padrino::Rendering
20
- Padrino::Rendering.engine_configurations[:haml] =
21
- {:escape_html => true}
22
-
23
- class Tilt::HamlTemplate
24
- include Padrino::Rendering::SafeTemplate
25
- end
26
- end
27
- rescue LoadError
28
- end
@@ -1,14 +0,0 @@
1
- begin
2
- require 'slim'
3
-
4
- if defined? Padrino::Rendering
5
- Padrino::Rendering.engine_configurations[:slim] =
6
- {:generator => Temple::Generators::RailsOutputBuffer,
7
- :buffer => "@_out_buf", :use_html_safe => true}
8
-
9
- class Slim::Template
10
- include Padrino::Rendering::SafeTemplate
11
- end
12
- end
13
- rescue LoadError
14
- end
@@ -1,1077 +0,0 @@
1
- require 'http_router' unless defined?(HttpRouter)
2
- require 'padrino-core/support_lite' unless defined?(SupportLite)
3
-
4
- ##
5
- # Adds to Sinatra +controller+ informations
6
- #
7
- class Sinatra::Request
8
- attr_accessor :route_obj
9
-
10
- def controller
11
- route_obj && route_obj.controller
12
- end
13
- def action
14
- route_obj && route_obj.action
15
- end
16
- end
17
-
18
-
19
- class HttpRouter
20
- def rewrite_partial_path_info(env, request); end
21
- def rewrite_path_info(env, request); end
22
-
23
- def process_destination_path(path, env)
24
- Thread.current['padrino.instance'].instance_eval do
25
- request.route_obj = path.route
26
- @_response_buffer = nil
27
- @route = path.route
28
- @params ||= {}
29
- @params.update(env['router.params'])
30
- @block_params = if match_data = env['router.request'].extra_env['router.regex_match']
31
- params_list = match_data.to_a
32
- params_list.shift
33
- @params[:captures] = params_list
34
- params_list
35
- else
36
- env['router.request'].params
37
- end
38
- # Provide access to the current controller to the request
39
- # Now we can eval route, but because we have "throw halt" we need to be
40
- # (en)sure to reset old layout and run controller after filters.
41
- original_params = @params
42
- parent_layout = @layout
43
- successful = false
44
- begin
45
- filter! :before
46
- (@route.before_filters - settings.filters[:before]).each { |block| instance_eval(&block) }
47
- @layout = path.route.use_layout if path.route.use_layout
48
- @route.custom_conditions.each { |block| pass if block.bind(self).call == false }
49
- halt_response = catch(:halt) { route_eval { @route.dest[self, @block_params] } }
50
- @_response_buffer = halt_response.is_a?(Array) ? halt_response.last : halt_response
51
- successful = true
52
- halt halt_response
53
- ensure
54
- (@route.after_filters - settings.filters[:after]).each { |block| instance_eval(&block) } if successful
55
- @layout = parent_layout
56
- @params = original_params
57
- end
58
- end
59
- end
60
-
61
- class Route
62
- VALID_HTTP_VERBS.replace %w[GET POST PUT PATCH DELETE HEAD OPTIONS LINK UNLINK]
63
-
64
- attr_accessor :use_layout, :controller, :action, :cache, :cache_key, :cache_expires_in, :parent
65
-
66
- def before_filters(&block)
67
- @_before_filters ||= []
68
- @_before_filters << block if block_given?
69
-
70
- @_before_filters
71
- end
72
-
73
- def after_filters(&block)
74
- @_after_filters ||= []
75
- @_after_filters << block if block_given?
76
-
77
- @_after_filters
78
- end
79
-
80
- def custom_conditions(&block)
81
- @_custom_conditions ||= []
82
- @_custom_conditions << block if block_given?
83
-
84
- @_custom_conditions
85
- end
86
-
87
- def significant_variable_names
88
- @significant_variable_names ||= if @original_path.is_a?(String)
89
- @original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
90
- elsif @original_path.is_a?(Regexp) and @original_path.respond_to?(:named_captures)
91
- @original_path.named_captures.keys.map(&:to_sym)
92
- else
93
- []
94
- end
95
- end
96
-
97
- def to(dest = nil, &dest_block)
98
- @dest = dest || dest_block || raise("you didn't specify a destination")
99
-
100
- @router.current_order ||= 0
101
- @order = @router.current_order
102
- @router.current_order += 1
103
-
104
- if @dest.respond_to?(:url_mount=)
105
- urlmount = UrlMount.new(@path_for_generation, @default_values || {}) # TODO url mount should accept nil here.
106
- urlmount.url_mount = @router.url_mount if @router.url_mount
107
- @dest.url_mount = urlmount
108
- end
109
- self
110
- end
111
-
112
- attr_accessor :order
113
-
114
- end
115
-
116
- attr_accessor :current_order
117
-
118
- def sort!
119
- @routes.sort!{ |a, b| a.order <=> b.order }
120
- end
121
-
122
- class Node::SpanningRegex
123
- def to_code
124
- params_count = @ordered_indicies.size
125
- whole_path_var = "whole_path#{root.next_counter}"
126
- "#{whole_path_var} = request.joined_path
127
- if match = #{@matcher.inspect}.match(#{whole_path_var}) and match.begin(0).zero?
128
- _#{whole_path_var} = request.path.dup
129
- " << param_capturing_code << "
130
- remaining_path = #{whole_path_var}[match[0].size + (#{whole_path_var}[match[0].size] == ?/ ? 1 : 0), #{whole_path_var}.size]
131
- request.path = remaining_path.split('/')
132
- #{node_to_code}
133
- request.path = _#{whole_path_var}
134
- request.params.slice!(#{-params_count}, #{params_count})
135
- end
136
- "
137
- end
138
- end
139
-
140
- # Monkey patching the Request class. Using Rack::Utils.unescape rather than
141
- # URI.unescape which can't handle utf-8 chars
142
- class Request
143
- def initialize(path, rack_request)
144
- @rack_request = rack_request
145
- @path = path.split(/\//).map{|part| Rack::Utils.unescape(part) }
146
- @path.shift if @path.first == ''
147
- @path.push('') if path[-1] == ?/
148
- @extra_env = {}
149
- @params = []
150
- @acceptable_methods = Set.new
151
- end
152
- end
153
-
154
- class Node::Path
155
- def to_code
156
- path_ivar = inject_root_ivar(self)
157
- "#{"if !callback && request.path.size == 1 && request.path.first == '' && (request.rack_request.head? || request.rack_request.get?) && request.rack_request.path_info[-1] == ?/
158
- catch(:pass) do
159
- response = ::Rack::Response.new
160
- response.redirect(request.rack_request.path_info[0, request.rack_request.path_info.size - 1], 302)
161
- return response.finish
162
- end
163
- end" if router.redirect_trailing_slash?}
164
-
165
- #{"if request.#{router.ignore_trailing_slash? ? 'path_finished?' : 'path.empty?'}" unless route.match_partially}
166
- catch(:pass) do
167
- if callback
168
- request.called = true
169
- callback.call(Response.new(request, #{path_ivar}))
170
- else
171
- env = request.rack_request.dup.env
172
- env['router.request'] = request
173
- env['router.params'] ||= {}
174
- #{"env['router.params'].merge!(Hash[#{param_names.inspect}.zip(request.params)])" if dynamic?}
175
- @router.rewrite#{"_partial" if route.match_partially}_path_info(env, request)
176
- response = @router.process_destination_path(#{path_ivar}, env)
177
- return response unless router.pass_on_response(response)
178
- end
179
- end
180
- #{"end" unless route.match_partially}"
181
- end
182
- end
183
- end
184
-
185
- module Padrino
186
- class Filter
187
- attr_reader :block
188
-
189
- def initialize(mode, scoped_controller, options, args, &block)
190
- @mode, @scoped_controller, @options, @args, @block = mode, scoped_controller, options, args, block
191
- end
192
-
193
- def apply?(request)
194
- detect = @args.any? do |arg|
195
- case arg
196
- when Symbol then request.route_obj && (request.route_obj.name == arg or request.route_obj.name == [@scoped_controller, arg].flatten.join("_").to_sym)
197
- else arg === request.path_info
198
- end
199
- end || @options.any? do |name, val|
200
- case name
201
- when :agent then val === request.user_agent
202
- else val === request.send(name)
203
- end
204
- end
205
- detect ^ !@mode
206
- end
207
-
208
- def to_proc
209
- if @args.empty? && @options.empty?
210
- block
211
- else
212
- filter = self
213
- proc { instance_eval(&filter.block) if filter.apply?(request) }
214
- end
215
- end
216
- end
217
-
218
- ##
219
- # Padrino provides advanced routing definition support to make routes and
220
- # url generation much easier. This routing system supports named route
221
- # aliases and easy access to url paths. The benefits of this is that instead
222
- # of having to hard-code route urls into every area of your application, now
223
- # we can just define the urls in a single spot and then attach an alias
224
- # which can be used to refer to the url throughout the application.
225
- #
226
- module Routing
227
- # Defines common content-type alias mappings.
228
- CONTENT_TYPE_ALIASES = { :htm => :html } unless defined?(CONTENT_TYPE_ALIASES)
229
- # Defines the available route priorities supporting route deferrals.
230
- ROUTE_PRIORITY = {:high => 0, :normal => 1, :low => 2} unless defined?(ROUTE_PRIORITY)
231
-
232
- # Raised when a route was invalid or cannot be processed.
233
- class UnrecognizedException < RuntimeError; end
234
-
235
- class Parent < String
236
- attr_reader :map
237
- attr_reader :optional
238
- attr_reader :options
239
-
240
- alias_method :optional?, :optional
241
-
242
- def initialize(value, options={})
243
- super(value.to_s)
244
- @map = options.delete(:map)
245
- @optional = options.delete(:optional)
246
- @options = options
247
- end
248
- end
249
-
250
- class << self
251
- ##
252
- # Main class that register this extension.
253
- #
254
- def registered(app)
255
- app.send(:include, InstanceMethods)
256
- app.extend(ClassMethods)
257
- end
258
- alias :included :registered
259
- end
260
-
261
- # Class methods responsible for enhanced routing for controllers.
262
- module ClassMethods
263
- ##
264
- # Method to organize our routes in a better way.
265
- #
266
- # @param [Array] args
267
- # Controller arguments.
268
- #
269
- # @yield []
270
- # The given block will be used to define the routes within the
271
- # Controller.
272
- #
273
- # @example
274
- # controller :admin do
275
- # get :index do; ...; end
276
- # get :show, :with => :id do; ...; end
277
- # end
278
- #
279
- # url(:admin_index) # => "/admin"
280
- # url(:admin_show, :id => 1) # "/admin/show/1"
281
- #
282
- # @example Using named routes follow the sinatra way:
283
- # controller "/admin" do
284
- # get "/index" do; ...; end
285
- # get "/show/:id" do; ...; end
286
- # end
287
- #
288
- # @example Supply +:provides+ to all controller routes:
289
- # controller :provides => [:html, :xml, :json] do
290
- # get :index do; "respond to html, xml and json"; end
291
- # post :index do; "respond to html, xml and json"; end
292
- # get :foo do; "respond to html, xml and json"; end
293
- # end
294
- #
295
- # @example Specify parent resources in padrino with the +:parent+ option on the controller:
296
- # controllers :product, :parent => :user do
297
- # get :index do
298
- # # url is generated as "/user/#{params[:user_id]}/product"
299
- # # url_for(:product, :index, :user_id => 5) => "/user/5/product"
300
- # end
301
- # get :show, :with => :id do
302
- # # url is generated as "/user/#{params[:user_id]}/product/show/#{params[:id]}"
303
- # # url_for(:product, :show, :user_id => 5, :id => 10) => "/user/5/product/show/10"
304
- # end
305
- # end
306
- #
307
- # @example Specify conditions to run for all routes:
308
- # controller :conditions => {:protect => true} do
309
- # def self.protect(protected)
310
- # condition do
311
- # halt 403, "No secrets for you!" unless params[:key] == "s3cr3t"
312
- # end if protected
313
- # end
314
- #
315
- # # This route will only return "secret stuff" if the user goes to
316
- # # `/private?key=s3cr3t`.
317
- # get("/private") { "secret stuff" }
318
- #
319
- # # And this one, too!
320
- # get("/also-private") { "secret stuff" }
321
- #
322
- # # But you can override the conditions for each route as needed.
323
- # # This route will be publicly accessible without providing the
324
- # # secret key.
325
- # get :index, :protect => false do
326
- # "Welcome!"
327
- # end
328
- # end
329
- #
330
- # @example Supply default values:
331
- # controller :lang => :de do
332
- # get :index, :map => "/:lang" do; "params[:lang] == :de"; end
333
- # end
334
- #
335
- # In a controller, before and after filters are scoped and don't
336
- # affect other controllers or the main app.
337
- # In a controller, layouts are scoped and don't affect other
338
- # controllers or the main app.
339
- #
340
- # @example
341
- # controller :posts do
342
- # layout :post
343
- # before { foo }
344
- # after { bar }
345
- # end
346
- #
347
- def controller(*args, &block)
348
- if block_given?
349
- options = args.extract_options!
350
-
351
- # Controller defaults.
352
- @_controller, original_controller = args, @_controller
353
- @_parents, original_parent = options.delete(:parent), @_parents
354
- @_provides, original_provides = options.delete(:provides), @_provides
355
- @_use_format, original_use_format = options.delete(:use_format), @_use_format
356
- @_cache, original_cache = options.delete(:cache), @_cache
357
- @_map, original_map = options.delete(:map), @_map
358
- @_conditions, original_conditions = options.delete(:conditions), @_conditions
359
- @_defaults, original_defaults = options, @_defaults
360
-
361
- # Application defaults.
362
- @filters, original_filters = { :before => @filters[:before].dup, :after => @filters[:after].dup }, @filters
363
- @layout, original_layout = nil, @layout
364
-
365
- instance_eval(&block)
366
-
367
- # Application defaults.
368
- @filters = original_filters
369
- @layout = original_layout
370
-
371
- # Controller defaults.
372
- @_controller, @_parents, @_cache = original_controller, original_parent, original_cache
373
- @_defaults, @_provides, @_map = original_defaults, original_provides, original_map
374
- @_conditions, @_use_format = original_conditions, original_use_format
375
- else
376
- include(*args) if extensions.any?
377
- end
378
- end
379
- alias :controllers :controller
380
-
381
- ##
382
- # Add a before filter hook.
383
- #
384
- # @see #construct_filter
385
- #
386
- def before(*args, &block)
387
- add_filter :before, &(args.empty? ? block : construct_filter(*args, &block))
388
- end
389
-
390
- ##
391
- # Add an after filter hook.
392
- #
393
- # @see #construct_filter
394
- #
395
- def after(*args, &block)
396
- add_filter :after, &(args.empty? ? block : construct_filter(*args, &block))
397
- end
398
-
399
- ##
400
- # Adds a filter hook to a request.
401
- #
402
- def add_filter(type, &block)
403
- filters[type] << block
404
- end
405
-
406
- ##
407
- # Creates a filter to process before/after the matching route.
408
- #
409
- # @param [Array] args
410
- #
411
- # @example We are be able to filter with String path
412
- # before('/') { 'only to :index' }
413
- # get(:index} { 'foo' } # => filter match only before this.
414
- # get(:main) { 'bar' }
415
- #
416
- # @example is the same of
417
- # before(:index) { 'only to :index' }
418
- # get(:index} { 'foo' } # => filter match only before this.
419
- # get(:main) { 'bar' }
420
- #
421
- # @example it works only for the given controller
422
- # controller :foo do
423
- # before(:index) { 'only to for :foo_index' }
424
- # get(:index} { 'foo' } # => filter match only before this.
425
- # get(:main) { 'bar' }
426
- # end
427
- #
428
- # controller :bar do
429
- # before(:index) { 'only to for :bar_index' }
430
- # get(:index} { 'foo' } # => filter match only before this.
431
- # get(:main) { 'bar' }
432
- # end
433
- #
434
- # @example if filters based on a symbol or regexp
435
- # before :index, /main/ do; ... end
436
- # # => match only path that are +/+ or contains +main+
437
- #
438
- # @example filtering everything except an occurrence
439
- # before :except => :index do; ...; end
440
- #
441
- # @example you can also filter using a request param
442
- # before :agent => /IE/ do; ...; end
443
- # # => match +HTTP_USER_AGENT+ containing +IE+
444
- #
445
- # @see http://www.padrinorb.com/guides/controllers#route-filters
446
- #
447
- def construct_filter(*args, &block)
448
- options = args.last.is_a?(Hash) ? args.pop : {}
449
- except = options.key?(:except) && Array(options.delete(:except))
450
- raise("You cannot use except with other options specified") if except && (!args.empty? || !options.empty?)
451
- options = except.last.is_a?(Hash) ? except.pop : {} if except
452
- Filter.new(!except, @_controller, options, Array(except || args), &block)
453
- end
454
-
455
- ##
456
- # Provides many parents with shallowing.
457
- #
458
- # @param [Symbol] name
459
- # The parent name.
460
- #
461
- # @param [Hash] options
462
- # Additional options.
463
- #
464
- # @example
465
- # controllers :product do
466
- # parent :shop, :optional => true, :map => "/my/stand"
467
- # parent :category, :optional => true
468
- # get :show, :with => :id do
469
- # # generated urls:
470
- # # "/product/show/#{params[:id]}"
471
- # # "/my/stand/#{params[:shop_id]}/product/show/#{params[:id]}"
472
- # # "/my/stand/#{params[:shop_id]}/category/#{params[:category_id]}/product/show/#{params[:id]}"
473
- # # url_for(:product, :show, :id => 10) => "/product/show/10"
474
- # # url_for(:product, :show, :shop_id => 5, :id => 10) => "/my/stand/5/product/show/10"
475
- # # url_for(:product, :show, :shop_id => 5, :category_id => 1, :id => 10) => "/my/stand/5/category/1/product/show/10"
476
- # end
477
- # end
478
- #
479
- def parent(name, options={})
480
- defaults = { :optional => false, :map => name.to_s }
481
- options = defaults.merge(options)
482
- @_parents = Array(@_parents) unless @_parents.is_a?(Array)
483
- @_parents << Parent.new(name, options)
484
- end
485
-
486
- ##
487
- # Using HttpRouter, for features and configurations.
488
- #
489
- # @example
490
- # router.add('/greedy/:greed')
491
- # router.recognize('/simple')
492
- #
493
- # @see http://github.com/joshbuddy/http_router
494
- #
495
- def router
496
- @router ||= HttpRouter.new
497
- block_given? ? yield(@router) : @router
498
- end
499
- alias :urls :router
500
-
501
- def compiled_router
502
- if @deferred_routes
503
- deferred_routes.each { |routes| routes.each { |(route, dest)| route.to(dest) } }
504
- @deferred_routes = nil
505
- router.sort!
506
- end
507
- router
508
- end
509
-
510
- def deferred_routes
511
- @deferred_routes ||= ROUTE_PRIORITY.map{[]}
512
- end
513
-
514
- def reset_router!
515
- @deferred_routes = nil
516
- router.reset!
517
- end
518
-
519
- ##
520
- # Recognize a given path.
521
- #
522
- # @param [String] path
523
- # Path+Query to parse
524
- #
525
- # @return [Symbol, Hash]
526
- # Returns controller and query params.
527
- #
528
- # @example Giving a controller like:
529
- # controller :foo do
530
- # get :bar, :map => 'foo-bar-:id'; ...; end
531
- # end
532
- #
533
- # @example You should be able to reverse:
534
- # MyApp.url(:foo_bar, :id => :mine)
535
- # # => /foo-bar-mine
536
- #
537
- # @example Into this:
538
- # MyApp.recognize_path('foo-bar-mine')
539
- # # => [:foo_bar, :id => :mine]
540
- #
541
- def recognize_path(path)
542
- responses = @router.recognize(Rack::MockRequest.env_for(path))
543
- responses = responses[0] if responses[0].is_a?(Array)
544
- [responses[0].path.route.name, responses[0].params]
545
- end
546
-
547
- ##
548
- # Instance method for url generation.
549
- #
550
- # @example
551
- # url(:show, :id => 1)
552
- # url(:show, :name => 'test', :id => 24)
553
- # url(:show, 1)
554
- # url(:controller_name, :show, :id => 21)
555
- # url(:controller_show, :id => 29)
556
- #
557
- def url(*args)
558
- params = args.extract_options! # parameters is hash at end
559
- names, params_array = args.partition{|a| a.is_a?(Symbol)}
560
- name = names.join("_").to_sym # route name is concatenated with underscores
561
- if params.is_a?(Hash)
562
- params[:format] = params[:format].to_s unless params[:format].nil?
563
- params = value_to_param(params)
564
- end
565
- url =
566
- if params_array.empty?
567
- compiled_router.path(name, params)
568
- else
569
- compiled_router.path(name, *(params_array << params))
570
- end
571
- url[0,0] = conform_uri(uri_root) if defined?(uri_root)
572
- url[0,0] = conform_uri(ENV['RACK_BASE_URI']) if ENV['RACK_BASE_URI']
573
- url = "/" if url.blank?
574
- url
575
- rescue HttpRouter::InvalidRouteException
576
- route_error = "route mapping for url(#{name.inspect}) could not be found!"
577
- raise Padrino::Routing::UnrecognizedException.new(route_error)
578
- end
579
- alias :url_for :url
580
-
581
- def get(path, *args, &block)
582
- conditions = @conditions.dup
583
- route('GET', path, *args, &block)
584
-
585
- @conditions = conditions
586
- route('HEAD', path, *args, &block)
587
- end
588
-
589
- private
590
- # Parse params from the url method
591
- def value_to_param(value)
592
- case value
593
- when Array
594
- value.map { |v| value_to_param(v) }.compact
595
- when Hash
596
- value.inject({}) do |memo, (k,v)|
597
- v = value_to_param(v)
598
- memo[k] = v unless v.nil?
599
- memo
600
- end
601
- when nil then nil
602
- else value.respond_to?(:to_param) ? value.to_param : value
603
- end
604
- end
605
-
606
- # Add prefix slash if its not present and remove trailing slashes.
607
- def conform_uri(uri_string)
608
- uri_string.gsub(/^(?!\/)(.*)/, '/\1').gsub(/[\/]+$/, '')
609
- end
610
-
611
- ##
612
- # Rewrite default routes.
613
- #
614
- # @example
615
- # get :index # => "/"
616
- # get :index, "/" # => "/"
617
- # get :index, :map => "/" # => "/"
618
- # get :show, "/show-me" # => "/show-me"
619
- # get :show, :map => "/show-me" # => "/show-me"
620
- # get "/foo/bar" # => "/show"
621
- # get :index, :parent => :user # => "/user/:user_id/index"
622
- # get :show, :with => :id, :parent => :user # => "/user/:user_id/show/:id"
623
- # get :show, :with => :id # => "/show/:id"
624
- # get [:show, :id] # => "/show/:id"
625
- # get :show, :with => [:id, :name] # => "/show/:id/:name"
626
- # get [:show, :id, :name] # => "/show/:id/:name"
627
- # get :list, :provides => :js # => "/list.{:format,js)"
628
- # get :list, :provides => :any # => "/list(.:format)"
629
- # get :list, :provides => [:js, :json] # => "/list.{!format,js|json}"
630
- # get :list, :provides => [:html, :js, :json] # => "/list(.{!format,js|json})"
631
- # get :list, :priority => :low # Defers route to be last
632
- # get /pattern/, :name => :foo, :generate_with => '/foo' # Generates :foo as /foo
633
- def route(verb, path, *args, &block)
634
- options = case args.size
635
- when 2
636
- args.last.merge(:map => args.first)
637
- when 1
638
- map = args.shift if args.first.is_a?(String)
639
- if args.first.is_a?(Hash)
640
- map ? args.first.merge(:map => map) : args.first
641
- else
642
- {:map => map || args.first}
643
- end
644
- when 0
645
- {}
646
- else raise
647
- end
648
-
649
- # Do padrino parsing. We dup options so we can build HEAD request correctly.
650
- route_options = options.dup
651
- route_options[:provides] = @_provides if @_provides
652
-
653
- # CSRF protection is always active except when explicitly switched off.
654
- if allow_disabled_csrf
655
- unless route_options[:csrf_protection] == false
656
- route_options[:csrf_protection] = true
657
- end
658
- end
659
-
660
- path, *route_options[:with] = path if path.is_a?(Array)
661
- action = path
662
- path, name, route_parents, options, route_options = *parse_route(path, route_options, verb)
663
- options.reverse_merge!(@_conditions) if @_conditions
664
-
665
- # Sinatra defaults
666
- method_name = "#{verb} #{path}"
667
- unbound_method = generate_method(method_name, &block)
668
-
669
- block = block.arity != 0 ?
670
- proc { |a,p| unbound_method.bind(a).call(*p) } :
671
- proc { |a,p| unbound_method.bind(a).call }
672
-
673
- invoke_hook(:route_added, verb, path, block)
674
-
675
- # HTTPRouter route construction
676
- route = router.add(path, route_options)
677
- route.name = name if name
678
- route.action = action
679
- priority_name = options.delete(:priority) || :normal
680
- priority = ROUTE_PRIORITY[priority_name] or raise("Priority #{priority_name} not recognized, try #{ROUTE_PRIORITY.keys.join(', ')}")
681
- route.cache = options.key?(:cache) ? options.delete(:cache) : @_cache
682
- route.parent = route_parents ? (route_parents.count == 1 ? route_parents.first : route_parents) : route_parents
683
- route.add_request_method(verb.downcase.to_sym)
684
- route.host = options.delete(:host) if options.key?(:host)
685
- route.user_agent = options.delete(:agent) if options.key?(:agent)
686
- if options.key?(:default_values)
687
- defaults = options.delete(:default_values)
688
- route.add_default_values(defaults) if defaults
689
- end
690
- options.delete_if do |option, _args|
691
- if route.significant_variable_names.include?(option)
692
- route.add_match_with(option => Array(_args).first)
693
- true
694
- end
695
- end
696
-
697
- # Add Sinatra conditions.
698
- options.each { |o, a| route.respond_to?(o) ? route.send(o, *a) : send(o, *a) }
699
- conditions, @conditions = @conditions, []
700
- route.custom_conditions.concat(conditions)
701
-
702
- invoke_hook(:padrino_route_added, route, verb, path, args, options, block)
703
-
704
- # Add Application defaults.
705
- route.before_filters.concat(@filters[:before])
706
- route.after_filters.concat(@filters[:after])
707
- if @_controller
708
- route.use_layout = @layout
709
- route.controller = Array(@_controller)[0].to_s
710
- end
711
-
712
- deferred_routes[priority] << [route, block]
713
-
714
- route
715
- end
716
-
717
- ##
718
- # Returns the final parsed route details (modified to reflect all
719
- # Padrino options) given the raw route. Raw route passed in could be
720
- # a named alias or a string and is parsed to reflect provides formats,
721
- # controllers, parents, 'with' parameters, and other options.
722
- #
723
- def parse_route(path, options, verb)
724
- route_options = {}
725
-
726
- # We need check if path is a symbol, if that it's a named route.
727
- map = options.delete(:map)
728
-
729
- # path i.e :index or :show
730
- if path.kind_of?(Symbol)
731
- name = path
732
- path = map ? map.dup : (path == :index ? '/' : path.to_s)
733
- end
734
-
735
- # Build our controller
736
- controller = Array(@_controller).map(&:to_s)
737
-
738
- case path
739
- when String # path i.e "/index" or "/show"
740
- # Now we need to parse our 'with' params
741
- if with_params = options.delete(:with)
742
- path = process_path_for_with_params(path, with_params)
743
- end
744
-
745
- # Now we need to parse our provides
746
- options.delete(:provides) if options[:provides].nil?
747
-
748
- if @_use_format or format_params = options[:provides]
749
- process_path_for_provides(path, format_params)
750
- # options[:add_match_with] ||= {}
751
- # options[:add_match_with][:format] = /[^\.]+/
752
- end
753
-
754
- absolute_map = map && map[0] == ?/
755
-
756
- unless controller.empty?
757
- # Now we need to add our controller path only if not mapped directly
758
- if map.blank? and !absolute_map
759
- controller_path = controller.join("/")
760
- path.gsub!(%r{^\(/\)|/\?}, "")
761
- path = File.join(controller_path, path) unless @_map
762
- end
763
- end
764
-
765
- # Now we need to parse our 'parent' params and parent scope.
766
- if !absolute_map and parent_params = options.delete(:parent) || @_parents
767
- parent_params = (Array(@_parents) + Array(parent_params)).uniq
768
- path = process_path_for_parent_params(path, parent_params)
769
- end
770
-
771
- # Add any controller level map to the front of the path.
772
- path = "#{@_map}/#{path}".squeeze('/') unless absolute_map or @_map.blank?
773
-
774
- # Small reformats
775
- path.gsub!(%r{/\?$}, '(/)') # Remove index path
776
- path.gsub!(%r{//$}, '/') # Remove index path
777
- path[0,0] = "/" if path !~ %r{^\(?/} # Paths must start with a /
778
- path.sub!(%r{/(\))?$}, '\\1') if path != "/" # Remove latest trailing delimiter
779
- path.gsub!(/\/(\(\.|$)/, '\\1') # Remove trailing slashes
780
- path.squeeze!('/')
781
- when Regexp
782
- route_options[:path_for_generation] = options.delete(:generate_with) if options.key?(:generate_with)
783
- end
784
-
785
- name = options.delete(:route_name) if name.nil? && options.key?(:route_name)
786
- name = options.delete(:name) if name.nil? && options.key?(:name)
787
- if name
788
- controller_name = controller.join("_")
789
- name = "#{controller_name}_#{name}".to_sym unless controller_name.blank?
790
- end
791
-
792
- # Merge in option defaults.
793
- options.reverse_merge!(:default_values => @_defaults)
794
-
795
- [path, name, parent_params, options, route_options]
796
- end
797
-
798
- ##
799
- # Processes the existing path and appends the 'with' parameters onto the route
800
- # Used for calculating path in route method.
801
- #
802
- def process_path_for_with_params(path, with_params)
803
- File.join(path, Array(with_params).map(&:inspect).join("/"))
804
- end
805
-
806
- ##
807
- # Processes the existing path and prepends the 'parent' parameters onto the route
808
- # Used for calculating path in route method.
809
- #
810
- def process_path_for_parent_params(path, parent_params)
811
- parent_prefix = parent_params.flatten.compact.uniq.map do |param|
812
- map = (param.respond_to?(:map) && param.map ? param.map : param.to_s)
813
- part = "#{map}/:#{param.to_s.singularize}_id/"
814
- part = "(#{part})" if param.respond_to?(:optional) && param.optional?
815
- part
816
- end
817
-
818
- [parent_prefix, path].flatten.join("")
819
- end
820
-
821
- ##
822
- # Processes the existing path and appends the 'format' suffix onto the route.
823
- # Used for calculating path in route method.
824
- #
825
- def process_path_for_provides(path, format_params)
826
- path << "(.:format)" unless path[-10, 10] == '(.:format)'
827
- end
828
-
829
- ##
830
- # Allows routing by MIME-types specified in the URL or ACCEPT header.
831
- #
832
- # By default, if a non-provided mime-type is specified in a URL, the
833
- # route will not match an thus return a 404.
834
- #
835
- # Setting the :treat_format_as_accept option to true allows treating
836
- # missing mime types specified in the URL as if they were specified
837
- # in the ACCEPT header and thus return 406.
838
- #
839
- # If no type is specified, the first in the provides-list will be
840
- # returned.
841
- #
842
- # @example
843
- # get "/a", :provides => [:html, :js]
844
- # # => GET /a => :html
845
- # # => GET /a.js => :js
846
- # # => GET /a.xml => 404
847
- #
848
- # get "/b", :provides => [:html]
849
- # # => GET /b; ACCEPT: html => html
850
- # # => GET /b; ACCEPT: js => 406
851
- #
852
- # enable :treat_format_as_accept
853
- # get "/c", :provides => [:html, :js]
854
- # # => GET /c.xml => 406
855
- #
856
- def provides(*types)
857
- @_use_format = true
858
- condition do
859
- mime_types = types.map { |t| mime_type(t) }.compact
860
- url_format = params[:format].to_sym if params[:format]
861
- accepts = request.accept.map(&:to_str)
862
-
863
- # Per rfc2616-sec14:
864
- # Assume */* if no ACCEPT header is given.
865
- catch_all = (accepts.delete "*/*" || accepts.empty?)
866
- matching_types = accepts.empty? ? mime_types.slice(0,1) : (accepts & mime_types)
867
- if matching_types.empty? && types.include?(:any)
868
- matching_types = accepts
869
- end
870
-
871
- if !url_format && matching_types.first
872
- type = ::Rack::Mime::MIME_TYPES.find { |k, v| v == matching_types.first }[0].sub(/\./,'').to_sym
873
- accept_format = CONTENT_TYPE_ALIASES[type] || type
874
- elsif catch_all && !types.include?(:any)
875
- type = types.first
876
- accept_format = CONTENT_TYPE_ALIASES[type] || type
877
- end
878
-
879
- matched_format = types.include?(:any) ||
880
- types.include?(accept_format) ||
881
- types.include?(url_format) ||
882
- ((!url_format) && request.accept.empty? && types.include?(:html))
883
-
884
- # Per rfc2616-sec14:
885
- # Answer with 406 if accept is given but types to not match any
886
- # provided type.
887
- halt 406 if
888
- (!url_format && !accepts.empty? && !matched_format) ||
889
- (settings.respond_to?(:treat_format_as_accept) && settings.treat_format_as_accept && url_format && !matched_format)
890
-
891
- if matched_format
892
- @_content_type = url_format || accept_format || :html
893
- content_type(@_content_type, :charset => 'utf-8')
894
- end
895
-
896
- matched_format
897
- end
898
- end
899
-
900
- ##
901
- # Implements CSRF checking when `allow_disabled_csrf` is set to true.
902
- #
903
- # This condition is always on, except when it is explicitly switched
904
- # off.
905
- #
906
- # @example
907
- # post("/", :csrf_protection => false)
908
- #
909
- def csrf_protection(on = true)
910
- if on
911
- condition { halt 403 if request.env['protection.csrf.failed'] }
912
- end
913
- end
914
- end
915
-
916
- ##
917
- # Instance methods related to recognizing and processing routes and serving static files.
918
- #
919
- module InstanceMethods
920
- ##
921
- # Instance method for URL generation.
922
- #
923
- # @example
924
- # url(:show, :id => 1)
925
- # url(:show, :name => :test)
926
- # url(:show, 1)
927
- # url("/foo")
928
- #
929
- # @see Padrino::Routing::ClassMethods#url
930
- #
931
- def url(*args)
932
- # Delegate to Sinatra 1.2 for simple url("/foo")
933
- # http://www.sinatrarb.com/intro#Generating%20URLs
934
- return super if args.first.is_a?(String) && !args[1].is_a?(Hash)
935
-
936
- # Delegate to Padrino named route URL generation.
937
- settings.url(*args)
938
- end
939
- alias :url_for :url
940
-
941
- ##
942
- # Returns absolute url. Calls Sinatra::Helpers#uri to generate protocol version, hostname and port.
943
- #
944
- # @example
945
- # absolute_url(:show, :id => 1) # => http://example.com/show?id=1
946
- # absolute_url(:show, 24) # => https://example.com/admin/show/24
947
- #
948
- def absolute_url( *args )
949
- uri url(*args), true, false
950
- end
951
-
952
- def recognize_path(path)
953
- settings.recognize_path(path)
954
- end
955
-
956
- ##
957
- # Returns the current path within a route from specified +path_params+.
958
- #
959
- def current_path(*path_params)
960
- if path_params.last.is_a?(Hash)
961
- path_params[-1] = params.merge(path_params[-1])
962
- else
963
- path_params << params
964
- end
965
- @route.path(*path_params)
966
- end
967
-
968
- ##
969
- # Returns the current route
970
- #
971
- # @example
972
- # -if route.controller == :press
973
- # %li=show_article
974
- #
975
- def route
976
- @route
977
- end
978
-
979
- ##
980
- # This is mostly just a helper so request.path_info isn't changed when
981
- # serving files from the public directory.
982
- #
983
- def static_file?(path_info)
984
- return if (public_dir = settings.public_folder).nil?
985
- public_dir = File.expand_path(public_dir)
986
- path = File.expand_path(public_dir + unescape(path_info))
987
- return if path[0, public_dir.length] != public_dir
988
- return unless File.file?(path)
989
- return path
990
- end
991
-
992
- #
993
- # Method for deliver static files.
994
- #
995
- def static!
996
- if path = static_file?(request.path_info)
997
- env['sinatra.static_file'] = path
998
- cache_control(*settings.static_cache_control) if settings.static_cache_control?
999
- send_file(path, :disposition => nil)
1000
- end
1001
- end
1002
-
1003
- ##
1004
- # Return the request format, this is useful when we need to respond to
1005
- # a given Content-Type.
1006
- #
1007
- # @param [Symbol, nil] type
1008
- #
1009
- # @param [Hash] params
1010
- #
1011
- # @example
1012
- # get :index, :provides => :any do
1013
- # case content_type
1014
- # when :js then ...
1015
- # when :json then ...
1016
- # when :html then ...
1017
- # end
1018
- # end
1019
- #
1020
- def content_type(type=nil, params={})
1021
- unless type.nil?
1022
- super(type, params)
1023
- @_content_type = type
1024
- end
1025
- @_content_type
1026
- end
1027
-
1028
- private
1029
-
1030
- def filter!(type, base=settings)
1031
- base.filters[type].each { |block| instance_eval(&block) }
1032
- end
1033
-
1034
- def dispatch!
1035
- invoke do
1036
- static! if settings.static? && (request.get? || request.head?)
1037
- route!
1038
- end
1039
- rescue ::Exception => boom
1040
- filter! :before if boom.kind_of? ::Sinatra::NotFound
1041
- invoke { @boom_handled = handle_exception!(boom) }
1042
- ensure
1043
- @boom_handled or begin
1044
- filter! :after unless env['sinatra.static_file']
1045
- rescue ::Exception => boom
1046
- invoke { handle_exception!(boom) } unless @env['sinatra.error']
1047
- end
1048
- end
1049
-
1050
- def route!(base=settings, pass_block=nil)
1051
- Thread.current['padrino.instance'] = self
1052
- if base.compiled_router and match = base.compiled_router.call(@request.env)
1053
- if match.respond_to?(:each)
1054
- route_eval do
1055
- match[1].each { |k,v| response[k] = v }
1056
- status match[0]
1057
- route_missing if match[0] == 404
1058
- route_missing if allow = response['Allow'] and allow.include?(request.env['REQUEST_METHOD'])
1059
- end
1060
- end
1061
- else
1062
- filter! :before
1063
- end
1064
-
1065
- # Run routes defined in superclass.
1066
- if base.superclass.respond_to?(:router)
1067
- route!(base.superclass, pass_block)
1068
- return
1069
- end
1070
-
1071
- route_eval(&pass_block) if pass_block
1072
-
1073
- route_missing
1074
- end
1075
- end
1076
- end
1077
- end