malt 0.3.0 → 0.4.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/.ruby +156 -0
  2. data/Assembly +28 -0
  3. data/COPYING.rdoc +33 -0
  4. data/Gemfile +10 -0
  5. data/HISTORY.rdoc +102 -0
  6. data/README.rdoc +16 -10
  7. data/Reapfile +4 -0
  8. data/lib/malt.rb +36 -8
  9. data/lib/malt.yml +156 -0
  10. data/lib/malt/conversions.rb +42 -0
  11. data/lib/malt/core_ext.rb +81 -3
  12. data/lib/malt/engines/abstract.rb +259 -50
  13. data/lib/malt/engines/bluecloth.rb +19 -9
  14. data/lib/malt/engines/builder.rb +93 -32
  15. data/lib/malt/engines/coffee.rb +46 -0
  16. data/lib/malt/engines/creole.rb +60 -0
  17. data/lib/malt/engines/erb.rb +69 -44
  18. data/lib/malt/engines/erector.rb +61 -30
  19. data/lib/malt/engines/erubis.rb +41 -31
  20. data/lib/malt/engines/haml.rb +13 -37
  21. data/lib/malt/engines/kramdown.rb +40 -15
  22. data/lib/malt/engines/less.rb +15 -14
  23. data/lib/malt/engines/liquid.rb +24 -14
  24. data/lib/malt/engines/markaby.rb +44 -22
  25. data/lib/malt/engines/maruku.rb +89 -0
  26. data/lib/malt/engines/mustache.rb +20 -14
  27. data/lib/malt/engines/nokogiri.rb +89 -0
  28. data/lib/malt/engines/radius.rb +72 -34
  29. data/lib/malt/engines/ragtag.rb +26 -18
  30. data/lib/malt/engines/rdiscount.rb +18 -11
  31. data/lib/malt/engines/rdoc.rb +21 -15
  32. data/lib/malt/engines/redcarpet.rb +137 -0
  33. data/lib/malt/engines/redcloth.rb +15 -7
  34. data/lib/malt/engines/ruby.rb +13 -12
  35. data/lib/malt/engines/sass.rb +30 -17
  36. data/lib/malt/engines/string.rb +36 -0
  37. data/lib/malt/engines/tenjin.rb +70 -27
  38. data/lib/malt/engines/wikicloth.rb +48 -0
  39. data/lib/malt/formats/abstract.rb +90 -29
  40. data/lib/malt/formats/abstract_template.rb +10 -8
  41. data/lib/malt/formats/builder.rb +39 -13
  42. data/lib/malt/formats/coffee.rb +54 -0
  43. data/lib/malt/formats/css.rb +3 -3
  44. data/lib/malt/formats/erb.rb +31 -66
  45. data/lib/malt/formats/haml.rb +8 -8
  46. data/lib/malt/formats/html.rb +1 -7
  47. data/lib/malt/formats/javascript.rb +27 -0
  48. data/lib/malt/formats/latex.rb +1 -1
  49. data/lib/malt/formats/less.rb +13 -11
  50. data/lib/malt/formats/liquid.rb +7 -7
  51. data/lib/malt/formats/markdown.rb +43 -44
  52. data/lib/malt/formats/mediawiki.rb +70 -0
  53. data/lib/malt/formats/mustache.rb +5 -5
  54. data/lib/malt/formats/pdf.rb +1 -7
  55. data/lib/malt/formats/radius.rb +5 -4
  56. data/lib/malt/formats/ragtag.rb +14 -13
  57. data/lib/malt/formats/rbhtml.rb +28 -20
  58. data/lib/malt/formats/rdoc.rb +5 -4
  59. data/lib/malt/formats/rhtml.rb +19 -43
  60. data/lib/malt/formats/ruby.rb +11 -45
  61. data/lib/malt/formats/sass.rb +16 -24
  62. data/lib/malt/formats/scss.rb +13 -30
  63. data/lib/malt/formats/string.rb +61 -0
  64. data/lib/malt/formats/tenjin.rb +4 -4
  65. data/lib/malt/formats/text.rb +1 -1
  66. data/lib/malt/formats/textile.rb +7 -19
  67. data/lib/malt/kernel.rb +1 -2
  68. data/lib/malt/machine.rb +83 -13
  69. data/lib/malt/tilted.rb +216 -0
  70. data/lib/malt/version.rb +21 -0
  71. data/test/helper.rb +15 -0
  72. data/test/unit/engines/case_engine_bluecloth.rb +40 -0
  73. data/test/unit/engines/case_engine_builder.rb +30 -0
  74. data/test/unit/engines/case_engine_coffee.rb +30 -0
  75. data/test/unit/engines/case_engine_creole.rb +35 -0
  76. data/test/unit/engines/case_engine_erb.rb +28 -0
  77. data/test/unit/engines/case_engine_erector.rb +36 -0
  78. data/test/unit/engines/case_engine_erubis.rb +28 -0
  79. data/test/unit/engines/case_engine_haml.rb +30 -0
  80. data/test/unit/engines/case_engine_kramdown.rb +30 -0
  81. data/test/unit/engines/case_engine_less.rb +40 -0
  82. data/test/unit/engines/case_engine_liquid.rb +28 -0
  83. data/test/unit/engines/case_engine_markaby.rb +20 -0
  84. data/test/unit/engines/case_engine_maruku.rb +30 -0
  85. data/test/unit/engines/case_engine_mustache.rb +28 -0
  86. data/test/unit/engines/case_engine_nokogiri.rb +30 -0
  87. data/test/unit/engines/case_engine_radius.rb +30 -0
  88. data/test/unit/engines/case_engine_ragtag.rb +40 -0
  89. data/test/unit/engines/case_engine_rdiscount.rb +30 -0
  90. data/test/unit/engines/case_engine_rdoc.rb +31 -0
  91. data/test/unit/engines/case_engine_redcarpet.rb +30 -0
  92. data/test/unit/engines/case_engine_redcloth.rb +31 -0
  93. data/test/unit/engines/case_engine_ruby.rb +28 -0
  94. data/test/unit/engines/case_engine_sass.rb +36 -0
  95. data/test/unit/engines/case_engine_string.rb +28 -0
  96. data/test/unit/engines/case_engine_tenjin.rb +28 -0
  97. data/test/unit/engines/case_engine_wikicloth.rb +25 -0
  98. data/test/unit/machine.rb +27 -0
  99. data/test/unit/malt.rb +12 -0
  100. metadata +364 -266
  101. data/History.rdoc +0 -64
  102. data/License.txt +0 -205
  103. data/Syckfile +0 -80
  104. data/features/consistent_rendering.feature +0 -36
  105. data/features/samples/sample.erb +0 -1
  106. data/features/samples/sample.erubis +0 -1
  107. data/features/samples/sample.liquid +0 -1
  108. data/features/samples/sample.mustache +0 -1
  109. data/features/samples/sample.radius +0 -1
  110. data/features/step_definitions/engine_steps.rb +0 -49
  111. data/features/support/loadpath.rb +0 -1
  112. data/features/support/sample_class.rb +0 -8
  113. data/lib/malt/formats/erector.rb +0 -53
  114. data/lib/malt/formats/markaby.rb +0 -53
  115. data/lib/malt/meta/data.rb +0 -26
  116. data/lib/malt/meta/package +0 -21
  117. data/lib/malt/meta/profile +0 -21
  118. data/meta/data.rb +0 -26
  119. data/meta/package +0 -21
  120. data/meta/profile +0 -21
  121. data/qed/01_overview.rdoc +0 -8
  122. data/qed/02_formats.rdoc +0 -39
  123. data/qed/03_formats/01_overview.rdoc +0 -7
  124. data/qed/03_formats/02_rdoc.rdoc +0 -83
  125. data/qed/03_formats/03_textile.rdoc +0 -48
  126. data/qed/03_formats/04_markdown.rdoc +0 -66
  127. data/qed/03_formats/05_erb.rdoc +0 -65
  128. data/qed/03_formats/06_liquid.rdoc +0 -54
  129. data/qed/03_formats/07_haml.rdoc +0 -44
  130. data/qed/03_formats/08_ragtag.rdoc +0 -19
  131. data/qed/03_formats/09_radius.rdoc +0 -43
  132. data/qed/03_formats/11_tenjin.rdoc +0 -47
  133. data/qed/03_formats/12_rbhtml.rdoc +0 -55
  134. data/qed/03_formats/13_sass.rdoc +0 -55
  135. data/qed/03_formats/14_scss.rdoc +0 -58
  136. data/qed/03_formats/15_less.rdoc +0 -46
  137. data/qed/03_formats/16_ruby.rdoc +0 -48
  138. data/qed/03_formats/17_markaby.rdoc +0 -50
  139. data/qed/03_formats/18_builder.rb +0 -50
  140. data/qed/03_formats/19_erector.rb +0 -50
  141. data/qed/03_formats/20_mustache.rdoc +0 -54
  142. data/qed/05_machine/01_limited_formats.rdoc +0 -29
  143. data/qed/05_machine/02_prioritized_engines.rdoc +0 -34
  144. data/qed/applique/malt.rb +0 -13
  145. data/qed/samples/data.yml +0 -4
  146. data/qed/samples/output-erb.txt +0 -1
  147. data/qed/samples/output-liquid.txt +0 -1
  148. data/qed/samples/output-mustache.txt +0 -1
  149. data/qed/samples/output-radius.txt +0 -1
  150. data/qed/samples/sample.erb +0 -1
  151. data/qed/samples/sample.liquid +0 -1
  152. data/qed/samples/sample.markdown +0 -308
  153. data/qed/samples/sample.mustache +0 -1
  154. data/qed/samples/sample.radius +0 -1
  155. data/qed/samples/sample.rdoc +0 -8
