rango 0.2 → 0.2.1.pre

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 (261) hide show
  1. data/.gitignore +9 -0
  2. data/.gitmodules +3 -0
  3. data/CHANGELOG +5 -0
  4. data/CONTRIBUTORS +1 -0
  5. data/Gemfile +20 -0
  6. data/LICENSE +1 -1
  7. data/README.textile +5 -4
  8. data/benchmarks/ab.rb +6 -0
  9. data/benchmarks/bm/boot.rb +20 -0
  10. data/{spec/rango/version_spec.rb → benchmarks/bm/callbacks.rb} +0 -0
  11. data/benchmarks/bm/request.rb +4 -0
  12. data/benchmarks/bm/routers.rb +22 -0
  13. data/benchmarks/bm/stack.rb +19 -0
  14. data/{spec/stubs/acqs/dir/lib.rb → benchmarks/bm/templates.rb} +0 -0
  15. data/benchmarks/helper.rb +7 -0
  16. data/benchmarks/stubs/merb-app/.gitignore +21 -0
  17. data/benchmarks/stubs/merb-app/Rakefile +35 -0
  18. data/benchmarks/stubs/merb-app/app/controllers/application.rb +4 -0
  19. data/benchmarks/stubs/merb-app/app/controllers/exceptions.rb +15 -0
  20. data/benchmarks/stubs/merb-app/app/helpers/global_helpers.rb +7 -0
  21. data/benchmarks/stubs/merb-app/app/models/user.rb +19 -0
  22. data/benchmarks/stubs/merb-app/app/views/exceptions/not_acceptable.html.erb +63 -0
  23. data/benchmarks/stubs/merb-app/app/views/exceptions/not_found.html.erb +47 -0
  24. data/benchmarks/stubs/merb-app/app/views/layout/application.html.erb +12 -0
  25. data/benchmarks/stubs/merb-app/autotest/discover.rb +4 -0
  26. data/benchmarks/stubs/merb-app/autotest/merb.rb +154 -0
  27. data/benchmarks/stubs/merb-app/autotest/merb_rspec.rb +167 -0
  28. data/benchmarks/stubs/merb-app/config/database.yml +33 -0
  29. data/benchmarks/stubs/merb-app/config/dependencies.rb +36 -0
  30. data/benchmarks/stubs/merb-app/config/environments/development.rb +17 -0
  31. data/benchmarks/stubs/merb-app/config/environments/production.rb +12 -0
  32. data/benchmarks/stubs/merb-app/config/environments/rake.rb +13 -0
  33. data/benchmarks/stubs/merb-app/config/environments/staging.rb +12 -0
  34. data/benchmarks/stubs/merb-app/config/environments/test.rb +14 -0
  35. data/benchmarks/stubs/merb-app/config/init.rb +26 -0
  36. data/benchmarks/stubs/merb-app/config/rack.rb +13 -0
  37. data/benchmarks/stubs/merb-app/config/router.rb +46 -0
  38. data/benchmarks/stubs/merb-app/doc/rdoc/generators/merb_generator.rb +1364 -0
  39. data/benchmarks/stubs/merb-app/doc/rdoc/generators/template/merb/api_grease.js +640 -0
  40. data/benchmarks/stubs/merb-app/doc/rdoc/generators/template/merb/index.html.erb +37 -0
  41. data/benchmarks/stubs/merb-app/doc/rdoc/generators/template/merb/merb.css +252 -0
  42. data/benchmarks/stubs/merb-app/doc/rdoc/generators/template/merb/merb.rb +353 -0
  43. data/benchmarks/stubs/merb-app/doc/rdoc/generators/template/merb/merb_doc_styles.css +492 -0
  44. data/benchmarks/stubs/merb-app/doc/rdoc/generators/template/merb/prototype.js +2515 -0
  45. data/benchmarks/stubs/merb-app/merb/merb-auth/setup.rb +46 -0
  46. data/benchmarks/stubs/merb-app/merb/merb-auth/strategies.rb +13 -0
  47. data/benchmarks/stubs/merb-app/merb/session/session.rb +11 -0
  48. data/benchmarks/stubs/merb-app/public/.htaccess +17 -0
  49. data/benchmarks/stubs/merb-app/public/favicon.ico +0 -0
  50. data/benchmarks/stubs/merb-app/public/images/merb.jpg +0 -0
  51. data/benchmarks/stubs/merb-app/public/javascripts/application.js +1 -0
  52. data/benchmarks/stubs/merb-app/public/javascripts/jquery.js +19 -0
  53. data/benchmarks/stubs/merb-app/public/merb.fcgi +22 -0
  54. data/benchmarks/stubs/merb-app/public/robots.txt +5 -0
  55. data/benchmarks/stubs/merb-app/public/stylesheets/master.css +119 -0
  56. data/{spec/stubs/acqs/dir/lib_spec.rb → benchmarks/stubs/merb-app/spec/spec.opts} +0 -0
  57. data/benchmarks/stubs/merb-app/spec/spec_helper.rb +27 -0
  58. data/benchmarks/stubs/merb-app/tasks/doc.thor +151 -0
  59. data/benchmarks/stubs/merb-app/tasks/merb.thor/app_script.rb +33 -0
  60. data/benchmarks/stubs/merb-app/tasks/merb.thor/common.rb +70 -0
  61. data/benchmarks/stubs/merb-app/tasks/merb.thor/gem_ext.rb +127 -0
  62. data/benchmarks/stubs/merb-app/tasks/merb.thor/main.thor +152 -0
  63. data/benchmarks/stubs/merb-app/tasks/merb.thor/ops.rb +95 -0
  64. data/benchmarks/stubs/merb-app/tasks/merb.thor/utils.rb +42 -0
  65. data/benchmarks/stubs/merb-core/.gitignore +21 -0
  66. data/benchmarks/stubs/merb-core/Rakefile +35 -0
  67. data/benchmarks/stubs/merb-core/app/controllers/application.rb +4 -0
  68. data/benchmarks/stubs/merb-core/app/controllers/exceptions.rb +15 -0
  69. data/benchmarks/stubs/merb-core/app/helpers/global_helpers.rb +7 -0
  70. data/benchmarks/stubs/merb-core/app/views/exceptions/not_acceptable.html.erb +63 -0
  71. data/benchmarks/stubs/merb-core/app/views/exceptions/not_found.html.erb +47 -0
  72. data/benchmarks/stubs/merb-core/app/views/layout/application.html.erb +12 -0
  73. data/benchmarks/stubs/merb-core/autotest/discover.rb +1 -0
  74. data/benchmarks/stubs/merb-core/autotest/merb.rb +151 -0
  75. data/benchmarks/stubs/merb-core/autotest/merb_rspec.rb +167 -0
  76. data/benchmarks/stubs/merb-core/config/environments/development.rb +17 -0
  77. data/benchmarks/stubs/merb-core/config/environments/production.rb +12 -0
  78. data/benchmarks/stubs/merb-core/config/environments/rake.rb +13 -0
  79. data/benchmarks/stubs/merb-core/config/environments/staging.rb +12 -0
  80. data/benchmarks/stubs/merb-core/config/environments/test.rb +14 -0
  81. data/benchmarks/stubs/merb-core/config/init.rb +27 -0
  82. data/benchmarks/stubs/merb-core/config/rack.rb +13 -0
  83. data/benchmarks/stubs/merb-core/config/router.rb +43 -0
  84. data/benchmarks/stubs/merb-core/doc/rdoc/generators/merb_generator.rb +1364 -0
  85. data/benchmarks/stubs/merb-core/doc/rdoc/generators/template/merb/api_grease.js +640 -0
  86. data/benchmarks/stubs/merb-core/doc/rdoc/generators/template/merb/index.html.erb +37 -0
  87. data/benchmarks/stubs/merb-core/doc/rdoc/generators/template/merb/merb.css +252 -0
  88. data/benchmarks/stubs/merb-core/doc/rdoc/generators/template/merb/merb.rb +353 -0
  89. data/benchmarks/stubs/merb-core/doc/rdoc/generators/template/merb/merb_doc_styles.css +492 -0
  90. data/benchmarks/stubs/merb-core/doc/rdoc/generators/template/merb/prototype.js +2515 -0
  91. data/benchmarks/stubs/merb-core/public/.htaccess +17 -0
  92. data/benchmarks/stubs/merb-core/public/favicon.ico +0 -0
  93. data/benchmarks/stubs/merb-core/public/images/merb.jpg +0 -0
  94. data/benchmarks/stubs/merb-core/public/javascripts/application.js +1 -0
  95. data/benchmarks/stubs/merb-core/public/merb.fcgi +22 -0
  96. data/benchmarks/stubs/merb-core/public/robots.txt +5 -0
  97. data/benchmarks/stubs/merb-core/public/stylesheets/master.css +119 -0
  98. data/{spec/stubs/acqs/lib.rb → benchmarks/stubs/merb-core/spec/spec.opts} +0 -0
  99. data/benchmarks/stubs/merb-core/spec/spec_helper.rb +22 -0
  100. data/benchmarks/stubs/merb-core/tasks/merb.thor/app_script.rb +33 -0
  101. data/benchmarks/stubs/merb-core/tasks/merb.thor/common.rb +70 -0
  102. data/benchmarks/stubs/merb-core/tasks/merb.thor/gem_ext.rb +127 -0
  103. data/benchmarks/stubs/merb-core/tasks/merb.thor/main.thor +152 -0
  104. data/benchmarks/stubs/merb-core/tasks/merb.thor/ops.rb +95 -0
  105. data/benchmarks/stubs/merb-core/tasks/merb.thor/utils.rb +42 -0
  106. data/benchmarks/stubs/merb-flat/.gitignore +21 -0
  107. data/benchmarks/stubs/merb-flat/README.txt +10 -0
  108. data/benchmarks/stubs/merb-flat/Rakefile +35 -0
  109. data/benchmarks/stubs/merb-flat/application.rb +17 -0
  110. data/benchmarks/stubs/merb-flat/config/framework.rb +9 -0
  111. data/benchmarks/stubs/merb-flat/config/init.rb +42 -0
  112. data/benchmarks/stubs/merb-flat/spec/spec_helper.rb +26 -0
  113. data/benchmarks/stubs/merb-flat/tasks/merb.thor/app_script.rb +33 -0
  114. data/benchmarks/stubs/merb-flat/tasks/merb.thor/common.rb +70 -0
  115. data/benchmarks/stubs/merb-flat/tasks/merb.thor/gem_ext.rb +127 -0
  116. data/benchmarks/stubs/merb-flat/tasks/merb.thor/main.thor +152 -0
  117. data/benchmarks/stubs/merb-flat/tasks/merb.thor/ops.rb +95 -0
  118. data/benchmarks/stubs/merb-flat/tasks/merb.thor/utils.rb +42 -0
  119. data/benchmarks/stubs/merb-flat/views/foo.html.erb +3 -0
  120. data/benchmarks/stubs/merb-very-flat/.gitignore +21 -0
  121. data/benchmarks/stubs/merb-very-flat/Rakefile +35 -0
  122. data/benchmarks/stubs/merb-very-flat/merb-very-flat.rb +61 -0
  123. data/benchmarks/stubs/merb-very-flat/spec/spec_helper.rb +26 -0
  124. data/benchmarks/stubs/merb-very-flat/tasks/merb.thor/app_script.rb +33 -0
  125. data/benchmarks/stubs/merb-very-flat/tasks/merb.thor/common.rb +70 -0
  126. data/benchmarks/stubs/merb-very-flat/tasks/merb.thor/gem_ext.rb +127 -0
  127. data/benchmarks/stubs/merb-very-flat/tasks/merb.thor/main.thor +152 -0
  128. data/benchmarks/stubs/merb-very-flat/tasks/merb.thor/ops.rb +95 -0
  129. data/benchmarks/stubs/merb-very-flat/tasks/merb.thor/utils.rb +42 -0
  130. data/benchmarks/stubs/rails/README +243 -0
  131. data/benchmarks/stubs/rails/Rakefile +10 -0
  132. data/benchmarks/stubs/rails/app/controllers/application_controller.rb +12 -0
  133. data/benchmarks/stubs/rails/app/helpers/application_helper.rb +5 -0
  134. data/benchmarks/stubs/rails/config/boot.rb +112 -0
  135. data/benchmarks/stubs/rails/config/database.yml +22 -0
  136. data/benchmarks/stubs/rails/config/environment.rb +43 -0
  137. data/benchmarks/stubs/rails/config/environments/development.rb +19 -0
  138. data/benchmarks/stubs/rails/config/environments/production.rb +30 -0
  139. data/benchmarks/stubs/rails/config/environments/test.rb +30 -0
  140. data/benchmarks/stubs/rails/config/initializers/backtrace_silencers.rb +9 -0
  141. data/benchmarks/stubs/rails/config/initializers/inflections.rb +12 -0
  142. data/benchmarks/stubs/rails/config/initializers/mime_types.rb +7 -0
  143. data/benchmarks/stubs/rails/config/initializers/new_rails_defaults.rb +21 -0
  144. data/benchmarks/stubs/rails/config/initializers/session_store.rb +17 -0
  145. data/benchmarks/stubs/rails/config/locales/en.yml +5 -0
  146. data/benchmarks/stubs/rails/config/routes.rb +45 -0
  147. data/benchmarks/stubs/rails/doc/README_FOR_APP +2 -0
  148. data/{spec/stubs/acqs/tasks.thor → benchmarks/stubs/rails/log/development.log} +0 -0
  149. data/{stubs/stack/content/TODO.txt → benchmarks/stubs/rails/log/production.log} +0 -0
  150. data/benchmarks/stubs/rails/log/server.log +0 -0
  151. data/benchmarks/stubs/rails/log/test.log +0 -0
  152. data/benchmarks/stubs/rails/public/404.html +30 -0
  153. data/benchmarks/stubs/rails/public/422.html +30 -0
  154. data/benchmarks/stubs/rails/public/500.html +30 -0
  155. data/benchmarks/stubs/rails/public/favicon.ico +0 -0
  156. data/benchmarks/stubs/rails/public/images/rails.png +0 -0
  157. data/benchmarks/stubs/rails/public/index.html +275 -0
  158. data/benchmarks/stubs/rails/public/javascripts/application.js +2 -0
  159. data/benchmarks/stubs/rails/public/javascripts/controls.js +963 -0
  160. data/benchmarks/stubs/rails/public/javascripts/dragdrop.js +973 -0
  161. data/benchmarks/stubs/rails/public/javascripts/effects.js +1128 -0
  162. data/benchmarks/stubs/rails/public/javascripts/prototype.js +4320 -0
  163. data/benchmarks/stubs/rails/public/robots.txt +5 -0
  164. data/benchmarks/stubs/rails/script/about +4 -0
  165. data/benchmarks/stubs/rails/script/console +3 -0
  166. data/benchmarks/stubs/rails/script/dbconsole +3 -0
  167. data/benchmarks/stubs/rails/script/destroy +3 -0
  168. data/benchmarks/stubs/rails/script/generate +3 -0
  169. data/benchmarks/stubs/rails/script/performance/benchmarker +3 -0
  170. data/benchmarks/stubs/rails/script/performance/profiler +3 -0
  171. data/benchmarks/stubs/rails/script/plugin +3 -0
  172. data/benchmarks/stubs/rails/script/runner +3 -0
  173. data/benchmarks/stubs/rails/script/server +3 -0
  174. data/benchmarks/stubs/rails/test/performance/browsing_test.rb +11 -0
  175. data/benchmarks/stubs/rails/test/test_helper.rb +40 -0
  176. data/benchmarks/stubs/ramaze.rb +0 -0
  177. data/benchmarks/stubs/sinatra.rb +11 -0
  178. data/bin/rango +2 -2
  179. data/deps.rip +7 -0
  180. data/deps.rip.rbe +7 -0
  181. data/gems/cache/abstract-1.0.0.gem +0 -0
  182. data/gems/cache/code-cleaner-0.1.gem +0 -0
  183. data/gems/cache/code-cleaner-0.2.gem +0 -0
  184. data/gems/cache/code-cleaner-0.3.gem +0 -0
  185. data/gems/cache/code-cleaner-0.4.gem +0 -0
  186. data/gems/cache/code-cleaner-0.5.gem +0 -0
  187. data/gems/cache/code-cleaner-0.6.gem +0 -0
  188. data/gems/cache/code-cleaner-0.7.gem +0 -0
  189. data/gems/cache/code-cleaner-0.8.1.gem +0 -0
  190. data/gems/cache/code-cleaner-0.8.gem +0 -0
  191. data/gems/cache/erubis-2.6.5.gem +0 -0
  192. data/gems/cache/extlib-0.9.14.gem +0 -0
  193. data/gems/cache/haml-2.2.16.gem +0 -0
  194. data/gems/cache/haml-2.2.17.gem +0 -0
  195. data/gems/cache/nake-0.0.2.gem +0 -0
  196. data/gems/cache/nake-0.0.3.gem +0 -0
  197. data/gems/cache/nake-0.0.5.gem +0 -0
  198. data/gems/cache/nake-0.0.6.gem +0 -0
  199. data/gems/cache/nake-0.0.8.gem +0 -0
  200. data/gems/cache/rack-1.0.1.gem +0 -0
  201. data/gems/cache/rack-1.1.0.gem +0 -0
  202. data/gems/cache/rspec-1.2.9.gem +0 -0
  203. data/gems/cache/rspec-1.3.0.gem +0 -0
  204. data/gems/cache/term-ansicolor-1.0.4.gem +0 -0
  205. data/gems/cache/tilt-0.4.gem +0 -0
  206. data/gems/cache/tilt-0.5.gem +0 -0
  207. data/lib/rango.rb +28 -28
  208. data/lib/rango/cli.rb +34 -0
  209. data/lib/rango/contrib/pagination/adapters/datamapper.rb +21 -17
  210. data/lib/rango/controller.rb +36 -4
  211. data/lib/rango/environments.rb +1 -15
  212. data/lib/rango/exceptions.rb +144 -86
  213. data/lib/rango/helpers.rb +10 -2
  214. data/lib/rango/mailer.rb +48 -0
  215. data/lib/rango/mixins/action_args.rb +5 -7
  216. data/lib/rango/mixins/filters.rb +18 -14
  217. data/lib/rango/mixins/message.rb +30 -24
  218. data/lib/rango/mixins/rendering.rb +54 -0
  219. data/lib/rango/orm/tasks/datamapper.nake +81 -0
  220. data/lib/rango/orm/tasks/sequel.nake +43 -0
  221. data/lib/rango/router/adapters/usher.rb +2 -1
  222. data/lib/rango/stacks/controller.rb +12 -0
  223. data/lib/rango/tasks/spec.nake +9 -0
  224. data/lib/rango/templates/exts/haml.rb +1 -1
  225. data/lib/rango/templates/exts/tilt.rb +10 -0
  226. data/lib/rango/templates/helpers.rb +29 -25
  227. data/lib/rango/templates/template.rb +7 -6
  228. data/rango.gemspec +52 -0
  229. data/rango.pre.gemspec +8 -0
  230. data/spec/rango/environments_spec.rb +1 -1
  231. data/spec/rango/exceptions_spec.rb +8 -7
  232. data/spec/rango/mixins/render_spec.rb +1 -1
  233. data/spec/rango/templates/template_spec.rb +1 -1
  234. data/stubs/stack/content/%name%.gemspec.rbt +52 -0
  235. data/stubs/stack/content/%name%.pre.gemspec.rbt +8 -0
  236. data/stubs/stack/content/CHANGELOG +0 -0
  237. data/stubs/stack/content/Gemfile.rbt +22 -11
  238. data/stubs/stack/content/README.textile.rbt +7 -0
  239. data/stubs/stack/content/config.ru.rbt +33 -62
  240. data/stubs/stack/content/deps.rip +0 -0
  241. data/stubs/stack/content/init.rb.rbt +14 -39
  242. data/stubs/stack/content/lib/%name%.rb.rbt +8 -0
  243. data/stubs/stack/content/lib/%name%/config.rb.rbt +0 -0
  244. data/stubs/stack/content/{environments.rb.rbt → lib/%name%/environments/development.rb.rbt} +5 -0
  245. data/stubs/stack/content/lib/%name%/environments/production.rb.rbt +0 -0
  246. data/stubs/stack/content/lib/%name%/environments/stagging.rb.rbt +0 -0
  247. data/stubs/stack/content/lib/%name%/initializers/middlewares.rb.rbt +5 -0
  248. data/stubs/stack/content/lib/%name%/initializers/urls.rb.rbt +24 -0
  249. data/stubs/stack/content/{models.rb.rbt → lib/%name%/models.rb.rbt} +7 -0
  250. data/stubs/stack/content/{views.rb.rbt → lib/%name%/views.rb.rbt} +2 -8
  251. data/stubs/stack/content/rackup.rb.rbt +41 -0
  252. data/stubs/stack/content/tasks.rb.rbt +52 -0
  253. data/stubs/stack/setup.rb +7 -1
  254. data/support/hooks/pre-commit +12 -0
  255. data/tasks.rb +49 -0
  256. metadata +250 -54
  257. data/Rakefile +0 -33
  258. data/lib/rango/rack/middlewares/email_obfuscator.rb +0 -25
  259. data/lib/rango/version.rb +0 -7
  260. data/stubs/stack/content/.rvmrc.rbt +0 -2
  261. data/stubs/stack/content/Rakefile.rbt +0 -12
