malt 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,5 +1,24 @@
1
1
  = Release History
2
2
 
3
+
4
+ == 0.3.0 | 2010-11-04
5
+
6
+ New release adds a Malt::Machine class that encapsulates all
7
+ Malt's class level functionality. This allow Malt to be
8
+ be more finaly controlled. For example an instance of
9
+ Malt::Machine can be used to limit rendering to a select
10
+ set of formats.
11
+
12
+ Changes:
13
+
14
+ * Add Machine class to ecapsulate toplevel functions.
15
+ * Add feature via Machine options to select available formats.
16
+ * Add `#to_default` to for converting to default format.
17
+ * Add `Malt.engine?` to test for supported engine types.
18
+ * Rename `Malt.support?` to `Malt.format?`.
19
+ * Rename `Malt.main` to `Malt.cli`.
20
+
21
+
3
22
  == 0.2.0 | 2010-10-22
4
23
 
5
24
  Malt now support Erector, Markaby, Builder and Mustache templates.
data/License.txt CHANGED
@@ -1,4 +1,5 @@
1
1
  .
2
+
2
3
  Apache License
3
4
  Version 2.0, January 2004
4
5
  http://www.apache.org/licenses/
@@ -201,4 +202,4 @@
201
202
  See the License for the specific language governing permissions and
202
203
  limitations under the License.
203
204
 
204
-
205
+ .
data/README.rdoc CHANGED
@@ -18,7 +18,7 @@ very easy to implement thanks to it's clean design.
18
18
 
19
19
  === Functional API
20
20
 
21
- Malt.render(:file=>'foo.erb', :format=>:html, :data=>data)
21
+ Malt.render(:file=>'foo.erb', :to=>:html, :data=>data)
22
22
 
23
23
  Where +data+ is a data source of some type. Malt will see
24
24
  that the file is an ERB template and render it accordingly.
data/bin/malt CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'malt'
3
- Malt.main(*ARGV)
3
+ Malt.cli(*ARGV)
4
4
 
data/lib/malt.rb CHANGED
@@ -1,5 +1,7 @@
1
+ require 'malt/meta/data'
1
2
  require 'malt/kernel'
2
- require 'malt/render'
3
+ require 'malt/machine'
4
+ require 'malt/core_ext'
3
5
 
4
6
  module Malt
5
7
 
@@ -8,60 +10,42 @@ module Malt
8
10
  end
9
11
 
10
12
  #
11
- def self.register(malt_class, *exts)
12
- exts.each do |ext|
13
- type = ext_to_type(ext)
14
- registry[type] = malt_class
15
- end
13
+ def self.machine
14
+ @machine ||= Machine.new
16
15
  end
17
16
 
18
17
  #
19
- def self.registry
20
- @registry ||= {}
18
+ def self.file(file, options={})
19
+ machine.file(file, options)
21
20
  end
22
21
 
23
22
  #
24
- def self.support?(ext)
25
- ext = ext.to_s
26
- type = ext.sub(/^\./, '').strip
27
- return false if type.empty?
28
- #@registry.key?(ext.to_sym)
29
- #Engine.registry[type.to_sym]
30
- Engine.registry.key?(type.to_sym)
23
+ def self.text(text, options={})
24
+ machine.text(text, options)
31
25
  end
32
26
 
33
27
  #
34
- def self.file(file, options={})
35
- type = options[:type] || options[:format] || File.extname(file)
36
- type = ext_to_type(type)
37
- malt_class = registry[type]
38
- raise "unkown type -- #{type}" unless malt_class
39
- malt_class.new(options.merge(:file=>file,:type=>type))
28
+ def self.open(url, options={})
29
+ machine.open(url, options)
40
30
  end
41
31
 
42
32
  #
43
- def self.text(text, options={})
44
- if file = options[:file]
45
- ext = File.extname(file)
46
- ext = nil if ext.empty?
47
- end
48
- type = options[:type] || options[:format] || ext
49
- type = ext_to_type(type)
50
- malt_class = registry[type] || Format::Text
51
- #raise "unkown type -- #{type}" unless malt_class
52
- malt_class.new(options.merge(:text=>text,:file=>file,:type=>type))
33
+ def self.render(params, &body)
34
+ machine.render(params, &body)
53
35
  end
