masterview 0.2.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. data/CHANGELOG +31 -1
  2. data/README +70 -69
  3. data/RELEASE_NOTES +70 -64
  4. data/Rakefile +26 -27
  5. data/TODO +13 -29
  6. data/doc/about.html +246 -0
  7. data/doc/configuration.html +49 -36
  8. data/doc/developer.html +423 -41
  9. data/doc/directives.html +139 -51
  10. data/doc/guide.html +19 -9
  11. data/doc/index.html +90 -224
  12. data/doc/installation.html +36 -28
  13. data/doc/media_list.html +30 -20
  14. data/doc/simple_diagram.html +3 -5
  15. data/doc/stylesheets/masterview.css +16 -1
  16. data/examples/rails_app_config/masterview/settings.rb +2 -1
  17. data/init.rb +1 -1
  18. data/lib/#ChangeLog# +6 -0
  19. data/lib/masterview/analyzer.rb +48 -34
  20. data/lib/masterview/attr_string_parser.rb +5 -1
  21. data/lib/masterview/case_insensitive_hash.rb +69 -0
  22. data/lib/masterview/{pathname_extensions.rb → core_ext/pathname.rb} +0 -0
  23. data/lib/masterview/{string_extensions.rb → core_ext/string.rb} +0 -0
  24. data/lib/masterview/deprecated/directive_base.rb +362 -0
  25. data/lib/masterview/directive_base.rb +201 -179
  26. data/lib/masterview/directive_dsl.rb +457 -0
  27. data/lib/masterview/directive_helpers.rb +28 -141
  28. data/lib/masterview/directive_load_path.rb +388 -0
  29. data/lib/masterview/directive_metadata.rb +377 -0
  30. data/lib/masterview/directive_registry.rb +259 -69
  31. data/lib/masterview/directives/.metadata +16 -0
  32. data/lib/masterview/directives/attr.rb +9 -8
  33. data/lib/masterview/directives/block.rb +11 -14
  34. data/lib/masterview/directives/check_box.rb +13 -18
  35. data/lib/masterview/directives/collection_select.rb +15 -29
  36. data/lib/masterview/directives/content.rb +9 -3
  37. data/lib/masterview/directives/else.rb +15 -13
  38. data/lib/masterview/directives/elsif.rb +14 -13
  39. data/lib/masterview/directives/eval.rb +20 -0
  40. data/lib/masterview/directives/form.rb +56 -9
  41. data/lib/masterview/directives/form_remote.rb +26 -0
  42. data/lib/masterview/directives/global_inline_erb.rb +10 -14
  43. data/lib/masterview/directives/hidden_field.rb +11 -20
  44. data/lib/masterview/directives/if.rb +13 -12
  45. data/lib/masterview/directives/image_tag.rb +20 -28
  46. data/lib/masterview/directives/import.rb +5 -12
  47. data/lib/masterview/directives/import_render.rb +7 -19
  48. data/lib/masterview/directives/insert_generated_comment.rb +8 -11
  49. data/lib/masterview/directives/javascript_include.rb +21 -12
  50. data/lib/masterview/directives/link_to.rb +14 -8
  51. data/lib/masterview/directives/link_to_function.rb +22 -0
  52. data/lib/masterview/directives/link_to_if.rb +15 -13
  53. data/lib/masterview/directives/link_to_remote.rb +13 -8
  54. data/lib/masterview/directives/omit_tag.rb +32 -16
  55. data/lib/masterview/directives/password_field.rb +10 -22
  56. data/lib/masterview/directives/radio_button.rb +11 -22
  57. data/lib/masterview/directives/replace.rb +7 -8
  58. data/lib/masterview/directives/select.rb +11 -24
  59. data/lib/masterview/directives/stylesheet_link.rb +20 -12
  60. data/lib/masterview/directives/submit.rb +11 -5
  61. data/lib/masterview/directives/text_area.rb +10 -23
  62. data/lib/masterview/directives/text_field.rb +10 -22
  63. data/lib/masterview/exceptions.rb +21 -0
  64. data/lib/masterview/extras/app/controllers/masterview_controller.rb +102 -75
  65. data/lib/masterview/extras/app/views/layouts/masterview_admin.rhtml +24 -23
  66. data/lib/masterview/extras/app/views/layouts/masterview_admin_config.rhtml +81 -0
  67. data/lib/masterview/extras/app/views/masterview/admin/configuration.rhtml +5 -1
  68. data/lib/masterview/extras/app/views/masterview/admin/create.rhtml +2 -2
  69. data/lib/masterview/extras/app/views/masterview/admin/directives.rhtml +5 -0
  70. data/lib/masterview/extras/app/views/masterview/admin/features.rhtml +5 -79
  71. data/lib/masterview/extras/app/views/masterview/admin/interact.rhtml +5 -0
  72. data/lib/masterview/extras/app/views/masterview/admin/list.rhtml +3 -71
  73. data/lib/masterview/extras/init_mv_admin_pages.rb +42 -23
  74. data/lib/masterview/filter_helpers.rb +26 -0
  75. data/lib/masterview/initializer.rb +99 -53
  76. data/lib/masterview/io.rb +19 -15
  77. data/lib/masterview/keyword_expander.rb +7 -2
  78. data/lib/masterview/masterview_info.rb +229 -23
  79. data/lib/masterview/masterview_version.rb +2 -2
  80. data/lib/masterview/parser.rb +275 -105
  81. data/lib/masterview/parser_helpers.rb +54 -0
  82. data/lib/masterview/rails_ext/action_controller_erb_direct.rb +29 -0
  83. data/lib/masterview/rails_ext/action_controller_reparse_checking.rb +27 -0
  84. data/lib/masterview/{extras/init_rails_erb_mv_direct.rb → rails_ext/action_view_erb_direct.rb} +12 -59
  85. data/lib/masterview/template_spec.rb +3 -2
  86. data/lib/masterview.rb +21 -12
  87. data/lib/rexml/parsers/baseparser_with_doctype_fix.rb +473 -0
  88. data/lib/rexml/parsers/sax2parser_with_doctype_fix.rb +243 -0
  89. data/test/directive_test_helper.rb +135 -0
  90. data/test/fixtures/directives/id_check.rb +18 -0
  91. data/test/fixtures/directives/test_directive_events.rb +70 -0
  92. data/test/test_helper.rb +18 -5
  93. data/test/tmp/views/layouts/product.rhtml +10 -10
  94. data/test/tmp/views/product/_form.rhtml +4 -4
  95. data/test/tmp/views/product/_product.rhtml +3 -3
  96. data/test/tmp/views/product/destroy.rhtml +5 -5
  97. data/test/tmp/views/product/edit.rhtml +4 -4
  98. data/test/tmp/views/product/list.rhtml +3 -3
  99. data/test/tmp/views/product/new.rhtml +4 -4
  100. data/test/tmp/views/product/show.rhtml +2 -2
  101. data/test/unit/attr_string_parser_test.rb +105 -0
  102. data/test/unit/case_insensitive_hash_mod_test.rb +104 -0
  103. data/test/unit/config_settings_test.rb +13 -1
  104. data/test/unit/default_generate_mio_filter_test.rb +3 -3
  105. data/test/unit/deprecated_directive_base_test.rb +30 -0
  106. data/test/unit/directive_attr_test.rb +111 -35
  107. data/test/unit/directive_base_test.rb +520 -1
  108. data/test/unit/directive_block_test.rb +30 -22
  109. data/test/unit/directive_content_test.rb +24 -11
  110. data/test/unit/directive_else_test.rb +18 -15
  111. data/test/unit/directive_elsif_test.rb +17 -15
  112. data/test/unit/directive_form_remote_test.rb +59 -0
  113. data/test/unit/directive_form_test.rb +31 -39
  114. data/test/unit/directive_global_inline_erb_test.rb +28 -17
  115. data/test/unit/directive_grid_test_notready.rb +38 -0
  116. data/test/unit/directive_helpers_test.rb +39 -0
  117. data/test/unit/directive_hidden_field_test.rb +44 -29
  118. data/test/unit/directive_if_test.rb +10 -7
  119. data/test/unit/directive_image_tag_test.rb +69 -61
  120. data/test/unit/directive_import_render_test.rb +28 -38
  121. data/test/unit/directive_import_test.rb +16 -14
  122. data/test/unit/directive_insert_generated_comment_test.rb +32 -0
  123. data/test/unit/directive_javascript_include_test.rb +40 -43
  124. data/test/unit/directive_link_to_function_test.rb +40 -0
  125. data/test/unit/directive_link_to_if_test.rb +52 -12
  126. data/test/unit/directive_link_to_remote_test.rb +58 -0
  127. data/test/unit/directive_link_to_test.rb +46 -31
  128. data/test/unit/directive_load_path_test.rb +257 -0
  129. data/test/unit/directive_metadata_test.rb +313 -0
  130. data/test/unit/directive_omit_tag_test.rb +73 -21
  131. data/test/unit/directive_password_field_test.rb +44 -38
  132. data/test/unit/directive_registry_test.rb +44 -0
  133. data/test/unit/directive_replace_test.rb +28 -12
  134. data/test/unit/directive_stylesheet_link_test.rb +43 -36
  135. data/test/unit/directive_submit_test.rb +29 -30
  136. data/test/unit/directive_text_area_test.rb +40 -36
  137. data/test/unit/directive_text_field_test.rb +44 -38
  138. data/test/unit/example_directive_child_events_test.rb +41 -0
  139. data/test/unit/example_test.rb +31 -4
  140. data/test/unit/file_mio_test.rb +18 -13
  141. data/test/unit/filter_helpers_test.rb +10 -8
  142. data/test/unit/find_directive_parent_test.rb +174 -0
  143. data/test/unit/keyword_expander_test.rb +4 -2
  144. data/test/unit/mio_test.rb +18 -11
  145. data/test/unit/mtime_string_hash_mio_tree_test.rb +5 -1
  146. data/test/unit/parser_test.rb +41 -29
  147. data/test/unit/pathname_extensions_test.rb +1 -1
  148. data/test/unit/run_parser_test.rb +2 -2
  149. data/test/unit/simplified_directive_base_test.rb +256 -0
  150. data/test/unit/string_hash_mio_test.rb +5 -1
  151. data/test/unit/template_file_watcher_test.rb +2 -2
  152. data/test/unit/template_test.rb +221 -46
  153. metadata +86 -45
  154. data/lib/masterview/directives/testfilter.rb +0 -55
  155. data/lib/masterview/extras/init_rails_reparse_checking.rb +0 -62
