middleman-core 3.1.0.rc.1 → 3.1.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (281) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +6 -0
  3. data/features/clean_build.feature +20 -3
  4. data/features/custom-source.feature +7 -0
  5. data/features/data.feature +27 -1
  6. data/features/front-matter-neighbor.feature +2 -2
  7. data/features/front-matter.feature +3 -3
  8. data/features/i18n_builder.feature +5 -1
  9. data/features/i18n_preview.feature +18 -0
  10. data/features/layouts_dir.feature +30 -0
  11. data/features/minify_javascript.feature +3 -3
  12. data/features/support/env.rb +6 -0
  13. data/fixtures/basic-data-app/source/data.html.erb +5 -1
  14. data/fixtures/basic-data-app/source/data3.html.erb +5 -1
  15. data/fixtures/chained-app/source/index.html.str.erb +1 -1
  16. data/fixtures/clean-nested-app/config.rb +1 -3
  17. data/fixtures/clean-nested-app/source/nested/nested.html +1 -0
  18. data/fixtures/custom-src-app/config.rb +1 -0
  19. data/fixtures/custom-src-app/src/index.html +0 -0
  20. data/fixtures/custom-src-app/src/layouts/layout.html.erb +1 -0
  21. data/fixtures/frontmatter-app/source/front-matter-2.php.erb +2 -2
  22. data/fixtures/frontmatter-app/source/front-matter-auto.erb +1 -1
  23. data/fixtures/frontmatter-app/source/front-matter-change.html.erb +1 -1
  24. data/fixtures/frontmatter-app/source/front-matter-encoding.html.erb +1 -1
  25. data/fixtures/frontmatter-app/source/front-matter-line-2.html.erb +1 -1
  26. data/fixtures/frontmatter-app/source/json-front-matter-2.php.erb +2 -2
  27. data/fixtures/frontmatter-app/source/json-front-matter-auto.erb +1 -1
  28. data/fixtures/frontmatter-app/source/json-front-matter-encoding.html.erb +1 -1
  29. data/fixtures/frontmatter-app/source/json-front-matter-line-2.html.erb +1 -1
  30. data/fixtures/frontmatter-app/source/json-front-matter.html.erb +1 -1
  31. data/fixtures/frontmatter-app/source/raw-front-matter.html +1 -1
  32. data/fixtures/frontmatter-neighbor-app/source/front-matter-2.php.erb +2 -2
  33. data/fixtures/frontmatter-neighbor-app/source/front-matter-auto.erb +1 -1
  34. data/fixtures/frontmatter-neighbor-app/source/front-matter-change.html.erb +1 -1
  35. data/fixtures/frontmatter-neighbor-app/source/front-matter-encoding.html.erb +1 -1
  36. data/fixtures/frontmatter-neighbor-app/source/json-front-matter-2.php.erb +2 -2
  37. data/fixtures/frontmatter-neighbor-app/source/json-front-matter-auto.erb +1 -1
  38. data/fixtures/frontmatter-neighbor-app/source/json-front-matter.html.erb +1 -1
  39. data/fixtures/frontmatter-neighbor-app/source/raw-front-matter.html +1 -1
  40. data/fixtures/i18n-nested-app/locales/en/more.yml +3 -0
  41. data/fixtures/i18n-nested-app/locales/en.yml +4 -0
  42. data/fixtures/i18n-nested-app/locales/es/mucho.yml +3 -0
  43. data/fixtures/i18n-nested-app/locales/es.yml +4 -0
  44. data/fixtures/i18n-nested-app/source/localizable/index.html.erb +3 -0
  45. data/fixtures/i18n-test-app/locales/es.yml +1 -0
  46. data/fixtures/i18n-test-app/source/one.en.md +1 -0
  47. data/fixtures/i18n-test-app/source/one.es.md +1 -0
  48. data/fixtures/layouts-dir-app/source/index.html.erb +2 -0
  49. data/fixtures/layouts-dir-app/source/layouts/layout.erb +3 -0
  50. data/fixtures/layouts-dir-app/source/layouts2/layout.erb +3 -0
  51. data/fixtures/layouts-dir-app/source/nested/layouts2/layout.erb +3 -0
  52. data/fixtures/nested-data-app/data/examples/deeper/stuff.yml +1 -0
  53. data/fixtures/nested-data-app/data/examples/more.yml +1 -0
  54. data/fixtures/nested-data-app/source/test.html.erb +3 -1
  55. data/fixtures/nested-layout-app/source/layouts/master.erb +2 -2
  56. data/fixtures/nested-layout-app/source/layouts/master_haml.haml +2 -2
  57. data/fixtures/nested-layout-app/source/layouts/master_slim.slim +2 -2
  58. data/lib/middleman-core/application.rb +20 -3
  59. data/lib/middleman-core/cli/build.rb +5 -8
  60. data/lib/middleman-core/configuration.rb +1 -1
  61. data/lib/middleman-core/core_extensions/extensions.rb +26 -9
  62. data/lib/middleman-core/core_extensions/file_watcher.rb +9 -1
  63. data/lib/middleman-core/core_extensions/front_matter.rb +145 -173
  64. data/lib/middleman-core/core_extensions/rendering.rb +4 -4
  65. data/lib/middleman-core/core_extensions.rb +63 -0
  66. data/lib/middleman-core/extensions.rb +61 -7
  67. data/lib/middleman-core/renderers/redcarpet.rb +2 -15
  68. data/lib/middleman-core/sitemap/extensions/ignores.rb +4 -1
  69. data/lib/middleman-core/sitemap/extensions/on_disk.rb +5 -1
  70. data/lib/middleman-core/sitemap/store.rb +10 -2
  71. data/lib/middleman-core/sitemap.rb +4 -4
  72. data/lib/middleman-core/templates/empty/Gemfile.tt +3 -0
  73. data/lib/middleman-core/templates/empty.rb +23 -0
  74. data/lib/middleman-core/templates/shared/Gemfile.tt +0 -2
  75. data/lib/middleman-core/templates.rb +13 -1
  76. data/lib/middleman-core/util.rb +0 -57
  77. data/lib/middleman-core/version.rb +1 -1
  78. data/lib/middleman-core.rb +0 -1
  79. data/lib/middleman-more/core_extensions/compass.rb +3 -3
  80. data/lib/middleman-more/core_extensions/default_helpers.rb +2 -1
  81. data/lib/middleman-more/core_extensions/i18n.rb +79 -57
  82. data/lib/middleman-more/extensions/asset_hash.rb +43 -30
  83. data/lib/middleman-more/extensions/automatic_image_sizes.rb +1 -1
  84. data/lib/middleman-more/extensions/directory_indexes.rb +1 -1
  85. data/lib/middleman-more/extensions/gzip.rb +17 -19
  86. data/lib/middleman-more/extensions/minify_css.rb +16 -16
  87. data/lib/middleman-more/extensions/minify_javascript.rb +26 -20
  88. data/lib/{middleman-more/extensions/automatic_image_sizes → vendored-middleman-deps}/fastimage.rb +0 -0
  89. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/CHANGES.textile +0 -0
  90. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/Gemfile +0 -0
  91. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/README.rdoc +0 -0
  92. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/Rakefile +0 -0
  93. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/hooks.gemspec +0 -0
  94. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/lib/hooks/inheritable_attribute.rb +0 -0
  95. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/lib/hooks.rb +0 -0
  96. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/test/hooks_test.rb +0 -0
  97. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/test/inheritable_attribute_test.rb +0 -0
  98. data/lib/{middleman-core/vendor → vendored-middleman-deps}/hooks-0.2.0/test/test_helper.rb +0 -0
  99. data/lib/vendored-middleman-deps/padrino-core-0.10.7/.document +5 -0
  100. data/lib/vendored-middleman-deps/padrino-core-0.10.7/.gitignore +22 -0
  101. data/lib/vendored-middleman-deps/padrino-core-0.10.7/.yardopts +1 -0
  102. data/lib/vendored-middleman-deps/padrino-core-0.10.7/LICENSE.txt +20 -0
  103. data/lib/vendored-middleman-deps/padrino-core-0.10.7/README.rdoc +294 -0
  104. data/lib/vendored-middleman-deps/padrino-core-0.10.7/Rakefile +5 -0
  105. data/lib/vendored-middleman-deps/padrino-core-0.10.7/bin/padrino +9 -0
  106. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/application/rendering.rb +292 -0
  107. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/application/routing.rb +943 -0
  108. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/application/showexceptions.rb +20 -0
  109. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/application.rb +269 -0
  110. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/caller.rb +53 -0
  111. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/cli/adapter.rb +24 -0
  112. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/cli/base.rb +155 -0
  113. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/cli/console.rb +20 -0
  114. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/cli/rake.rb +25 -0
  115. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/cli/rake_tasks.rb +59 -0
  116. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/command.rb +38 -0
  117. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/images/404.png +0 -0
  118. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/images/500.png +0 -0
  119. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/loader.rb +211 -0
  120. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/cs.yml +34 -0
  121. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/da.yml +34 -0
  122. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/de.yml +34 -0
  123. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/en.yml +34 -0
  124. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/es.yml +34 -0
  125. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/fr.yml +34 -0
  126. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/hu.yml +34 -0
  127. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/it.yml +40 -0
  128. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/ja.yml +34 -0
  129. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/lv.yml +34 -0
  130. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/nl.yml +34 -0
  131. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/no.yml +35 -0
  132. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/pl.yml +34 -0
  133. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/pt_br.yml +40 -0
  134. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/ro.yml +34 -0
  135. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/ru.yml +35 -0
  136. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/sv.yml +34 -0
  137. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/tr.yml +34 -0
  138. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/uk.yml +34 -0
  139. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/zh_cn.yml +34 -0
  140. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/locale/zh_tw.yml +34 -0
  141. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/logger.rb +428 -0
  142. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/mounter.rb +224 -0
  143. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/reloader.rb +254 -0
  144. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/router.rb +98 -0
  145. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/server.rb +79 -0
  146. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/support_lite.rb +207 -0
  147. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/tasks.rb +21 -0
  148. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core/version.rb +20 -0
  149. data/lib/vendored-middleman-deps/padrino-core-0.10.7/lib/padrino-core.rb +152 -0
  150. data/lib/vendored-middleman-deps/padrino-core-0.10.7/padrino-core.gemspec +38 -0
  151. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/apps/.components +6 -0
  152. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/apps/.gitignore +7 -0
  153. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/apps/complex.rb +32 -0
  154. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/apps/simple.rb +33 -0
  155. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/dependencies/a.rb +9 -0
  156. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/dependencies/b.rb +4 -0
  157. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/dependencies/c.rb +1 -0
  158. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/dependencies/circular/e.rb +13 -0
  159. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/dependencies/circular/f.rb +2 -0
  160. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/dependencies/circular/g.rb +2 -0
  161. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/fixtures/dependencies/d.rb +4 -0
  162. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/helper.rb +83 -0
  163. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/mini_shoulda.rb +45 -0
  164. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_application.rb +108 -0
  165. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_core.rb +77 -0
  166. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_dependencies.rb +44 -0
  167. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_filters.rb +278 -0
  168. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_locale.rb +21 -0
  169. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_logger.rb +154 -0
  170. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_mounter.rb +177 -0
  171. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_reloader_complex.rb +75 -0
  172. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_reloader_simple.rb +98 -0
  173. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_rendering.rb +461 -0
  174. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_restful_routing.rb +33 -0
  175. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_router.rb +146 -0
  176. data/lib/vendored-middleman-deps/padrino-core-0.10.7/test/test_routing.rb +1695 -0
  177. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/.document +5 -0
  178. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/.gitignore +21 -0
  179. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/.yardopts +1 -0
  180. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/LICENSE.txt +20 -0
  181. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/README.rdoc +239 -0
  182. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/Rakefile +5 -0
  183. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/asset_tag_helpers.rb +417 -0
  184. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/form_builder/abstract_form_builder.rb +251 -0
  185. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/form_builder/standard_form_builder.rb +43 -0
  186. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/form_helpers.rb +787 -0
  187. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/format_helpers.rb +381 -0
  188. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/cs.yml +103 -0
  189. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/da.yml +91 -0
  190. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/de.yml +81 -0
  191. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/en.yml +103 -0
  192. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/es.yml +103 -0
  193. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/fr.yml +80 -0
  194. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/hu.yml +103 -0
  195. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/it.yml +89 -0
  196. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/ja.yml +103 -0
  197. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/lv.yml +103 -0
  198. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/nl.yml +82 -0
  199. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/no.yml +91 -0
  200. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/pl.yml +95 -0
  201. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/pt_br.yml +103 -0
  202. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/ro.yml +103 -0
  203. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/ru.yml +103 -0
  204. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/sv.yml +103 -0
  205. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/tr.yml +103 -0
  206. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/uk.yml +103 -0
  207. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/zh_cn.yml +104 -0
  208. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/locale/zh_tw.yml +103 -0
  209. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/number_helpers.rb +288 -0
  210. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/output_helpers/abstract_handler.rb +98 -0
  211. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/output_helpers/erb_handler.rb +79 -0
  212. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/output_helpers/haml_handler.rb +63 -0
  213. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/output_helpers/slim_handler.rb +81 -0
  214. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/output_helpers.rb +175 -0
  215. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/render_helpers.rb +60 -0
  216. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/tag_helpers.rb +260 -0
  217. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers/translation_helpers.rb +38 -0
  218. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/lib/padrino-helpers.rb +59 -0
  219. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/padrino-helpers.gemspec +27 -0
  220. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/app.rb +73 -0
  221. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/capture_concat.erb +14 -0
  222. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/capture_concat.haml +12 -0
  223. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/capture_concat.slim +13 -0
  224. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/content_for.erb +14 -0
  225. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/content_for.haml +12 -0
  226. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/content_for.slim +12 -0
  227. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/content_tag.erb +11 -0
  228. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/content_tag.haml +9 -0
  229. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/content_tag.slim +9 -0
  230. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/current_engine.erb +5 -0
  231. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/current_engine.haml +5 -0
  232. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/current_engine.slim +5 -0
  233. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/fields_for.erb +20 -0
  234. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/fields_for.haml +15 -0
  235. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/fields_for.slim +15 -0
  236. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/form_for.erb +72 -0
  237. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/form_for.haml +59 -0
  238. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/form_for.slim +59 -0
  239. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/form_tag.erb +86 -0
  240. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/form_tag.haml +70 -0
  241. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/form_tag.slim +70 -0
  242. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/link_to.erb +5 -0
  243. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/link_to.haml +4 -0
  244. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/link_to.slim +4 -0
  245. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/mail_to.erb +3 -0
  246. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/mail_to.haml +3 -0
  247. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/mail_to.slim +3 -0
  248. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/meta_tag.erb +3 -0
  249. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/meta_tag.haml +3 -0
  250. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/meta_tag.slim +3 -0
  251. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/partials/_erb.erb +1 -0
  252. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/partials/_haml.haml +1 -0
  253. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/partials/_slim.slim +1 -0
  254. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/simple_partial.erb +1 -0
  255. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/simple_partial.haml +1 -0
  256. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/markup_app/views/simple_partial.slim +1 -0
  257. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/app.rb +50 -0
  258. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/current_engine.haml +5 -0
  259. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/current_engines/_erb.erb +1 -0
  260. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/current_engines/_haml.haml +1 -0
  261. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/current_engines/_slim.slim +1 -0
  262. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/erb/test.erb +1 -0
  263. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/explicit_engine.haml +5 -0
  264. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/haml/test.haml +1 -0
  265. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/template/_user.haml +7 -0
  266. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/template/haml_template.haml +1 -0
  267. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/fixtures/render_app/views/template/some_template.haml +2 -0
  268. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/helper.rb +66 -0
  269. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_asset_tag_helpers.rb +334 -0
  270. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_form_builder.rb +1106 -0
  271. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_form_helpers.rb +776 -0
  272. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_format_helpers.rb +227 -0
  273. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_locale.rb +20 -0
  274. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_number_helpers.rb +139 -0
  275. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_output_helpers.rb +152 -0
  276. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_render_helpers.rb +76 -0
  277. data/lib/vendored-middleman-deps/padrino-helpers-0.10.7/test/test_tag_helpers.rb +106 -0
  278. data/middleman-core.gemspec +2 -2
  279. data/spec/spec_helper.rb +5 -0
  280. metadata +243 -18
  281. data/lib/middleman-more.rb +0 -102