54
36
 
55
37
  #
56
- def self.open(url, options={})
57
- require 'open-uri'
58
- text = open(url).read
59
- file = File.basename(url) # parse better with URI.parse
60
- text(text, :file=>file)
38
+ def self.format?(ext)
39
+ machine.format?(ext)
40
+ end
41
+
42
+ # Returns true if the extension given is renderable.
43
+ def self.engine?(ext)
44
+ machine.engine?(ext)
61
45
  end
62
46
 
63
47
  #
64
- def self.main(*args)
48
+ def self.cli(*args)
65
49
  require 'optparse'
66
50
  itype, otype = nil, nil
67
51
  OptionParser.new{|o|
@@ -22,6 +22,10 @@ module Engine
22
22
  @registry ||= {}
23
23
  end
24
24
 
25
+ #
26
+ def self.defaults
27
+ @defaults ||= {}
28
+ end
25
29
 
26
30
  # Abstract Template class serves as the base
27
31
  # class for all other Template classes.
@@ -38,10 +42,15 @@ module Engine
38
42
  def self.default(*exts)
39
43
  register(*exts)
40
44
  exts.each do |ext|
41
- Malt.config.engine[ext.to_sym] = self
45
+ Engine.defaults[ext.to_sym] = self
42
46
  end
43
47
  end
44
48
 
49
+ #
50
+ def self.type
51
+ basename.downcase.to_sym
52
+ end
53
+
45
54
  #
46
55
  def initialize(settings={})
47
56
  @settings = settings.rekey
@@ -3,6 +3,23 @@ require 'malt/kernel'
3
3
  module Malt
4
4
  module Format
5
5
 
6
+ class << self
7
+ include Malt::Kernel
8
+ end
9
+
10
+ #
11
+ def self.register(malt_class, *exts)
12
+ exts.each do |ext|
13
+ type = ext_to_type(ext)
14
+ registry[type] = malt_class
15
+ end
16
+ end
17
+
18
+ #
19
+ def self.registry
20
+ @registry ||= {}
21
+ end
22
+
6
23
  # Abstract format class serves as the base
7
24
  # class for all other format classes.
8
25
  #
@@ -12,7 +29,7 @@ module Format
12
29
  # Register the class to an extension type.
13
30
  def self.register(*exts)
14
31
  @extensions = exts
15
- Malt.register(self, *exts)
32
+ Malt::Format.register(self, *exts)
16
33
 
17
34
  #exts.each do |ext|
18
35
  # Abstract.module_eval %{
@@ -10,7 +10,7 @@ module Format
10
10
 
11
11
  #
12
12
  def to(type, data=nil, &yld)
13
- new_class = Malt.registry[type.to_sym]
13
+ new_class = Malt::Format.registry[type.to_sym] # TODO: Malt.machine.format?
14
14
  new_text = render(type, data, &yld)
15
15
  new_file = refile(type)
16
16
  new_options = options.merge(:text=>new_text, :file=>new_file, :type=>type)
@@ -28,11 +28,11 @@ module Format
28
28
 
29
29
  # ERB templates can be any type.
30
30
  def method_missing(sym, *args, &yld)
31
- if Malt.registry.key?(sym)
31
+ if Malt::Format.registry.key?(sym) # TODO: Malt.machine.format?
32
32
  return render(sym, *args, &yld).to_s
33
33
  elsif md = /^to_/.match(sym.to_s)
34
34
  type = md.post_match.to_sym
35
- if Malt.registry.key?(type)
35
+ if Malt::Format.registry.key?(type) # TODO: Malt.machine.format?
36
36
  return to(type, *args, &yld)
37
37
  end
38
38
  end
@@ -29,7 +29,7 @@ module Malt::Format
29
29
 
30
30
  #
31
31
  def to(type, data=nil, &yld)
32
- new_class = Malt.registry[type.to_sym]
32
+ new_class = Malt::Format.registry[type.to_sym] # TODO: Malt.machine.format?
33
33
  new_text = render(data, &yld)
34
34
  new_file = refile(type)
35
35
  new_options = options.merge(:text=>new_text, :file=>new_file)
@@ -38,11 +38,11 @@ module Malt::Format
38
38
 
39
39
  # Ruby templates can be any type.
40
40
  def method_missing(sym, *args, &yld)
41
- if Malt.registry.key?(sym)
41
+ if Malt::Format.registry.key?(sym)
42
42
  return to(sym, *args, &yld).to_s
43
43
  elsif md = /^to_/.match(sym.to_s)
44
44
  type = md.post_match.to_sym
45
- if Malt.registry.key?(type)
45
+ if Malt::Format.registry.key?(type) # TODO: Malt.machine.format?
46
46
  return to(type, *args, &yld)
47
47
  end
48
48
  end
@@ -0,0 +1,227 @@
1
+ module Malt
2
+
3
+ # The Machine class encapsulates Malt's main methods
4
+ # along with configuratable settings to control
5
+ # which engines and formats are used for rendering.
6
+ #--
7
+ # TODO: Can we dynamically generate the MARKUP and TEMPLATE constants
8
+ # from the format classes? In anycase, the still need tweaking.
9
+ #++
10
+ class Machine
11
+
12
+ # List of markup types. These are formats that just allow markup transformations
13
+ # and do not provide for data injection.
14
+ MARKUP = [:rdoc, :markdown, :textile, :scss, :sass, :less, :css, :html, :xml]
15
+
16
+ # List of template types. These are template formats that provide data injection.
17
+ TEMPLATES = [:ruby, :erb, :liquid, :mustache, :tenjin, :ragtag, :radius, :erector, :builder, :markaby]
18
+
19
+ # Template types that prevent arbitrary Ruby code execution.
20
+ TEMPLATES_SAFE = [:liquid, :mustache]
21
+
22
+ # New Malt Machine.
23
+ #
24
+ # * config[:types] - list of formats to handle
25
+ # * config[:priority] - list of prioritized engines
26
+ #
27
+ def initialize(config={})
28
+ if priority = config[:priority]
29
+ priority.map!{ |e| e.to_sym }
30
+ else
31
+ priority = []
32
+ end
33
+ if types = config[:types] || config[:type]
34
+ formats = {}
35
+ engines = {}
36
+ types.each do |type|
37
+ k = ext_to_type(type)
38
+ formats[k] = Malt::Format.registry[k]
39
+ engines[k] = Malt::Engine.registry[k]
40
+ end
41
+ else
42
+ formats = Malt::Format.registry #.dup
43
+ engines = Malt::Engine.registry #.dup
44
+ end
45
+ @formats = formats
46
+ @engines = engines
47
+ @priority = priority
48
+ end
49
+
50
+ #
51
+ def formats
52
+ @formats
53
+ end
54
+
55
+ #
56
+ def engines
57
+ @engines
58
+ end
59
+
60
+ # Engine priorities.
61
+ #
62
+ # Returns an Array of symbolic engine names.
63
+ def priority(type=nil)
64
+ if type
65
+ type = type.to_s.downcase.to_sym
66
+ @priority.unshift(type)
67
+ @priority.uniq! # assuming first are kept
68
+ end
69
+ @priority
70
+ end
71
+
72
+ #
73
+ def engine?(ext)
74
+ type = ext_to_type(ext)
75
+ engines.key?(type)
76
+ ##ext = ext.to_s
77
+ ##type = ext.sub(/^\./, '').strip
78
+ ##return false if type.empty?
79
+ ###@registry.key?(ext.to_sym)
80
+ ###Engine.registry[type.to_sym]
81
+ ##Engine.registry.key?(type.to_sym)
82
+ end
83
+
84
+ #
85
+ def format?(ext)
86
+ type = ext_to_type(ext)
87
+ formats.key?(type)
88
+ end
89
+
90
+ #
91
+ def file(file, options={})
92
+ type = options[:type] || options[:format] || File.extname(file)
93
+ type = ext_to_type(type)
94
+ malt_class = formats[type]
95
+ raise "unkown type -- #{type}" unless malt_class
96
+ malt_class.new(options.merge(:file=>file,:type=>type))
97
+ end
98
+
99
+ #
100
+ def text(text, options={})
101
+ if file = options[:file]
102
+ ext = File.extname(file)
103
+ ext = nil if ext.empty?
104
+ end
105
+ type = options[:type] || options[:format] || ext
106
+ type = ext_to_type(type)
107
+ malt_class = formats[type] || Format::Text # :pass ?
108
+ #raise "unkown type -- #{type}" unless malt_class
109
+ malt_class.new(options.merge(:text=>text,:file=>file,:type=>type))
110
+ end
111
+
112
+ # Open a URL as a Malt Format object.
113
+ def open(url, options={})
114
+ require 'open-uri'
115
+ text = open(url).read
116
+ file = File.basename(url) # parse better with URI.parse
117
+ text(text, :file=>file)
118
+ end
119
+
120
+ # Render template directly.
121
+ #
122
+ # parameters[:file] - File name of template. Used to read text.
123
+ # parameters[:text] - Text of template document.
124
+ # parameters[:type] - File type/extension used to look up engine.
125
+ # parameters[:pass] - If not a supported type return text rather than raise an error.
126
+ # parameters[:engine] - Force the use of a this specific engine.
127
+ # parameters[:to] - Format to convert to (usual default is `html`).
128
+ #
129
+ def render(parameters={}, &body)
130
+ type = parameters[:type]
131
+ file = parameters[:file]
132
+ text = parameters[:text]
133
+ engine = parameters[:engine]
134
+
135
+ type = file_type(file, type)
136
+ text = file_read(file) unless text
137
+
138
+ engine_class = engine(type, engine)
139
+
140
+ if engine_class
141
+ parameters[:type] = type
142
+ parameters[:text] = text
143
+
144
+ engine = engine_class.new
145
+ engine.render(parameters, &body)
146
+ else
147
+ if parameters[:pass]
148
+ text
149
+ else
150
+ raise NoEngineError, "no engine to handle `#{type}' format"
151
+ end
152
+ end
153
+ end
154
+
155
+ private
156
+
157
+ #
158
+ def engine(type, engine=nil)
159
+ type = ext_to_type(type)
160
+ #engine = engine || Malt.config.engine[type] # FIXME
161
+ case engine
162
+ when Class
163
+ #raise unless Engine.registry[type].include?(engine)
164
+ engine
165
+ when String, Symbol
166
+ match = engine.to_s.downcase.to_sym
167
+ #Engine.registry[type].find{ |e| e.basename.downcase == match }
168
+ #engines[type].find{ |e| e.basename.downcase == match }
169
+ engines[type].find{ |e| match == e.type }
170
+ else
171
+ if engines[type]
172
+ #Engine.registry[type].first
173
+ types = engines[type]
174
+ if prior = types.find{ |e| priority.include?(e.type) }
175
+ return prior
176
+ end
177
+ if default = Engine.defaults[type]
178
+ return default #if engine?(default.type)
179
+ end
180
+ types.first
181
+ else
182
+ nil
183
+ end
184
+ end
185
+ end
186
+
187
+ #
188
+ def file_type(file, type=nil)
189
+ ext = type || File.extname(file)
190
+ ext = ext.to_s.downcase
191
+ if ext.empty?
192
+ nil
193
+ elsif ext[0,1] == '.'
194
+ ext[1..-1].to_sym
195
+ else
196
+ ext.to_sym
197
+ end
198
+ end
199
+
200
+ #
201
+ #def ext_type(type)
202
+ # type.to_s.downcase.sub(/^\./,'').to_sym
203
+ #end
204
+
205
+ # TODO: Handle File objects and URLs.
206
+ def file_read(file)
207
+ File.read(file)
208
+ end
209
+
210
+ # Normal file extension to a symbol type reference.
211
+ def ext_to_type(ext)
212
+ ext = ext.to_s.downcase
213
+ return nil if ext.empty?
214
+ if ext[0,1] == '.'
215
+ ext[1..-1].to_sym
216
+ else
217
+ ext.to_sym
218
+ end
219
+ end
220
+
221
+ end
222
+
223
+ #
224
+ class NoEngineError < ArgumentError
225
+ end
226
+
227
+ end
@@ -1,6 +1,6 @@
1
1
  name : malt
2
- date : 2010-10-22
3
- version : 0.2.0
2
+ date : 2010-11-04
3
+ version : 0.3.0
4
4
 
5
5
  requires:
6
6
  - syckle (build)
data/meta/package CHANGED
@@ -1,6 +1,6 @@
1
1
  name : malt
2
- date : 2010-10-22
3
- version : 0.2.0
2
+ date : 2010-11-04
3
+ version : 0.3.0
4
4
 
5
5
  requires:
6
6
  - syckle (build)
@@ -0,0 +1,29 @@
1
+ == Limited Formats
2
+
3
+ The Machine class makes it possible to control which formats
4
+ are available for rendering.
5
+
6
+ For example, let's make a Machine that only support RDoc format
7
+ and no others.
8
+
9
+ malt = Malt::Machine.new(:types=>[:rdoc])
10
+
11
+ Now we use the `malt` machine object to handle rendering. First let's
12
+ make sure that the machine is infact setup to limit formats to just RDoc.
13
+
14
+ malt.formats.keys.assert = [:rdoc]
15
+
16
+ malt.assert.format?('.rdoc')
17
+ malt.refute.format?('.markdown')
18
+
19
+ This being the case we should be able to render an RDoc file without issue.
20
+
21
+ malt.render(:file=>'qed/samples/sample.rdoc')
22
+
23
+ Where as another format type, though usually supported, but excluded in this
24
+ case, will fail.
25
+
26
+ expect Malt::NoEngineError do
27
+ malt.render(:file=>'qed/samples/sample.markdown')
28
+ end
29
+
@@ -0,0 +1,34 @@
1
+ == Prioritized Engines
2
+
3
+ The Malt Machine class can also be used to prioritize engines.
4
+ For instance, by default markdown documents are handled by
5
+ the RDiscount library.
6
+
7
+ malt = Malt::Machine.new
8
+
9
+ engine = malt.pry.engine(:markdown)
10
+ engine.assert == Malt::Engine::RDiscount
11
+
12
+ To use Kramdown instead, we can specify
13
+ it as a priority when initilizeing a new Machine.
14
+
15
+ malt = Malt::Machine.new(:priority=>[:kramdown])
16
+
17
+ Lets check to make sure.
18
+
19
+ engine = malt.pry.engine(:markdown)
20
+ engine.assert == Malt::Engine::Kramdown
21
+
22
+ To change the engine priorities of the master Malt Machine, provide
23
+ the #priority method with the type and it will put it at the top of
24
+ the priority list.
25
+
26
+ Malt.machine.priority :kramdown
27
+
28
+ Lets check to make sure.
29
+
30
+ engine = Malt.machine.pry.engine(:markdown)
31
+ engine.assert == Malt::Engine::Kramdown
32
+
33
+ (If you are wondering, #pry is simply used to call a private method.)
34
+
data/qed/applique/malt.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'malt'
2
+ require 'ae/pry'
2
3
 
3
4
  When "say we have a (((\\w+))) document called '(((\\S+)))' containing" do |type, fname, text|
4
5
  file = File.join('tmp',fname)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: malt
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Thomas Sawyer
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-28 00:00:00 -04:00
18
+ date: 2010-11-04 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -247,7 +247,6 @@ files:
247
247
  - features/step_definitions/engine_steps.rb
248
248
  - features/support/loadpath.rb
249
249
  - features/support/sample_class.rb
250
- - lib/malt/config.rb
251
250
  - lib/malt/core_ext.rb
252
251
  - lib/malt/engines/abstract.rb
253
252
  - lib/malt/engines/bluecloth.rb
@@ -300,11 +299,11 @@ files:
300
299
  - lib/malt/formats/yaml.rb
301
300
  - lib/malt/formats.rb
302
301
  - lib/malt/kernel.rb
302
+ - lib/malt/machine.rb
303
303
  - lib/malt/markup.rb
304
304
  - lib/malt/meta/data.rb
305
305
  - lib/malt/meta/package
306
306
  - lib/malt/meta/profile
307
- - lib/malt/render.rb
308
307
  - lib/malt/template.rb
309
308
  - lib/malt.rb
310
309
  - meta/data.rb
@@ -331,6 +330,8 @@ files:
331
330
  - qed/03_formats/18_builder.rb
332
331
  - qed/03_formats/19_erector.rb
333
332
  - qed/03_formats/20_mustache.rdoc
333
+ - qed/05_machine/01_limited_formats.rdoc
334
+ - qed/05_machine/02_prioritized_engines.rdoc
334
335
  - qed/applique/malt.rb
335
336
  - qed/samples/data.yml
336
337
  - qed/samples/output-erb.txt
data/lib/malt/config.rb DELETED
@@ -1,12 +0,0 @@
1
- module Malt
2
-
3
- class Config
4
-
5
- #
6
- def engine
7
- @engine ||= {}
8
- end
9
-
10
- end
11
-
12
- end
data/lib/malt/render.rb DELETED
@@ -1,93 +0,0 @@
1
- require 'malt/kernel'
2
- require 'malt/config'
3
- require 'malt/core_ext'
4
-
5
- module Malt
6
-
7
- extend Kernel
8
-
9
- #
10
- def self.config
11
- @config ||= Config.new
12
- end
13
-
14
- # Render template.
15
- #
16
- # parameters[:file] - File name of template. Used to read text.
17
- # parameters[:text] - Text of template document.
18
- # parameters[:type] - File type/extension used to look up engine.
19
- # parameters[:pass] - If not a supported type return text rather than raise an error.
20
- # parameters[:engine] - Force the use of a this specific engine.
21
- # parameters[:to] - Format to convert to (usual default is `html`).
22
- #
23
- def self.render(parameters={}, &body)
24
- type = parameters[:type]
25
- file = parameters[:file]
26
- text = parameters[:text]
27
- engine = parameters[:engine]
28
-
29
- type = file_type(file, type)
30
- text = file_read(file) unless text
31
-
32
- engine_class = engine(type, engine)
33
-
34
- if engine_class
35
- parameters[:type] = type
36
- parameters[:text] = text
37
-
38
- engine = engine_class.new
39
- engine.render(parameters, &body)
40
- else
41
- if parameters[:pass]
42
- text
43
- else
44
- raise "no engine to handle `#{type}' format"
45
- end
46
- end
47
- end
48
-
49
- #
50
- def self.engine(type, engine=nil)
51
- type = ext_to_type(type)
52
- engine = engine || config.engine[type]
53
- case engine
54
- when Class
55
- #raise unless Engine.registry[type].include?(engine)
56
- engine
57
- when String, Symbol
58
- match = engine.to_s.downcase
59
- Engine.registry[type].find{ |e| e.basename.downcase == match }
60
- else
61
- if Engine.registry[type]
62
- Engine.registry[type].first
63
- else
64
- nil
65
- end
66
- end
67
- end
68
-
69
- #
70
- def self.file_type(file, type=nil)
71
- ext = type || File.extname(file)
72
- ext = ext.to_s.downcase
73
- if ext.empty?
74
- nil
75
- elsif ext[0,1] == '.'
76
- ext[1..-1].to_sym
77
- else
78
- ext.to_sym
79
- end
80
- end
81
-
82
- #
83
- #def self.ext_type(type)
84
- # type.to_s.downcase.sub(/^\./,'').to_sym
85
- #end
86
-
87
- # TODO: Handle File objects and URLs.
88
- def self.file_read(file)
89
- File.read(file)
90
- end
91
-
92
- end
93
-