@@ -0,0 +1,156 @@
1
+ ---
2
+ source:
3
+ - var
4
+ authors:
5
+ - name: trans
6
+ email: transfire@gmail.com
7
+ copyrights:
8
+ - holder: Rubyworks
9
+ year: '2010'
10
+ license: BSD-2-Clause
11
+ replacements: []
12
+ alternatives: []
13
+ requirements:
14
+ - name: blankslate
15
+ - name: detroit
16
+ groups:
17
+ - build
18
+ development: true
19
+ - name: qed
20
+ groups:
21
+ - test
22
+ development: true
23
+ - name: test
24
+ groups:
25
+ - test
26
+ development: true
27
+ - name: lemon
28
+ groups:
29
+ - test
30
+ development: true
31
+ - name: ae
32
+ groups:
33
+ - test
34
+ development: true
35
+ - name: rdoc
36
+ version: 3+
37
+ groups:
38
+ - test
39
+ development: true
40
+ - name: RedCloth
41
+ groups:
42
+ - test
43
+ development: true
44
+ - name: bluecloth
45
+ groups:
46
+ - test
47
+ development: true
48
+ - name: kramdown
49
+ groups:
50
+ - test
51
+ development: true
52
+ - name: rdiscount
53
+ groups:
54
+ - test
55
+ development: true
56
+ - name: haml
57
+ groups:
58
+ - test
59
+ development: true
60
+ - name: sass
61
+ groups:
62
+ - test
63
+ development: true
64
+ - name: less
65
+ groups:
66
+ - test
67
+ development: true
68
+ - name: tenjin
69
+ groups:
70
+ - test
71
+ development: true
72
+ - name: rtals
73
+ groups:
74
+ - test
75
+ development: true
76
+ - name: liquid
77
+ groups:
78
+ - test
79
+ development: true
80
+ - name: erubis
81
+ groups:
82
+ - test
83
+ development: true
84
+ - name: mustache
85
+ groups:
86
+ - test
87
+ development: true
88
+ - name: markaby
89
+ groups:
90
+ - test
91
+ development: true
92
+ - name: builder
93
+ groups:
94
+ - test
95
+ development: true
96
+ - name: radius
97
+ groups:
98
+ - test
99
+ development: true
100
+ - name: ragtag
101
+ groups:
102
+ - test
103
+ development: true
104
+ - name: redcarpet
105
+ groups:
106
+ - test
107
+ development: true
108
+ - name: wikicloth
109
+ groups:
110
+ - test
111
+ development: true
112
+ - name: maruku
113
+ groups:
114
+ - test
115
+ development: true
116
+ - name: creole
117
+ groups:
118
+ - test
119
+ development: true
120
+ - name: erector
121
+ groups:
122
+ - test
123
+ development: true
124
+ - name: active_support
125
+ groups:
126
+ - test
127
+ development: true
128
+ - name: coffee-script
129
+ groups:
130
+ - test
131
+ development: true
132
+ dependencies: []
133
+ conflicts: []
134
+ repositories:
135
+ - uri: git@github.com:rubyworks/malt.git
136
+ scm: git
137
+ name: upstream
138
+ resources:
139
+ home: http://rubyworks.github.com/malt
140
+ code: http://github.com/rubyworks/malt
141
+ wiki: http://wiki.github.com/rubyworks/malt
142
+ docs: http://rubyworks.github.com/malt/docs/api
143
+ bugs: http://github.com/rubyworks/malt/issues
144
+ extra: {}
145
+ load_path:
146
+ - lib
147
+ revision: 0
148
+ created: '2010-06-22'
149
+ summary: Multi-template/multi-markup rendering engine
150
+ title: Malt
151
+ version: 0.4.0
152
+ name: malt
153
+ description: Malt provides a factory framework for rendering a variety of template
154
+ and markup document formats.
155
+ organization: rubyworks
156
+ date: '2011-11-26'
@@ -0,0 +1,42 @@
1
+ module Malt
2
+
3
+ module Conversions
4
+
5
+ module Binding
6
+ extend self
7
+
8
+ #
9
+ def to_binding(binding)
10
+ binding
11
+ end
12
+
13
+ #
14
+ def to_hash(binding)
15
+ Hash.new{ |h,k| h[k] = binding.eval(k) }
16
+ end
17
+
18
+ #
19
+ def to_object(binding)
20
+ obj = binding.eval("self")
21
+
22
+ vars = binding.eval("local_variables")
23
+ vals = binding.eval("[#{vars.join(',')}]")
24
+ data = Hash[*vars.zip(vals).flatten]
25
+
26
+ adhoc = (class << obj; self; end)
27
+ data.each do |name,value|
28
+ adhoc.__send__(:define_method, name){ value }
29
+ end
30
+
31
+ obj
32
+ end
33
+
34
+ end
35
+
36
+ module Object
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -1,8 +1,10 @@
1
1
  require 'ostruct'