@@ -0,0 +1,787 @@
1
+ module Padrino
2
+ module Helpers
3
+ ##
4
+ # Helpers related to producing form related tags and inputs into templates.
5
+ #
6
+ module FormHelpers
7
+ ##
8
+ # Constructs a form for object using given or default form_builder
9
+ #
10
+ # @param [Object] object
11
+ # The object for which the form is being built.
12
+ # @param [String] url
13
+ # The url this form will submit to.
14
+ # @param [Hash] settings
15
+ # The settings associated with this form. Accepts html options.
16
+ # @option settings [String] :builder ("StandardFormBuilder")
17
+ # The FormBuilder class to use such as StandardFormBuilder.
18
+ # @param [Proc] block
19
+ # The fields and content inside this form.
20
+ #
21
+ # @yield [AbstractFormBuilder] The form builder used to compose fields.
22
+ #
23
+ # @return [String] The html object-backed form with the specified options and input fields.
24
+ #
25
+ # @example
26
+ # form_for :user, '/register' do |f| ... end
27
+ # form_for @user, '/register', :id => 'register' do |f| ... end
28
+ #
29
+ # @api public
30
+ def form_for(object, url, settings={}, &block)
31
+ form_html = capture_html(builder_instance(object, settings), &block)
32
+ form_tag(url, settings) { form_html }
33
+ end
34
+
35
+ ##
36
+ # Constructs form fields for an object using given or default form_builder
37
+ # Used within an existing form to allow alternate objects within one form
38
+ #
39
+ # @param [Object] object
40
+ # The object for which the fields are being built.
41
+ # @param [Hash] settings
42
+ # The settings associated with these fields. Accepts html options.
43
+ # @param [Proc] block
44
+ # The content inside this set of fields.
45
+ #
46
+ # @return [String] The html fields with the specified options.
47
+ #
48
+ # @example
49
+ # fields_for @user.assignment do |assignment| ... end
50
+ # fields_for :assignment do |assigment| ... end
51
+ #
52
+ # @api public
53
+ def fields_for(object, settings={}, &block)
54
+ instance = builder_instance(object, settings)
55
+ fields_html = capture_html(instance, &block)
56
+ fields_html << instance.hidden_field(:id) if instance.send(:nested_object_id)
57
+ concat_content fields_html
58
+ end
59
+
60
+ ##
61
+ # Constructs a form without object based on options
62
+ #
63
+ # @param [String] url
64
+ # The url this form will submit to.
65
+ # @param [Hash] options
66
+ # The html options associated with this form.
67
+ # @param [Proc] block
68
+ # The fields and content inside this form.
69
+ #
70
+ # @return [String] The html form with the specified options and input fields.
71
+ #
72
+ # @example
73
+ # form_tag '/register', :class => "registration_form" do ... end
74
+ #
75
+ # @api public
76
+ def form_tag(url, options={}, &block)
77
+ desired_method = options[:method].to_s
78
+ options.delete(:method) unless desired_method =~ /get|post/i
79
+ options.reverse_merge!(:method => 'post', :action => url)
80
+ options[:enctype] = 'multipart/form-data' if options.delete(:multipart)
81
+ options['accept-charset'] ||= 'UTF-8'
82
+ inner_form_html = hidden_form_method_field(desired_method)
83
+ inner_form_html += capture_html(&block)
84
+ concat_content content_tag(:form, inner_form_html, options)
85
+ end
86
+
87
+ ##
88
+ # Returns the hidden method field for 'put' and 'delete' forms
89
+ # Only 'get' and 'post' are allowed within browsers;
90
+ # 'put' and 'delete' are just specified using hidden fields with form action still 'put'.
91
+ #
92
+ # @param [String] desired_method
93
+ # The method this hidden field represents (i.e put or delete))
94
+ #
95
+ # @return [String] The hidden field representing the +desired_method+ for the form.
96
+ #
97
+ # @example
98
+ # # Generate: <input name="_method" value="delete" />
99
+ # hidden_form_method_field('delete')
100
+ #
101
+ # @api semipublic
102
+ def hidden_form_method_field(desired_method)
103
+ return '' if desired_method.blank? || desired_method.to_s =~ /get|post/i
104
+ hidden_field_tag(:_method, :value => desired_method)
105
+ end
106
+
107
+ ##
108
+ # Constructs a field_set to group fields with given options
109
+ #
110
+ # @overload field_set_tag(legend=nil, options={}, &block)
111
+ # @param [String] legend The legend caption for the fieldset
112
+ # @param [Hash] options The html options for the fieldset.
113
+ # @param [Proc] block The content inside the fieldset.
114
+ # @overload field_set_tag(options={}, &block)
115
+ # @param [Hash] options The html options for the fieldset.
116
+ # @param [Proc] block The content inside the fieldset.
117
+ #
118
+ # @return [String] The html for the fieldset tag based on given +options+.
119
+ #
120
+ # @example
121
+ # field_set_tag(:class => "office-set") { }
122
+ # field_set_tag("Office", :class => 'office-set') { }
123
+ #
124
+ # @api public
125
+ def field_set_tag(*args, &block)
126
+ options = args.extract_options!
127
+ legend_text = args[0].is_a?(String) ? args.first : nil
128
+ legend_html = legend_text.blank? ? '' : content_tag(:legend, legend_text)
129
+ field_set_content = legend_html + capture_html(&block)
130
+ concat_content content_tag(:fieldset, field_set_content, options)
131
+ end
132
+
133
+ ##
134
+ # Constructs list html for the errors for a given symbol
135
+ #
136
+ # @overload error_messages_for(*objects, options = {})
137
+ # @param [Array<Object>] object Splat of objects to display errors for.
138
+ # @param [Hash] options Error message display options.
139
+ # @option options [String] :header_tag ("h2")
140
+ # Used for the header of the error div
141
+ # @option options [String] :id ("field-errors")
142
+ # The id of the error div.
143
+ # @option options [String] :class ("field-errors")
144
+ # The class of the error div.
145
+ # @option options [Array<Object>] :object
146
+ # The object (or array of objects) for which to display errors,
147
+ # if you need to escape the instance variable convention.
148
+ # @option options [String] :object_name
149
+ # The object name to use in the header, or any text that you prefer.
150
+ # If +:object_name+ is not set, the name of the first object will be used.
151
+ # @option options [String] :header_message ("X errors prohibited this object from being saved")
152
+ # The message in the header of the error div. Pass +nil+ or an empty string
153
+ # to avoid the header message altogether.
154
+ # @option options [String] :message ("There were problems with the following fields:")
155
+ # The explanation message after the header message and before
156
+ # the error list. Pass +nil+ or an empty string to avoid the explanation message
157
+ # altogether.
158
+ #
159
+ # @return [String] The html section with all errors for the specified +objects+
160
+ #
161
+ # @example
162
+ # error_messages_for :user
163
+ #
164
+ # @api public
165
+ def error_messages_for(*objects)
166
+ options = objects.extract_options!.symbolize_keys
167
+ objects = objects.map { |object_name|
168
+ object_name.is_a?(Symbol) ? instance_variable_get("@#{object_name}") : object_name
169
+ }.compact
170
+ count = objects.inject(0) { |sum, object| sum + object.errors.size }
171
+
172
+ unless count.zero?
173
+ html = {}
174
+ [:id, :class, :style].each do |key|
175
+ if options.include?(key)
176
+ value = options[key]
177
+ html[key] = value unless value.blank?
178
+ else
179
+ html[key] = 'field-errors' unless key == :style
180
+ end
181
+ end
182
+
183
+ options[:object_name] ||= objects.first.class
184
+
185
+ I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
186
+ header_message = if options.include?(:header_message)
187
+ options[:header_message]
188
+ else
189
+ object_name = options[:object_name].to_s.underscore.gsub(/\//, ' ')
190
+ object_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
191
+ locale.t :header, :count => count, :model => object_name
192
+ end
193
+ message = options.include?(:message) ? options[:message] : locale.t(:body)
194
+ error_messages = objects.map { |object|
195
+ object_name = options[:object_name].to_s.underscore.gsub(/\//, ' ')
196
+ object.errors.map { |f, msg|
197
+ field = I18n.t(f, :default => f.to_s.humanize, :scope => [:models, object_name, :attributes])
198
+ content_tag(:li, "%s %s" % [field, msg])
199
+ }
200
+ }.join
201
+
202
+ contents = ''
203
+ contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
204
+ contents << content_tag(:p, message) unless message.blank?
205
+ contents << content_tag(:ul, error_messages)
206
+
207
+ content_tag(:div, contents, html)
208
+ end
209
+ else
210
+ ''
211
+ end
212
+ end
213
+
214
+ ##
215
+ # Returns a string containing the error message attached to the +method+ on the +object+ if one exists.
216
+ #
217
+ # @param [Object] object
218
+ # The object to display the error for.
219
+ # @param [Symbol] field
220
+ # The field on the +object+ to display the error for.
221
+ # @param [Hash] options
222
+ # The options to control the error display.
223
+ # @option options [String] :tag ("span")
224
+ # The tag that encloses the error.
225
+ # @option options [String] :prepend ("")
226
+ # The text to prepend before the field error.
227
+ # @option options [String] :append ("")
228
+ # The text to append after the field error.
229
+ #
230
+ # @example
231
+ # # => <span class="error">can't be blank</div>
232
+ # error_message_on :post, :title
233
+ # error_message_on @post, :title
234
+ #
235
+ # # => <div class="custom" style="border:1px solid red">can't be blank</div>
236
+ # error_message_on :post, :title, :tag => :id, :class => :custom, :style => "border:1px solid red"
237
+ #
238
+ # # => <div class="error">This title can't be blank (or it won't work)</div>
239
+ # error_message_on :post, :title, :prepend => "This title", :append => "(or it won't work)"
240
+ #
241
+ # @return [String] The html display of an error for a particular +object+ and +field+.
242
+ #
243
+ # @api public
244
+ def error_message_on(object, field, options={})
245
+ object = object.is_a?(Symbol) ? instance_variable_get("@#{object}") : object
246
+ error = object.errors[field] rescue nil
247
+ # Array(error).first is necessary because some ORMs give us an array others directly a value
248
+ if error = Array(error)[0]
249
+ options.reverse_merge!(:tag => :span, :class => :error)
250
+ tag = options.delete(:tag)
251
+ error = [options.delete(:prepend), error, options.delete(:append)].compact.join(" ")
252
+ content_tag(tag, error, options)
253
+ else
254
+ ''
255
+ end
256
+ end
257
+
258
+ ##
259
+ # Constructs a label tag from the given options
260
+ #
261
+ # @param [String] name
262
+ # The name of the field to label.
263
+ # @param [Hash] options
264
+ # The html options for this label.
265
+ # @option options :caption
266
+ # The caption for this label.
267
+ # @param [Proc] block
268
+ # The content to be inserted into the label.
269
+ #
270
+ # @return [String] The html for this label with the given +options+.
271
+ #
272
+ # @example
273
+ # label_tag :username, :class => 'long-label'
274
+ # label_tag :username, :class => 'long-label' do ... end
275
+ #
276
+ # @api public
277
+ def label_tag(name, options={}, &block)
278
+ options.reverse_merge!(:caption => "#{name.to_s.humanize}: ", :for => name)
279
+ caption_text = options.delete(:caption)
280
+ caption_text << "<span class='required'>*</span> " if options.delete(:required)
281
+ if block_given? # label with inner content
282
+ label_content = caption_text + capture_html(&block)
283
+ concat_content(content_tag(:label, label_content, options))
284
+ else # regular label
285
+ content_tag(:label, caption_text, options)
286
+ end
287
+ end
288
+
289
+ ##
290
+ # Creates a text field input with the given name and options
291
+ #
292
+ # @macro [new] text_field
293
+ # @param [Symbol] name
294
+ # The name of the input to create.
295
+ # @param [Hash] options
296
+ # The HTML options to include in this field.
297
+ #
298
+ # @option options [String] :id
299
+ # Specifies a unique identifier for the field.
300
+ # @option options [String] :class
301
+ # Specifies the stylesheet class of the field.
302
+ # @option options [String] :name
303
+ # Specifies the name of the field.
304
+ # @option options [String] :accesskey
305
+ # Specifies a shortcut key to access the field.
306
+ # @option options [Integer] :tabindex
307
+ # Specifies the tab order of the field.
308
+ # @option options [Integer] :maxlength
309
+ # Specifies the maximum length, in characters, of the field.
310
+ # @option options [Integer] :size
311
+ # Specifies the width, in characters, of the field.
312
+ # @option options [String] :placeholder
313
+ # Specifies a short hint that describes the expected value of the field.
314
+ # @option options [Boolean] :hidden
315
+ # Specifies whether or not the field is hidden from view.
316
+ # @option options [Boolean] :spellcheck
317
+ # Specifies whether or not the field should have it's spelling and grammar checked for errors.
318
+ # @option options [Boolean] :draggable
319
+ # Specifies whether or not the field is draggable. (true, false, :auto)
320
+ # @option options [String] :pattern
321
+ # Specifies the regular expression pattern that the field's value is checked against.
322
+ # @option options [Symbol] :autocomplete
323
+ # Specifies whether or not the field should have autocomplete enabled. (:on, :off)
324
+ # @option options [Boolean] :autofocus
325
+ # Specifies whether or not the field should automatically get focus when the page loads.
326
+ # @option options [Boolean] :required
327
+ # Specifies whether or not the field is required to be completeled before the form is submitted.
328
+ # @option options [Boolean] :readonly
329
+ # Specifies whether or not the field is read only.
330
+ # @option options [Boolean] :disabled
331
+ # Specifies whether or not the field is disabled.
332
+ #
333
+ # @return [String]
334
+ # Generated HTML with specified +options+
335
+ #
336
+ # @example
337
+ # text_field_tag :first_name, :maxlength => 40, :required => true
338
+ # # => <input name="first_name" maxlength="40" required type="text">
339
+ #
340
+ # text_field_tag :last_name, :class => 'string', :size => 40
341
+ # # => <input name="last_name" class="string" size="40" type="text">
342
+ #
343
+ # text_field_tag :username, :placeholder => 'Your Username'
344
+ # # => <input name="username" placeholder="Your Username" type="text">
345
+ #
346
+ # @api public
347
+ def text_field_tag(name, options={})
348
+ input_tag(:text, options.reverse_merge!(:name => name))
349
+ end
350
+
351
+ ##
352
+ # Creates a number field input with the given name and options
353
+ #
354
+ # @macro [new] number_field
355
+ # @param [Symbol] name
356
+ # The name of the input to create.
357
+ # @param [Hash] options
358
+ # The HTML options to include in this field.
359
+ #
360
+ # @option options [String] :id
361
+ # Specifies a unique identifier for the field.
362
+ # @option options [String] :class
363
+ # Specifies the stylesheet class of the field.
364
+ # @option options [String] :name
365
+ # Specifies the name of the field.
366
+ # @option options [String] :accesskey
367
+ # Specifies a shortcut key to access the field.
368
+ # @option options [Integer] :tabindex
369
+ # Specifies the tab order of the field.
370
+ # @option options [Integer] :min
371
+ # Specifies the minimum value of the field.
372
+ # @option options [Integer] :max
373
+ # Specifies the maximum value of the field.
374
+ # @option options [Integer] :step
375
+ # Specifies the legal number intervals of the field.
376
+ # @option options [Boolean] :hidden
377
+ # Specifies whether or not the field is hidden from view.
378
+ # @option options [Boolean] :spellcheck
379
+ # Specifies whether or not the field should have it's spelling and grammar checked for errors.
380
+ # @option options [Boolean] :draggable
381
+ # Specifies whether or not the field is draggable. (true, false, :auto)
382
+ # @option options [String] :pattern
383
+ # Specifies the regular expression pattern that the field's value is checked against.
384
+ # @option options [Symbol] :autocomplete
385
+ # Specifies whether or not the field should have autocomplete enabled. (:on, :off)
386
+ # @option options [Boolean] :autofocus
387
+ # Specifies whether or not the field should automatically get focus when the page loads.
388
+ # @option options [Boolean] :required
389
+ # Specifies whether or not the field is required to be completeled before the form is submitted.
390
+ # @option options [Boolean] :readonly
391
+ # Specifies whether or not the field is read only.
392
+ # @option options [Boolean] :disabled
393
+ # Specifies whether or not the field is disabled.
394
+ #
395
+ # @return [String]
396
+ # Generated HTML with specified +options+
397
+ #
398
+ # @example
399
+ # number_field_tag :quanity, :class => 'numeric'
400
+ # # => <input name="quanity" class="numeric" type="number">
401
+ #
402
+ # number_field_tag :zip_code, :pattern => /[0-9]{5}/
403
+ # # => <input name="zip_code" pattern="[0-9]{5}" type="number">
404
+ #
405
+ # number_field_tag :credit_card, :autocomplete => :off
406
+ # # => <input name="credit_card" autocomplete="off" type="number">
407
+ #
408
+ # number_field_tag :age, :min => 18, :max => 120, :step => 1
409
+ # # => <input name="age" min="18" max="120" step="1" type="number">
410
+ #
411
+ # @api public
412
+ def number_field_tag(name, options={})
413
+ input_tag(:number, options.reverse_merge(:name => name))
414
+ end
415
+
416
+ ##
417
+ # Creates a telephone field input with the given name and options
418
+ #
419
+ # @macro text_field
420
+ #
421
+ # @example
422
+ # telephone_field_tag :phone_number, :class => 'string'
423
+ # # => <input name="phone_number" class="string" type="tel">
424
+ #
425
+ # telephone_field_tag :cell_phone, :tabindex => 1
426
+ # telephone_field_tag :work_phone, :tabindex => 2
427
+ # telephone_field_tag :home_phone, :tabindex => 3
428
+ #
429
+ # # => <input name="cell_phone" tabindex="1" type="tel">
430
+ # # => <input name="work_phone" tabindex="2" type="tel">
431
+ # # => <input name="home_phone" tabindex="3" type="tel">
432
+ #
433
+ # @api public
434
+ def telephone_field_tag(name, options={})
435
+ input_tag(:tel, options.reverse_merge(:name => name))
436
+ end
437
+ alias_method :phone_field_tag, :telephone_field_tag
438
+
439
+ ##
440
+ # Creates an email field input with the given name and options
441
+ #
442
+ # @macro text_field
443
+ #
444
+ # @example
445
+ # email_field_tag :email, :placeholder => 'you@example.com'
446
+ # # => <input name="email" placeholder="you@example.com" type="email">
447
+ #
448
+ # email_field_tag :email, :value => 'padrinorb@gmail.com', :readonly => true
449
+ # # => <input name="email" value="padrinorb@gmail.com" readonly type="email">
450
+ #
451
+ # @api public
452
+ def email_field_tag(name, options={})
453
+ input_tag(:email, options.reverse_merge(:name => name))
454
+ end
455
+
456
+ ##
457
+ # Creates a search field input with the given name and options
458
+ #
459
+ # @macro text_field
460
+ #
461
+ # @example
462
+ # search_field_tag :search, :placeholder => 'Search this website...'
463
+ # # => <input name="search" placeholder="Search this website..." type="search">
464
+ #
465
+ # search_field_tag :search, :maxlength => 15, :class => ['search', 'string']
466
+ # # => <input name="search" maxlength="15" class="search string">
467
+ #
468
+ # search_field_tag :search, :id => 'search'
469
+ # # => <input name="search" id="search" type="search">
470
+ #
471
+ # search_field_tag :search, :autofocus => true
472
+ # # => <input name="search" autofocus type="search">
473
+ #
474
+ # @api public
475
+ def search_field_tag(name, options={})
476
+ input_tag(:search, options.reverse_merge(:name => name))
477
+ end
478
+
479
+ ##
480
+ # Creates a url field input with the given name and options
481
+ #
482
+ # @macro text_field
483
+ #
484
+ # @example
485
+ # url_field_tag :favorite_website, :placeholder => 'http://padrinorb.com'
486
+ # <input name="favorite_website" placeholder="http://padrinorb.com." type="url">
487
+ #
488
+ # url_field_tag :home_page, :class => 'string url'
489
+ # <input name="home_page" class="string url", type="url">
490
+ #
491
+ # @api public
492
+ def url_field_tag(name, options={})
493
+ input_tag(:url, options.reverse_merge(:name => name))
494
+ end
495
+
496
+ ##
497
+ # Constructs a hidden field input from the given options
498
+ #
499
+ # @macro text_field
500
+ #
501
+ # @example
502
+ # hidden_field_tag :session_key, :value => "__secret__"
503
+ #
504
+ # @api public
505
+ def hidden_field_tag(name, options={})
506
+ options.reverse_merge!(:name => name)
507
+ input_tag(:hidden, options)
508
+ end
509
+
510
+ ##
511
+ # Constructs a text area input from the given options
512
+ #
513
+ # @macro text_field
514
+ #
515
+ # @example
516
+ # text_area_tag :username, :class => 'long', :value => "Demo?"
517
+ #
518
+ # @api public
519
+ def text_area_tag(name, options={})
520
+ options.reverse_merge!(:name => name, :rows => "", :cols => "")
521
+ content_tag(:textarea, options.delete(:value).to_s, options)
522
+ end
523
+
524
+ ##
525
+ # Constructs a password field input from the given options
526
+ #
527
+ # @macro text_field
528
+ #
529
+ # @example
530
+ # password_field_tag :password, :class => 'long'
531
+ #
532
+ # @api public
533
+ def password_field_tag(name, options={})
534
+ options.reverse_merge!(:name => name)
535
+ input_tag(:password, options)
536
+ end
537
+
538
+ ##
539
+ # Constructs a check_box from the given options
540
+ #
541
+ # @macro text_field
542
+ #
543
+ # @example
544
+ # check_box_tag :remember_me, :value => 'Yes'
545
+ #
546
+ # @api public
547
+ def check_box_tag(name, options={})
548
+ options.reverse_merge!(:name => name, :value => '1')
549
+ input_tag(:checkbox, options)
550
+ end
551
+
552
+ ##
553
+ # Constructs a radio_button from the given options
554
+ #
555
+ # @macro text_field
556
+ #
557
+ # @example
558
+ # radio_button_tag :remember_me, :value => 'true'
559
+ #
560
+ # @api public
561
+ def radio_button_tag(name, options={})
562
+ options.reverse_merge!(:name => name)
563
+ input_tag(:radio, options)
564
+ end
565
+
566
+ ##
567
+ # Constructs a file field input from the given options
568
+ #
569
+ # @macro text_field
570
+ #
571
+ # @example
572
+ # file_field_tag :photo, :class => 'long'
573
+ #
574
+ # @api public
575
+ def file_field_tag(name, options={})
576
+ options.reverse_merge!(:name => name)
577
+ input_tag(:file, options)
578
+ end
579
+
580
+ ##
581
+ # Constructs a select from the given options
582
+ #
583
+ # @example
584
+ # options = [['caption', 'value'], ['Green', 'green1'], ['Blue', 'blue1'], ['Black', "black1"]]
585
+ # options = ['option', 'red', 'yellow' ]
586
+ # select_tag(:favorite_color, :options => ['red', 'yellow'], :selected => 'green1')
587
+ # select_tag(:country, :collection => @countries, :fields => [:name, :code], :include_blank => 'None')
588
+ #
589
+ # # Optgroups can be generated using :grouped_options => (Hash or nested Array)
590
+ # grouped_options = [['Friends',['Yoda',['Obiwan',1]]],['Enemies',['Palpatine',['Darth Vader',3]]]]
591
+ # grouped_options = {'Friends' => ['Yoda',['Obiwan',1]],'Enemies' => ['Palpatine',['Darth Vader',3]]}
592
+ # select_tag(:color, :grouped_options => [['warm',['red','yellow']],['cool',['blue', 'purple']]])
593
+ #
594
+ # # Optgroups can be generated using :grouped_options => (Hash or nested Array)
595
+ # grouped_options = [['Friends',['Yoda',['Obiwan',1]]],['Enemies',['Palpatine',['Darth Vader',3]]]]
596
+ # grouped_options = {'Friends' => ['Yoda',['Obiwan',1]],'Enemies' => ['Palpatine',['Darth Vader',3]]}
597
+ # select_tag(:color, :grouped_options => [['warm',['red','yellow']],['cool',['blue', 'purple']]])
598
+ #
599
+ # @param [String] name
600
+ # The name of the input field.
601
+ # @param [Hash] options
602
+ # The html options for the input field.
603
+ # @option options [Array<String, Array>] :options
604
+ # Explicit options to display in the select. Can be strings or string tuples.
605
+ # @option options [Array<Array>] :grouped_options
606
+ # List of options for each group in the select. See examples for details.
607
+ # @option options [Array<Object>] :collection
608
+ # Collection of objects used as options in the select.
609
+ # @option options [Array<Symbol>] :fields
610
+ # The attributes used as "label" and "value" for each +collection+ object.
611
+ # @option options [String] :selected (nil)
612
+ # The option value initially selected.
613
+ # @option options [Boolean] :include_blank (false)
614
+ # Include a blank option in the select.
615
+ # @option options [Boolean] :multiple (false)
616
+ # Allow multiple options to be selected at once.
617
+ #
618
+ # @return [String] The html input field based on the +options+ specified
619
+ #
620
+ # @api public
621
+ def select_tag(name, options={})
622
+ options.reverse_merge!(:name => name)
623
+ collection, fields = options.delete(:collection), options.delete(:fields)
624
+ options[:options] = options_from_collection(collection, fields) if collection
625
+ prompt = options.delete(:include_blank)
626
+ select_options_html = if options[:options]
627
+ options_for_select(options.delete(:options), options.delete(:selected))
628
+ elsif options[:grouped_options]
629
+ grouped_options_for_select(options.delete(:grouped_options), options.delete(:selected), prompt)
630
+ end
631
+ select_options_html = select_options_html.unshift(blank_option(prompt)) if select_options_html.is_a?(Array)
632
+ options.merge!(:name => "#{options[:name]}[]") if options[:multiple]
633
+ content_tag(:select, select_options_html, options)
634
+ end
635
+
636
+ ##
637
+ # Constructs a button input from the given options
638
+ #
639
+ # @param [String] caption
640
+ # The caption for the button.
641
+ # @param [Hash] options
642
+ # The html options for the input field.
643
+ #
644
+ # @return [String] The html button based on the +options+ specified.
645
+ #
646
+ # @example
647
+ # button_tag "Cancel", :class => 'clear'
648
+ #
649
+ # @api public
650
+ def button_tag(caption, options = {})
651
+ options.reverse_merge!(:value => caption)
652
+ input_tag(:button, options)
653
+ end
654
+
655
+ ##
656
+ # Constructs a submit button from the given options
657
+ #
658
+ # @param [String] caption
659
+ # The caption for the submit button.
660
+ # @param [Hash] options
661
+ # The html options for the input field.
662
+ #
663
+ # @return [String] The html submit button based on the +options+ specified.
664
+ #
665
+ # @example
666
+ # submit_tag "Create", :class => 'success'
667
+ #
668
+ # @api public
669
+ def submit_tag(caption="Submit", options={})
670
+ options.reverse_merge!(:value => caption)
671
+ input_tag(:submit, options)
672
+ end
673
+
674
+ # Constructs a submit button from the given options
675
+ #
676
+ # @param [String] source
677
+ # The source image path for the button.
678
+ # @param [Hash] options
679
+ # The html options for the input field.
680
+ #
681
+ # @return [String] The html image button based on the +options+ specified.
682
+ #
683
+ # @example
684
+ # submit_tag "Create", :class => 'success'
685
+ #
686
+ # @api public
687
+ def image_submit_tag(source, options={})
688
+ options.reverse_merge!(:src => image_path(source))
689
+ input_tag(:image, options)
690
+ end
691
+
692
+ protected
693
+
694
+ ##
695
+ # Returns an array of option items for a select field based on the given collection
696
+ # fields is an array containing the fields to display from each item in the collection
697
+ #
698
+ def options_from_collection(collection, fields)
699
+ collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
700
+ end
701
+
702
+ #
703
+ # Returns the options tags for a select based on the given option items
704
+ #
705
+ def options_for_select(option_items, selected_value=nil)
706
+ return [] if option_items.blank?
707
+ option_items.map do |caption, value|
708
+ value ||= caption
709
+ content_tag(:option, caption, :value => value, :selected => option_is_selected?(value, caption, selected_value))
710
+ end
711
+ end
712
+
713
+ #
714
+ # Returns the optgroups with options tags for a select based on the given :grouped_options items
715
+ #
716
+ def grouped_options_for_select(collection, selected=nil, prompt=false)
717
+ if collection.is_a?(Hash)
718
+ collection.map do |key, value|
719
+ content_tag :optgroup, :label => key do
720
+ options_for_select(value, selected)
721
+ end
722
+ end
723
+ elsif collection.is_a?(Array)
724
+ collection.map do |optgroup|
725
+ content_tag :optgroup, :label => optgroup.first do
726
+ options_for_select(optgroup.last, selected)
727
+ end
728
+ end
729
+ end
730
+ end
731
+
732
+ #
733
+ # Returns the blank option serving as a prompt if passed
734
+ #
735
+ def blank_option(prompt)
736
+ return unless prompt
737
+ case prompt
738
+ when String then content_tag(:option, prompt, :value => '')
739
+ when Array then content_tag(:option, prompt.first, :value => prompt.last)
740
+ else content_tag(:option, '', :value => '')
741
+ end
742
+ end
743
+
744
+ private
745
+ ##
746
+ # Returns the FormBuilder class to use based on all available setting sources
747
+ # If explicitly defined, returns that, otherwise returns defaults.
748
+ #
749
+ # @example
750
+ # configured_form_builder_class(nil) => StandardFormBuilder
751
+ #
752
+ # @api private
753
+ def configured_form_builder_class(explicit_builder=nil)
754
+ default_builder = self.respond_to?(:settings) && self.settings.default_builder
755
+ configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
756
+ configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
757
+ configured_builder
758
+ end
759
+
760
+ ##
761
+ # Returns an initialized builder instance for the given object and settings
762
+ #
763
+ # @example
764
+ # builder_instance(@account, :nested => { ... }) => <FormBuilder>
765
+ #
766
+ # @api private
767
+ def builder_instance(object, settings={})
768
+ builder_class = configured_form_builder_class(settings.delete(:builder))
769
+ builder_class.new(self, object, settings)
770
+ end
771
+
772
+ ##
773
+ # Returns whether the option should be selected or not
774
+ #
775
+ # @example
776
+ # option_is_selected?("red", "Red", ["red", "blue"]) => true
777
+ # option_is_selected?("red", "Red", ["green", "blue"]) => false
778
+ #
779
+ # @api private
780
+ def option_is_selected?(value, caption, selected_values)
781
+ Array(selected_values).any? do |selected|
782
+ [value.to_s, caption.to_s].include?(selected.to_s)
783
+ end
784
+ end
785
+ end # FormHelpers
786
+ end # Helpers
787
+ end # Padrino