@@ -1,48 +1,3 @@
1
- <html>
2
- <head>
3
- <title>Masterview Admin</title>
4
-
5
- <%= stylesheet_link_tag 'masterview/style' %>
6
- <%= stylesheet_link_tag 'masterview/sidebox' %>
7
- <%= stylesheet_link_tag 'masterview/color-scheme' %>
8
- <%= javascript_include_tag :defaults %>
9
-
10
- </head>
11
- <body>
12
-
13
- <!-- ###### Header ###### -->
14
-
15
- <div id="header">
16
- <span class="headerTitle">Admin</span>
17
- <div class="menuBar">
18
- <%= link_to 'Home', :action => :index %>
19
- <!-- | <a href="">Another link</a> -->
20
- </div>
21
- </div>
22
-
23
-
24
- <div class="main">
25
-
26
- <div class="mv_admin_list sidebar LHS">
27
- <h2>Tasks:</h2>
28
- <ul>
29
- <li><%= link_to 'View Configuration', :action => 'configuration' %></li>
30
- <li><%= link_to 'View Loaded Features', :action => 'features' %></li>
31
- <li><%= link_to 'Interactive Render', :action => 'interact' %></li>
32
- <li style="margin-top: 6px; padding-top: 4px; border-top: 1px dashed;"><%= link_to 'Rebuild all outdated templates', :action => 'rebuild_all' %></li>
33
- </ul>
34
- </div>
35
-
36
- <div class="mv_admin_list content">
37
- <h1>MasterView Admin</h1>
38
-
39
- <% if @flash[:notice] %>
40
- <div class="messages" id="admin_messages">
41
- <%= h @flash[:notice] %>
42
- </div>
43
- <% end %>
44
-
45
-
46
1
  <table border="1">