2
2
  require 'facets/module/basename'
3
+ require 'facets/to_hash'
4
+ require 'facets/hash/rekey'
3
5
 
6
+ =begin
4
7
  class Hash
5
-
6
8
  #
7
9
  def to_hash
8
10
  dup
@@ -18,14 +20,90 @@ class Hash
18
20
  end
19
21
  h
20
22
  end unless method_defined?(:rekey)
23
+ end
24
+ =end
25
+
26
+
27
+ class Binding
28
+ # Conversion for bindings.
29
+ #
30
+ # @todo Is there any way to integrate the optional data and block?
31
+ def to_binding
32
+ self
33
+ end
34
+
35
+ #
36
+ def itself
37
+ eval('self')
38
+ end
39
+
40
+ # Create a new binding incorporating the current binding and
41
+ # the given local settings hash and yield block.
42
+ #
43
+ # The yield code was neccessary b/c Ruby does not respect the use
44
+ # of yield in a lambda (boo hiss).
45
+ def with(_hash, &_yield)
46
+ _hash = (_hash || {}).to_hash
47
+
48
+ if _yield
49
+ vars = eval('local_variables')
50
+ vals = eval("[#{vars.join(',')}]")
51
+
52
+ vars += _hash.keys
53
+ vals += _hash.values
54
+
55
+ code = <<-END
56
+ def self.___with(#{vars.join(',')})
57
+ binding
58
+ end
59
+ method(:___with)
60
+ END
61
+ eval(code).call(*vals, &_yield)
21
62
 
63
+ #_args = _hash.empty? ? '' : '|' + _hash.keys.join(',') + ',&y|'
64
+ #lamb = eval("lambda{#{_args} binding}")
65
+ #(class << self; self; end).send(:define_method, :__temp__, &lamb)
66
+ #method(:__temp__).call(*_hash.values, &_yield)
67
+ else
68
+ _args = _hash.empty? ? '' : '|' + _hash.keys.join(',') + '|'
69
+ eval("lambda{#{_args} binding}").call(*_hash.values)
70
+ end
71
+ end
72
+ end
73
+
74
+ class Object
75
+ def to_binding
76
+ binding
77
+ end
78
+ end
79
+
80
+ class Struct
81
+ def to_struct
82
+ self
83
+ end
84
+
85
+ def to_h
86
+ Hash[members.zip(values)]
87
+ end unless method_defined?(:to_h)
88
+
89
+ #def to_hash
90
+ # Hash[members.zip(values)]
91
+ #end
22
92
  end
23
93
 
24
94
  class OpenStruct
95
+ def to_struct
96
+ self
97
+ end
25
98
 
26
99
  #
27
- def to_hash
100
+ def to_h #ash
28
101
  @table.dup
29
- end unless method_defined?(:to_hash)
102
+ end unless method_defined?(:to_h)
103
+ end
30
104
 
105
+ unless defined?(::BasicObject)
106
+ require 'blankslate'
107
+ ::BasicObject = ::BlankSlate
31
108
  end
109
+
@@ -58,36 +58,62 @@ module Engine
58
58
  @cache = {}
59
59
  @source = {}
60
60
 
61
- initialize_engine
61
+ require_engine
62
62
  end
63
63
 
64
64
  # Access to the options given to the initializer.
65
65
  attr :settings
66
66
 
67
67
  #
68
- def render(text, options={}) #format, text, file, db, &yld)
69
- if format = options[:format]
70
- raise "unsupported rendering -- #{format}"
68
+ def cache?
69
+ !settings[:nocache]
70
+ end
71
+
72
+ #
73
+ def render(params, &block)
74
+ if into = params[:to]
75
+ raise NotImplementedError, "unsupported rendering -- #{into}"
71
76
  else
72
- raise "unsupported rendering"
77
+ raise NotImplementedError, "unsupported rendering"
73
78
  end
74
79
  end
75
80
 
76
- #
77
- def compile(db, &yld)
78
- raise "not implemented"
81
+ # Prepare engine for rendering.
82
+ def prepare_engine(params={}, &content)
83
+ create_engine(params, &content)
79
84
  end
80
85
 
86
+ # Instantiate engine class with engine options and template text,
87
+ # if possible.
81
88
  #
82
- def cache?
83
- !settings[:nocache]
89
+ # The initialization MUST never include template data and should
90
+ # support caching, if feasible.
91
+ #
92
+ def create_engine(params={})
93
+ raise NotImplementedError, "not implemented"
84
94
  end
85
95
 
86
- private
96
+ # Convert a rendition to Ruby source code. Not all engines support compiling.
97
+ #
98
+ #def compile(*data, &content)
99
+ # raise NotImplementedError, "not implemented"
100
+ #end
101
+
102
+ private
103
+
104
+ # Cached yield reuslt with given key if cache mode is active.
105
+ #
106
+ def cached(*key)
107
+ if cache?
108
+ @cache[key] ||= yield
109
+ else
110
+ yield
111
+ end
112
+ end
87
113
 
88
114
  # Override this to load template engine library and
89
115
  # prepare is for geeral usage.
90
- def initialize_engine
116
+ def require_engine
91
117
  end
92
118
 
93
119
  # Require template library.
@@ -95,63 +121,246 @@ module Engine
95
121
  require(path)
96
122
  end
97
123
 
98
- # Convert a data source into a Binding.
99
- # TODO: handle yld.
100
- def make_binding(db, &yld)
101
- return db if Binding === db # FIXME: no yld
124
+ # - - - D A T A H A N D L I N G - - -
125
+
126
+ # Take `scope` and `locals` data sources are return them as object and
127
+ # locals hash.
128
+ #
129
+ # @param [Object,Binding] scope
130
+ #
131
+ # @param [Hash] locals
132
+ #
133
+ # @return [Array<Object,Hash>] Two element array of scope object and data hash.
134
+ def make_ready(scope, locals=nil, &content)
135
+ locals ||= {}
136
+
137
+ case scope
138
+ when Binding
139
+ vars = scope.eval("local_variables")
140
+ vals = scope.eval("[#{vars.join(',')}]")
141
+ locals = locals.merge(Hash[*vars.zip(vals).flatten])
142
+ scope = scope.eval("self")
143
+ end
144
+
145
+ if scope.respond_to?(:to_struct)
146
+ locals = locals.merge(scope.to_struct.to_h)
147
+ scope = Object.new
148
+ end
102
149
 
103
- if db.respond_to?(:to_binding)
104
- return db.to_binding(&yld)
150
+ if scope.respond_to?(:to_hash)
151
+ locals = locals.merge(scope.to_hash)
152
+ scope = Object.new
105
153
  end
106
154
 
107
- db = make_object(db, &yld)
155
+ scope ||= Object.new
108
156
 
109
- return db.instance_eval{ binding }
157
+ locals[:content] = content.call if content
158
+
159
+ return scope, locals
110
160
  end
111
161
 
112
- # Convert a data source into an Object (aka a "scope").
113
- def make_object(db, &yld)
114
- if db.respond_to?(:to_hash)
115
- hash = db.to_hash
116
- hash[:yield] = yld.call if yld
117
- attrs = hash.keys.map{ |k| k.to_sym }
118
- return Struct.new(*attrs).new(*hash.values)
162
+ # Take scope and locals are return the same reworked for use as externalized
163
+ # template variables.
164
+ #
165
+ # @return [Array<Object,Hash>]
166
+ # Two element array of scope object and data hash.
167
+ def make_external(scope, locals=nil, &content)
168
+ locals ||= {}
169
+
170
+ case scope
171
+ when Binding
172
+ vars = scope.eval("local_variables")
173
+ vals = scope.eval("[#{vars.join(',')}]")
174
+ locals = locals.merge(Hash[*vars.zip(vals).flatten])
175
+ scope = scope.eval("self")
176
+ end
177
+
178
+ if scope.respond_to?(:to_struct)
179
+ locals = locals.merge(scope.to_struct.to_h)
180
+ #scope = Object.new
119
181
  end
120
182
 
121
- if Binding === db
122
- eval('self', binding) # FIXME: no yld
183
+ if scope.respond_to?(:to_hash)
184
+ locals = locals.merge(scope.to_hash)
185
+ scope = Object.new
123
186
  end
124
187
 
125
- return db
188
+ scope ||= Object.new
189
+ scope = make_object(scope || Object.new)
190
+
191
+ locals[:scope] = scope
192
+ locals[:content] = content.call if content
193
+
194
+ return scope, locals
126
195
  end
127
196
 
128
- # Convert a data source into a Hash.
129
- def make_hash(db, &yld)
130
- if Binding === db
131
- db = make_object(db)
197
+ # Convert scope and data into a Binding.
198
+ #
199
+ # @param [Object,Binding,Hash,Array] data
200
+ # The data source used for evaluation.
201
+ #
202
+ # @see #split_data
203
+ #
204
+ # @return [Object] The data and yield block converted to a Binding.
205
+ def make_binding(scope, locals=nil, &content)
206
+ case scope
207
+ when Binding
208
+ locals ||= {}
209
+ locals[:content] = content.call if content
210
+ scope.with(locals)
211
+ else
212
+ scope, locals = make_ready(scope, locals, &content)
213
+ scope.to_binding.with(locals)
132
214
  end
215
+ end
133
216
 
134
- if db.respond_to?(:to_hash)
135
- db = db.to_hash
136
- db[:yield] = yld.call if yld
137
- return db
217
+ # TODO: Simplify the #make_object method.
218
+
219
+ # Convert data into an object.
220
+ #
221
+ # @param [Object,Binding,Hash,Array] data
222
+ # The data source used for evaluation.
223
+ #
224
+ # @return [Object] The data and yield block converted to an Object.
225
+ def make_object(scope, locals=nil)
226
+ locals ||= {}
227
+
228
+ case scope
229
+ when nil
230
+ hash = locals.to_hash.dup
231
+ if hash.empty?
232
+ Object.new
233
+ else
234
+ vars, vals = [], []
235
+ hash.each_pair do |k,v|
236
+ vars << k; vals << v
237
+ end
238
+ Struct.new(*vars).new(*vals)
239
+ end
240
+ when Binding
241
+ Class.new(::BasicObject){
242
+ define_method(:method_missing) do |s, *a|
243
+ if locals.key?(s)
244
+ locals[s]
245
+ elsif locals.key?(s.to_s)
246
+ locals[s.to_s]
247
+ else
248
+ scope.eval(s.to_s)
249
+ end
250
+ end
251
+ }.new
252
+ when Struct
253
+ vars, vals = [], []
254
+ scope.each_pair do |k,v|
255
+ vars << k; vals << v
256
+ end
257
+ locals.each_pair do |k,v|
258
+ vars << k; vals << v
259
+ end
260
+ Struct.new(*vars).new(*vals)
261
+ else
262
+ if scope.respond_to?(:to_hash)
263
+ hash = scope.to_hash.merge(locals.to_hash)
264
+ if hash.empty?
265
+ Object.new
266
+ else
267
+ vars, vals = [], []
268
+ hash.each_pair do |k,v|
269
+ vars << k; vals << v
270
+ end
271
+ Struct.new(*vars).new(*vals)
272
+ end
273
+ else
274
+ Class.new(::BasicObject){
275
+ define_method(:method_missing) do |s, *a, &b|
276
+ if locals.key?(s)
277
+ locals[s]
278
+ elsif locals.key?(s.to_s)
279
+ locals[s.to_s]
280
+ else
281
+ scope.__send__(s.to_s, *a, &b)
282
+ end
283
+ end
284
+ }.new
285
+ end
138
286
  end
287
+ end
139
288
 
140
- if db.respond_to?(:to_h)
141
- db = db.to_h
142
- db[:yield] = yld.call if yld
143
- return db
289
+ # Convert data source into a hash.
290
+ #
291
+ # @param [Object,Binding,Hash,Array] data
292
+ # The data source used for evaluation.
293
+ #
294
+ # @see #scope_vs_hash
295
+ #
296
+ # @return [Hash] The data and yield block converted to a Hash.
297
+ def make_hash(scope, locals=nil, &content)
298
+ case scope
299
+ when nil
300
+ hash = locals || {}
301
+ when Binding
302
+ #hash = Hash.new{ |h,k| p h,k; h[k] = data.key?(k) ? data[k] : scope.eval(k) }
303
+ hash = Hash.new{ |h,k| h[k] = scope.eval(k) }
304
+ else
305
+ if scope.respond_to?(:to_hash)
306
+ hash = scope.to_hash.merge(data)
307
+ else
308
+ #hash = Hash.new{ |h,k| data.key?(k) ? data[k] : h[k] = scope.__send__(k) }
309
+ hash = Hash.new{ |h,k| h[k] = scope.__send__(k) }
310
+ end
144
311
  end
145
312
 
146
- # last resort
147
- db = db.instance_variables.inject({}) do |h, i|
148
- k = i.sub('@','').to_sym
149
- v = instance_variable_get(i)
150
- h[k] = v
151
- h
313
+ hash = hash.merge(locals || {})
314
+
315
+ if content
316
+ hash[:content] = content.call.to_s # rescue nil ?
317
+ end
318
+
319
+ hash
320
+ end
321
+
322
+ #
323
+ #def make_scope_and_data(data, &content)
324
+ # scope, data = scope_vs_data(data)
325
+ # case scope
326
+ # when Binding
327
+ # vars = scope.eval("local_variables")
328
+ # vals = scope.eval("[#{vars.join(',')}]")
329
+ # data = data.merge(Hash[*vars.zip(vals).flatten])
330
+ # scope = scope.eval("self")
331
+ # else
332
+ # scope ||= Object.new
333
+ # end
334
+ # return scope, data
335
+ #end
336
+
337
+ #
338
+ def engine_options(params)
339
+ opts = {}
340
+ engine_option_names.each do |o|
341
+ o = o.to_sym
342
+ v = params[o] || settings[o]
343
+ opts[o] = v if v
344
+ end
345
+ opts
346
+ end
347
+
348
+ # Override this.
349
+ def engine_option_names
350
+ []
351
+ end
352
+
353
+ # Helper method to get paramters.
354
+ def parameters(params, *names)
355
+ pvals = names.map do |name|
356
+ params[name.to_sym] || settings[name.to_sym]
357
+ end
358
+
359
+ if names.size == 1
360
+ return pvals.first
361
+ else
362
+ return *pvals
152
363
  end
153
- db[:yield] = yld.call if yld
154
- return db
155
364
  end
156
365
 
157
366
  end