honkster-erector 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/README.txt +116 -0
  2. data/VERSION.yml +4 -0
  3. data/bin/erector +14 -0
  4. data/lib/erector.rb +34 -0
  5. data/lib/erector/abstract_widget.rb +172 -0
  6. data/lib/erector/after_initialize.rb +34 -0
  7. data/lib/erector/caching.rb +93 -0
  8. data/lib/erector/convenience.rb +58 -0
  9. data/lib/erector/dependencies.rb +24 -0
  10. data/lib/erector/dependency.rb +30 -0
  11. data/lib/erector/erect/erect.rb +160 -0
  12. data/lib/erector/erect/erected.rb +75 -0
  13. data/lib/erector/erect/indenting.rb +36 -0
  14. data/lib/erector/erect/rhtml.treetop +233 -0
  15. data/lib/erector/errors.rb +12 -0
  16. data/lib/erector/extensions/hash.rb +21 -0
  17. data/lib/erector/extensions/object.rb +18 -0
  18. data/lib/erector/externals.rb +97 -0
  19. data/lib/erector/html.rb +352 -0
  20. data/lib/erector/inline.rb +37 -0
  21. data/lib/erector/jquery.rb +36 -0
  22. data/lib/erector/mixin.rb +12 -0
  23. data/lib/erector/needs.rb +94 -0
  24. data/lib/erector/output.rb +117 -0
  25. data/lib/erector/rails.rb +27 -0
  26. data/lib/erector/rails/extensions/action_controller.rb +16 -0
  27. data/lib/erector/rails/extensions/rails_helpers.rb +159 -0
  28. data/lib/erector/rails/extensions/rails_widget.rb +126 -0
  29. data/lib/erector/rails/rails_form_builder.rb +24 -0
  30. data/lib/erector/rails/rails_version.rb +6 -0
  31. data/lib/erector/rails/template_handlers/ert_handler.rb +32 -0
  32. data/lib/erector/rails/template_handlers/rb_handler.rb +52 -0
  33. data/lib/erector/raw_string.rb +8 -0
  34. data/lib/erector/sass.rb +22 -0
  35. data/lib/erector/unicode.rb +18185 -0
  36. data/lib/erector/unicode_builder.rb +67 -0
  37. data/lib/erector/version.rb +12 -0
  38. data/lib/erector/widget.rb +54 -0
  39. data/lib/erector/widgets.rb +6 -0
  40. data/lib/erector/widgets/environment_badge.rb +29 -0
  41. data/lib/erector/widgets/external_renderer.rb +51 -0
  42. data/lib/erector/widgets/field_table.rb +110 -0
  43. data/lib/erector/widgets/form.rb +30 -0
  44. data/lib/erector/widgets/page.rb +165 -0
  45. data/lib/erector/widgets/table.rb +104 -0
  46. data/rails/init.rb +4 -0
  47. data/spec/erect/erect_rails_spec.rb +114 -0
  48. data/spec/erect/erect_spec.rb +175 -0
  49. data/spec/erect/erected_spec.rb +164 -0
  50. data/spec/erect/rhtml_parser_spec.rb +361 -0
  51. data/spec/erector/caching_spec.rb +269 -0
  52. data/spec/erector/convenience_spec.rb +259 -0
  53. data/spec/erector/dependency_spec.rb +67 -0
  54. data/spec/erector/externals_spec.rb +236 -0
  55. data/spec/erector/html_spec.rb +509 -0
  56. data/spec/erector/indentation_spec.rb +211 -0
  57. data/spec/erector/inline_spec.rb +94 -0
  58. data/spec/erector/jquery_spec.rb +35 -0
  59. data/spec/erector/mixin_spec.rb +65 -0
  60. data/spec/erector/needs_spec.rb +120 -0
  61. data/spec/erector/output_spec.rb +199 -0
  62. data/spec/erector/sample-file.txt +1 -0
  63. data/spec/erector/sass_spec.rb +33 -0
  64. data/spec/erector/unicode_builder_spec.rb +75 -0
  65. data/spec/erector/widget_spec.rb +250 -0
  66. data/spec/erector/widgets/field_table_spec.rb +133 -0
  67. data/spec/erector/widgets/form_spec.rb +31 -0
  68. data/spec/erector/widgets/page_spec.rb +85 -0
  69. data/spec/erector/widgets/table_spec.rb +99 -0
  70. data/spec/spec_helper.rb +95 -0
  71. metadata +191 -0