47
2
  <tr>
48
3
  <th>Template</th>
@@ -59,18 +14,18 @@
59
14
  </td>
60
15
  <td>
61
16
  <% if template_spec.status == MasterView::TemplateSpec::Status::ImportsOutdated %>
62
- <%= link_to 'Rebuild', :action => :rebuild, :id => path %>
17
+ <%= link_to 'Rebuild', :action => :rebuild, :file => path %>
63
18
  <% end %>
64
19
 
65
20
  <% if template_spec.status == MasterView::TemplateSpec::Status::OK %>
66
- <%= link_to 'Copy', :action => 'create', :id => path %>
21
+ <%= link_to 'Copy', :action => 'create', :file => path %>
67
22
  <% end %>
68
23
  </td>
69
24
  <td><%= h template_spec.message %></td>
70
25
  <td>
71
26
  <% template_spec.gen_parts.each do |part| %>
72
27
  <% if MasterView::EnableMasterViewAdminViewRHTML %>
73
- <%= link_to part, {:action => :view_rhtml, :id => part}, :title => 'View RHTML - '+part %>
28
+ <%= link_to part, {:action => :view_rhtml, :file => part}, :title => 'View RHTML - '+part %>
74
29
  <% else %>
75
30
  <%= part %>
76
31
  <% end %>
@@ -79,26 +34,3 @@
79
34
  </tr>
80
35
  <% end %>
81
36
  </table>
82
- </div>
83
-
84
- </div>
85
-
86
- <!-- ###### Footer ###### -->
87
-
88
- <div id="footer">
89
- <div class="footerLHS">
90
- <a href="http://validator.w3.org/check/referer">Valid XHTML 1.0 Strict</a>
91
- </div>
92
-
93
- <div class="footerLHS">
94
- <a href="http://jigsaw.w3.org/css-validator/check/referer">Valid CSS 2</a>
95
- </div>
96
-
97
- <div>
98
- <a href="http://masterview.org">Powered by MasterView</a>
99
- </div>
100
- </div>
101
-
102
-
103
- </body>
104
- </html>
@@ -1,24 +1,24 @@
1
1
 
2
2
  # verify that stylesheets we use are available and if not copy them to public/stylesheets
3
- mv_generator_templates_dir = "#{MasterView::LoadedConfiguration.mv_installation_dir}/generators/masterview/templates"
4
- unless File.exist?(mv_generator_templates_dir)
3
+ mv_generator_templates_dir = "#{MasterView::ConfigSettings.mv_installation_dir}/generators/masterview/templates"
4
+ unless File.exist?(mv_generator_templates_dir)
5
5
  # we are in a gem so things are in different directories
6
6
  MasterView::Log.debug{ 'MasterView appears to be installed as a gem...' }
7
- mv_generator_dir = MasterView::LoadedConfiguration.mv_installation_dir.gsub('\\','/').gsub( %r{/masterview-([^/]+)$}, '/masterview_generator-\1' )
7
+ mv_generator_dir = MasterView::ConfigSettings.mv_installation_dir.gsub('\\','/').gsub( %r{/masterview-([^/]+)$}, '/masterview_generator-\1' )
8
8
  mv_generator_templates_dir = "#{mv_generator_dir}/templates"
9
9
  end
10
10
  MasterView::Log.debug{ 'MasterView gem admin stylesheet src dir='+mv_generator_templates_dir }
11
11
 
12
12
  if File.directory?(mv_generator_templates_dir)
13
- rails_app_stylesheets_dir = Pathname.for_path(RAILS_ROOT) + 'public/stylesheets/masterview'
13
+ rails_app_stylesheets_dir = Pathname.for_path(RAILS_ROOT) + 'public/stylesheets/masterview'
14
14
  stylesheet_specs = [
15
15
  # from/to spec: [ <src filename in templates dir>, <target filename in app stylesheets dir> ]
16
16
  [ 'style.css', 'style.css' ],
17
17
  [ 'sidebox.css', 'sidebox.css' ],
18
18
  [ 'color-scheme.css', 'color-scheme.css' ]
19
19
  ]
