fabulator 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,22 @@
1
- === 0.0.1 2010-02-23
1
+ === 0.0.4 2010-08-16
2
2
 
3
- * 1 major enhancement:
4
- * Initial release
3
+ * 5 minor enhancements
4
+ * Add RedCloth gem dependence to gem spec
5
+ * f:string-length() returns 0 for nil values
6
+ * f:dump() now shows attributes
7
+ * compile-time context tree tracks line numbers of associated XML elements
8
+ * minor bug fixes in template tags
9
+ * tempate form XML element 'file' is now 'asset'
10
+
11
+ * 1 major enhancement
12
+ * add_default_values() should now work for parsed templates
13
+ * to_html() can now return form contents only
14
+ * parsed templates will be returned as a string if they are not
15
+
16
+ === 0.0.3 2010-08-10
17
+
18
+ * 1 minor enhancement
19
+ * Add libxslt-ruby gem dependence to gem spec
5
20
 
6
21
  === 0.0.2 2010-08-10
7
22
 
@@ -13,7 +28,8 @@
13
28
  * Use LibXSLT to apply template to html transform (requires the
14
29
  libxslt-ruby gem)
15
30
 
16
- === 0.0.3 2010-08-10
31
+ === 0.0.1 2010-02-23
32
+
33
+ * 1 major enhancement:
34
+ * Initial release
17
35
 
18
- * 1 minor enhancement
19
- * Add libxslt-ruby gem dependence to gem spec
@@ -19,7 +19,7 @@ XML language coupled with an XQuery-like expression language.
19
19
  require 'fabulator'
20
20
 
21
21
  parser = Fabulator::Expr::Parser.new
22
- context = Fabulator::Expr::Context.new_context_environment
22
+ context = Fabulator::Expr::Context.new
23
23
 
24
24
  context.set_value( '/a', 'some_values' )
25
25
  expr = parser.parse( 'f:sum(/a[. > 0]' )
@@ -30,8 +30,9 @@ XML language coupled with an XQuery-like expression language.
30
30
  == REQUIREMENTS:
31
31
 
32
32
  The expression engine does not depend on any external libraries. The
33
- XML framework depends on the Ruby libxml libraries at
34
- <http://libxml.rubyforge.org/>.
33
+ XML framework depends on the Ruby libxml and libxslt libraries at
34
+ <http://libxml.rubyforge.org/>. It also needs the RedCloth and radius
35
+ gems for the template engine.
35
36
 
36
37
  == INSTALL:
37
38
 
data/Rakefile CHANGED
@@ -10,6 +10,7 @@ begin
10
10
  gem.add_dependency(%q<libxml-ruby>, [">= 1.1.3"])
11
11
  gem.add_dependency(%q<libxslt-ruby>, [">= 0.9.7"])
12
12
  gem.add_dependency(%q<radius>, [">= 0.6.1"])
13
+ gem.add_dependency(%q<RedCloth>, [">= 4.2.0"])
13
14
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
15
  end
15
16
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
@@ -60,7 +60,6 @@ Feature: Function calls and lists
60
60
  Then I should get 1 item
61
61
  And item 0 should be [2]
62
62
 
63
- @hist
64
63
  Scenario: Histogram of text
65
64
  Given a context
66
65
  And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
@@ -68,7 +67,6 @@ Feature: Function calls and lists
68
67
  Then I should get 1 item
69
68
  And item 0 should be [4]
70
69
 
71
- @hist
72
70
  Scenario: Histogram of text with attributes
73
71
  Given a context
74
72
  And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
@@ -16,3 +16,20 @@ Feature: Simple Math
16
16
  | 30 | div | 6 | 5 |
17
17
  | 15 | mod | 4 | 3 |
18
18
 
