masterview 0.0.17 → 0.1.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.
- data/CHANGELOG +4 -0
- data/README +22 -6
- data/RELEASE_NOTES +26 -3
- data/Rakefile +1 -0
- data/TODO +2 -0
- data/init.rb +1 -0
- data/lib/masterview/analyzer.rb +252 -0
- data/lib/masterview/directive_helpers.rb +10 -0
- data/lib/masterview/directives/import.rb +22 -0
- data/lib/masterview/directives/import_render.rb +23 -0
- data/lib/masterview/extras/app/controllers/masterview_controller.rb +78 -0
- data/lib/masterview/extras/app/views/masterview/admin/create.rhtml +96 -0
- data/lib/masterview/extras/app/views/masterview/admin/empty.rhtml +15 -0
- data/lib/masterview/extras/app/views/masterview/admin/list.rhtml +97 -0
- data/lib/masterview/extras/rails_init.rb +5 -0
- data/lib/masterview/extras/watcher.rb +12 -11
- data/lib/masterview/masterview_version.rb +2 -2
- data/lib/masterview/parser.rb +29 -18
- data/lib/masterview/template_spec.rb +226 -0
- data/lib/masterview.rb +16 -1
- data/test/import_render_test.rb +30 -0
- data/test/import_test.rb +29 -0
- data/test/template_file_watcher_test.rb +1 -1
- data/test/template_spec_test.rb +344 -0
- data/test/template_test.rb +76 -0
- metadata +18 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
0.1.0 - May 27th - Major additions. Added rake admin tasks, MasterView admin controller/views. Allow user to easily have distributed files and keep sync'd. Generator defaults to generating split files.
|
2
|
+
|
3
|
+
0.0.18 - May 12, 2006 - Refactored watcher
|
4
|
+
|
1
5
|
0.0.17 - May 4, 2006 - Added some additional css style and generator options, change the showOne option
|
2
6
|
|
3
7
|
0.0.16 - April 28, 2006 - Corrected gem version dependencies
|
data/README
CHANGED
@@ -22,7 +22,7 @@ License:: MIT open source license like Rails
|
|
22
22
|
- Design it specifically for ruby and rails. Use the full power and not be limited in its capabilities over what can be done with ERb
|
23
23
|
- Work nicely with layouts, partials, and rails html helpers.
|
24
24
|
- Reduce complexity, work with existing rails code, no extra view logic or hashes than what is used by ERb. Scaffold generate initial templates or work from existing html prototype.
|
25
|
-
-
|
25
|
+
- Reduce the numbers of files, simplifying editing. Define partials and layouts naturallyl right in the template, no need to go to another file.
|
26
26
|
- Preview in browser without running an app. Allow for dummy data in the template so that the page can be viewed and styled independently of the application.
|
27
27
|
- Performance equal to ERb
|
28
28
|
|
@@ -61,16 +61,22 @@ This will copy entire MasterView system into your vendor/plugin/masterview direc
|
|
61
61
|
|
62
62
|
You may add MasterView attributes to existing (x)html or you may use the masterview generator to create a complete working application. The generator can create controllers, models, and the MasterView template file similar to how the built-in generator works. Simply change directory to your rails application and run the following
|
63
63
|
|
64
|
-
script/generate masterview YourModelName [YourControllerName] [--show-all | --show-only list]
|
64
|
+
script/generate masterview YourModelName [YourControllerName] [--style [cssStylesheet]] [--single-file] [--show-all | --show-only list]
|
65
65
|
|
66
|
-
|
66
|
+
The generator by default will generate five masterview template files, one for each distinct page, list, new, edit, show, and destroy. They exist in the app/views/masterview directory with the filename controller_action.html. The layout and message partial are defined in the list template file and imported into the others. Similarly the new template defines the form partial which is imported into edit, and finally the show file defines a _show partial which is imported into destroy. Thus there is one definition of each part (layout and partial) and they are imported into the other files where needed to provide accurate WYSIWYG design time editing. By generating separate files, teams can work on a project easier, however MasterView also supports generating all parts to a single file for the ultimate in DRY.
|
67
67
|
|
68
|
-
|
68
|
+
By adding the --single-file switch MasterView will create a single file and to make it easier to use this template at design time, some design time css stylesheets are included in the file to hide all sections except one. By default the NEW section is the only one shown. Other options are --show-all which makes all sections visible or [--show-only list] which shows only the LIST section. When you are editing the masterview file you may comment/uncomment one of the other css files to show a different section. The --style param allows you to suppress default style generation and specify an existing stylesheet to use, if you exlude the stylesheet none will be used, if you include this option multiple times with different stylesheets each will be used.
|
69
69
|
|
70
|
-
|
70
|
+
Once it is done generating, the generated MasterView template file will be created in app/views/masterview/controller.html. This file is html and can be edited with any standard html editor. The rails specific logic is contained in simple attributes which are ignored by html editors. The syntax for these attributes is heavily derived from the rails helper tags themselves so it should feel natural to the rails developer.
|
71
|
+
|
72
|
+
Another interesting thing to know is that while all of the pages for this Model have been bundled up into a few html file for ease of editing, at runtime these templates gets rendered into the exact same layouts and partials that you would use if you were building from scratch. Its jsut that now you can see what your pages will render like in your wysiwyg html editor and change and layout accordingly. Additionally MasterView supplies some javascript to show only one action view at time (list, new, show, edit, destroy) so you can view in your browser without running in Rails. Dummy html can be included to improve the accuracy of the page which can be easily removed at runtime. To make it easier to work with in an editor, design time stylesheets are included in the file to allow you to hide all sections except the one you are working on, simply uncomment the appropriate stylesheet for the section you would like to work with.
|
71
73
|
|
72
74
|
MasterView is designed to be easy for a developer and designer to work together. By keeping the template in an html friendly format, designers can apply style, layout changes, wording changes, without causing havoc on the rails view code. The designer can be involved at anytime during the development cycle including being able to change style and layout after the system is built. This is great for allowing design or wording changes without reinvolving the developers. One can even start from a designer created prototype and add MasterView tags to make it become real. Whichever way you prefer to work, MasterView accomodates you.
|
73
75
|
|
76
|
+
With Version 0.1.0 a MasterView admin controller/view was added to provide a birds-eye view of all your masterview templates, the status of those templates (OK, Invalid xhtml, Conflicts, Imports outdated), the details regarding the status, and the ultimate erb files generated from each template. By default the MasterView admin controller is enabled by the plugin and is available at http://yourserver/masterview This controller can easily be disabled if not wanted by setting the EnableMasterViewAdminPages = false in the vendor/plugins/masterview/init.rb file. Additionally all of the power of the MasterView admin controller is available via a set of rake commands as well. rake mv:list mv:list_all mv:rebuild mv:rebuild_all mv:copy_layout. rake -T will give you further information about these commands.
|
77
|
+
|
78
|
+
Since it can be difficult to import a layout by hand into a new file, the MasterView admin controller has a link where you can copy the layout into a new file by providing the new files Action. It will take the layout from the template chosen and create a new file controller_action.html with the layout imported and a shell for the new Action code. You can also do this from command line using rake mv:copy_layout TEMPLATE=foo_list.html ACTION=newaction command.
|
79
|
+
|
74
80
|
== MasterView attribute directive syntax
|
75
81
|
|
76
82
|
These attribute directives are provided by MasterView and you can create your own custom attributes for even more power.
|
@@ -109,6 +115,11 @@ mv:generate="layouts/product.rhtml"
|
|
109
115
|
<form></form>
|
110
116
|
</div>
|
111
117
|
|
118
|
+
mv:import="layouts/product.rhtml"
|
119
|
+
When the import directive is used, it is a mirror image of the generate directive, except that this directive
|
120
|
+
doesn't generate any output, it is only used for design time editing. The code inside this tag represents a point
|
121
|
+
in time capture of the real generated code and if it ever gets out of sync it can easily be sync'd back up by
|
122
|
+
visiting the MasterView admin page or using rake mv:rebuild_all
|
112
123
|
|
113
124
|
mv:gen_render=":partial => 'product/form'"
|
114
125
|
This directive does two things it creates a partial and it outputs the appropriate code to render this
|
@@ -146,6 +157,11 @@ mv:gen_render=":partial => 'product/form'"
|
|
146
157
|
|
147
158
|
which will create the partial shared/_product.rhtml and will render this partial over a collection
|
148
159
|
|
160
|
+
mv:import_render="partial => 'product/form'"
|
161
|
+
Similar to how import directive is a mirror to generate, import_render is a mirror to gen_render. This directive
|
162
|
+
generates the appropriate render partial helper, but doesn't generate any additional output, it is only used for
|
163
|
+
design time editing and can be easily sync'd up if it ever gets out of sync with the original code.
|
164
|
+
|
149
165
|
mv:gen_replace="whatToLeave"
|
150
166
|
When used in conjunction with mv:generate directive it causes the value of the attribute to be erb
|
151
167
|
executed output in the parent file before transferring to the child (nested) output file. for example...
|
@@ -589,5 +605,5 @@ in documentation, examples, test cases, additional directives, etc., so I would
|
|
589
605
|
appreciate any feedback and ideas that you have. Thanks for taking the time to
|
590
606
|
review MasterView!
|
591
607
|
|
592
|
-
Jeff Barczewski (jeff.barczewski
|
608
|
+
Jeff Barczewski (jeff.barczewski @ gmail.com)
|
593
609
|
|
data/RELEASE_NOTES
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
= MasterView - Rails-optimized (x)html friendly template engine
|
2
2
|
|
3
|
+
== Recent changes
|
4
|
+
|
5
|
+
MasterView now by default generates five masterview template files instead of one, though you can specify the --single-file option to only generate one file. Using one masterview template file gives the most DRY implementation but since all the views are in one file, it can become a point of contention and is a little more difficult for designers to work with. This Version 0.1.0 upgrade fixes that by generating one masterview template for each action (list, new, edit, show, destroy). The layout and message partials are defined in the list template and are imported into the other files so that you can have a complete page rendering when working with style and design of page. Similarly new defines the form partial which is imported into edit, and show defines a _show partial which is imported into destroy.
|
6
|
+
|
7
|
+
One can edit the layout or other partials in the file they are defined in, so for instance to edit the layout, edit the list template and once finished, you can trigger the other templates to be rebuilt with the current information. MasterView now contains an MasterView admin controller/view to visually see all the status and details about the templates. You can rebuild any out of sync templates from this page. Alternatively you can view and rebuild templates from the command line as well using the built in rake commands (mv:list, mv:list_all, mv:rebuild TEMPLATE=foo.html, mv:rebuild_all).
|
8
|
+
|
9
|
+
To make it easy to add additional actions which also import the layout, MasterView now has a way to generate a starter template file for your action by simply choosing from which other template file you want to import the layout from. For instance say you want to add an action called hello to your Product controller. Find the masterview template you want to get the layout imported from which could be (product_list.html, product_new.html, product_edit.html, ...), you can choose any of the templates that have the layout you want (it doesn't matter whether they defined the layout or simply imported it. To generate the starter template go to the MasterView Admin page http://yourserver/masterview and click copy link next to the appropriate template. On the next screen indicate the name of the action you wish to add (in this case 'hello') and click the submit button. MasterView generates a starter template file product_hello.html which imports the layout from the template file you chose and it creates some placeholder divs in the template that you can edit to add your hello view code. Alternatively there is also a rake mv:copy_layout TEMPLATE=product_list.html ACTION=hello command to allow you to do the same thing via command line.
|
10
|
+
|
11
|
+
Note that you don't have to use the starter or generated files to use MasterView (you can just add MasterView attribute directives manually), but I found that once you had things started and wanted to reuse that same information, that having an automated way to get the layout imported makes it much easier and quicker to get things going. You can also change the default action div that is generated by simply creating your own file in app/views/masterview/admin/empty.rhtml which if found the copy_layout will use it, otherwise it uses the one from the gem/plugin.
|
12
|
+
|
13
|
+
|
14
|
+
== Description
|
15
|
+
|
3
16
|
MasterView is a ruby/rails optimized HTML/XHTML friendly template engine.
|
4
17
|
It is designed to use the full power and productivity of rails including
|
5
18
|
layouts, partials, and rails html helpers while still being editable/styleable
|
@@ -22,7 +35,7 @@ License:: MIT open source license like Rails
|
|
22
35
|
- Design it specifically for ruby and rails. Use the full power and not be limited in its capabilities over what can be done with ERb
|
23
36
|
- Work nicely with layouts, partials, and rails html helpers.
|
24
37
|
- Reduce complexity, work with existing rails code, no extra view logic or hashes than what is used by ERb. Scaffold generate initial templates or work from existing html prototype.
|
25
|
-
-
|
38
|
+
- Reduce the numbers of files, simplifying editing. Define partials and layouts naturallyl right in the template, no need to go to another file.
|
26
39
|
- Preview in browser without running an app. Allow for dummy data in the template so that the page can be viewed and styled independently of the application.
|
27
40
|
- Performance equal to ERb
|
28
41
|
|
@@ -61,8 +74,18 @@ This will copy entire MasterView system into your vendor/plugin/masterview direc
|
|
61
74
|
|
62
75
|
You may add MasterView attributes to existing (x)html or you may use the masterview generator to create a complete working application. The generator can create controllers, models, and the MasterView template file similar to how the built-in generator works. Simply change directory to your rails application and run the following
|
63
76
|
|
64
|
-
script/generate masterview YourModelName [YourControllerName] [--show-all | --show-only list]
|
77
|
+
script/generate masterview YourModelName [YourControllerName] [--style [cssStylesheet]] [--single-file] [--show-all | --show-only list]
|
78
|
+
|
79
|
+
The generator by default will generate five masterview template files, one for each distinct page, list, new, edit, show, and destroy. They exist in the app/views/masterview directory with the filename controller_action.html. The layout and message partial are defined in the list template file and imported into the others. Similarly the new template defines the form partial which is imported into edit, and finally the show file defines a _show partial which is imported into destroy. Thus there is one definition of each part (layout and partial) and they are imported into the other files where needed to provide accurate WYSIWYG design time editing. By generating separate files, teams can work on a project easier, however MasterView also supports generating all parts to a single file for the ultimate in DRY.
|
80
|
+
|
81
|
+
By adding the --single-file switch MasterView will create a single file and to make it easier to use this template at design time, some design time css stylesheets are included in the file to hide all sections except one. By default the NEW section is the only one shown. Other options are --show-all which makes all sections visible or [--show-only list] which shows only the LIST section. When you are editing the masterview file you may comment/uncomment one of the other css files to show a different section. The --style param allows you to suppress default style generation and specify an existing stylesheet to use, if you exlude the stylesheet none will be used, if you include this option multiple times with different stylesheets each will be used.
|
82
|
+
|
83
|
+
Once it is done generating, the generated MasterView template file will be created in app/views/masterview/controller.html. This file is html and can be edited with any standard html editor. The rails specific logic is contained in simple attributes which are ignored by html editors. The syntax for these attributes is heavily derived from the rails helper tags themselves so it should feel natural to the rails developer.
|
84
|
+
|
85
|
+
Another interesting thing to know is that while all of the pages for this Model have been bundled up into a few html file for ease of editing, at runtime these templates gets rendered into the exact same layouts and partials that you would use if you were building from scratch. Its jsut that now you can see what your pages will render like in your wysiwyg html editor and change and layout accordingly. Additionally MasterView supplies some javascript to show only one action view at time (list, new, show, edit, destroy) so you can view in your browser without running in Rails. Dummy html can be included to improve the accuracy of the page which can be easily removed at runtime. To make it easier to work with in an editor, design time stylesheets are included in the file to allow you to hide all sections except the one you are working on, simply uncomment the appropriate stylesheet for the section you would like to work with.
|
65
86
|
|
66
|
-
|
87
|
+
MasterView is designed to be easy for a developer and designer to work together. By keeping the template in an html friendly format, designers can apply style, layout changes, wording changes, without causing havoc on the rails view code. The designer can be involved at anytime during the development cycle including being able to change style and layout after the system is built. This is great for allowing design or wording changes without reinvolving the developers. One can even start from a designer created prototype and add MasterView tags to make it become real. Whichever way you prefer to work, MasterView accomodates you.
|
67
88
|
|
89
|
+
With Version 0.1.0 a MasterView admin controller/view was added to provide a birds-eye view of all your masterview templates, the status of those templates (OK, Invalid xhtml, Conflicts, Imports outdated), the details regarding the status, and the ultimate erb files generated from each template. By default the MasterView admin controller is enabled by the plugin and is available at http://yourserver/masterview This controller can easily be disabled if not wanted by setting the EnableMasterViewAdminPages = false in the vendor/plugins/masterview/init.rb file. Additionally all of the power of the MasterView admin controller is available via a set of rake commands as well. rake mv:list mv:list_all mv:rebuild mv:rebuild_all mv:copy_layout. rake -T will give you further information about these commands.
|
68
90
|
|
91
|
+
Since it can be difficult to import a layout by hand into a new file, the MasterView admin controller has a link where you can copy the layout into a new file by providing the new files Action. It will take the layout from the template chosen and create a new file controller_action.html with the layout imported and a shell for the new Action code. You can also do this from command line using rake mv:copy_layout TEMPLATE=foo_list.html ACTION=newaction command.
|
data/Rakefile
CHANGED
data/TODO
CHANGED
data/init.rb
CHANGED
@@ -37,6 +37,7 @@ module ::MasterView
|
|
37
37
|
#DefaultDirectiveLoadPaths.push File.join( File.dirname(__FILE__), 'directives') #uncomment if you want to add a local directives dir
|
38
38
|
#DefaultParserOptions = { :tidy => false, :escape_erb => true }
|
39
39
|
#TidyPath = '/usr/lib/libtidy.so'
|
40
|
+
#EnableMasterViewAdminPages = true
|
40
41
|
end
|
41
42
|
|
42
43
|
require 'masterview/extras/rails_init.rb'
|
@@ -0,0 +1,252 @@
|
|
1
|
+
module MasterView
|
2
|
+
module Analyzer
|
3
|
+
|
4
|
+
ExpandAlwaysElements = %w{ script textarea }
|
5
|
+
|
6
|
+
module Common
|
7
|
+
def calc_hash(data)
|
8
|
+
#data.gsub( /\s+/, '' ).hash
|
9
|
+
data.hash
|
10
|
+
end
|
11
|
+
|
12
|
+
def src_hash(data_orig)
|
13
|
+
data = data_orig.gsub MasterView::NamespacePrefix+'import_render', MasterView::NamespacePrefix+'gen_render'
|
14
|
+
data = data.gsub MasterView::NamespacePrefix+'import', MasterView::NamespacePrefix+'generate'
|
15
|
+
calc_hash(data)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class ContentEntry
|
21
|
+
include Common
|
22
|
+
attr_accessor :hash, :data
|
23
|
+
|
24
|
+
def initialize(data)
|
25
|
+
@data = data
|
26
|
+
@hash = src_hash(data)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class StackEntry
|
32
|
+
attr_accessor :name, :buffer, :depth, :import, :parts
|
33
|
+
|
34
|
+
def initialize(name, depth, import)
|
35
|
+
@name = name
|
36
|
+
@depth = depth
|
37
|
+
@import = import
|
38
|
+
@buffer = []
|
39
|
+
@parts = 0
|
40
|
+
end
|
41
|
+
|
42
|
+
def inc_parts
|
43
|
+
@parts += 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ListEntry
|
48
|
+
attr_accessor :name, :index, :import
|
49
|
+
attr_writer :hash_invalid
|
50
|
+
def initialize(name, index, import)
|
51
|
+
@name = name
|
52
|
+
@index = index
|
53
|
+
@import = import
|
54
|
+
end
|
55
|
+
|
56
|
+
def hash_invalid?
|
57
|
+
@hash_invalid
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# builder class facilitates the hash_check and building process by monitoring if all parts of a
|
62
|
+
# file have been requested, if not when a higher index part is requested all the other previous
|
63
|
+
# parts will be sent along as well, this is necessary for cases where a file doesn't have as many
|
64
|
+
# internal parts or none at all. This way the hash and all the parts of the file will still be there
|
65
|
+
# if layout has two parts and only last part -1 is requested, this builder will give back part 0 and part 1
|
66
|
+
# if layout would have had three parts then it would have given back all three.
|
67
|
+
# if a part does not exist then it will come back as empty string, same for an index out of bounds
|
68
|
+
class Builder
|
69
|
+
include Common
|
70
|
+
def initialize(content_hash)
|
71
|
+
@content_hash = content_hash
|
72
|
+
@builder_hash = {} #will contain next index to use
|
73
|
+
end
|
74
|
+
|
75
|
+
def hash(name, index)
|
76
|
+
src_hash(data(name, index))
|
77
|
+
end
|
78
|
+
|
79
|
+
def data(name, index)
|
80
|
+
content = ''
|
81
|
+
content_parts = @content_hash[name]
|
82
|
+
next_index_to_use = (nind = @builder_hash[name]) ? nind : 0
|
83
|
+
next_index_to_use = 0 if (-1 == index) && (next_index_to_use+1 > content_parts.length) # allow -1 to rerequest part as needed (singlefile)
|
84
|
+
return '' if content_parts.nil? || (next_index_to_use+1 > content_parts.length)
|
85
|
+
highest_index = content_parts.length - 1
|
86
|
+
requested_index = (index == -1) ? highest_index : index
|
87
|
+
content = content_parts[next_index_to_use..requested_index].collect do |ce|
|
88
|
+
(ce.data.gsub( /\s/, '' ).empty?) ? '' : ce.data # if only white space then get rid of it
|
89
|
+
end.join
|
90
|
+
@builder_hash[name] = requested_index + 1 # store next index to use
|
91
|
+
content
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Listener
|
96
|
+
include REXML::SAX2Listener
|
97
|
+
include DirectiveHelpers
|
98
|
+
include Common
|
99
|
+
attr_accessor :list, :content
|
100
|
+
|
101
|
+
def initialize( options = {} )
|
102
|
+
@depth = 0
|
103
|
+
@stack = []
|
104
|
+
@list = []
|
105
|
+
@content = options[:content_hash] || {}
|
106
|
+
@options = options
|
107
|
+
@only_check_hash = options[:only_check_hash] || false
|
108
|
+
@builder = Builder.new(@content)
|
109
|
+
Log.debug { "only_check_hash => true" } if @only_check_hash
|
110
|
+
end
|
111
|
+
|
112
|
+
def only_check_hash?
|
113
|
+
@only_check_hash
|
114
|
+
end
|
115
|
+
|
116
|
+
def xmldecl(version, encoding, standalone)
|
117
|
+
#todo
|
118
|
+
end
|
119
|
+
|
120
|
+
def start_document
|
121
|
+
#todo
|
122
|
+
end
|
123
|
+
|
124
|
+
def doctype(name, pub, sys, long_name, uri)
|
125
|
+
#todo
|
126
|
+
end
|
127
|
+
|
128
|
+
def start_element(uri, localname, qname, attributes)
|
129
|
+
unescape_attributes!(attributes)
|
130
|
+
@depth += 1
|
131
|
+
|
132
|
+
import = false
|
133
|
+
if attributes[::MasterView::NamespacePrefix+'generate']
|
134
|
+
path = attributes[::MasterView::NamespacePrefix+'generate']
|
135
|
+
elsif attributes[::MasterView::NamespacePrefix+'gen_render']
|
136
|
+
partial = find_string_val_in_string_hash( attributes[::MasterView::NamespacePrefix+'gen_render'], :partial)
|
137
|
+
path = render_partial_name_to_file_name(partial)
|
138
|
+
elsif attributes[::MasterView::NamespacePrefix+'import']
|
139
|
+
path = attributes[::MasterView::NamespacePrefix+'import']
|
140
|
+
import = true
|
141
|
+
elsif attributes[::MasterView::NamespacePrefix+'import_render']
|
142
|
+
partial = find_string_val_in_string_hash( attributes[::MasterView::NamespacePrefix+'import_render'], :partial)
|
143
|
+
path = render_partial_name_to_file_name(partial)
|
144
|
+
import = true
|
145
|
+
end
|
146
|
+
|
147
|
+
if path
|
148
|
+
store_last_buffer false
|
149
|
+
@stack << StackEntry.new(path, @depth, import)
|
150
|
+
end
|
151
|
+
|
152
|
+
unless @stack.empty?
|
153
|
+
@stack.last.buffer << "<#{qname}"
|
154
|
+
sorted_attributes = attributes.sort do |a,b| # sort import and import_render like generate and gen_render so hashs work
|
155
|
+
a_working = a[0]
|
156
|
+
b_working = b[0]
|
157
|
+
working_cmp = [a_working, b_working].collect do |working|
|
158
|
+
if working == ::MasterView::NamespacePrefix+'import_render'
|
159
|
+
working = ::MasterView::NamespacePrefix+'gen_render'
|
160
|
+
elsif working == ::MasterView::NamespacePrefix+'import'
|
161
|
+
working = ::MasterView::NamespacePrefix+'generate'
|
162
|
+
end
|
163
|
+
working
|
164
|
+
end
|
165
|
+
working_cmp[0] <=> working_cmp[1]
|
166
|
+
end
|
167
|
+
sorted_attributes.each do |name, value|
|
168
|
+
@stack.last.buffer << " #{name}=\"#{value}\""
|
169
|
+
end
|
170
|
+
@stack.last.buffer << '>' #must output as separate string so simplify_empty_elements can find it
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def characters(text)
|
175
|
+
@stack.last.buffer << text unless @stack.empty?
|
176
|
+
end
|
177
|
+
|
178
|
+
def comment(comment)
|
179
|
+
@stack.last.buffer << '<!--' << comment << '-->' unless @stack.empty?
|
180
|
+
end
|
181
|
+
|
182
|
+
def cdata(content)
|
183
|
+
(@stack.last.buffer << '<![CDATA[' << content << ']]>') unless @stack.empty?
|
184
|
+
end
|
185
|
+
|
186
|
+
def end_element(uri, localname, qname)
|
187
|
+
unless @stack.empty?
|
188
|
+
if @stack.last.buffer.last == '>' && !ExpandAlwaysElements.include?(qname) #simplify empty elements
|
189
|
+
@stack.last.buffer.pop
|
190
|
+
@stack.last.buffer << '/>'
|
191
|
+
else
|
192
|
+
@stack.last.buffer << '</' << "#{qname}>" #must output </ as separate string so simplify_empty_elements can find it
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
if @depth == @stack.last.depth
|
197
|
+
store_last_buffer true
|
198
|
+
@stack.pop
|
199
|
+
end
|
200
|
+
@depth -= 1
|
201
|
+
end
|
202
|
+
|
203
|
+
def end_document
|
204
|
+
#todo
|
205
|
+
end
|
206
|
+
|
207
|
+
def unescape_attributes!(attributes)
|
208
|
+
attributes.each do |name, value|
|
209
|
+
value.replace CGI::unescapeHTML(value)
|
210
|
+
value.gsub!(''', '\'')
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
def store_last_buffer(end_element)
|
216
|
+
unless @stack.empty?
|
217
|
+
@stack.last.inc_parts
|
218
|
+
index = end_element ? -1 : @stack.last.parts-1
|
219
|
+
data = @stack.last.buffer.join
|
220
|
+
hash_invalid = false;
|
221
|
+
if @stack.last.import
|
222
|
+
if only_check_hash?
|
223
|
+
hash = src_hash(data)
|
224
|
+
bdata = @builder.data(@stack.last.name, index)
|
225
|
+
hash_invalid = src_hash(bdata) != hash
|
226
|
+
if hash_invalid
|
227
|
+
Log.debug { 'hash_invalid contents'}
|
228
|
+
Log.debug { 'src='+bdata }
|
229
|
+
Log.debug { 'imp='+data }
|
230
|
+
end
|
231
|
+
#hash_invalid = @builder.hash(@stack.last.name, index) != hash
|
232
|
+
end
|
233
|
+
elsif !only_check_hash?
|
234
|
+
@content[@stack.last.name] ||= []
|
235
|
+
@content[@stack.last.name] << ContentEntry.new(data)
|
236
|
+
end
|
237
|
+
|
238
|
+
@stack.last.buffer = []
|
239
|
+
@list << ListEntry.new(@stack.last.name, index, @stack.last.import)
|
240
|
+
|
241
|
+
if only_check_hash? #only set these flags if doing hash_check, not accurate for first round parse
|
242
|
+
@list.last.hash_invalid = hash_invalid
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
end #end Analyzer module
|
250
|
+
|
251
|
+
|
252
|
+
end
|
@@ -10,14 +10,24 @@ module MasterView
|
|
10
10
|
#higher priority (lower value) will be executed first in chain
|
11
11
|
module DirectivePriorities
|
12
12
|
Highest = 0
|
13
|
+
VeryHigh = 0x3FFFFFFF/8
|
13
14
|
High = 0x3FFFFFFF/4
|
14
15
|
MediumHigh = 0x3FFFFFFF/3
|
15
16
|
Medium = 0x3FFFFFFF/2
|
16
17
|
MediumLow = (0x3FFFFFFF/3)*2
|
17
18
|
Low = (0x3FFFFFFF/4)*3
|
19
|
+
VeryLow = (0x3FFFFFFF/8)*7
|
18
20
|
Lowest = 0x3FFFFFFF
|
19
21
|
end
|
20
22
|
|
23
|
+
# convert render_partial_name to file_name, ex foo/bar to foo/_bar.rhtml
|
24
|
+
def render_partial_name_to_file_name(render_partial_name)
|
25
|
+
dir = File.dirname(render_partial_name)
|
26
|
+
base = File.basename(render_partial_name, PartialExtension)
|
27
|
+
filename = '_'+base+PartialExtension
|
28
|
+
path = ( (dir != '.') ? File.join(dir,filename) : filename )
|
29
|
+
end
|
30
|
+
|
21
31
|
|
22
32
|
# find the last string that fully matches exactly the
|
23
33
|
# parent tags content string array
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module MasterView
|
2
|
+
module Directives
|
3
|
+
|
4
|
+
# just eat this output since it is only used for design time
|
5
|
+
class Import < MasterView::DirectiveBase
|
6
|
+
def priority
|
7
|
+
DirectivePriorities::VeryHigh
|
8
|
+
end
|
9
|
+
|
10
|
+
def stag(dcs)
|
11
|
+
#output nothing
|
12
|
+
end
|
13
|
+
|
14
|
+
def etag(dcs)
|
15
|
+
tag = dcs.context[:tag]
|
16
|
+
tag.content = [] # clear out any content including from children
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module MasterView
|
2
|
+
module Directives
|
3
|
+
|
4
|
+
# just eat this output since it is only used for design time
|
5
|
+
class Import_render < MasterView::DirectiveBase
|
6
|
+
def priority
|
7
|
+
DirectivePriorities::VeryHigh
|
8
|
+
end
|
9
|
+
|
10
|
+
def stag(dcs)
|
11
|
+
#output nothing
|
12
|
+
end
|
13
|
+
|
14
|
+
def etag(dcs)
|
15
|
+
tag = dcs.context[:tag]
|
16
|
+
tag.content = [] # clear out any content including from children
|
17
|
+
ret = []
|
18
|
+
ret << erb_content('render( '+attr_value+' )')
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class MasterviewController < ApplicationController
|
2
|
+
|
3
|
+
def index
|
4
|
+
redirect_to :action => :list
|
5
|
+
end
|
6
|
+
|
7
|
+
def list
|
8
|
+
template_specs, content_hash = MasterView::TemplateSpec.scan
|
9
|
+
@template_specs_sorted = template_specs.sort
|
10
|
+
smart_render 'masterview/admin/list'
|
11
|
+
end
|
12
|
+
|
13
|
+
def rebuild_all
|
14
|
+
files_rebuilt = []
|
15
|
+
MasterView::TemplateSpec.scan do |template_spec, content_hash|
|
16
|
+
if template_spec.status == MasterView::TemplateSpec::Status::ImportsOutdated &&
|
17
|
+
template_spec.rebuild_template(content_hash, :write_to_file => true)
|
18
|
+
files_rebuilt << template_spec.path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
unless files_rebuilt.empty?
|
22
|
+
flash[:notice] = files_rebuilt.join(', ')+' were updated'
|
23
|
+
end
|
24
|
+
redirect_to :action => :list
|
25
|
+
end
|
26
|
+
|
27
|
+
def rebuild
|
28
|
+
path = params[:id]
|
29
|
+
template_specs, content_hash = MasterView::TemplateSpec.scan
|
30
|
+
template_spec = template_specs[path]
|
31
|
+
raise 'Template '+path+' not found' unless template_spec
|
32
|
+
if template_spec.rebuild_template(content_hash, :write_to_file => true)
|
33
|
+
flash[:notice] = 'File '+path+' updated'
|
34
|
+
else
|
35
|
+
flash[:notice] = 'Identical content - no update needed for '+path
|
36
|
+
end
|
37
|
+
redirect_to :action => :list
|
38
|
+
end
|
39
|
+
|
40
|
+
def create
|
41
|
+
if @request.post?
|
42
|
+
action_to_create = params[:action_name]
|
43
|
+
short_name = File.basename(params[:id])
|
44
|
+
src_file = File.join('app/views', MasterView::TemplateSrcRelativePath, short_name)
|
45
|
+
|
46
|
+
empty_file_path = find_path('app/views/masterview/admin/empty.rhtml')
|
47
|
+
empty_insert_erb = File.readlines(empty_file_path).join
|
48
|
+
|
49
|
+
dst_file = MasterView::TemplateSpec.create_empty_shell_for_action(src_file, action_to_create, empty_insert_erb, :write_to_file => true)
|
50
|
+
flash[:notice] = dst_file+' was created'
|
51
|
+
redirect_to :action => :list
|
52
|
+
else
|
53
|
+
smart_render 'masterview/admin/create'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# checks app path first for views and files, then falls back to files in MV
|
60
|
+
def find_path(path)
|
61
|
+
local_path = File.join(RAILS_ROOT, path)
|
62
|
+
mv_path = File.join(File.dirname(__FILE__), '../..', path)
|
63
|
+
working_path = (File.exist?(local_path)) ? local_path : mv_path
|
64
|
+
end
|
65
|
+
|
66
|
+
# render local template file if exists otherwise render file from mv
|
67
|
+
def smart_render(short_path)
|
68
|
+
local_path = File.join(RAILS_ROOT, 'app/views', short_path)+'.rhtml'
|
69
|
+
if File.exist?(local_path)
|
70
|
+
render :template => short_path
|
71
|
+
else
|
72
|
+
mv_path = File.join(File.dirname(__FILE__), '../../app/views', short_path)+'.rhtml'
|
73
|
+
MasterView::Log.debug { 'mv_path='+mv_path }
|
74
|
+
render :file => mv_path
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|