20
- src_dir_accessor = MasterView::FileMIOTree.new( mv_generator_templates_dir )
21
- dst_dir_accessor = MasterView::FileMIOTree.new( rails_app_stylesheets_dir, '.css', :logging => true)
20
+ src_dir_accessor = MasterView::MIO::FileMIOTree.new( mv_generator_templates_dir )
21
+ dst_dir_accessor = MasterView::MIO::FileMIOTree.new( rails_app_stylesheets_dir, '.css', :logging => true)
22
22
  stylesheet_specs.each { | from, to |
23
23
  src_file = src_dir_accessor.path(from)
24
24
  dst_file = dst_dir_accessor.path(to)
@@ -27,29 +27,48 @@ if File.directory?(mv_generator_templates_dir)
27
27
  end
28
28
 
29
29
  # add our app directories with the masterview_controller to the load path
30
- mv_controller_code_dirs = Dir[File.join(MasterView::LoadedConfiguration.mv_code_base_dir, '/extras/app/controllers')].select { |dir| File.directory?(dir) }
31
- mv_controller_code_dirs.each { |dir| $LOAD_PATH.push dir }
32
- MasterView::Log.debug{ 'MasterView AdminPages controller directories = '+mv_controller_code_dirs.inspect }
30
+ mv_controller_code_dirs = Dir[File.join(MasterView::ConfigSettings.mv_code_base_dir, '/extras/app/controllers')].select { |dir| File.directory?(dir) }
33
31
 
34
- # rails 1.1.5+ added additional safe_load_path which we need to add our directories so that controller will be found
35
- if (not mv_controller_code_dirs.empty? and #we have dirs to add
36
- ActionController::Routing::ControllerComponent.respond_to?(:safe_load_paths) and #we are in rails 1.1.5+
37
- not ActionController::Routing::ControllerComponent.respond_to?(:safe_load_paths_pre_mv)) # we have not already been added
32
+ if (not mv_controller_code_dirs.empty?) # we have some controller dirs to get into load path
33
+ mv_controller_code_dirs.each { |dir| $LOAD_PATH.push dir }
34
+ MasterView::Log.debug{ 'MasterView AdminPages controller directories = '+mv_controller_code_dirs.inspect }
38
35
 
39
- MasterView::Log.info{ 'Adding MasterView AdminPages controller directory to safe_load_path' }
40
- ActionController::Routing::ControllerComponent.class_eval <<-END
41
- class << self
42
- alias_method :safe_load_paths_pre_mv, :safe_load_paths
36
+ # rails 1.2 introduced controller_paths mattr_accessor
37
+ if( ActionController::Routing.respond_to?(:controller_paths) and
38
+ defined?(:Dependencies) and Dependencies.respond_to?(:load_paths) )
39
+ MasterView::Log.info{ 'Adding MasterView AdminPages controller directories to controller_paths' }
40
+ ActionController::Routing.class_eval(<<-EOS, __FILE__, __LINE__)
41
+ class << self
42
+ alias_method :controller_paths_pre_mv, :controller_paths
43
43
 
44
- protected
44
+ def controller_paths #:nodoc:
45
+ # concatenate our controller dirs to original controller_paths
46
+ controller_paths_pre_mv.concat #{mv_controller_code_dirs.inspect}
47
+ end
48
+ end
49
+ EOS
50
+
51
+ mv_controller_code_dirs.each { |dir| Dependencies.load_paths.push(dir) }
52
+
53
+ # rails 1.1.5+ added additional safe_load_path which we need to add our directories so that controller will be found
54
+ elsif (ActionController::Routing.const_defined?(:ControllerComponent) and #we have ControllerComponent
55
+ ActionController::Routing::ControllerComponent.respond_to?(:safe_load_paths)) #we are in rails 1.1.5+
56
+
57
+ MasterView::Log.info{ 'Adding MasterView AdminPages controller directory to safe_load_path' }
58
+ ActionController::Routing::ControllerComponent.class_eval(<<-EOS, __FILE__, __LINE__)
59
+ class << self
60
+ alias_method :safe_load_paths_pre_mv, :safe_load_paths
61
+
62
+ protected
45
63
 
46
- def safe_load_paths #:nodoc:
47
- # concatenate our controller dirs to original safe_load_path
48
- safe_load_paths_pre_mv.concat #{mv_controller_code_dirs.inspect}
64
+ def safe_load_paths #:nodoc:
65
+ # concatenate our controller dirs to original safe_load_path
66
+ safe_load_paths_pre_mv.concat #{mv_controller_code_dirs.inspect}
67
+ end
49
68
  end
50
- end
51
- END
69
+ EOS
52
70
 
71
+ end
53
72
  end
54
73
 
55
74
  MasterView::Log.info{ 'MasterView Admin pages enabled' }
@@ -1,5 +1,26 @@
1
1
  module MasterView
2
+
3
+ # Helper services to support a preprocessing filter to run a template
4
+ # document through HTML Tidy to automatically clean up the markup
5
+ # to ensure valid xhtml. Optionally applied to all incoming templates
6
+ # prior to MasterView processing if the MasterView <code>:tidy</code> parser
7
+ # option is enabled.
8
+ #
9
+ # Unlike web browsers, which for historical and cultural reasons typically
10
+ # accept all sorts of mangled and invalid html and attempt to always
11
+ # produce some form of rendering, MasterView's template parsing is
12
+ # based on XML parsing technology and requires a syntactically valid
13
+ # xhtml document. If you're not sure your templates are well-formed,
14
+ # you can turn on the MasterView <code>:tidy</code> parser option
15
+ # to have tidy automatically applied as a preprocessing filter
16
+ # on your templates. (Requires that you have tidy installed on your system;
17
+ # use the MasterView <code>:tidy_path</code> option to specify how
18
+ # MasterView should invoke tidy)
19
+ #
2
20
  module TidyHelper
21
+
22
+ # Run HTML tidy on an html document and return the tidy'd output.
23
+ #
3
24
  def self.tidy(html)
4
25
  Tidy.path = ::MasterView::TidyPath unless Tidy.path
5
26
  xml = Tidy.open do |tidy|
@@ -16,6 +37,11 @@ module MasterView
16
37
 
17
38
  end
18
39
 
40
+ # Helper service to support a preprocessing filter to escape Erb markup
41
+ # into inline-erb notation within a template document.
42
+ # Optionally applied to all incoming templates prior to MasterView processing
43
+ # if the MasterView <code>:escape_erb</code> parser option is enabled.
44
+ #
19
45
  module EscapeErbHelper
20
46
  def self.escape_erb(html)
21
47
  html = html.gsub(/<%/, InlineErbStart)
@@ -46,6 +46,13 @@
46
46
  #
47
47
 
48
48
  require 'date'
49
+ # we can't be assured of the load path state if initializer is run standalone
50
+ # to construct a configuration prior to full MasterView initialization
51
+ currentPath = File.dirname(__FILE__)
52
+ require File.join( currentPath, 'directive_metadata' )
53
+ require File.join( currentPath, 'directive_load_path' )
54
+
55
+ DEBUG_DIRECTIVE_PATH = false #:nodoc: # temp debug
49
56
 
50
57
  module MasterView
51
58
 
@@ -154,10 +161,43 @@ module MasterView
154
161
  # that directory is also automatically added to the directives
155
162
  # load path.
156
163
  #
157
- # Append additional path(s) to load custom directives from specific
158
- # locations.
159
- attr_accessor :directive_paths
164
+ # A directive load path entry specifiess a directory path
165
+ # from which masterview directives are loaded.
166
+ # Configuration options can optionally be specified to override
167
+ # or extend any .metadata specifications in the directory.
168
+ #
169
+ # Use add_directive_path to append additional directory path(s)
170
+ # from which to load custom directives.
171
+ #
172
+ attr_accessor :directive_load_path
173
+
174
+ # Deprecated - use directive_load_path
175
+ def directive_paths
176
+ @directive_load_path
177
+ end
178
+
179
+ # For use by Initializer to reset cleaned path
180
+ def directive_load_path=(path) #:nodoc:
181
+ @directive_load_path = path
182
+ end
160
183
 
184
+ # Add an entry to the directive_load_path list for a directory
185
+ # containing directive implementation classes to be loaded
186
+ # into the MasterView processing configuration.
187
+ #
188
+ # Optionally specify options for the directives loaded
189
+ # from this directory:
190
+ #
191
+ # :default - metadata defaults
192
+ #
193
+ # Metadata defaults extend or override any defaults specified
194
+ # in the dir_path/.metadata file, if defined, allowing application
195
+ # customization of the default defaults.
196
+ #
197
+ def add_directive_path(dir_path, options=nil)
198
+ directive_load_path << DirectiveLoadPath::PathEntry.new( dir_path, options )
199
+ end
200
+
161
201
  # Relative path from +root_path+ of the temp directory used for creating
162
202
  # backup files before rebuilding/updating a template file.
163
203
  #
@@ -333,12 +373,18 @@ module MasterView
333
373
  # Allows invalid xhmtl to be corrected before masterview template parsing is performed.
334
374
  attr_accessor :tidy_path
335
375
 
336
- # XML name space prefix for MasterView directive attributes in template html.
376
+ # XML name space prefix for builtin MasterView directive attributes in template html.
337
377
  # e.g. mv:generate="target.rhtml".
338
378
  #
339
379
  # Default: <tt>'mv:'</tt>
340
380
  attr_accessor :namespace_prefix
341
381
 
382
+ # XML name space prefix for MasterView extension directive attributes in template html.
383
+ # e.g. mvx:custom_directive="foo".
384
+ #
385
+ # Default: <tt>'mvx:'</tt>
386
+ attr_accessor :namespace_prefix_extensions
387
+
342
388
  # Xhtml-safe substitution for '<%' in a masterview template
343
389
  # NOTE: you must also update inline_erb_substitution_regex if this is changed.
344
390
  #
@@ -422,6 +468,10 @@ module MasterView
422
468
  # to disable they specifically set something to false or nil
423
469
  OriginalDefaultParserOptions = { :tidy => false, :escape_erb => true, :default_generate => true } # :nodoc: save the originals
424
470
 
471
+ # list of [ :log_level, msg ] pairs for config initialization/validation messages
472
+ # used by the initializer to validate load path and report any problems
473
+ attr_accessor :initialization_messages #:nodoc:
474
+
425
475
  # Create a new Configuration instance, initialized with the default
426
476
  # values.
427
477
  #
@@ -438,13 +488,7 @@ module MasterView
438
488
  # Use +rails_app_root_path+ when operating on a Rails application which
439
489
  # isn't actually running; use +app_root_path+ for a non-rails application.
440
490
  #
441
-
442
- # list of [ :log_level, msg ] pairs for config initialization/validation messages
443
- # used by the initializer to validate load path and report any problems
444
- attr_accessor :initialization_messages #:nodoc:
445
- ####:invalid_directive_paths
446
-
447
- def initialize( params={} )
491
+ def initialize( params={} ) #:nodoc:
448
492
 
449
493
  rails_env = (defined?(RAILS_ENV)) ? RAILS_ENV : nil
450
494
  # unpack the supported keyword args
@@ -524,7 +568,8 @@ module MasterView
524
568
  # A standalone client needs to proactively tell us where to find their settings.
525
569
  self.config_dir_path = rails_app? ? "config/masterview" : nil
526
570
  self.environment = on_rails? ? ::RAILS_ENV : env
527
- self.directive_paths = [ builtin_directives_path ]
571
+ self.directive_load_path = DirectiveLoadPath::Path.new
572
+ add_directive_path builtin_directives_path, { :use_masterview_namespace => true, }
528
573
  discover_standard_directive_path_additions()
529
574
 
530
575
  #TODO: if rails_app? && File.exist?( "#{rails_root_path}/app/masterview/directives" ) THEN append it as well
@@ -540,7 +585,7 @@ module MasterView
540
585
  STDOUT.puts "...root_path=#{root_path}"
541
586
  STDOUT.puts "...config_dir_path=#{config_dir_path || 'nil'}"
542
587
  STDOUT.puts "...environment=#{environment || 'nil'}"
543
- STDOUT.puts "...directive_paths=[ #{directive_paths.join(', ')} ]"
588
+ STDOUT.puts "...directive_load_path=[ #{directive_load_path.directory_paths.join(', ')} ]"
544
589
  end
545
590
 
546
591
  # template source options
@@ -575,6 +620,7 @@ module MasterView
575
620
  # default locations where tidy likely to be found; assume on user's PATH if on Windows
576
621
  self.tidy_path = RUBY_PLATFORM =~ /mswin32/ ? 'c:/tidy/lib/tidy.dll' : '/usr/lib/libtidy.so'
577
622
  self.namespace_prefix = 'mv:'
623
+ self.namespace_prefix_extensions = 'mvx:'
578
624
  self.inline_erb_start = '{{{'
579
625
  self.inline_erb_end = '}}}'
580
626
  self.inline_erb_substitution_regex = /\{\{\{(([^}]|\}[^}]|\}\}[^}])*)\}\}\}/