@@ -0,0 +1,167 @@
1
+ # encoding: utf-8
2
+
3
+ # Adapted from Autotest::Rails, RSpec's autotest class, as well as merb-core's.
4
+ require 'autotest'
5
+
6
+ class RspecCommandError < StandardError; end
7
+
8
+ # This class maps your application's structure so Autotest can understand what
9
+ # specs to run when files change.
10
+ #
11
+ # Fixtures are _not_ covered by this class. If you change a fixture file, you
12
+ # will have to run your spec suite manually, or, better yet, provide your own
13
+ # Autotest map explaining how your fixtures are set up.
14
+ class Autotest::MerbRspec < Autotest
15
+ def initialize
16
+ super
17
+
18
+ # Ignore any happenings in these directories
19
+ add_exception %r%^\./(?:doc|log|public|tmp|\.git|\.hg|\.svn|framework|gems|schema|\.DS_Store|autotest|bin|.*\.sqlite3|.*\.thor)%
20
+ # Ignore SCM directories and custom Autotest mappings
21
+ %w[.svn .hg .git .autotest].each { |exception| add_exception(exception) }
22
+
23
+ # Ignore any mappings that Autotest may have already set up
24
+ clear_mappings
25
+
26
+ # Anything in /lib could have a spec anywhere, if at all. So, look for
27
+ # files with roughly the same name as the file in /lib
28
+ add_mapping %r%^lib\/(.*)\.rb% do |_, m|
29
+ files_matching %r%^spec\/#{m[1]}%
30
+ end
31
+
32
+ add_mapping %r%^spec/(spec_helper|shared/.*)\.rb$% do
33
+ all_specs
34
+ end
35
+
36
+ # Changing a spec will cause it to run itself
37
+ add_mapping %r%^spec/.*\.rb$% do |filename, _|
38
+ filename
39
+ end
40
+
41
+ # Any change to a model will cause it's corresponding test to be run
42
+ add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
43
+ spec_for(m[1], 'model')
44
+ end
45
+
46
+ # Any change to global_helpers will result in all view and controller
47
+ # tests being run
48
+ add_mapping %r%^app/helpers/global_helpers\.rb% do
49
+ files_matching %r%^spec/(views|controllers|helpers|requests)/.*_spec\.rb$%
50
+ end
51
+
52
+ # Any change to a helper will cause its spec to be run
53
+ add_mapping %r%^app/helpers/((.*)_helper(s)?)\.rb% do |_, m|
54
+ spec_for(m[1], 'helper')
55
+ end
56
+
57
+ # Changes to a view cause its spec to be run
58
+ add_mapping %r%^app/views/(.*)/% do |_, m|
59
+ spec_for(m[1], 'view')
60
+ end
61
+
62
+ # Changes to a controller result in its corresponding spec being run. If
63
+ # the controller is the exception or application controller, all
64
+ # controller specs are run.
65
+ add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
66
+ if ["application", "exception"].include?(m[1])
67
+ files_matching %r%^spec/controllers/.*_spec\.rb$%
68
+ else
69
+ spec_for(m[1], 'controller')
70
+ end
71
+ end
72
+
73
+ # If a change is made to the router, run controller, view and helper specs
74
+ add_mapping %r%^config/router.rb$% do
75
+ files_matching %r%^spec/(controllers|views|helpers)/.*_spec\.rb$%
76
+ end
77
+
78
+ # If any of the major files governing the environment are altered, run
79
+ # everything
80
+ add_mapping %r%^config/(init|rack|environments/test).*\.rb|database\.yml% do
81
+ all_specs
82
+ end
83
+ end
84
+
85
+ def failed_results(results)
86
+ results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m)
87
+ end
88
+
89
+ def handle_results(results)
90
+ @failures = failed_results(results)
91
+ @files_to_test = consolidate_failures(@failures)
92
+ @files_to_test.empty? && !$TESTING ? hook(:green) : hook(:red)
93
+ @tainted = !@files_to_test.empty?
94
+ end
95
+
96
+ def consolidate_failures(failed)
97
+ filters = Hash.new { |h,k| h[k] = [] }
98
+ failed.each do |spec, failed_trace|
99
+ if f = test_files_for(failed).find { |f| f =~ /spec\// }
100
+ filters[f] << spec
101
+ break
102
+ end
103
+ end
104
+ filters
105
+ end
106
+
107
+ def make_test_cmd(specs_to_runs)
108
+ [
109
+ ruby,
110
+ "-S",
111
+ spec_command,
112
+ add_options_if_present,
113
+ files_to_test.keys.flatten.join(' ')
114
+ ].join(' ')
115
+ end
116
+
117
+ def add_options_if_present
118
+ File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : ""
119
+ end
120
+
121
+ # Finds the proper spec command to use. Precendence is set in the
122
+ # lazily-evaluated method spec_commands. Alias + Override that in
123
+ # ~/.autotest to provide a different spec command then the default
124
+ # paths provided.
125
+ def spec_command(separator=File::ALT_SEPARATOR)
126
+ unless defined?(@spec_command)
127
+ @spec_command = spec_commands.find { |cmd| File.exists?(cmd) }
128
+
129
+ raise RspecCommandError, "No spec command could be found" unless @spec_command
130
+
131
+ @spec_command.gsub!(File::SEPARATOR, separator) if separator
132
+ end
133
+ @spec_command
134
+ end
135
+
136
+ # Autotest will look for spec commands in the following
137
+ # locations, in this order:
138
+ #
139
+ # * default spec bin/loader installed in Rubygems
140
+ # * any spec command found in PATH
141
+ def spec_commands
142
+ [File.join(Config::CONFIG['bindir'], 'spec'), 'spec']
143
+ end
144
+
145
+ private
146
+
147
+ # Runs +files_matching+ for all specs
148
+ def all_specs
149
+ files_matching %r%^spec/.*_spec\.rb$%
150
+ end
151
+
152
+ # Generates a path to some spec given its kind and the match from a mapping
153
+ #
154
+ # ==== Arguments
155
+ # match<String>:: the match from a mapping
156
+ # kind<String>:: the kind of spec that the match represents
157
+ #
158
+ # ==== Returns
159
+ # String
160
+ #
161
+ # ==== Example
162
+ # > spec_for('post', :view')
163
+ # => "spec/views/post_spec.rb"
164
+ def spec_for(match, kind)
165
+ File.join("spec", kind + 's', "#{match}_spec.rb")
166
+ end
167
+ end
@@ -0,0 +1,33 @@
1
+ ---
2
+ # This is a sample database file for the DataMapper ORM
3
+ development: &defaults
4
+ # These are the settings for repository :default
5
+ adapter: sqlite3
6
+ database: sample_development.db
7
+
8
+ # Add more repositories
9
+ # repositories:
10
+ # repo1:
11
+ # adapter: sqlite3
12
+ # database: sample_1_development.db
13
+ # repo2:
14
+ # ...
15
+
16
+ test:
17
+ <<: *defaults
18
+ database: sample_test.db
19
+
20
+ # repositories:
21
+ # repo1:
22
+ # database: sample_1_test.db
23
+
24
+ production:
25
+ <<: *defaults
26
+ database: production.db
27
+
28
+ # repositories:
29
+ # repo1:
30
+ # database: sample_production.db
31
+
32
+ rake:
33
+ <<: *defaults
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ # dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading.
4
+ merb_gems_version = "1.0.11"
5
+ dm_gems_version = "0.9.11"
6
+ do_gems_version = "0.9.11"
7
+
8
+ # For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components
9
+ dependency "merb-core", merb_gems_version
10
+ dependency "merb-action-args", merb_gems_version
11
+ dependency "merb-assets", merb_gems_version
12
+ dependency("merb-cache", merb_gems_version) do
13
+ Merb::Cache.setup do
14
+ register(Merb::Cache::FileStore) unless Merb.cache
15
+ end
16
+ end
17
+ dependency "merb-helpers", merb_gems_version
18
+ dependency "merb-mailer", merb_gems_version
19
+ dependency "merb-slices", merb_gems_version
20
+ dependency "merb-auth-core", merb_gems_version
21
+ dependency "merb-auth-more", merb_gems_version
22
+ dependency "merb-auth-slice-password", merb_gems_version
23
+ dependency "merb-param-protection", merb_gems_version
24
+ dependency "merb-exceptions", merb_gems_version
25
+
26
+ dependency "data_objects", do_gems_version
27
+ dependency "do_sqlite3", do_gems_version # If using another database, replace this
28
+ dependency "dm-core", dm_gems_version
29
+ dependency "dm-aggregates", dm_gems_version
30
+ dependency "dm-migrations", dm_gems_version
31
+ dependency "dm-timestamps", dm_gems_version
32
+ dependency "dm-types", dm_gems_version
33
+ dependency "dm-validations", dm_gems_version
34
+ dependency "dm-serializer", dm_gems_version
35
+
36
+ dependency "merb_datamapper", merb_gems_version
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ Merb.logger.info("Loaded DEVELOPMENT Environment...")
4
+ Merb::Config.use { |c|
5
+ c[:exception_details] = true
6
+ c[:reload_templates] = true
7
+ c[:reload_classes] = true
8
+ c[:reload_time] = 0.5
9
+ c[:ignore_tampered_cookies] = true
10
+ c[:log_auto_flush ] = true
11
+ c[:log_level] = :debug
12
+
13
+ c[:log_stream] = STDOUT
14
+ c[:log_file] = nil
15
+ # Or redirect logging into a file:
16
+ # c[:log_file] = Merb.root / "log" / "development.log"
17
+ }
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ Merb.logger.info("Loaded PRODUCTION Environment...")
4
+ Merb::Config.use { |c|
5
+ c[:exception_details] = false
6
+ c[:reload_classes] = false
7
+ c[:log_level] = :error
8
+
9
+ c[:log_file] = Merb.root / "log" / "production.log"
10
+ # or redirect logger using IO handle
11
+ # c[:log_stream] = STDOUT
12
+ }
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ Merb.logger.info("Loaded RAKE Environment...")
4
+ Merb::Config.use { |c|
5
+ c[:exception_details] = true
6
+ c[:reload_classes] = false
7
+ c[:log_auto_flush ] = true
8
+
9
+ c[:log_stream] = STDOUT
10
+ c[:log_file] = nil
11
+ # Or redirect logging into a file:
12
+ # c[:log_file] = Merb.root / "log" / "development.log"
13
+ }
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ Merb.logger.info("Loaded STAGING Environment...")
4
+ Merb::Config.use { |c|
5
+ c[:exception_details] = false
6
+ c[:reload_classes] = false
7
+ c[:log_level] = :error
8
+
9
+ c[:log_file] = Merb.root / "log" / "staging.log"
10
+ # or redirect logger using IO handle
11
+ # c[:log_stream] = STDOUT
12
+ }
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ Merb.logger.info("Loaded TEST Environment...")
4
+ Merb::Config.use { |c|
5
+ c[:testing] = true
6
+ c[:exception_details] = true
7
+ c[:log_auto_flush ] = true
8
+ # log less in testing environment
9
+ c[:log_level] = :error
10
+
11
+ #c[:log_file] = Merb.root / "log" / "test.log"
12
+ # or redirect logger using IO handle
13
+ c[:log_stream] = STDOUT
14
+ }
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ # Go to http://wiki.merbivore.com/pages/init-rb
4
+
5
+ require 'config/dependencies.rb'
6
+
7
+ use_orm :datamapper
8
+ use_test :rspec
9
+ use_template_engine :erb
10
+
11
+ Merb::Config.use do |c|
12
+ c[:use_mutex] = false
13
+ c[:session_store] = 'cookie' # can also be 'memory', 'memcache', 'container', 'datamapper
14
+
15
+ # cookie session store configuration
16
+ c[:session_secret_key] = '5db48ea087b5190770eb75a0421769897ffe2be7' # required for cookie session store
17
+ c[:session_id_key] = '_merb-app_session_id' # cookie session id key, defaults to "_session_id"
18
+ end
19
+
20
+ Merb::BootLoader.before_app_loads do
21
+ # This will get executed after dependencies have been loaded but before your app's classes have loaded.
22
+ end
23
+
24
+ Merb::BootLoader.after_app_loads do
25
+ # This will get executed after your app's classes have been loaded.
26
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ # use PathPrefix Middleware if :path_prefix is set in Merb::Config
4
+ if prefix = ::Merb::Config[:path_prefix]
5
+ use Merb::Rack::PathPrefix, prefix
6
+ end
7
+
8
+ # comment this out if you are running merb behind a load balancer
9
+ # that serves static files
10
+ use Merb::Rack::Static, Merb.dir_for(:public)
11
+
12
+ # this is our main merb application
13
+ run Merb::Rack::Application.new
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ # Merb::Router is the request routing mapper for the merb framework.
4
+ #
5
+ # You can route a specific URL to a controller / action pair:
6
+ #
7
+ # match("/contact").
8
+ # to(:controller => "info", :action => "contact")
9
+ #
10
+ # You can define placeholder parts of the url with the :symbol notation. These
11
+ # placeholders will be available in the params hash of your controllers. For example:
12
+ #
13
+ # match("/books/:book_id/:action").
14
+ # to(:controller => "books")
15
+ #
16
+ # Or, use placeholders in the "to" results for more complicated routing, e.g.:
17
+ #
18
+ # match("/admin/:module/:controller/:action/:id").
19
+ # to(:controller => ":module/:controller")
20
+ #
21
+ # You can specify conditions on the placeholder by passing a hash as the second
22
+ # argument of "match"
23
+ #
24
+ # match("/registration/:course_name", :course_name => /^[a-z]{3,5}-\d{5}$/).
25
+ # to(:controller => "registration")
26
+ #
27
+ # You can also use regular expressions, deferred routes, and many other options.
28
+ # See merb/specs/merb/router.rb for a fairly complete usage sample.
29
+
30
+ Merb.logger.info("Compiling routes...")
31
+ Merb::Router.prepare do
32
+ # RESTful routes
33
+ # resources :posts
34
+
35
+ # Adds the required routes for merb-auth using the password slice
36
+ slice(:merb_auth_slice_password, :name_prefix => nil, :path_prefix => "")
37
+
38
+ # This is the default route for /:controller/:action/:id
39
+ # This is fine for most cases. If you're heavily using resource-based
40
+ # routes, you may want to comment/remove this line to prevent
41
+ # clients from calling your create or destroy actions with a GET
42
+ default_routes
43
+
44
+ # Change this for your home page to be available at /
45
+ # match('/').to(:controller => 'whatever', :action =>'index')
46
+ end
@@ -0,0 +1,1364 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ # # We're responsible for generating all the HTML files
5
+ # from the object tree defined in code_objects.rb. We
6
+ # generate:
7
+ #
8
+ # [files] an html file for each input file given. These
9
+ # input files appear as objects of class
10
+ # TopLevel
11
+ #
12
+ # [classes] an html file for each class or module encountered.
13
+ # These classes are not grouped by file: if a file
14
+ # contains four classes, we'll generate an html
15
+ # file for the file itself, and four html files
16
+ # for the individual classes.
17
+ #
18
+ # Method descriptions appear in whatever entity (file, class,
19
+ # or module) that contains them.
20
+ #
21
+ # We generate files in a structure below a specified subdirectory,
22
+ # normally +doc+.
23
+ #
24
+ # opdir
25
+ # |
26
+ # |___ files
27
+ # | |__ per file summaries
28
+ # |
29
+ # |___ classes
30
+ # |__ per class/module descriptions
31
+ #
32
+ # HTML is generated using the Template class.
33
+ #
34
+
35
+ require 'ftools'
36
+
37
+ require 'rdoc/options'
38
+ require 'rdoc/template'
39
+ require 'rdoc/markup/simple_markup'
40
+ require 'rdoc/markup/simple_markup/to_html'
41
+ require 'cgi'
42
+
43
+ module Generators
44
+
45
+ # Name of sub-direcories that hold file and class/module descriptions
46
+
47
+ FILE_DIR = "files"
48
+ CLASS_DIR = "classes"
49
+ CSS_NAME = "stylesheet.css"
50
+
51
+
52
+ ##
53
+ # Build a hash of all items that can be cross-referenced.
54
+ # This is used when we output required and included names:
55
+ # if the names appear in this hash, we can generate
56
+ # an html cross reference to the appropriate description.
57
+ # We also use this when parsing comment blocks: any decorated
58
+ # words matching an entry in this list are hyperlinked.
59
+
60
+ class AllReferences
61
+ @@refs = {}
62
+
63
+ def AllReferences::reset
64
+ @@refs = {}
65
+ end
66
+
67
+ def AllReferences.add(name, html_class)
68
+ @@refs[name] = html_class
69
+ end
70
+
71
+ def AllReferences.[](name)
72
+ @@refs[name]
73
+ end
74
+
75
+ def AllReferences.keys
76
+ @@refs.keys
77
+ end
78
+ end
79
+
80
+
81
+ ##
82
+ # Subclass of the SM::ToHtml class that supports looking
83
+ # up words in the AllReferences list. Those that are
84
+ # found (like AllReferences in this comment) will
85
+ # be hyperlinked
86
+
87
+ class HyperlinkHtml < SM::ToHtml
88
+ # We need to record the html path of our caller so we can generate
89
+ # correct relative paths for any hyperlinks that we find
90
+ def initialize(from_path, context)
91
+ super()
92
+ @from_path = from_path
93
+
94
+ @parent_name = context.parent_name
95
+ @parent_name += "::" if @parent_name
96
+ @context = context
97
+ end
98
+
99
+ # We're invoked when any text matches the CROSSREF pattern
100
+ # (defined in MarkUp). If we fine the corresponding reference,
101
+ # generate a hyperlink. If the name we're looking for contains
102
+ # no punctuation, we look for it up the module/class chain. For
103
+ # example, HyperlinkHtml is found, even without the Generators::
104
+ # prefix, because we look for it in module Generators first.
105
+
106
+ def handle_special_CROSSREF(special)
107
+ name = special.text
108
+ if name[0,1] == '#'
109
+ lookup = name[1..-1]
110
+ name = lookup unless Options.instance.show_hash
111
+ else
112
+ lookup = name
113
+ end
114
+
115
+ if /([A-Z].*)[.\#](.*)/ =~ lookup
116
+ container = $1
117
+ method = $2
118
+ ref = @context.find_symbol(container, method)
119
+ else
120
+ ref = @context.find_symbol(lookup)
121
+ end
122
+
123
+ if ref and ref.document_self
124
+ "<a href=\"index.html?a=#{ref.aref}&name=#{name}\">#{name}</a>"
125
+ else
126
+ name #it does not need to be a link
127
+ end
128
+ end
129
+
130
+
131
+ # Generate a hyperlink for url, labeled with text. Handle the
132
+ # special cases for img: and link: described under handle_special_HYPEDLINK
133
+ def gen_url(url, text)
134
+ if url =~ /([A-Za-z]+):(.*)/
135
+ type = $1
136
+ path = $2
137
+ else
138
+ type = "http"
139
+ path = url
140
+ url = "http://#{url}"
141
+ end
142
+
143
+ if type == "link"
144
+ url = path
145
+ end
146
+
147
+ if (type == "http" || type == "link") && url =~ /\.(gif|png|jpg|jpeg|bmp)$/
148
+ "<img src=\"#{url}\">"
149
+ elsif (type == "http" || type == "link")
150
+ "<a href=\"#{url}\" target=\"_blank\">#{text}</a>"
151
+ else
152
+ "<a href=\"#\" onclick=\"jsHref('#{url}');\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
153
+
154
+ end
155
+ end
156
+
157
+ # And we're invoked with a potential external hyperlink mailto:
158
+ # just gets inserted. http: links are checked to see if they
159
+ # reference an image. If so, that image gets inserted using an
160
+ # <img> tag. Otherwise a conventional <a href> is used. We also
161
+ # support a special type of hyperlink, link:, which is a reference
162
+ # to a local file whose path is relative to the --op directory.
163
+
164
+ def handle_special_HYPERLINK(special)
165
+ url = special.text
166
+ gen_url(url, url)
167
+ end
168
+
169
+ # HEre's a hypedlink where the label is different to the URL
170
+ # <label>[url]
171
+ #
172
+
173
+ def handle_special_TIDYLINK(special)
174
+ text = special.text
175
+ # unless text =~ /(\S+)\[(.*?)\]/
176
+ unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
177
+ return text
178
+ end
179
+ label = $1
180
+ url = $2
181
+ gen_url(url, label)
182
+ end
183
+
184
+ end
185
+
186
+
187
+
188
+ #####################################################################
189
+ #
190
+ # Handle common markup tasks for the various Html classes
191
+ #
192
+
193
+ module MarkUp
194
+
195
+ # Convert a string in markup format into HTML. We keep a cached
196
+ # SimpleMarkup object lying around after the first time we're
197
+ # called per object.
198
+
199
+ def markup(str, remove_para=false)
200
+ return '' unless str
201
+ unless defined? @markup
202
+ @markup = SM::SimpleMarkup.new
203
+
204
+ # class names, variable names, file names, or instance variables
205
+ @markup.add_special(/(
206
+ \b([A-Z]\w*(::\w+)*[.\#]\w+) # A::B.meth
207
+ | \b([A-Z]\w+(::\w+)*) # A::B..
208
+ | \#\w+[!?=]? # #meth_name
209
+ | \b\w+([_\/\.]+\w+)+[!?=]? # meth_name
210
+ )/x, :CROSSREF)
211
+
212
+ # external hyperlinks
213
+ @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
214
+
215
+ # and links of the form <text>[<url>]
216
+ @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
217
+ # @markup.add_special(/\b(\S+?\[\S+?\.\S+?\])/, :TIDYLINK)
218
+
219
+ end
220
+ unless defined? @html_formatter
221
+ @html_formatter = HyperlinkHtml.new(self.path, self)
222
+ end
223
+
224
+ # Convert leading comment markers to spaces, but only
225
+ # if all non-blank lines have them
226
+
227
+ if str =~ /^(?>\s*)[^\#]/
228
+ content = str
229
+ else
230
+ content = str.gsub(/^\s*(#+)/) { $1.tr('#',' ') }
231
+ end
232
+
233
+ res = @markup.convert(content, @html_formatter)
234
+ if remove_para
235
+ res.sub!(/^<p>/, '')
236
+ res.sub!(/<\/p>$/, '')
237
+ end
238
+ res
239
+ end
240
+
241
+
242
+ def style_url(path, css_name=nil)
243
+ css_name ||= CSS_NAME
244
+ end
245
+
246
+ # Build a webcvs URL with the given 'url' argument. URLs with a '%s' in them
247
+ # get the file's path sprintfed into them; otherwise they're just catenated
248
+ # together.
249
+
250
+ def cvs_url(url, full_path)
251
+ if /%s/ =~ url
252
+ return sprintf( url, full_path )
253
+ else
254
+ return url + full_path
255
+ end
256
+ end
257
+ end
258
+
259
+
260
+ #####################################################################
261
+ #
262
+ # A Context is built by the parser to represent a container: contexts
263
+ # hold classes, modules, methods, require lists and include lists.
264
+ # ClassModule and TopLevel are the context objects we process here
265
+ #
266
+ class ContextUser
267
+
268
+ include MarkUp
269
+
270
+ attr_reader :context
271
+
272
+ def initialize(context, options)
273
+ @context = context
274
+ @options = options
275
+
276
+ end
277
+
278
+ # convenience method to build a hyperlink # Where's the DRY in this?? Put this in the template where it belongs
279
+ def href(link, cls, name)
280
+ %{"<a href=\"#\" onclick=\"jsHref('#{link}');\" class=\"#{cls}\">#{name}</a>"}
281
+ end
282
+
283
+ # Create a list of HtmlMethod objects for each method
284
+ # in the corresponding context object. If the @options.show_all
285
+ # variable is set (corresponding to the <tt>--all</tt> option,
286
+ # we include all methods, otherwise just the public ones.
287
+
288
+ def collect_methods
289
+ list = @context.method_list
290
+ unless @options.show_all
291
+ list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation }
292
+ end
293
+ @methods = list.collect {|m| HtmlMethod.new(m, self, @options) }
294
+ end
295
+
296
+ # Build a summary list of all the methods in this context
297
+ def build_method_summary_list(path_prefix="")
298
+ collect_methods unless @methods
299
+ meths = @methods.sort
300
+ res = []
301
+ meths.each do |meth|
302
+ res << {
303
+ "name" => CGI.escapeHTML(meth.name),
304
+ "aref" => meth.aref,
305
+ "href" => meth.path
306
+ }
307
+ end
308
+ res
309
+ end
310
+
311
+
312
+ # Build a list of aliases for which we couldn't find a
313
+ # corresponding method
314
+ def build_alias_summary_list(section)
315
+ values = []
316
+ @context.aliases.each do |al|
317
+ next unless al.section == section
318
+ res = {
319
+ 'old_name' => al.old_name,
320
+ 'new_name' => al.new_name,
321
+ }
322
+ if al.comment && !al.comment.empty?
323
+ res['desc'] = markup(al.comment, true)
324
+ end
325
+ values << res
326
+ end
327
+ values
328
+ end
329
+
330
+ # Build a list of constants
331
+ def build_constants_summary_list(section)
332
+ values = []
333
+ @context.constants.each do |co|
334
+ next unless co.section == section
335
+ res = {
336
+ 'name' => co.name,
337
+ 'value' => CGI.escapeHTML(co.value)
338
+ }
339
+ res['desc'] = markup(co.comment, true) if co.comment && !co.comment.empty?
340
+ values << res
341
+ end
342
+ values
343
+ end
344
+
345
+ def build_requires_list(context)
346
+ potentially_referenced_list(context.requires) {|fn| [fn + ".rb"] }
347
+ end
348
+
349
+ def build_include_list(context)
350
+ potentially_referenced_list(context.includes)
351
+ end
352
+
353
+ # Build a list from an array of <i>Htmlxxx</i> items. Look up each
354
+ # in the AllReferences hash: if we find a corresponding entry,
355
+ # we generate a hyperlink to it, otherwise just output the name.
356
+ # However, some names potentially need massaging. For example,
357
+ # you may require a Ruby file without the .rb extension,
358
+ # but the file names we know about may have it. To deal with
359
+ # this, we pass in a block which performs the massaging,
360
+ # returning an array of alternative names to match
361
+
362
+ def potentially_referenced_list(array)
363
+ res = []
364
+ array.each do |i|
365
+ ref = AllReferences[i.name]
366
+ # if !ref
367
+ # container = @context.parent
368
+ # while !ref && container
369
+ # name = container.name + "::" + i.name
370
+ # ref = AllReferences[name]
371
+ # container = container.parent
372
+ # end
373
+ # end
374
+
375
+ ref = @context.find_symbol(i.name)
376
+ ref = ref.viewer if ref
377
+
378
+ if !ref && block_given?
379
+ possibles = yield(i.name)
380
+ while !ref and !possibles.empty?
381
+ ref = AllReferences[possibles.shift]
382
+ end
383
+ end
384
+ h_name = CGI.escapeHTML(i.name)
385
+ if ref and ref.document_self
386
+ path = ref.path
387
+ res << { "name" => h_name, "href" => path }
388
+ else
389
+ res << { "name" => h_name, "href" => "" }
390
+ end
391
+ end
392
+ res
393
+ end
394
+
395
+ # Build an array of arrays of method details. The outer array has up
396
+ # to six entries, public, private, and protected for both class
397
+ # methods, the other for instance methods. The inner arrays contain
398
+ # a hash for each method
399
+
400
+ def build_method_detail_list(section)
401
+ outer = []
402
+
403
+ methods = @methods.sort
404
+ for singleton in [true, false]
405
+ for vis in [ :public, :protected, :private ]
406
+ res = []
407
+ methods.each do |m|
408
+ if m.section == section and
409
+ m.document_self and
410
+ m.visibility == vis and
411
+ m.singleton == singleton
412
+ row = {}
413
+ if m.call_seq
414
+ row["callseq"] = m.call_seq.gsub(/->/, '&rarr;')
415
+ else
416
+ row["name"] = CGI.escapeHTML(m.name)
417
+ row["params"] = m.params
418
+ end
419
+ desc = m.description.strip
420
+ row["m_desc"] = desc unless desc.empty?
421
+ row["aref"] = m.aref
422
+ row["href"] = m.path
423
+ row["m_seq"] = m.seq
424
+ row["visibility"] = m.visibility.to_s
425
+
426
+ alias_names = []
427
+ m.aliases.each do |other|
428
+ if other.viewer # won't be if the alias is private
429
+ alias_names << {
430
+ 'name' => other.name,
431
+ 'href' => other.viewer.path,
432
+ 'aref' => other.viewer.aref
433
+ }
434
+ end
435
+ end
436
+ unless alias_names.empty?
437
+ row["aka"] = alias_names
438
+ end
439
+
440
+ #if @options.inline_source
441
+ code = m.source_code
442
+ row["sourcecode"] = code if code
443
+ #else
444
+ # code = m.src_url
445
+ #if code
446
+ # row["codeurl"] = code
447
+ # row["imgurl"] = m.img_url
448
+ #end
449
+ #end
450
+ res << row
451
+ end
452
+ end
453
+ if res.size > 0
454
+ outer << {
455
+ "type" => vis.to_s.capitalize,
456
+ "category" => singleton ? "Class" : "Instance",
457
+ "methods" => res
458
+ }
459
+ end
460
+ end
461
+ end
462
+ outer
463
+ end
464
+
465
+ # Build the structured list of classes and modules contained
466
+ # in this context.
467
+
468
+ def build_class_list(level, from, section, infile=nil)
469
+ res = ""
470
+ prefix = "&nbsp;&nbsp;::" * level;
471
+
472
+ from.modules.sort.each do |mod|
473
+ next unless mod.section == section
474
+ next if infile && !mod.defined_in?(infile)
475
+ if mod.document_self
476
+ res <<
477
+ prefix <<
478
+ "Module " <<
479
+ href(mod.viewer.path, "link", mod.full_name) <<
480
+ "<br />\n" <<
481
+ build_class_list(level + 1, mod, section, infile)
482
+ end
483
+ end
484
+
485
+ from.classes.sort.each do |cls|
486
+ next unless cls.section == section
487
+ next if infile && !cls.defined_in?(infile)
488
+ if cls.document_self
489
+ res <<
490
+ prefix <<
491
+ "Class " <<
492
+ href(cls.viewer.path, "link", cls.full_name) <<
493
+ "<br />\n" <<
494
+ build_class_list(level + 1, cls, section, infile)
495
+ end
496
+ end
497
+
498
+ res
499
+ end
500
+
501
+ def document_self
502
+ @context.document_self
503
+ end
504
+
505
+ def diagram_reference(diagram)
506
+ res = diagram.gsub(/((?:src|href)=")(.*?)"/) {
507
+ $1 + $2 + '"'
508
+ }
509
+ res
510
+ end
511
+
512
+
513
+ # Find a symbol in ourselves or our parent
514
+ def find_symbol(symbol, method=nil)
515
+ res = @context.find_symbol(symbol, method)
516
+ if res
517
+ res = res.viewer
518
+ end
519
+ res
520
+ end
521
+
522
+ # create table of contents if we contain sections
523
+
524
+ def add_table_of_sections
525
+ toc = []
526
+ @context.sections.each do |section|
527
+ if section.title
528
+ toc << {
529
+ 'secname' => section.title,
530
+ 'href' => section.sequence
531
+ }
532
+ end
533
+ end
534
+
535
+ @values['toc'] = toc unless toc.empty?
536
+ end
537
+
538
+
539
+ end
540
+
541
+ #####################################################################
542
+ #
543
+ # Wrap a ClassModule context
544
+
545
+ class HtmlClass < ContextUser
546
+
547
+ @@c_seq = "C00000000"
548
+
549
+ attr_reader :path
550
+
551
+ def initialize(context, html_file, prefix, options)
552
+ super(context, options)
553
+ @@c_seq = @@c_seq.succ
554
+ @c_seq = @@c_seq
555
+ @html_file = html_file
556
+ @is_module = context.is_module?
557
+ @values = {}
558
+
559
+ context.viewer = self
560
+
561
+ @path = http_url(context.full_name, prefix)
562
+
563
+ collect_methods
564
+
565
+ AllReferences.add(name, self)
566
+ end
567
+
568
+ # return the relative file name to store this class in,
569
+ # which is also its url
570
+ def http_url(full_name, prefix)
571
+ path = full_name.dup
572
+ if path['<<']
573
+ path.gsub!(/<<\s*(\w*)/) { "from-#$1" }
574
+ end
575
+ File.join(prefix, path.split("::")) + ".html"
576
+ end
577
+
578
+ def seq
579
+ @c_seq
580
+ end
581
+
582
+ def aref
583
+ @c_seq
584
+ end
585
+
586
+ def scope
587
+ a = @context.full_name.split("::")
588
+ if a.length > 1
589
+ a.pop
590
+ a.join("::")
591
+ else
592
+ ""
593
+ end
594
+ end
595
+
596
+ def name
597
+ @context.full_name.gsub("#{scope}::", '')
598
+ end
599
+
600
+ def full_name
601
+ @context.full_name
602
+ end
603
+
604
+ def parent_name
605
+ @context.parent.full_name
606
+ end
607
+
608
+ def write_on(f)
609
+ value_hash
610
+ template = TemplatePage.new(RDoc::Page::BODY,
611
+ RDoc::Page::CLASS_PAGE,
612
+ RDoc::Page::METHOD_LIST)
613
+ template.write_html_on(f, @values)
614
+ end
615
+
616
+ def value_hash
617
+ class_attribute_values
618
+ add_table_of_sections
619
+
620
+ @values["charset"] = @options.charset
621
+ @values["style_url"] = style_url(path, @options.css)
622
+
623
+ # Convert README to html
624
+ unless File.exist?('files/README.html')
625
+ File.open('files/README.html', 'w') do |file|
626
+ file << markup(File.read(File.expand_path(@options.main_page)))
627
+ end
628
+ end
629
+
630
+ d = markup(@context.comment)
631
+ @values["description"] = d unless d.empty?
632
+
633
+ ml = build_method_summary_list
634
+ @values["methods"] = ml unless ml.empty?
635
+
636
+ il = build_include_list(@context)
637
+ @values["includes"] = il unless il.empty?
638
+
639
+ @values["sections"] = @context.sections.map do |section|
640
+
641
+ secdata = {
642
+ "sectitle" => section.title,
643
+ "secsequence" => section.sequence,
644
+ "seccomment" => markup(section.comment)
645
+ }
646
+
647
+ al = build_alias_summary_list(section)
648
+ secdata["aliases"] = al unless al.empty?
649
+
650
+ co = build_constants_summary_list(section)
651
+ secdata["constants"] = co unless co.empty?
652
+
653
+ al = build_attribute_list(section)
654
+ secdata["attributes"] = al unless al.empty?
655
+
656
+ cl = build_class_list(0, @context, section)
657
+ secdata["classlist"] = cl unless cl.empty?
658
+
659
+ mdl = build_method_detail_list(section)
660
+ secdata["method_list"] = mdl unless mdl.empty?
661
+
662
+ secdata
663
+ end
664
+
665
+ @values
666
+ end
667
+
668
+ def build_attribute_list(section)
669
+ atts = @context.attributes.sort
670
+ res = []
671
+ atts.each do |att|
672
+ next unless att.section == section
673
+ if att.visibility == :public || att.visibility == :protected || @options.show_all
674
+ entry = {
675
+ "name" => CGI.escapeHTML(att.name),
676
+ "rw" => att.rw,
677
+ "a_desc" => markup(att.comment, true)
678
+ }
679
+ unless att.visibility == :public || att.visibility == :protected
680
+ entry["rw"] << "-"
681
+ end
682
+ res << entry
683
+ end
684
+ end
685
+ res
686
+ end
687
+
688
+ def class_attribute_values
689
+ h_name = CGI.escapeHTML(name)
690
+
691
+ @values["classmod"] = @is_module ? "Module" : "Class"
692
+ @values["title"] = "#{@values['classmod']}: #{h_name}"
693
+
694
+ c = @context
695
+ c = c.parent while c and !c.diagram
696
+ if c && c.diagram
697
+ @values["diagram"] = diagram_reference(c.diagram)
698
+ end
699
+
700
+ @values["full_name"] = h_name
701
+ @values["class_seq"] = seq
702
+ parent_class = @context.superclass
703
+
704
+ if parent_class
705
+ @values["parent"] = CGI.escapeHTML(parent_class)
706
+
707
+ if parent_name
708
+ lookup = parent_name + "::" + parent_class
709
+ else
710
+ lookup = parent_class
711
+ end
712
+
713
+ parent_url = AllReferences[lookup] || AllReferences[parent_class]
714
+
715
+ if parent_url and parent_url.document_self
716
+ @values["par_url"] = parent_url.path
717
+ end
718
+ end
719
+
720
+ files = []
721
+ @context.in_files.each do |f|
722
+ res = {}
723
+ full_path = CGI.escapeHTML(f.file_absolute_name)
724
+
725
+ res["full_path"] = full_path
726
+ res["full_path_url"] = f.viewer.path if f.document_self
727
+
728
+ if @options.webcvs
729
+ res["cvsurl"] = cvs_url( @options.webcvs, full_path )
730
+ end
731
+
732
+ files << res
733
+ end
734
+
735
+ @values['infiles'] = files
736
+ end
737
+
738
+ def <=>(other)
739
+ self.name <=> other.name
740
+ end
741
+
742
+ end
743
+
744
+ #####################################################################
745
+ #
746
+ # Handles the mapping of a file's information to HTML. In reality,
747
+ # a file corresponds to a +TopLevel+ object, containing modules,
748
+ # classes, and top-level methods. In theory it _could_ contain
749
+ # attributes and aliases, but we ignore these for now.
750
+
751
+ class HtmlFile < ContextUser
752
+
753
+ @@f_seq = "F00000000"
754
+
755
+ attr_reader :path
756
+ attr_reader :name
757
+
758
+ def initialize(context, options, file_dir)
759
+ super(context, options)
760
+ @@f_seq = @@f_seq.succ
761
+ @f_seq = @@f_seq
762
+ @values = {}
763
+
764
+ @path = http_url(file_dir)
765
+ @source_file_path = File.expand_path(@context.file_relative_name).gsub("\/doc\/", "/")
766
+ @name = @context.file_relative_name
767
+
768
+ collect_methods
769
+ AllReferences.add(name, self)
770
+ context.viewer = self
771
+ end
772
+
773
+ def http_url(file_dir)
774
+ File.join(file_dir, @context.file_relative_name.tr('.', '_')) + ".html"
775
+ end
776
+
777
+ def filename_to_label
778
+ @context.file_relative_name.gsub(/%|\/|\?|\#/) {|s| '%' + ("%x" % s[0]) }
779
+ end
780
+
781
+ def seq
782
+ @f_seq
783
+ end
784
+
785
+ def aref
786
+ @f_seq
787
+ end
788
+
789
+ def name
790
+ full_path = @context.file_absolute_name
791
+ short_name = File.basename(full_path)
792
+ end
793
+
794
+ def full_name
795
+ @context.file_absolute_name
796
+ end
797
+
798
+ def scope
799
+ @context.file_relative_name.gsub(/\/#{name}$/, '')
800
+ end
801
+
802
+ def parent_name
803
+ nil
804
+ end
805
+
806
+ def full_file_source
807
+ ret_str = ""
808
+ File.open(@source_file_path, 'r') do |f|
809
+ while(!f.eof?) do
810
+ ret_str += f.readline()
811
+ end
812
+ end
813
+ ret_str
814
+ rescue
815
+ "file not found -#{@source_file_path}-"
816
+ #@source_file_path
817
+ end
818
+
819
+ def value_hash
820
+ file_attribute_values
821
+ add_table_of_sections
822
+
823
+ @values["charset"] = @options.charset
824
+ @values["href"] = path
825
+ @values["style_url"] = style_url(path, @options.css)
826
+ @values["file_seq"] = seq
827
+
828
+ #pulling in the source for this file
829
+ #@values["source_code"] = @context.token_stream
830
+
831
+ @values["file_source_code"] = CGI.escapeHTML(full_file_source)
832
+
833
+ if @context.comment
834
+ d = markup(@context.comment)
835
+ @values["description"] = d if d.size > 0
836
+ end
837
+
838
+ ml = build_method_summary_list
839
+ @values["methods"] = ml unless ml.empty?
840
+
841
+ il = build_include_list(@context)
842
+ @values["includes"] = il unless il.empty?
843
+
844
+ rl = build_requires_list(@context)
845
+ @values["requires"] = rl unless rl.empty?
846
+
847
+
848
+ file_context = @context
849
+
850
+ @values["sections"] = @context.sections.map do |section|
851
+
852
+ secdata = {
853
+ "sectitle" => section.title,
854
+ "secsequence" => section.sequence,
855
+ "seccomment" => markup(section.comment)
856
+ }
857
+
858
+ cl = build_class_list(0, @context, section, file_context)
859
+ @values["classlist"] = cl unless cl.empty?
860
+
861
+ mdl = build_method_detail_list(section)
862
+ secdata["method_list"] = mdl unless mdl.empty?
863
+
864
+ al = build_alias_summary_list(section)
865
+ secdata["aliases"] = al unless al.empty?
866
+
867
+ co = build_constants_summary_list(section)
868
+ @values["constants"] = co unless co.empty?
869
+
870
+ secdata
871
+ end
872
+
873
+ @values
874
+ end
875
+
876
+ def write_on(f)
877
+ value_hash
878
+ template = TemplatePage.new(RDoc::Page::SRC_BODY,RDoc::Page::FILE_PAGE, RDoc::Page::METHOD_LIST)
879
+ template.write_html_on(f, @values)
880
+ end
881
+
882
+ def file_attribute_values
883
+ full_path = @context.file_absolute_name
884
+ short_name = File.basename(full_path)
885
+
886
+ @values["title"] = CGI.escapeHTML("File: #{short_name}")
887
+
888
+ if @context.diagram
889
+ @values["diagram"] = diagram_reference(@context.diagram)
890
+ end
891
+
892
+ @values["short_name"] = CGI.escapeHTML(short_name)
893
+ @values["full_path"] = CGI.escapeHTML(full_path)
894
+ @values["dtm_modified"] = @context.file_stat.mtime.to_s
895
+
896
+ if @options.webcvs
897
+ @values["cvsurl"] = cvs_url( @options.webcvs, @values["full_path"] )
898
+ end
899
+ end
900
+
901
+ def <=>(other)
902
+ self.name <=> other.name
903
+ end
904
+ end
905
+
906
+ #####################################################################
907
+
908
+ class HtmlMethod
909
+ include MarkUp
910
+
911
+ attr_reader :context
912
+ attr_reader :src_url
913
+ attr_reader :img_url
914
+ attr_reader :source_code
915
+
916
+ @@m_seq = "M000000"
917
+
918
+ @@all_methods = []
919
+
920
+ def HtmlMethod::reset
921
+ @@all_methods = []
922
+ end
923
+
924
+ def initialize(context, html_class, options)
925
+ @context = context
926
+ @html_class = html_class
927
+ @options = options
928
+ @@m_seq = @@m_seq.succ
929
+ @m_seq = @@m_seq
930
+ @@all_methods << self
931
+
932
+ context.viewer = self
933
+
934
+ if (ts = @context.token_stream)
935
+ @source_code = markup_code(ts)
936
+ #unless @options.inline_source
937
+ # @src_url = create_source_code_file(@source_code)
938
+ # @img_url = MERBGenerator.gen_url(path, 'source.png')
939
+ #end
940
+ end
941
+ AllReferences.add(name, self)
942
+ end
943
+
944
+ def seq
945
+ @m_seq
946
+ end
947
+
948
+ def aref
949
+ @m_seq
950
+ end
951
+
952
+ def scope
953
+ @html_class.full_name
954
+ end
955
+
956
+ # return a reference to outselves to be used as an href=
957
+ # the form depends on whether we're all in one file
958
+ # or in multiple files
959
+
960
+ def name
961
+ @context.name
962
+ end
963
+
964
+ def section
965
+ @context.section
966
+ end
967
+
968
+ def parent_name
969
+ if @context.parent.parent
970
+ @context.parent.parent.full_name
971
+ else
972
+ nil
973
+ end
974
+ end
975
+
976
+ def path
977
+ @html_class.path
978
+ end
979
+
980
+ def description
981
+ markup(@context.comment)
982
+ end
983
+
984
+ def visibility
985
+ @context.visibility
986
+ end
987
+
988
+ def singleton
989
+ @context.singleton
990
+ end
991
+
992
+ def call_seq
993
+ cs = @context.call_seq
994
+ if cs
995
+ cs.gsub(/\n/, "<br />\n")
996
+ else
997
+ nil
998
+ end
999
+ end
1000
+
1001
+ def params
1002
+ # params coming from a call-seq in 'C' will start with the
1003
+ # method name
1004
+ p = @context.params
1005
+ if p !~ /^\w/
1006
+ p = @context.params.gsub(/\s*\#.*/, '')
1007
+ p = p.tr("\n", " ").squeeze(" ")
1008
+ p = "(" + p + ")" unless p[0] == ?(
1009
+
1010
+ if (block = @context.block_params)
1011
+ # If this method has explicit block parameters, remove any
1012
+ # explicit &block
1013
+
1014
+ p.sub!(/,?\s*&\w+/, '')
1015
+
1016
+ block.gsub!(/\s*\#.*/, '')
1017
+ block = block.tr("\n", " ").squeeze(" ")
1018
+ if block[0] == ?(
1019
+ block.sub!(/^\(/, '').sub!(/\)/, '')
1020
+ end
1021
+ p << " {|#{block.strip}| ...}"
1022
+ end
1023
+ end
1024
+ CGI.escapeHTML(p)
1025
+ end
1026
+
1027
+ def create_source_code_file(code_body)
1028
+ meth_path = @html_class.path.sub(/\.html$/, '.src')
1029
+ File.makedirs(meth_path)
1030
+ file_path = File.join(meth_path, seq) + ".html"
1031
+
1032
+ template = TemplatePage.new(RDoc::Page::SRC_PAGE)
1033
+ File.open(file_path, "w") do |f|
1034
+ values = {
1035
+ 'title' => CGI.escapeHTML(name),
1036
+ 'code' => code_body,
1037
+ 'style_url' => style_url(file_path, @options.css),
1038
+ 'charset' => @options.charset
1039
+ }
1040
+ template.write_html_on(f, values)
1041
+ end
1042
+ file_path
1043
+ end
1044
+
1045
+ def HtmlMethod.all_methods
1046
+ @@all_methods
1047
+ end
1048
+
1049
+ def <=>(other)
1050
+ @context <=> other.context
1051
+ end
1052
+
1053
+ ##
1054
+ # Given a sequence of source tokens, mark up the source code
1055
+ # to make it look purty.
1056
+
1057
+
1058
+ def markup_code(tokens)
1059
+ src = ""
1060
+ tokens.each do |t|
1061
+ next unless t
1062
+ # p t.class
1063
+ # style = STYLE_MAP[t.class]
1064
+ style = case t
1065
+ when RubyToken::TkCONSTANT then "ruby-constant"
1066
+ when RubyToken::TkKW then "ruby-keyword kw"
1067
+ when RubyToken::TkIVAR then "ruby-ivar"
1068
+ when RubyToken::TkOp then "ruby-operator"
1069
+ when RubyToken::TkId then "ruby-identifier"
1070
+ when RubyToken::TkNode then "ruby-node"
1071
+ when RubyToken::TkCOMMENT then "ruby-comment cmt"
1072
+ when RubyToken::TkREGEXP then "ruby-regexp re"
1073
+ when RubyToken::TkSTRING then "ruby-value str"
1074
+ when RubyToken::TkVal then "ruby-value"
1075
+ else
1076
+ nil
1077
+ end
1078
+
1079
+ text = CGI.escapeHTML(t.text)
1080
+
1081
+ if style
1082
+ src << "<span class=\"#{style}\">#{text}</span>"
1083
+ else
1084
+ src << text
1085
+ end
1086
+ end
1087
+
1088
+ add_line_numbers(src)
1089
+ src
1090
+ end
1091
+
1092
+ # we rely on the fact that the first line of a source code
1093
+ # listing has
1094
+ # # File xxxxx, line dddd
1095
+
1096
+ def add_line_numbers(src)
1097
+ if src =~ /\A.*, line (\d+)/
1098
+ first = $1.to_i - 1
1099
+ last = first + src.count("\n")
1100
+ size = last.to_s.length
1101
+ real_fmt = "%#{size}d: "
1102
+ fmt = " " * (size+2)
1103
+ src.gsub!(/^/) do
1104
+ res = sprintf(fmt, first)
1105
+ first += 1
1106
+ fmt = real_fmt
1107
+ res
1108
+ end
1109
+ end
1110
+ end
1111
+
1112
+ def document_self
1113
+ @context.document_self
1114
+ end
1115
+
1116
+ def aliases
1117
+ @context.aliases
1118
+ end
1119
+
1120
+ def find_symbol(symbol, method=nil)
1121
+ res = @context.parent.find_symbol(symbol, method)
1122
+ if res
1123
+ res = res.viewer
1124
+ end
1125
+ res
1126
+ end
1127
+ end
1128
+
1129
+ #####################################################################
1130
+
1131
+ class MERBGenerator
1132
+
1133
+ include MarkUp
1134
+
1135
+ # Generators may need to return specific subclasses depending
1136
+ # on the options they are passed. Because of this
1137
+ # we create them using a factory
1138
+
1139
+ def MERBGenerator.for(options)
1140
+ AllReferences::reset
1141
+ HtmlMethod::reset
1142
+
1143
+ MERBGenerator.new(options)
1144
+
1145
+ end
1146
+
1147
+ class <<self
1148
+ protected :new
1149
+ end
1150
+
1151
+ # Set up a new HTML generator. Basically all we do here is load
1152
+ # up the correct output temlate
1153
+
1154
+ def initialize(options) #:not-new:
1155
+ @options = options
1156
+ load_html_template
1157
+ end
1158
+
1159
+
1160
+ ##
1161
+ # Build the initial indices and output objects
1162
+ # based on an array of TopLevel objects containing
1163
+ # the extracted information.
1164
+
1165
+ def generate(toplevels)
1166
+ @toplevels = toplevels
1167
+ @files = []
1168
+ @classes = []
1169
+
1170
+ write_style_sheet
1171
+ write_javascript
1172
+ gen_sub_directories()
1173
+ build_indices
1174
+ generate_html
1175
+ end
1176
+
1177
+ private
1178
+
1179
+ ##
1180
+ # Load up the AJAX HTML template specified in the options.
1181
+ # If the template name contains a slash, use it literally
1182
+ #
1183
+ def load_html_template
1184
+ template = @options.template
1185
+ unless template =~ %r{/|\\}
1186
+ template = File.join("rdoc/generators/template", @options.generator.key, template)
1187
+ end
1188
+ require template
1189
+ extend RDoc::Page
1190
+ rescue LoadError
1191
+ $stderr.puts "Could not find AJAX template '#{template}'"
1192
+ exit 99
1193
+ end
1194
+
1195
+ ##
1196
+ # Write out the style sheet used by the main frames
1197
+ #
1198
+
1199
+ def write_style_sheet
1200
+ template = TemplatePage.new(RDoc::Page::STYLE)
1201
+ File.open(CSS_NAME, "w") do |f|
1202
+ values = { "font" => "helvetica"} #this is not used anywhere but the template function demands a hash of values
1203
+ template.write_html_on(f, values)
1204
+ end
1205
+ end
1206
+
1207
+ def write_javascript
1208
+ #Argh... I couldn't figure out how to copy these from the template dir so they were copied into
1209
+ # the template file "ajax.rb" and processed similarlly to the style sheets. Not exactly a good thing to do with
1210
+ # external library code. Not very DRY.
1211
+
1212
+ File.open("api_grease.js", "w") do |f|
1213
+ f << RDoc::Page::API_GREASE_JS
1214
+ end
1215
+
1216
+ File.open("prototype.js", "w") do |f|
1217
+ f << RDoc::Page::PROTOTYPE_JS
1218
+ end
1219
+
1220
+ rescue LoadError
1221
+ $stderr.puts "Could not find AJAX template"
1222
+ exit 99
1223
+ end
1224
+
1225
+ ##
1226
+ # See the comments at the top for a description of the
1227
+ # directory structure
1228
+
1229
+ def gen_sub_directories
1230
+ File.makedirs(FILE_DIR, CLASS_DIR)
1231
+ rescue
1232
+ $stderr.puts $!.message
1233
+ exit 1
1234
+ end
1235
+
1236
+ ##
1237
+ # Generate:
1238
+ #
1239
+ # * a list of HtmlFile objects for each TopLevel object.
1240
+ # * a list of HtmlClass objects for each first level
1241
+ # class or module in the TopLevel objects
1242
+ # * a complete list of all hyperlinkable terms (file,
1243
+ # class, module, and method names)
1244
+
1245
+ def build_indices
1246
+
1247
+ @toplevels.each do |toplevel|
1248
+ @files << HtmlFile.new(toplevel, @options, FILE_DIR)
1249
+ end
1250
+
1251
+ RDoc::TopLevel.all_classes_and_modules.each do |cls|
1252
+ build_class_list(cls, @files[0], CLASS_DIR)
1253
+ end
1254
+ end
1255
+
1256
+ def build_class_list(from, html_file, class_dir)
1257
+ @classes << HtmlClass.new(from, html_file, class_dir, @options)
1258
+ from.each_classmodule do |mod|
1259
+ build_class_list(mod, html_file, class_dir)
1260
+ end
1261
+ end
1262
+
1263
+ ##
1264
+ # Generate all the HTML
1265
+ #
1266
+ def generate_html
1267
+ # the individual descriptions for files and classes
1268
+ gen_into(@files)
1269
+ gen_into(@classes)
1270
+ # and the index files
1271
+ gen_file_index
1272
+ gen_class_index
1273
+ gen_method_index
1274
+ gen_main_index
1275
+
1276
+ # this method is defined in the template file
1277
+ write_extra_pages if defined? write_extra_pages
1278
+ end
1279
+
1280
+ def gen_into(list)
1281
+ list.each do |item|
1282
+ if item.document_self
1283
+ op_file = item.path
1284
+ File.makedirs(File.dirname(op_file))
1285
+ File.open(op_file, "w") { |file| item.write_on(file) }
1286
+ end
1287
+ end
1288
+
1289
+ end
1290
+
1291
+ def gen_file_index
1292
+ gen_an_index(@files, 'Files',
1293
+ RDoc::Page::FILE_INDEX,
1294
+ "fr_file_index.html")
1295
+ end
1296
+
1297
+ def gen_class_index
1298
+ gen_an_index(@classes, 'Classes',
1299
+ RDoc::Page::CLASS_INDEX,
1300
+ "fr_class_index.html")
1301
+ end
1302
+
1303
+ def gen_method_index
1304
+ gen_an_index(HtmlMethod.all_methods, 'Methods',
1305
+ RDoc::Page::METHOD_INDEX,
1306
+ "fr_method_index.html")
1307
+ end
1308
+
1309
+
1310
+ def gen_an_index(collection, title, template, filename)
1311
+ template = TemplatePage.new(RDoc::Page::FR_INDEX_BODY, template)
1312
+ res = []
1313
+ collection.sort.each do |f|
1314
+ if f.document_self
1315
+ res << { "href" => f.path, "name" => f.name, "scope" => f.scope, "seq_id" => f.seq }
1316
+ end
1317
+ end
1318
+
1319
+ values = {
1320
+ "entries" => res,
1321
+ 'list_title' => CGI.escapeHTML(title),
1322
+ 'index_url' => main_url,
1323
+ 'charset' => @options.charset,
1324
+ 'style_url' => style_url('', @options.css),
1325
+ }
1326
+
1327
+ File.open(filename, "w") do |f|
1328
+ template.write_html_on(f, values)
1329
+ end
1330
+ end
1331
+
1332
+ # The main index page is mostly a template frameset, but includes
1333
+ # the initial page. If the <tt>--main</tt> option was given,
1334
+ # we use this as our main page, otherwise we use the
1335
+ # first file specified on the command line.
1336
+
1337
+ def gen_main_index
1338
+ template = TemplatePage.new(RDoc::Page::INDEX)
1339
+ File.open("index.html", "w") do |f|
1340
+ tStr = ""
1341
+ #File.open(main_url, 'r') do |g|
1342
+ # tStr = markup(g)
1343
+ #end
1344
+ values = {
1345
+ "initial_page" => tStr,
1346
+ 'title' => CGI.escapeHTML(@options.title),
1347
+ 'charset' => @options.charset,
1348
+ 'content' => File.read('files/README.html')
1349
+ }
1350
+
1351
+ values['inline_source'] = true
1352
+ template.write_html_on(f, values)
1353
+ end
1354
+ end
1355
+
1356
+ # return the url of the main page
1357
+ def main_url
1358
+ "files/README.html"
1359
+ end
1360
+
1361
+
1362
+ end
1363
+
1364
+ end