19
+ @bool
20
+ Scenario Outline: boolean ops
21
+ Given a context
22
+ And that [/a] is set to [<a>]
23
+ And that [/b] is set to [<b>]
24
+ When I run the expression (a <op> b)
25
+ Then I should get 1 item
26
+ And item 0 should be <ans>
27
+
28
+ Examples:
29
+ | a | op | b | ans |
30
+ | 0 | = | 1 | false |
31
+ | 2 | = | 2 | true |
32
+ | 'a' | = | 'a' | true |
33
+ | 'a' | = | 'b' | false |
34
+ | 'a' | = | 1 | false |
35
+ | 1 | < | 'a' | true |
@@ -190,3 +190,15 @@ Feature: Simple state machines
190
190
  Then it should be in the 'stop' state
191
191
  And the expression (/foo) should equal ['bar']
192
192
  And the expression (/bar) should equal ['baz']
193
+
194
+ @var
195
+ Scenario: simple machine with a <variable /> and <value />
196
+ Given the statemachine
197
+ """
198
+ <f:application xmlns:f="http://dh.tamu.edu/ns/fabulator/1.0#">
199
+ <f:variable f:name="foo" f:select="'baz'" />
200
+ <f:value f:path="/foo" f:select="$foo" />
201
+ </f:application>
202
+ """
203
+ Then it should be in the 'start' state
204
+ And the expression (/foo) should equal ['baz']
@@ -5,6 +5,7 @@ end
5
5
  When /^I render the template$/ do
6
6
  parser = Fabulator::Template::Parser.new
7
7
  @template_result = parser.parse(@context, @template_text)
8
+ #puts @template_result.to_html unless @template_result.is_a?(String)
8
9
  end
9
10
 
10
11
  When /^I set the captions to:$/ do |caption_table|
@@ -16,6 +17,16 @@ When /^I set the captions to:$/ do |caption_table|
16
17
  @template_result.add_captions(captions)
17
18
  end
18
19
 
20
+ When /^I set the defaults to:$/ do |caption_table|
21
+ captions = { }
22
+ ctx = @context.with_root(@context.root.anon_node(nil))
23
+ caption_table.hashes.each do |h|
24
+ ctx.set_value(h['path'], Fabulator::Expr::Literal.new(h['default']))
25
+ end
26
+
27
+ @template_result.add_default_values(ctx)
28
+ end
29
+
19
30
  Then /^the rendered text should equal$/ do |doc|
20
31
  @template_result.to_s.should == %{<?xml version="1.0" encoding="UTF-8"?>\n} + doc + "\n"
21
32
  end
@@ -96,5 +96,30 @@ Feature: Templates
96
96
  <textline id="foo"><caption>FooCaption</caption></textline>
97
97
  <submit id="submit"><caption>SubmitCaption</caption></submit>
98
98
  </form>
99
+ </view>
100
+ """
101
+
102
+ @def
103
+ Scenario: Rendering a form with defaults
104
+ Given a context
105
+ And the prefix f as "http://dh.tamu.edu/ns/fabulator/1.0#"
106
+ And the template
107
+ """
108
+ <view>
109
+ <form>
110
+ <textline id='foo'><caption>Foo</caption></textline>
111
+ </form>
112
+ </view>
113
+ """
114
+ When I render the template
115
+ And I set the defaults to:
116
+ | path | default |
117
+ | foo | FooDefault |
118
+ Then the rendered text should equal
119
+ """
120
+ <view>
121
+ <form>
122
+ <textline id="foo"><caption>Foo</caption><default>FooDefault</default></textline>
123
+ </form>
99
124
  </view>