@@ -615,7 +661,8 @@ module MasterView
615
661
  app_directives_path = rails_app? ? "app/masterview/directives" : nil #??"masterview/directives"?
616
662
  app_directives_path = File.join( root_path, app_directives_path )
617
663
  if File.directory?(app_directives_path) #?and not empty?
618
- directive_paths << app_directives_path #root_path already expanded
664
+ #{ :use_masterview_namespace => false, }
665
+ add_directive_path app_directives_path #root_path already expanded
619
666
  end
620
667
  end
621
668
 
@@ -729,7 +776,6 @@ module MasterView
729
776
  configuration.decide_if_running_rails
730
777
  # keep a permananent record of how we got started
731
778
  configuration.freeze
732
- configuration.directive_paths.freeze
733
779
  MasterView.const_set('ConfigSettings', configuration)
734
780
  end
735
781
 
@@ -768,21 +814,15 @@ module MasterView
768
814
  #??config.root_path = File.expand_path(config.root_path) if config.root_path #?? ensure bolted down firmly?
769
815
 
770
816
  # ensure that the directive load path entries are clean and available
771
- if not config.directive_paths.empty?
772
- clean_paths = []
773
- config.directive_paths.each { | dir |
774
- if dir.nil?: continue; end
775
- if ! File.directory?(dir)
776
- err_msg = "Invalid directive load path directory: '#{dir}'"
777
- #overzealous: raise InvalidPathError.new(err_msg)
778
- # just note the problem and let initializer report it later
779
- config.initialization_messages << [ :error, err_msg ]
780
- else
781
- dir_path = File.expand_path( dir )
782
- clean_paths << dir_path if ! clean_paths.include?(dir_path) # no dups
783
- end
817
+ if not config.directive_load_path.empty?
818
+ STDOUT.puts "###DEBUG: cleaning directive_load_path #{config.directive_load_path.inspect}" if DEBUG_DIRECTIVE_PATH
819
+ clean_path = DirectiveLoadPath.clean_path( config.directive_load_path, :dup_policy => :use_latest ) { | ex |
820
+ # record validation error from a path entry and press on
821
+ # just note the problem and let initializer report it later
822
+ config.initialization_messages << [ :error, ex.message ]
784
823
  }
785
- config.directive_paths = clean_paths
824
+ config.directive_load_path = clean_path
825
+ STDOUT.puts "###DEBUG: CLEANED directive_load_path #{config.directive_load_path.inspect}" if DEBUG_DIRECTIVE_PATH
786
826
  end
787
827
 
788
828
  # template source and generation options
@@ -809,14 +849,12 @@ module MasterView
809
849
  # Install the configuration settings
810
850
  def install_config_settings #:nodoc:
811
851
  set_module_constants
852
+ DirectiveLoadPath.default_path_specs = configuration.directive_load_path # does clone before freezing config
812
853
  end
813
854
 
814
855
  def set_module_constants #:nodoc:
815
856
 
816
857
  config = configuration
817
-
818
- # save configuration so we can get to it later
819
- MasterView.const_set('LoadedConfiguration', config)
820
858
 
821
859
  # create loaded feature map - this map will track exactly what was loaded taking into account failures, so it can differ
822
860
  # from what is configured. key = feature symbol, value = true if enabled and loaded
@@ -825,8 +863,6 @@ module MasterView
825
863
  # we don't record root_path or config_dir_path - their purpose is satisfied
826
864
  # by the time we're done processing this installation configuration
827
865
 
828
- MasterView.const_set('DefaultDirectiveLoadPaths', config.directive_paths.clone) # clone before freezing
829
-
830
866
  # template source options
831
867
  MasterView.const_set('TemplateFilenamePattern', config.template_filename_pattern)
832
868
 
@@ -839,7 +875,6 @@ module MasterView
839
875
  MasterView.const_set('RescueExceptions', config.handle_parse_exceptions)
840
876
  MasterView.const_set('DefaultParserOptions', Configuration::OriginalDefaultParserOptions.merge(config.default_parser_options)) # merge in changes with original, so we can add more defaults later, users have to explicitly set an option to false to cancel them
841
877
  MasterView.const_set('TidyPath', config.tidy_path)
842
- MasterView.const_set('NamespacePrefix', config.namespace_prefix)
843
878
  MasterView.const_set('InlineErbStart', config.inline_erb_start)
844
879
  MasterView.const_set('InlineErbEnd', config.inline_erb_end)
845
880
  MasterView.const_set('InlineErbSubstitutionRegex', config.inline_erb_substitution_regex)
@@ -850,12 +885,6 @@ module MasterView
850
885
  MasterView.const_set('EnableMasterViewAdminPages', config.enable_admin_pages)
851
886
  MasterView.const_set('EnableMasterViewAdminViewRHTML', config.enable_view_rhtml)
852
887
 
853
- # convenience constants for MV attributes involving output generation and imports
854
- MasterView.const_set('GenerateAttribute', config.namespace_prefix + 'generate')
855
- MasterView.const_set('ImportAttribute', config.namespace_prefix + 'import')
856
- MasterView.const_set('GenRenderAttribute', config.namespace_prefix + 'gen_partial')
857
- MasterView.const_set('ImportRenderAttribute', config.namespace_prefix + 'import_render')
858
-
859
888
  end
860
889
 
861
890
  # Load the masterview code
@@ -866,6 +895,9 @@ module MasterView
866
895
  # Complete installation of masterview after its own code has been loaded
867
896
  def complete_plugin_installation #:nodoc:
868
897
  #?? return if MasterView.const_defined?(:Initialized) ??
898
+ MasterView::DirectiveRegistry.register_default_namespaces(
899
+ configuration.namespace_prefix,
900
+ configuration.namespace_prefix_extensions )
869
901
  initialize_logger
870
902
  initialize_mio
871
903
  #Back out experiment: causes load order problems
@@ -889,11 +921,11 @@ module MasterView
889
921
  # Initialize the MasterView I/O subsystem
890
922
  def initialize_mio
891
923
  config = configuration
892
- MasterView.const_set('DefaultSerializer', MIOSerializer)
924
+ MasterView.const_set('DefaultSerializer', TemplateProcessing::MIOSerializer)
893
925
  # all root_path directory anchor points for I/O are expanded absolute paths
894
- io_mgr = MIOTrees.new
926
+ io_mgr = MIO::MIOTrees.new
895
927
  template_extension = File.extname( config.template_filename_pattern )
896
- io_mgr.template = FileMIOTree.new( config.template_src_dir_path, template_extension,
928
+ io_mgr.template = MIO::FileMIOTree.new( config.template_src_dir_path, template_extension,
897
929
  :escape_erb => DefaultParserOptions[:escape_erb], # use DefaultParserOptions since already has config merged
898
930
  :tidy => DefaultParserOptions[:tidy],
899
931
  :default_generate => DefaultParserOptions[:default_generate],
@@ -902,21 +934,22 @@ module MasterView
902
934
  :logging => true )
903
935
 
904
936
  if config.generate_rhtml_files
905
- io_mgr.erb = FileMIOTree.new( config.template_dst_dir_path, config.generated_file_default_extension, :logging => true)
937
+ io_mgr.erb = MIO::FileMIOTree.new( config.template_dst_dir_path, config.generated_file_default_extension, :logging => true)
906
938
  else
907
- io_mgr.erb = RailsErbCacheMIOTree.new( config.generated_file_default_extension, :logging => true)
939
+ io_mgr.erb = MIO::RailsErbCacheMIOTree.new( config.generated_file_default_extension, :logging => true)
908
940
  end
909
- io_mgr.backup = FileMIOTree.new( config.rebuild_backups_tmp_dir_path ) if config.rebuild_backups_tmp_dir_path
941
+ io_mgr.backup = MIO::FileMIOTree.new( config.rebuild_backups_tmp_dir_path ) if config.rebuild_backups_tmp_dir_path
910
942
  MasterView.const_set('IOMgr', io_mgr)
911
943
  MasterView::LoadedFeatures[:tidy_template_read] = config.default_parser_options[:tidy]
912
944
  end
913
945
 
946
+ #NOTE: not currently used - caused problems during startup, so reverted to original
947
+ # scheme where loading is triggered on demand by template parsing
948
+ # [SJL 20-Sep-2006]
914
949
  def load_directives #:nodoc:
915
950
  # get the directives loaded prior to firing up any template parsing
916
951
  return if ! configuration.on_rails? #ISSUE: causes problem for test cases; is this ever a good idea??
917
- MasterView::DirectivesRegistry.process_directives_load_path(
918
- configuration.directive_paths,
919
- configuration.namespace_prefix )
952
+ MasterView::DirectiveRegistry.current.process_directives_load_path( configuration.directive_load_path )
920
953
  end
921
954
 
922
955
  def install_in_rails #:nodoc:
@@ -945,19 +978,32 @@ module MasterView
945
978
  end
946
979
  end
947
980
 
981
+ #--
982
+ # DBC-style notation per DbC - rubydbc-0.1 (Andy Hunt's Design by Contract)
983
+ #pre( MasterView::ParseMasterViewTemplatesAtStartup )
984
+ #pre( MasterView::ReparseChangedMasterViewTemplates )
985
+ #pre( defined?(ActionController) && ActionController::Base.perform_caching )
986
+ #++
948
987
  def enable_reparse_changed_templates #:nodoc:
949
988
  if configuration.reparse_changed_masterview_templates #MasterView::ReparseChangedMasterViewTemplates
950
989
  # if not caching then check for masterview updates on every request
951
- # assert not ActionController::Base.perform_caching
990
+ # DBC-style notation per DbC - rubydbc-0.1 (Andy Hunt's Design by Contract)
991
+ #pre( MasterView::ParseMasterViewTemplatesAtStartup )
992
+ #pre( defined?(ActionController) && ActionController::Base.perform_caching )
952
993
  require 'masterview/extras/watcher' #:nodoc:
953
- require 'masterview/extras/init_rails_reparse_checking'
994
+ MasterView::Log.info { 'Adding hook to allow MasterView to check for templates that have changed when processing a request' }
995
+ require 'masterview/rails_ext/action_controller_reparse_checking' #:nodoc:
996
+ MasterView::LoadedFeatures[:rails_reparse_checking] = true
954
997
  end
955
998
  end
956
999
 
957
1000
  def enable_rails_erb_direct #:nodoc:
958
1001
  unless configuration.generate_rhtml_files
959
1002
  # if not generating rhtml the read erb directly from masterview
960
- require 'masterview/extras/init_rails_erb_mv_direct'
1003
+ MasterView::Log.info { 'Adding hooks to enable Rails to read erb directly from MasterView' }
1004
+ require 'masterview/rails_ext/action_view_erb_direct' #:nodoc:
1005
+ require 'masterview/rails_ext/action_controller_erb_direct' #:nodoc:
1006
+ MasterView::LoadedFeatures[:rails_erb_mv_direct] = true
961
1007
  end
962
1008
  end
963
1009
 
data/lib/masterview/io.rb CHANGED
@@ -1,12 +1,23 @@
1
1
  require 'ostruct'
2
2
  require 'pathname'
3
3
  require 'stringio'
4
- require File.join( File.dirname(__FILE__), 'pathname_extensions' )
5
- require File.join( File.dirname(__FILE__), 'mtime_tracking_hash' )
6
4
  require File.join( File.dirname(__FILE__), '../facets/core/string/starts_with' )
5
+ require File.join( File.dirname(__FILE__), 'core_ext/pathname' )
6
+ require File.join( File.dirname(__FILE__), 'exceptions' )
7
+ require File.join( File.dirname(__FILE__), 'mtime_tracking_hash' )
7
8
  require File.join( File.dirname(__FILE__), 'filter_helpers' )
8
9
 
9
10
  module MasterView
11
+
12
+ # An InvalidPathError that is raised when an invalid template path is given,
13
+ # or if the path is outside of the root_path of the template
14
+ # processing operating context.
15
+ #
16
+ class InvalidIOPathError < InvalidPathError
17
+ end
18
+
19
+ # The MIO module contains facilities for template processing I/O.
20
+ module MIO
10
21
  # IOManager which retrieves the proper MasterViewIOTree object for the type of object being requested
11
22
  # set and access MasterViewIOTree by using accessors
12
23
  # IOMgr.template = FileMIOTree()
@@ -90,7 +101,7 @@ module MasterView
90
101
  end
91
102
 
92
103
  def path(path)
93
- raise InvalidPathError.new('Invalid path specified ('+path.to_s+'). Path is limited to directories under root_path ('+self.to_s+')') unless (self+path).expand_path.to_s.starts_with?(self.expand_path.to_s) #ensure sandbox
104
+ raise InvalidIOPathError.new(path, 'Invalid path specified ('+path.to_s+'). Path is limited to directories under root_path ('+self.to_s+')') unless (self+path).expand_path.to_s.starts_with?(self.expand_path.to_s) #ensure sandbox
94
105
  mio = FileMIO.new(path, self + path)
95
106
  apply_filters(mio, @options, @new_mio_block)
96
107
  end
@@ -355,11 +366,12 @@ module MasterView
355
366
  # do the actual insertion of generate directive if not found
356
367
  def add_default_gen_if_needed(content)
357
368
  # building this right before needed in case the Namespace was changed during initialize
358
- @@generate_gen_partial_search_regex ||= Regexp.new( '\s'+::MasterView::NamespacePrefix+'(generate=|gen_partial=)' )
369
+ mv_ns = DirectiveRegistry.current.mv_namespace_prefix
370
+ @@generate_gen_partial_search_regex ||= Regexp.new( '\s'+mv_ns+'(generate=|gen_partial=)' )
359
371
 
360
372
  # these are the directives that will be used for body and no body cases
361
- @@generate_body_directives ||= ::MasterView::NamespacePrefix+'generate="{template_path}" '+::MasterView::NamespacePrefix+'omit_tag=""'
362
- @@generate_non_body_directives ||= ::MasterView::NamespacePrefix+'generate="{template_path}"'
373
+ @@generate_body_directives ||= mv_ns+'generate="{template_path}" '+mv_ns+'omit_tag=""'
374
+ @@generate_non_body_directives ||= mv_ns+'generate="{template_path}"'
363
375
 
364
376
  unless content =~ @@generate_gen_partial_search_regex
365
377
  Log.debug { "no generate or gen_partial directives found, DefaultGenerateFilter is adding generate=\"{template_path}\"" }
@@ -384,13 +396,5 @@ module MasterView
384
396
  end
385
397
  end
386
398
 
387
-
388
- # raised when an invalid path is given, or if the path is outside of the root_path
389
- class InvalidPathError < RuntimeError
390
- end
391
-
392
- # raised when a method is not called with the appropriate arguments
393
- class InvalidArgumentError < RuntimeError
394
- end
395
-
399
+ end
396
400
  end
@@ -1,6 +1,11 @@
1
1
  module MasterView
2
- # Keyword expander is used to hold variables defined to be used in expansion of
3
- # attributes.
2
+ # KeywordExpander is used to hold variables defined to be used in expansion of
3
+ # directive attributes.
4
+ #
5
+ # Keywords in a directive attribute value are expanded into their variable values
6
+ # in the current template processing contenxt prior to invocation of the
7
+ # directive processing implementation.
8
+ #
4
9
  class KeywordExpander
5
10
 
6
11
  #--