data/README.txt ADDED
@@ -0,0 +1,116 @@
1
+ = Erector
2
+
3
+ * http://erector.rubyforge.org
4
+ * mailto:erector@googlegroups.com
5
+ * http://www.pivotaltracker.com/projects/482
6
+
7
+ == DESCRIPTION
8
+
9
+ Erector is a Builder-like view framework, inspired by Markaby but overcoming
10
+ some of its flaws. In Erector all views are objects, not template files,
11
+ which allows the full power of object-oriented programming (inheritance,
12
+ modular decomposition, encapsulation) in views. See the rdoc for the
13
+ Erector::Widget class to learn how to make your own widgets, and visit the
14
+ project site at http://erector.rubyforge.org for more documentation.
15
+
16
+ No, seriously, we've got hella docs at http://erector.rubyforge.org -- go
17
+ check it out.
18
+
19
+ == SYNOPSIS
20
+
21
+ require 'erector'
22
+
23
+ class Hello < Erector::Widget
24
+ def content
25
+ html do
26
+ head do
27
+ title "Hello"
28
+ end
29
+ body do
30
+ text "Hello, "
31
+ b @target, :class => 'big'
32
+ text "!"
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ Hello.new(:target => 'world').to_html
39
+ => "<html><head><title>Hello</title></head><body>Hello, <b class=\"big\">world</b>!</body></html>"
40
+
41
+ include Erector::Mixin
42
+ erector { div "love", :class => "big" }
43
+ => "<div class=\"big\">love</div>"
44
+
45
+ == REQUIREMENTS
46
+
47
+ The gem depends on rake and treetop, although this is just for using the command-line tool,
48
+ so deployed applications won't need these. The Rails-dependent code is now separated so
49
+ you can use Erector cleanly in a non-Rails app.
50
+
51
+ == INSTALL
52
+
53
+ To install as a gem:
54
+
55
+ * sudo gem install erector
56
+
57
+ Then add "require 'erector'" to any files which need erector.
58
+
59
+ To install as a Rails plugin:
60
+
61
+ * Copy the erector source to vendor/plugins/erector in your Rails directory.
62
+
63
+ When installing this way, erector is automatically available to your Rails code
64
+ (no require directive is needed).
65
+
66
+ == TESTS
67
+
68
+ Three spec rake tasks are provided: spec:core (core functionality),
69
+ spec:erect (the erector command line tool), and spec:rails (rails integration).
70
+ You do not need to have Rails installed to run the latter two; they will clone
71
+ the rails git repository and set it up for testing automatically. You can test
72
+ against a different version of Rails by changing the constants in
73
+ lib/erector/rails/rails_version.rb
74
+
75
+ 'rake spec' will run the complete set of specs.
76
+
77
+ == CREDITS:
78
+
79
+ Core Team:
80
+ * Alex Chaffee
81
+ * Brian Takita
82
+
83
+ Special Thanks To:
84
+ * Abby (Chaffee's muse & Best friend)
85
+ * Jim Kingdon
86
+ * Jeff Dean
87
+ * John Firebaugh
88
+ * Nathan Sobo
89
+ * Nick Kallen
90
+ * Alon Salant
91
+ * Andy Peterson
92
+
93
+ == LICENSE:
94
+
95
+ (The MIT License)
96
+
97
+ Copyright (c) 2007-2010 Pivotal Labs and the Erector Project
98
+
99
+ Permission is hereby granted, free of charge, to any person obtaining
100
+ a copy of this software and associated documentation files (the
101
+ "Software"), to deal in the Software without restriction, including
102
+ without limitation the rights to use, copy, modify, merge, publish,
103
+ distribute, sublicense, and/or sell copies of the Software, and to
104
+ permit persons to whom the Software is furnished to do so, subject to
105
+ the following conditions:
106
+
107
+ The above copyright notice and this permission notice shall be
108
+ included in all copies or substantial portions of the Software.
109
+
110
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
111
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
112
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
113
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
114
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
115
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
116
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 8
4
+ :patch: 1
data/bin/erector ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'erector'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ require 'erector'
8
+ end
9
+
10
+ require 'erector/erect/erect'
11
+
12
+ unless Erector::Erect.new(ARGV).run
13
+ exit 1
14
+ end
data/lib/erector.rb ADDED
@@ -0,0 +1,34 @@
1
+ module Erector
2
+ end
3
+
4
+ require "cgi"
5
+ require "yaml"
6
+ begin
7
+ require "sass"
8
+ rescue LoadError => e
9
+ # oh well, no Sass
10
+ end
11
+
12
+ require "erector/errors"
13
+ require "erector/extensions/object"
14
+ require "erector/extensions/hash"
15
+ require "erector/raw_string"
16
+ require "erector/dependencies"
17
+ require "erector/dependency"
18
+ require "erector/externals"
19
+ require "erector/output"
20
+ require "erector/caching"
21
+ require "erector/after_initialize"
22
+ require "erector/needs"
23
+ require "erector/html"
24
+ require "erector/convenience"
25
+ require "erector/jquery"
26
+ require "erector/sass"
27
+ require "erector/abstract_widget"
28
+ require "erector/widget"
29
+
30
+ require "erector/inline"
31
+ require "erector/unicode"
32
+ require "erector/widgets"
33
+ require "erector/version"
34
+ require "erector/mixin"
@@ -0,0 +1,172 @@
1
+ module Erector
2
+
3
+ # Abstract base class for Widget. This pattern allows Widget to include lots of nicely organized modules and still
4
+ # have proper semantics for "super" in subclasses. See the rdoc for Widget for the list of all the included modules.
5
+ class AbstractWidget
6
+ @@prettyprint_default = false
7
+ def prettyprint_default
8
+ @@prettyprint_default
9
+ end
10
+
11
+ def self.prettyprint_default
12
+ @@prettyprint_default
13
+ end
14
+
15
+ def self.prettyprint_default=(enabled)
16
+ @@prettyprint_default = enabled
17
+ end
18
+
19
+ def self.inline(*args, &block)
20
+ Class.new(self) do
21
+ include Erector::Inline
22
+ end.new(*args, &block)
23
+ end
24
+
25
+ [:helpers, :assigns, :output, :parent, :block].each do |attr|
26
+ class_eval(<<-SRC, __FILE__, __LINE__ + 1)
27
+ def #{attr}
28
+ @_#{attr}
29
+ end
30
+ SRC
31
+ end
32
+
33
+ def initialize(assigns = {}, &block)
34
+ unless assigns.is_a? Hash
35
+ raise "Erector widgets are initialized with only a parameter hash. (Other parameters are passed to to_html, or the #widget method.)"
36
+ end
37
+
38
+ @_assigns = assigns
39
+
40
+ assigns.each do |name, value|
41
+ instance_variable_set(name.to_s[0..0] == '@' ? name : "@#{name}", value)
42
+ end
43
+
44
+ @_parent = eval("self", block.binding) if block
45
+ @_block = block
46
+ end
47
+
48
+ # Entry point for rendering a widget (and all its children). This method
49
+ # creates a new output string (if necessary), calls this widget's #content
50
+ # method and returns the string.
51
+ #
52
+ # Options:
53
+ # output:: the string to output to. Default: a new empty string
54
+ # prettyprint:: whether Erector should add newlines and indentation.
55
+ # Default: the value of prettyprint_default (which is false
56
+ # by default).
57
+ # indentation:: the amount of spaces to indent. Ignored unless prettyprint
58
+ # is true.
59
+ # max_length:: preferred maximum length of a line. Line wraps will only
60
+ # occur at space characters, so a long word may end up creating
61
+ # a line longer than this. If nil (default), then there is no
62
+ # arbitrary limit to line lengths, and only internal newline
63
+ # characters and prettyprinting will determine newlines in the
64
+ # output.
65
+ # helpers:: a helpers object containing utility methods. Usually this is a
66
+ # Rails view object.
67
+ # content_method_name:: in case you want to call a method other than
68
+ # #content, pass its name in here.
69
+ def to_html(options = {})
70
+ raise "Erector::Widget#to_html takes an options hash, not a symbol. Try calling \"to_html(:content_method_name=> :#{options})\"" if options.is_a? Symbol
71
+ _render(options).to_s
72
+ end
73
+
74
+ # alias for #to_html
75
+ # @deprecated Please use {#to_html} instead
76
+ def to_s(*args)
77
+ unless defined? @@already_warned_to_s
78
+ $stderr.puts "Erector::Widget#to_s is deprecated. Please use #to_html instead. Called from #{caller.first}"
79
+ @@already_warned_to_s = true
80
+ end
81
+ to_html(*args)
82
+ end
83
+
84
+ # Entry point for rendering a widget (and all its children). Same as #to_html
85
+ # only it returns an array, for theoretical performance improvements when using a
86
+ # Rack server (like Sinatra or Rails Metal).
87
+ #
88
+ # # Options: see #to_html
89
+ def to_a(options = {})
90
+ _render(options).to_a
91
+ end
92
+
93
+ # Template method which must be overridden by all widget subclasses.
94
+ # Inside this method you call the magic #element methods which emit HTML
95
+ # and text to the output string. If you call "super" (or don't override
96
+ # +content+, or explicitly call "call_block") then your widget will
97
+ # execute the block that was passed into its constructor. The semantics of
98
+ # this block are confusing; make sure to read the rdoc for Erector#call_block
99
+ def content
100
+ call_block
101
+ end
102
+
103
+ # When this method is executed, the default block that was passed in to
104
+ # the widget's constructor will be executed. The semantics of this
105
+ # block -- that is, what "self" is, and whether it has access to
106
+ # Erector methods like "div" and "text", and the widget's instance
107
+ # variables -- can be quite confusing. The rule is, most of the time the
108
+ # block is evaluated using "call" or "yield", which means that its scope
109
+ # is that of the caller. So if that caller is not an Erector widget, it
110
+ # will *not* have access to the Erector methods, but it *will* have access
111
+ # to instance variables and methods of the calling object.
112
+ #
113
+ # If you want this block to have access to Erector methods then use
114
+ # Erector::Inline#content or Erector#inline.
115
+ def call_block
116
+ @_block.call(self) if @_block
117
+ end
118
+
119
+ # Emits a (nested) widget onto the current widget's output stream. Accepts
120
+ # either a class or an instance. If the first argument is a class, then
121
+ # the second argument is a hash used to populate its instance variables.
122
+ # If the first argument is an instance then the hash must be unspecified
123
+ # (or empty). If a block is passed to this method, then it gets set as the
124
+ # rendered widget's block.
125
+ #
126
+ # This is the preferred way to call one widget from inside another. This
127
+ # method assures that the same output string is used, which gives better
128
+ # performance than using +capture+ or +to_html+.
129
+ def widget(target, assigns = {}, options = {}, &block)
130
+ if target.is_a? Class
131
+ target.new(assigns, &block)._render_via(self, options)
132
+ else
133
+ unless assigns.empty?
134
+ raise "Unexpected second parameter. Did you mean to pass in assigns when you instantiated the #{target.class.to_s}?"
135
+ end
136
+ target._render_via(self, options, &block)
137
+ end
138
+ end
139
+
140
+ # Creates a whole new output string, executes the block, then converts the
141
+ # output string to a string and returns it as raw text. If at all possible
142
+ # you should avoid this method since it hurts performance, and use +widget+
143
+ # instead.
144
+ def capture
145
+ original, @_output = output, Output.new
146
+ yield
147
+ original.widgets.concat(output.widgets) # todo: test!!!
148
+ output.to_s
149
+ ensure
150
+ @_output = original
151
+ end
152
+
153
+ protected
154
+ def _render(options = {}, &block)
155
+ @_block = block if block
156
+ @_parent = options[:parent] || parent
157
+ @_helpers = options[:helpers] || parent
158
+ @_output = options[:output]
159
+ @_output = Output.new(options) unless output.is_a?(Output)
160
+
161
+ output.widgets << self.class
162
+ send(options[:content_method_name] || :content)
163
+ output
164
+ end
165
+
166
+ def _render_via(parent, options = {}, &block)
167
+ _render(options.merge(:parent => parent,
168
+ :output => parent.output,
169
+ :helpers => parent.helpers), &block)
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,34 @@
1
+ module Erector
2
+ module AfterInitialize
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def after_initialize(instance=nil, &blk)
9
+ if blk
10
+ after_initialize_parts << blk
11
+ elsif instance
12
+ if superclass.respond_to?(:after_initialize)
13
+ superclass.after_initialize instance
14
+ end
15
+ after_initialize_parts.each do |part|
16
+ instance.instance_eval &part
17
+ end
18
+ else
19
+ raise ArgumentError, "You must provide either an instance or a block"
20
+ end
21
+ end
22
+
23
+ protected
24
+ def after_initialize_parts
25
+ @after_initialize_parts ||= []
26
+ end
27
+ end
28
+
29
+ def initialize(*args, &blk)
30
+ super
31
+ self.class.after_initialize self
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,93 @@
1
+ module Erector
2
+ class Cache
3
+ def initialize
4
+ @stores = {}
5
+ end
6
+
7
+ def store_for(klass)
8
+ @stores[klass] ||= Hash.new {|h,k| h[k] = {}}
9
+ end
10
+
11
+ def []=(*args)
12
+ value = args.pop
13
+ klass = args.shift
14
+ params = args.first.is_a?(Hash) ? args.first : {}
15
+ content_method = args.last.is_a?(Symbol) ? args.last : nil
16
+ store_for(klass)[key(params)][content_method] = value
17
+ end
18
+
19
+ def [](klass, params = {}, content_method = nil)
20
+ store_for(klass)[key(params)][content_method]
21
+ end
22
+
23
+ def delete(klass, params = {})
24
+ store_for(klass).delete(key(params))
25
+ end
26
+
27
+ def delete_all(klass)
28
+ @stores.delete(klass)
29
+ end
30
+
31
+ # convert hash-key to array-key for compatibility with 1.8.6
32
+ def key(params)
33
+ params.to_a
34
+ end
35
+ end
36
+
37
+ module Caching
38
+ def self.included(base)
39
+ base.extend ClassMethods
40
+ end
41
+
42
+ module ClassMethods
43
+ def cacheable(value = true)
44
+ @cachable = value
45
+ end
46
+
47
+ def cachable(value = true)
48
+ @cachable = value
49
+ end
50
+
51
+ def cachable?
52
+ if @cachable.nil?
53
+ superclass.respond_to?(:cachable?) && superclass.cachable?
54
+ else
55
+ @cachable
56
+ end
57
+ end
58
+
59
+ def cache
60
+ @@cache ||= nil
61
+ end
62
+
63
+ def cache=(c)
64
+ @@cache = c
65
+ end
66
+ end
67
+
68
+ def cache
69
+ self.class.cache
70
+ end
71
+
72
+ def should_cache?
73
+ cache && block.nil? && self.class.cachable?
74
+ end
75
+
76
+ def _render(options = {})
77
+ if should_cache?
78
+ cache[self.class, assigns, options[:content_method_name]] ||= super
79
+ else
80
+ super
81
+ end
82
+ end
83
+
84
+ def _render_via(parent, options = {})
85
+ if should_cache?
86
+ parent.output << cache[self.class, assigns, options[:content_method_name]] ||= parent.capture { super }
87
+ parent.output.widgets << self.class # todo: test!!!
88
+ else
89
+ super
90
+ end
91
+ end
92
+ end
93
+ end