100
125
  """
@@ -263,7 +263,7 @@ module Fabulator
263
263
  # f:string-length(node-list) => node-list
264
264
  #
265
265
  mapping 'string-length' do |ctx, arg|
266
- arg.to_s.length
266
+ (arg.to_s.length rescue 0)
267
267
  end
268
268
 
269
269
  mapping 'normalize-space' do |ctx, arg|
@@ -347,7 +347,7 @@ module Fabulator
347
347
  ###
348
348
  ### Boolean
349
349
  ###
350
-
350
+
351
351
  function 'true', BOOLEAN do |ctx, args|
352
352
  return [ ctx.root.anon_node( true, [ FAB_NS, 'boolean' ] ) ]
353
353
  end
@@ -24,6 +24,7 @@ module Fabulator
24
24
 
25
25
  def compile_xml(xml, context = nil, callbacks = { })
26
26
  # /statemachine/states
27
+ XML.default_line_numbers = true
27
28
  if xml.is_a?(String)
28
29
  xml = LibXML::XML::Document.string xml
29
30
  end
@@ -10,6 +10,7 @@ module Fabulator
10
10
  @variables = { }
11
11
  @position = nil
12
12
  @last = nil
13
+ @line_num = nil
13
14
 
14
15
  if parent_c.nil?
15
16
  if xml.nil? || (xml.root rescue nil).nil?
@@ -23,6 +24,8 @@ module Fabulator
23
24
  if xml.is_a?(self.class)
24
25
  @run_time_parent = xml
25
26
  else
27
+ @line_num = xml.line_num
28
+
26
29
  parser = Fabulator::Expr::Parser.new
27
30
 
28
31
  xml.namespaces.each do |ns|
@@ -54,6 +57,12 @@ module Fabulator
54
57
  @last = !!l
55
58
  end
56
59
 
60
+ def line_num
61
+ return @line_num unless @line_num.nil?
62
+ return @parent.line_num unless @parent.nil?
63
+ return 0
64
+ end
65
+
57
66
  def position
58
67
  return @position unless @position.nil?
59
68
  return @position if @run_time_parent.nil?
@@ -14,7 +14,10 @@ module Fabulator
14
14
  r[:children] = cs unless cs.empty?
15
15
  r[:value] = self.value unless self.value.nil?
16
16
  r[:type] = self.vtype.join('') unless self.vtype.nil?
17
-
17
+ r[:attributes] = { }
18
+ self.attributes.each do |a|
19
+ r[:attributes][a.name] = a.value
20
+ end
18
21
  r
19
22
  end
20
23
 
@@ -6,6 +6,7 @@ module Fabulator::Template
6
6
 
7
7
  @@fabulator_xslt_file = File.join(File.dirname(__FILE__), "..", "..", "..", "xslt", "form.xsl")
8
8
 
9
+
9
10
  @@fabulator_xslt_doc = LibXML::XML::Document.file(@@fabulator_xslt_file)
10
11
  @@fabulator_xslt = LibXSLT::XSLT::Stylesheet.new(@@fabulator_xslt_doc)
11
12
 
@@ -15,6 +16,7 @@ module Fabulator::Template
15
16
  end
16
17
 
17
18
  def add_default_values(context)
19
+ return if context.nil?
18
20
  each_form_element do |el|
19
21
  own_id = el.attributes['id']
20
22
  next if own_id.nil? || own_id.to_s == ''
@@ -22,42 +24,43 @@ module Fabulator::Template
22
24
  default = nil
23
25
  is_grid = false
24
26
  if el.name == 'grid'
25
- default = el.find('./default | ./row/default | ./column/default')
27
+ default = el.find('./default | ./row/default | ./column/default').to_a
26
28
  is_grid = true
27
29
  else
28
- default = el.find('./default')
30
+ default = el.find('./default').to_a
29
31
  end
30
32
 
31
33
  id = el_id(el)
32
34
  ids = id.split('/')
33
- if !context.nil? && (default.is_a?(Array) && default.empty? || !default)
34
- l = context.traverse_path(ids)
35
- if !l.nil? && !l.empty?
36
- if is_grid
37
- count = (el.attributes['count'].to_s rescue '')
38
- how_many = 'multiple'
39
- direction = 'both'
40
- if count =~ %r{^(multiple|single)(-by-(row|column))?$}
41
- how_many = $1
42
- direction = $3 || 'both'
43
- end
44
- if direction == 'both'
45
- l.collect{|ll| ll.value}.each do |v|
46
- el << XML::Node.new('default', v)
47
- end
48
- elsif direction == 'row' || direction == 'column'
49
- el.find("./#{direction}").each do |div|
50
- id = (div.attributes['id'].to_s rescue '')
51
- next if id == ''
52
- l.collect{|c| context.with_root(c).traverse_path(id)}.flatten.collect{|c| c.value}.each do |v|
53
- div << XML::Node.new('default', v)
54
- end
55
- end
56
- end
57
- else
35
+ l = context.traverse_path(ids)
36
+ if !l.nil? && !l.empty?
37
+ if !default.nil? && !default.empty?
38
+ default.each { |d| d.remove! }
39
+ end
40
+ if is_grid
41
+ count = (el.attributes['count'].to_s rescue '')
42
+ how_many = 'multiple'
43
+ direction = 'both'
44
+ if count =~ %r{^(multiple|single)(-by-(row|column))?$}
45
+ how_many = $1
46
+ direction = $3 || 'both'
47
+ end
48
+ if direction == 'both'
58
49
  l.collect{|ll| ll.value}.each do |v|
59
50
  el << XML::Node.new('default', v)
60
51
  end
52
+ elsif direction == 'row' || direction == 'column'
53
+ el.find("./#{direction}").each do |div|
54
+ id = (div.attributes['id'].to_s rescue '')
55
+ next if id == ''
56
+ l.collect{|c| context.with_root(c).traverse_path(id)}.flatten.collect{|c| c.value}.each do |v|
57
+ div << XML::Node.new('default', v)
58
+ end
59
+ end
60
+ end
61
+ else
62
+ l.collect{|ll| ll.value}.each do |v|
63
+ el << XML::Node.new('default', v)
61
64
  end
62
65
  end
63
66
  end
@@ -111,8 +114,16 @@ module Fabulator::Template
111
114
  @doc.to_s
112
115
  end
113
116
 
114
- def to_html
115
- @@fabulator_xslt.apply(@doc).to_s
117
+ def to_html(popts = { })
118
+ opts = { :form => true }.update(popts)
119
+
120
+ res = @@fabulator_xslt.apply(@doc)
121
+
122
+ if opts[:form]
123
+ res.to_s
124
+ else
125
+ res.find('//form/*').collect{ |e| e.to_s}.join('')
126
+ end
116
127
  end
117
128
 
118
129
  protected
@@ -11,7 +11,8 @@ module Fabulator::Template
11
11
  @parser = Radius::Parser.new(@context, :tag_prefix => 'r')
12
12
  end
13
13
  @context.globals.context = context
14
- Fabulator::Template::ParseResult.new(@parser.parse(text))
14
+ r = @parser.parse(text)
15
+ (Fabulator::Template::ParseResult.new(r) rescue r)
15
16
  end
16
17
  end
17
18
  end
@@ -13,23 +13,22 @@ module Fabulator::Template
13
13
  selection = tag.attr['select']
14
14
  c = tag.locals.context || tag.globals.context
15
15
  # ns = get_fabulator_ns(tag)
16
- items = c.nil? ? [] : c.eval_expression(selection, ns)
16
+ items = c.nil? ? [] : c.eval_expression(selection)
17
17
  sort_by = tag.attr['sort']
18
18
  sort_dir = tag.attr['order'] || 'asc'
19
19
 
20
20
  if !sort_by.nil? && sort_by != ''
21
21
  parser = Fabulator::Expr::Parser.new
22
- sort_by_f = parser.parse(sort_by, ns)
23
- items = items.sort_by { |i| i.eval_expression(sort_by, ns).first.value }
22
+ sort_by_f = parser.parse(sort_by, c)
23
+ items = items.sort_by { |i| c.with_root(i).eval_expression(sort_by_f).first.value }
24
24
  if sort_dir == 'desc'
25
25
  items.reverse!
26
26
  end
27
27
  end
28
28
  res = ''
29
- #Rails.logger.info("Found #{items.size} items for for-each")
30
29
  items.each do |i|
31
30
  next if i.empty?
32
- tag.locals.context = i
31
+ tag.locals.context = c.with_root(i)
33
32
  res = res + tag.expand
34
33
  end
35
34
  res
@@ -46,7 +45,7 @@ module Fabulator::Template
46
45
  tag 'value' do |tag|
47
46
  selection = tag.attr['select']
48
47
  c = tag.locals.context || tag.globals.context
49
- items = c.nil? ? [] : c.eval_expression(selection, get_fabulator_ns(tag))
48
+ items = c.nil? ? [] : c.eval_expression(selection)
50
49
  items.collect{|i| i.to([Fabulator::FAB_NS, 'html']).value }.join('')
51
50
  end
52
51
 
@@ -730,7 +730,7 @@
730
730
  <xsl:attribute name="relation">
731
731
  <xsl:text>rel:</xsl:text><xsl:apply-templates select="ancestor::option[1]" mode="id"/>
732
732
  </xsl:attribute>
733
- <xsl:apply-templates select="text|textline|textbox|editbox|file|grid|password|selection|form|group|textreader|list">
733
+ <xsl:apply-templates select="text|textline|textbox|editbox|asset|grid|password|selection|form|group|textreader|list">
734
734
  <!-- xsl:with-param name="form_id"><xsl:value-of select="@id"/></xsl:with-param -->
735
735
  <xsl:with-param name="form_level"><value-of select="$form_level"/></xsl:with-param>
736
736
  </xsl:apply-templates>
@@ -747,7 +747,7 @@
747
747
  </span>
748
748
  </xsl:when>
749
749
  <xsl:otherwise>
750
- <xsl:apply-templates select="text|textline|textbox|editbox|file|grid|password|selection|form|group|textreader|list">
750
+ <xsl:apply-templates select="text|textline|textbox|editbox|asset|grid|password|selection|form|group|textreader|list">
751
751
  <!-- xsl:with-param name="form_id"><xsl:value-of select="@id"/></xsl:with-param -->
752
752
  <xsl:with-param name="form_level"><value-of select="$form_level"/></xsl:with-param>
753
753
  </xsl:apply-templates>
@@ -786,13 +786,13 @@
786
786
  <xsl:attribute name="method">
787
787
  <xsl:choose>
788
788
  <xsl:when test="@method = 'POST'">POST</xsl:when>
789
- <xsl:when test=".//file">POST</xsl:when>
789
+ <xsl:when test=".//asset">POST</xsl:when>
790
790
  <xsl:when test=".//textbox">POST</xsl:when>
791
791
  <xsl:when test=".//editbox">POST</xsl:when>
792
792
  <xsl:otherwise>POST</xsl:otherwise>
793
793
  </xsl:choose>
794
794
  </xsl:attribute>
795
- <xsl:if test=".//file">
795
+ <xsl:if test=".//asset">
796
796
  <xsl:attribute name="type">application/x-multipart</xsl:attribute>
797
797
  </xsl:if>
798
798
  <xsl:if test="./caption">
@@ -1232,14 +1232,13 @@
1232
1232
 
1233
1233
  <xsl:template match="text/caption"/>
1234
1234
 
1235
- <xsl:template match="form/file">
1235
+ <xsl:template match="form/asset">
1236
1236
  <!-- xsl:param name="form_id"/ -->
1237
- <tr>
1238
- <td align="right" valign="top"> <!-- width="50%"> -->
1237
+ <span class="form-element">
1238
+ <span class="form-element-label">
1239
1239
  <xsl:apply-templates select="caption"/>
1240
1240
  <xsl:apply-templates select="help"/>
1241
- </td>
1242
- <td valign="top"> <!-- width="50%"> -->
1241
+ </span>
1243
1242
  <input type="file">
1244
1243
  <!-- xsl:attribute name="name"><xsl:value-of select="$form_id"/>.<xsl:value-of select="@id"/></xsl:attribute -->
1245
1244
  <xsl:attribute name="name"><xsl:apply-templates select="." mode="id"/></xsl:attribute>
@@ -1247,8 +1246,7 @@
1247
1246
  <xsl:attribute name="accept"><xsl:value-of select="@accept"/></xsl:attribute>
1248
1247
  </xsl:if>
1249
1248
  </input>
1250
- </td>
1251
- </tr>
1249
+ </span>
1252
1250
  </xsl:template>
1253
1251
 
1254
1252
  <xsl:template match="form//stored">
@@ -1334,7 +1332,7 @@
1334
1332
  <xsl:apply-templates select="caption"/>
1335
1333
  <xsl:text>: </xsl:text>
1336
1334
  </xsl:if>
1337
- <xsl:apply-templates select="text|grid|textline|textbox|editbox|file|password|selection|form|group|textreader">
1335
+ <xsl:apply-templates select="text|grid|textline|textbox|editbox|asset|password|selection|form|group|textreader">
1338
1336
  <!-- xsl:with-param name="form_id">
1339
1337
  <xsl:if test="@id">
1340
1338
  <xsl:value-of select="@id"/>
@@ -1367,7 +1365,7 @@
1367
1365
  <xsl:attribute name="method">
1368
1366
  <xsl:choose>
1369
1367
  <xsl:when test="@method = 'POST'">POST</xsl:when>
1370
- <xsl:when test=".//file">POST</xsl:when>
1368
+ <xsl:when test=".//asset">POST</xsl:when>
1371
1369
  <xsl:when test=".//textbox">POST</xsl:when>
1372
1370
  <xsl:when test=".//editbox">POST</xsl:when>
1373
1371
  <xsl:otherwise>POST</xsl:otherwise>
@@ -1376,14 +1374,14 @@
1376
1374
  <xsl:if test="@target">
1377
1375
  <xsl:attribute name="action"><xsl:value-of select="@target"/></xsl:attribute>
1378
1376
  </xsl:if>
1379
- <xsl:if test=".//file">
1377
+ <xsl:if test=".//asset">
1380
1378
  <xsl:attribute name="type">application/x-multipart</xsl:attribute>
1381
1379
  </xsl:if>
1382
1380
  <xsl:if test="./caption">
1383
1381
  <xsl:apply-templates select="caption"/>
1384
1382
  <xsl:text>: </xsl:text>
1385
1383
  </xsl:if>
1386
- <xsl:apply-templates select="text|grid|textline|textbox|editbox|file|password|selection|form|group|textreader">
1384
+ <xsl:apply-templates select="text|grid|textline|textbox|editbox|asset|password|selection|form|group|textreader">
1387
1385
  <!-- xsl:with-param name="form_id">
1388
1386
  <xsl:if test="@id">
1389
1387
  <xsl:value-of select="@id"/>
@@ -1728,6 +1726,7 @@
1728
1726
  <!-- xsl:attribute name="name"><xsl:if test="$form_id != ''"><xsl:value-of select="$form_id"/>.</xsl:if><xsl:value-of select="@id"/></xsl:attribute -->
1729
1727
  <xsl:attribute name="name"><xsl:apply-templates select="." mode="id"/></xsl:attribute>
1730
1728
  <xsl:value-of select="default"/>
1729
+ <xsl:value-of select="' '"/>
1731
1730
  </textarea>
1732
1731
  </xsl:template>
1733
1732
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fabulator
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 4
10
+ version: 0.0.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - James Smith
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-10 00:00:00 +00:00
18
+ date: 2010-08-17 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -66,6 +66,22 @@ dependencies:
66
66
  version: 0.6.1
67
67
  type: :runtime
68
68
  version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: RedCloth
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 55
78
+ segments:
79
+ - 4
80
+ - 2
81
+ - 0
82
+ version: 4.2.0
83
+ type: :runtime
84
+ version_requirements: *id004
69
85
  description: The fabulator library provides a state machine implementation of a core set of semantics for building data-driven applications using a simple XML language coupled with an XQuery-like expression language.
70
86
  email: jgsmith@tamu.edu
71
87
  executables: []
@@ -78,7 +94,6 @@ extra_rdoc_files:
78
94
  files:
79
95
  - History.txt
80
96
  - Manifest.txt
81
- - PostInstall.txt
82
97
  - README.rdoc
83
98
  - Rakefile
84
99
  - VERSION
@@ -1,7 +0,0 @@
1
-
2
- For more information on fabulator, see http://github.com/jgsmith/ruby-fabulator
3
-
4
- NOTE: Change this information in PostInstall.txt
5
- You can also delete it if you don't want it.
6
-
7
-