middleman-core 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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